From 0b4e3aa066abc0728aacb4bbeb86f53f9737156e Mon Sep 17 00:00:00 2001 From: Apple <opensource@apple.com> Date: Sat, 9 Aug 2003 23:33:25 +0000 Subject: [PATCH] xnu-201.tar.gz --- EXTERNAL_HEADERS/mach-o/reloc.h | 201 ++ bsd/conf/MASTER | 4 + bsd/conf/Makefile | 9 +- bsd/conf/Makefile.template | 5 +- bsd/conf/files | 19 +- bsd/conf/version.minor | 2 +- bsd/conf/version.variant | 1 - bsd/dev/Makefile | 1 + bsd/dev/disk.h | 7 +- bsd/dev/i386/cons.c | 5 +- bsd/dev/i386/unix_startup.c | 4 + bsd/dev/ppc/cons.c | 5 +- bsd/dev/ppc/unix_startup.c | 11 + bsd/dev/random/Makefile | 37 + .../include/WindowsTypesForMac.h | 66 + .../random/YarrowCoreLib/include/macos_defs.h | 1658 +++++++++++ bsd/dev/random/YarrowCoreLib/include/yarrow.h | 160 + .../YarrowCoreLib/include/yarrowUtils.h | 42 +- .../dev/random/YarrowCoreLib/port/smf.c | 57 +- .../random/YarrowCoreLib/src/assertverify.h | 72 + bsd/dev/random/YarrowCoreLib/src/comp.c | 181 ++ bsd/dev/random/YarrowCoreLib/src/comp.h | 87 + .../random/YarrowCoreLib/src/entropysources.h | 46 +- .../dev/random/YarrowCoreLib/src/macOnly.h | 62 +- bsd/dev/random/YarrowCoreLib/src/prng.c | 624 ++++ bsd/dev/random/YarrowCoreLib/src/prng.h | 66 + bsd/dev/random/YarrowCoreLib/src/prngpriv.h | 118 + .../YarrowCoreLib/src/readme-prnguser.txt | 90 + bsd/dev/random/YarrowCoreLib/src/sha1mod.c | 226 ++ bsd/dev/random/YarrowCoreLib/src/sha1mod.h | 61 + bsd/dev/random/YarrowCoreLib/src/smf.h | 95 + .../random/YarrowCoreLib/src/userdefines.h | 47 + .../random/YarrowCoreLib/src/yarrowUtils.c | 58 +- bsd/dev/random/randomdev.c | 305 ++ .../PoolAlloc.c => bsd/dev/random/randomdev.h | 28 +- bsd/hfs/MacOSStubs.c | 40 +- bsd/hfs/Makefile | 2 +- bsd/hfs/hfs.h | 115 +- bsd/hfs/hfs_btreeio.c | 7 +- bsd/hfs/hfs_encodinghint.c | 823 +++++ bsd/hfs/hfs_link.c | 2 +- bsd/hfs/hfs_lookup.c | 84 +- bsd/hfs/hfs_macos_defs.h | 22 +- bsd/hfs/hfs_readwrite.c | 596 ++-- bsd/hfs/hfs_vfsops.c | 76 +- bsd/hfs/hfs_vfsutils.c | 356 ++- bsd/hfs/hfs_vhash.c | 6 +- bsd/hfs/hfs_vnodeops.c | 401 ++- bsd/hfs/hfscommon/Catalog/Catalog.c | 72 +- bsd/hfs/hfscommon/Catalog/CatalogUtilities.c | 54 +- bsd/hfs/hfscommon/Catalog/FileIDsServices.c | 5 +- bsd/hfs/hfscommon/Misc/FileExtentMapping.c | 192 +- bsd/hfs/hfscommon/Misc/VolumeAllocation.c | 1350 +++------ bsd/hfs/hfscommon/Misc/VolumeRequests.c | 139 - bsd/hfs/hfscommon/headers/FileMgrInternal.h | 410 +-- bsd/hfs/rangelist.c | 435 +++ .../IOAccelTypes.h => bsd/hfs/rangelist.h | 67 +- bsd/i386/param.h | 2 +- bsd/i386/types.h | 4 +- bsd/isofs/cd9660/cd9660_lookup.c | 4 +- bsd/isofs/cd9660/cd9660_util.c | 6 +- bsd/isofs/cd9660/cd9660_vfsops.c | 47 +- bsd/isofs/cd9660/cd9660_vnops.c | 1 + bsd/isofs/cd9660/iso.h | 10 +- bsd/kern/bsd_init.c | 5 +- bsd/kern/bsd_stubs.c | 31 +- bsd/kern/init_sysent.c | 4 +- bsd/kern/kdebug.c | 28 +- bsd/kern/kern_clock.c | 4 +- bsd/kern/kern_core.c | 3 +- bsd/kern/kern_descrip.c | 17 +- bsd/kern/kern_exec.c | 154 +- bsd/kern/kern_exit.c | 289 +- bsd/kern/kern_fork.c | 207 +- bsd/kern/kern_lock.c | 10 +- bsd/kern/kern_mman.c | 2 +- bsd/kern/kern_newsysctl.c | 4 +- bsd/kern/kern_pcsamples.c | 121 +- bsd/kern/kern_prot.c | 21 + bsd/kern/kern_shutdown.c | 9 +- bsd/kern/kern_sig.c | 150 +- bsd/kern/kern_symfile.c | 459 +-- bsd/kern/kern_synch.c | 67 +- bsd/kern/kern_sysctl.c | 35 +- bsd/kern/kern_time.c | 10 +- bsd/kern/mach_fat.c | 3 +- bsd/kern/mach_loader.c | 376 +-- bsd/kern/mach_loader.h | 5 +- bsd/kern/mach_process.c | 20 +- bsd/kern/subr_log.c | 5 +- bsd/kern/sys_generic.c | 387 ++- bsd/kern/sys_socket.c | 27 +- bsd/kern/syscalls.c | 4 +- bsd/kern/sysctl_init.c | 4 + bsd/kern/tty.c | 56 +- bsd/kern/tty_pty.c | 7 +- bsd/kern/tty_subr.c | 10 +- bsd/kern/tty_tty.c | 5 +- bsd/kern/ubc_subr.c | 930 +++--- bsd/kern/uipc_mbuf.c | 7 +- bsd/kern/uipc_mbuf2.c | 2 +- bsd/kern/uipc_socket.c | 26 +- bsd/kern/uipc_socket2.c | 123 +- bsd/kern/uipc_usrreq.c | 12 + bsd/libkern/random.c | 41 +- bsd/miscfs/deadfs/dead_vnops.c | 1 + bsd/miscfs/devfs/devfs_tree.c | 5 + bsd/miscfs/devfs/devfs_vfsops.c | 5 + bsd/miscfs/devfs/devfsdefs.h | 4 +- bsd/miscfs/fdesc/fdesc_vnops.c | 3 +- bsd/miscfs/fifofs/fifo.h | 41 +- bsd/miscfs/fifofs/fifo_vnops.c | 48 +- bsd/miscfs/specfs/spec_vnops.c | 31 +- bsd/miscfs/synthfs/synthfs_vfsops.c | 4 + bsd/miscfs/synthfs/synthfs_vnops.c | 1 + bsd/miscfs/umapfs/umap_subr.c | 2 +- bsd/miscfs/union/union_vnops.c | 1 + bsd/miscfs/volfs/volfs_vnops.c | 4 +- bsd/net/bpf.c | 16 +- bsd/net/bridge.c | 6 + bsd/net/dlil.c | 165 +- bsd/net/dlil.h | 7 +- bsd/net/dlil_ethersubr.c | 4 +- bsd/net/ether_if_module.c | 4 +- bsd/net/ether_inet6_pr_module.c | 6 +- bsd/net/ether_inet_pr_module.c | 19 +- bsd/net/if.h | 19 +- bsd/net/if_gif.c | 2 +- bsd/net/if_loop.c | 4 + bsd/net/if_media.c | 2 +- bsd/net/if_spppsubr.c | 12 +- bsd/net/if_tun.c | 10 +- bsd/net/if_vlan.c | 4 +- bsd/net/kext_net.h | 4 + bsd/net/ndrv.c | 8 +- bsd/net/radix.h | 2 +- bsd/net/raw_cb.h | 1 + bsd/net/route.h | 1 + bsd/net/rtsock.c | 2 +- bsd/netat/asp_proto.c | 799 ++--- bsd/netat/at.c | 6 +- bsd/netat/atp.h | 15 +- bsd/netat/atp_alloc.c | 4 + bsd/netat/atp_misc.c | 53 +- bsd/netat/atp_open.c | 3 + bsd/netat/atp_write.c | 74 +- bsd/netat/aurp_aurpd.c | 8 +- bsd/netat/ddp.c | 13 +- bsd/netat/ddp_aarp.c | 50 +- bsd/netat/ddp_lap.c | 2 +- bsd/netat/ddp_nbp.c | 7 +- bsd/netat/ddp_usrreq.c | 4 + bsd/netat/sys_glue.c | 256 +- bsd/netccitt/pk_subr.c | 3 +- bsd/netinet/Makefile | 8 +- bsd/netinet/fil.c | 1344 --------- bsd/netinet/if_ether.c | 33 +- bsd/netinet/igmp.c | 4 +- bsd/netinet/in.c | 79 +- bsd/netinet/in.h | 6 + bsd/netinet/in_bootp.c | 17 +- bsd/netinet/in_cksum.c | 241 +- bsd/netinet/in_gif.c | 4 + bsd/netinet/in_hostcache.c | 2 + bsd/netinet/in_pcb.c | 6 +- bsd/netinet/in_pcb.h | 1 + bsd/netinet/ip_auth.c | 527 ---- bsd/netinet/ip_auth.h | 85 - bsd/netinet/ip_compat.h | 18 - bsd/netinet/ip_dummynet.c | 4 +- bsd/netinet/ip_fil.h | 546 ---- bsd/netinet/ip_frag.c | 487 --- bsd/netinet/ip_frag.h | 79 - bsd/netinet/ip_fw.c | 4 +- bsd/netinet/ip_icmp.c | 2 + bsd/netinet/ip_input.c | 46 +- bsd/netinet/ip_log.c | 503 ---- bsd/netinet/ip_nat.c | 1393 --------- bsd/netinet/ip_nat.h | 201 -- bsd/netinet/ip_output.c | 203 +- bsd/netinet/ip_proxy.c | 362 --- bsd/netinet/ip_proxy.h | 113 - bsd/netinet/ip_state.c | 821 ----- bsd/netinet/ip_state.h | 164 - bsd/netinet/ip_var.h | 1 + bsd/netinet/raw_ip.c | 12 +- bsd/netinet/tcp_fsm.h | 16 +- bsd/netinet/tcp_input.c | 75 +- bsd/netinet/tcp_output.c | 32 +- bsd/netinet/tcp_seq.h | 2 + bsd/netinet/tcp_subr.c | 85 +- bsd/netinet/tcp_timer.c | 2 +- bsd/netinet/tcp_usrreq.c | 16 +- bsd/netinet/tcp_var.h | 6 + bsd/netinet/udp_usrreq.c | 49 +- bsd/netinet6/ah_core.c | 8 +- bsd/netinet6/frag6.c | 7 - bsd/netinet6/in6.c | 8 +- bsd/netinet6/in6_ifattach.c | 3 +- bsd/netinet6/in6_prefix.c | 22 +- bsd/netinet6/in6_prefix.h | 1 + bsd/netinet6/in6_rmx.c | 44 +- bsd/netinet6/ip6_fw.c | 6 +- bsd/netinet6/ip6_input.c | 8 +- bsd/netinet6/ip6_mroute.c | 23 +- bsd/netinet6/ipsec.c | 4 +- bsd/netinet6/mip6.c | 30 +- bsd/netinet6/mip6_ha.c | 24 +- bsd/netinet6/mip6_mn.c | 12 +- bsd/netinet6/natpt_tslot.c | 4 +- bsd/netinet6/nd6.c | 48 +- bsd/netinet6/nd6.h | 1 + bsd/netinet6/nd6_nbr.c | 32 +- bsd/netinet6/nd6_rtr.c | 2 +- bsd/netinet6/raw_ip6.c | 4 + bsd/netkey/key.c | 17 +- bsd/netkey/keydb.c | 12 +- bsd/netkey/keysock.c | 2 +- bsd/nfs/nfs_bio.c | 69 +- bsd/nfs/nfs_serv.c | 33 +- bsd/nfs/nfs_socket.c | 31 +- bsd/nfs/nfs_syscalls.c | 2 +- bsd/nfs/nfs_vfsops.c | 42 +- bsd/nfs/nfs_vnops.c | 865 +++--- bsd/ppc/types.h | 4 +- bsd/sys/Makefile | 2 +- bsd/sys/attr.h | 1 + bsd/sys/buf.h | 4 +- bsd/sys/cdefs.h | 4 +- bsd/sys/conf.h | 2 +- bsd/sys/domain.h | 1 + bsd/sys/fcntl.h | 5 +- bsd/sys/file.h | 2 +- bsd/sys/kdebug.h | 7 + bsd/sys/lock.h | 15 + bsd/sys/mbuf.h | 5 +- bsd/sys/mount.h | 5 + bsd/sys/proc.h | 7 + bsd/sys/protosw.h | 3 +- bsd/sys/ptrace.h | 1 + .../IOAccelerator.cpp => bsd/sys/random.h | 10 +- bsd/sys/select.h | 21 +- bsd/sys/socket.h | 4 +- bsd/sys/socketvar.h | 112 +- bsd/sys/sockio.h | 8 + bsd/sys/syscall.h | 3 +- bsd/sys/tty.h | 4 +- bsd/sys/types.h | 2 +- bsd/sys/ubc.h | 45 +- bsd/sys/user.h | 10 +- bsd/sys/utfconv.h | 3 +- bsd/sys/vnode.h | 6 +- bsd/sys/vnode_if.h | 20 +- bsd/ufs/ffs/ffs_vfsops.c | 16 + bsd/ufs/ffs/ffs_vnops.c | 1 - bsd/ufs/mfs/mfs_vfsops.c | 5 + bsd/ufs/ufs/inode.h | 2 + bsd/ufs/ufs/ufs_ihash.c | 10 + bsd/ufs/ufs/ufs_inode.c | 5 + bsd/ufs/ufs/ufs_readwrite.c | 12 +- bsd/ufs/ufs/ufs_vnops.c | 17 +- bsd/vfs/vfs_bio.c | 148 +- bsd/vfs/vfs_cluster.c | 975 ++++-- bsd/vfs/vfs_lookup.c | 22 +- bsd/vfs/vfs_subr.c | 641 ++-- bsd/vfs/vfs_support.c | 10 +- bsd/vfs/vfs_syscalls.c | 119 +- bsd/vfs/vfs_utfconv.c | 624 +++- bsd/vfs/vfs_vnops.c | 48 +- bsd/vfs/vnode_if.src | 2 + bsd/vm/dp_backing_file.c | 9 +- bsd/vm/vm_unix.c | 82 +- bsd/vm/vnode_pager.c | 97 +- bsd/vm/vnode_pager.h | 2 - .../ata/drvApplePIIXATA/AppleATAPIIX.cpp | 2 +- .../drvAppleADBDevices/AppleADBButtons.cpp | 263 -- .../drvAppleADBDevices/AppleADBButtons.h | 78 - .../drvAppleADBDevices/AppleADBDisplay.cpp | 368 --- .../drvAppleADBDevices/AppleADBDisplay.h | 104 - .../drvAppleADBDevices/AppleADBKeyboard.cpp | 414 --- .../drvAppleADBDevices/AppleADBKeyboard.h | 132 - .../drvAppleADBDevices/AppleADBMouse.cpp | 454 --- .../drvAppleADBDevices/AppleADBMouse.h | 94 - .../drvApplePS2Keyboard/ApplePS2Keyboard.cpp | 1091 ------- .../drvApplePS2Keyboard/ApplePS2Keyboard.h | 89 - .../drvApplePS2Mouse/ApplePS2Mouse.cpp | 518 ---- .../drvApplePS2Mouse/ApplePS2Mouse.h | 85 - iokit/Drivers/network/AppleBPF/AppleBPF.cpp | 120 - iokit/Drivers/network/AppleBPF/bpf.c | 1290 -------- iokit/Drivers/network/AppleBPF/bpf_filter.c | 563 ---- .../Drivers/network/drvIntel82557/i82557.cpp | 820 ----- iokit/Drivers/network/drvIntel82557/i82557.h | 311 -- .../Drivers/network/drvIntel82557/i82557HW.h | 608 ---- .../network/drvIntel82557/i82557Inline.h | 112 - .../network/drvIntel82557/i82557PHY.cpp | 628 ---- .../Drivers/network/drvIntel82557/i82557PHY.h | 199 -- .../network/drvIntel82557/i82557Private.cpp | 1692 ----------- .../network/drvIntel82557/i82557eeprom.cpp | 182 -- .../network/drvIntel82557/i82557eeprom.h | 211 -- .../Drivers/network/drvMaceEnet/MaceEnet.cpp | 918 ------ iokit/Drivers/network/drvMaceEnet/MaceEnet.h | 245 -- .../network/drvMaceEnet/MaceEnetPrivate.cpp | 1793 ----------- .../network/drvMaceEnet/MaceEnetPrivate.h | 43 - .../network/drvMaceEnet/MaceEnetRegisters.h | 265 -- iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp | 1199 -------- iokit/Drivers/network/drvPPCBMac/BMacEnet.h | 272 -- .../Drivers/network/drvPPCBMac/BMacEnetHW.cpp | 135 - .../network/drvPPCBMac/BMacEnetMII.cpp | 386 --- .../Drivers/network/drvPPCBMac/BMacEnetMII.h | 171 -- .../network/drvPPCBMac/BMacEnetPrivate.cpp | 1958 ------------ .../network/drvPPCBMac/BMacEnetPrivate.h | 49 - .../network/drvPPCBMac/BMacEnetRegisters.h | 212 -- iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp | 1071 ------- iokit/Drivers/network/drvPPCUniN/UniNEnet.h | 314 -- .../Drivers/network/drvPPCUniN/UniNEnetHW.cpp | 72 - .../network/drvPPCUniN/UniNEnetMII.cpp | 259 -- .../Drivers/network/drvPPCUniN/UniNEnetMII.h | 231 -- .../network/drvPPCUniN/UniNEnetPrivate.cpp | 1701 ----------- .../network/drvPPCUniN/UniNEnetPrivate.h | 39 - .../network/drvPPCUniN/UniNEnetRegisters.h | 529 ---- .../network/drvPPCUniN/UniNPowerSaver.cpp | 378 --- .../pci/drvApplePCI/AppleGracklePCI.cpp | 356 --- .../Drivers/pci/drvApplePCI/AppleGracklePCI.h | 94 - .../Drivers/pci/drvApplePCI/AppleI386PCI.cpp | 563 ---- iokit/Drivers/pci/drvApplePCI/AppleI386PCI.h | 106 - .../pci/drvApplePCI/AppleMacRiscPCI.cpp | 800 ----- .../Drivers/pci/drvApplePCI/AppleMacRiscPCI.h | 180 -- .../platform/drvAppleCuda/AppleCuda.cpp | 161 +- .../Drivers/platform/drvAppleCuda/AppleCuda.h | 17 + .../drvAppleCuda/AppleCudaUserClient.cpp | 182 ++ .../drvAppleCuda/AppleCudaUserClient.h | 51 + .../drvAppleCuda/IOCudaADBController.cpp | 18 +- .../drvAppleCuda/IOCudaADBController.h | 1 + .../platform/drvAppleGossamerPE/Gossamer.cpp | 10 - .../drvAppleGossamerPE/GossamerCPU.cpp | 9 +- .../platform/drvAppleGossamerPE/GossamerCPU.h | 4 +- .../platform/drvAppleMacIO/AppleMacIO.cpp | 2 +- .../drvApplePMU/IOPMUADBController.cpp | 69 +- .../platform/drvApplePMU/IOPMUADBController.h | 3 +- .../ApplePS2Controller.cpp | 1080 ------- .../ApplePS2Controller.h | 233 -- .../ApplePS2KeyboardDevice.cpp | 97 - .../ApplePS2MouseDevice.cpp | 97 - .../drvAppleRootDomain/RootDomain.cpp | 796 ++++- .../RootDomainUserClient.cpp | 12 + iokit/Families/IOADBBus/IOADBController.cpp | 35 +- .../IOADBBus}/IOADBDevice.cpp | 9 + .../Families/IOATAHDDrive/IOATAHDCommand.cpp | 612 ---- iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp | 584 ---- .../Families/IOATAHDDrive/IOATAHDDriveNub.cpp | 245 -- iokit/Families/IOATAHDDrive/IOATAHDPower.cpp | 590 ---- .../IOATAPICDDrive/IOATAPICDCommand.cpp | 196 -- .../IOATAPICDDrive/IOATAPICDDrive.cpp | 513 ---- .../IOATAPICDDrive/IOATAPICDDriveNub.cpp | 362 --- .../IOATAPIDVDDrive/IOATAPIDVDCommand.cpp | 146 - .../IOATAPIDVDDrive/IOATAPIDVDDrive.cpp | 529 ---- .../IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp | 397 --- .../IOATAPIHDDrive/IOATAPIHDCommand.cpp | 325 -- .../IOATAPIHDDrive/IOATAPIHDDrive.cpp | 556 ---- .../IOATAPIHDDrive/IOATAPIHDDriveNub.cpp | 247 -- .../IOATAStandard/IOATAStandardDriverDma.cpp | 4 + .../IOATAStandard/IOATAStandardDriverPio.cpp | 4 + .../IOBlockStorage/IOBlockStorageDevice.cpp | 74 - .../IOCDBlockStorageDevice.cpp | 57 - .../Families/IOCDStorage/IOCDAudioControl.cpp | 116 - .../IOCDAudioControlUserClient.cpp | 324 -- .../IOCDStorage/IOCDBlockStorageDriver.cpp | 607 ---- iokit/Families/IOCDStorage/IOCDMedia.cpp | 320 -- .../IOCDStorage/IOCDPartitionScheme.cpp | 800 ----- .../IODVDBlockStorageDevice.cpp | 72 - .../IODVDStorage/IODVDBlockStorageDriver.cpp | 158 - iokit/Families/IODVDStorage/IODVDMedia.cpp | 168 -- iokit/Families/IOGraphics/ADBTest.m | 70 - iokit/Families/IOGraphics/AppleDDCDisplay.cpp | 311 -- .../IOGraphics/AppleG3SeriesDisplay.cpp | 453 --- iokit/Families/IOGraphics/DDCInfo.m | 80 - .../Families/IOGraphics/IOBootFramebuffer.cpp | 230 -- iokit/Families/IOGraphics/IOBootFramebuffer.h | 80 - iokit/Families/IOGraphics/IOCursorBlits.h | 425 --- iokit/Families/IOGraphics/IODisplay.cpp | 518 ---- .../Families/IOGraphics/IODisplayWrangler.cpp | 720 ----- iokit/Families/IOGraphics/IODisplayWrangler.h | 99 - iokit/Families/IOGraphics/IOFramebuffer.cpp | 1847 ------------ .../IOGraphics/IOFramebufferReallyPrivate.h | 39 - .../IOGraphics/IOFramebufferUserClient.cpp | 801 ----- .../IOGraphics/IOFramebufferUserClient.h | 173 -- .../Families/IOGraphics/IOGraphicsDevice.cpp | 39 - .../IOHIDDescriptorParser/HIDCheckReport.c | 113 - .../HIDCountDescriptorItems.c | 238 -- .../IOHIDDescriptorParser/HIDGetButtonCaps.c | 493 --- .../IOHIDDescriptorParser/HIDGetButtons.c | 165 - .../HIDGetButtonsOnPage.c | 213 -- .../IOHIDDescriptorParser/HIDGetCaps.c | 257 -- .../HIDGetCollectionNodes.c | 121 - .../IOHIDDescriptorParser/HIDGetData.c | 133 - .../HIDGetNextButtonInfo.c | 151 - .../HIDGetNextUsageValueInfo.c | 153 - .../HIDGetReportLength.c | 122 - .../IOHIDDescriptorParser/HIDGetUsageValue.c | 270 -- .../HIDGetUsageValueArray.c | 178 -- .../IOHIDDescriptorParser/HIDGetValueCaps.c | 543 ---- .../IOHIDDescriptorParser/HIDHasUsage.c | 189 -- .../IOHIDDescriptorParser/HIDInitReport.c | 224 -- .../HIDIsButtonOrValue.c | 167 -- .../IOHIDDescriptorParser/HIDLib.h | 132 - .../HIDMaxUsageListLength.c | 111 - .../IOHIDDescriptorParser/HIDNextItem.c | 169 -- .../HIDOpenCloseDescriptor.c | 195 -- .../HIDParseDescriptor.c | 173 -- .../HIDPostProcessRIValue.c | 112 - .../IOHIDDescriptorParser/HIDPriv.h | 390 --- .../HIDProcessCollection.c | 141 - .../HIDProcessGlobalItem.c | 195 -- .../HIDProcessLocalItem.c | 295 -- .../HIDProcessMainItem.c | 95 - .../HIDProcessReportItem.c | 213 -- .../IOHIDDescriptorParser/HIDPutData.c | 166 -- .../HIDScaleUsageValue.c | 198 -- .../IOHIDDescriptorParser/HIDSetButtons.c | 244 -- .../HIDSetScaledUsageValue.c | 155 - .../IOHIDDescriptorParser/HIDSetUsageValue.c | 156 - .../HIDSetUsageValueArray.c | 175 -- .../HIDUsageAndPageFromIndex.c | 140 - .../IOHIDDescriptorParser/HIDUsageInRange.c | 97 - .../HIDUsageListDifference.c | 122 - .../IOHIDDescriptorParser/MacTypes.h | 31 - iokit/Families/IOHIDSystem/IOHIDIO.cpp | 55 - iokit/Families/IOHIDSystem/IOHIDSystem.cpp | 2643 ----------------- .../Families/IOHIDSystem/IOHIDUserClient.cpp | 246 -- iokit/Families/IOHIDSystem/IOHIDUserClient.h | 102 - iokit/Families/IOHIDSystem/IOHIDevice.cpp | 82 - iokit/Families/IOHIDSystem/IOHIKeyboard.cpp | 579 ---- .../IOHIDSystem/IOHIKeyboardMapper.cpp | 768 ----- iokit/Families/IOHIDSystem/IOHIPointing.cpp | 790 ----- iokit/Families/IOHIDSystem/IOHITablet.cpp | 107 - .../IOHIDSystem/IOHITabletPointer.cpp | 69 - iokit/Families/IONDRVSupport/IONDRV.cpp | 322 -- iokit/Families/IONDRVSupport/IONDRV.h | 190 -- .../IONDRVSupport/IONDRVFramebuffer.cpp | 2224 -------------- .../IONDRVSupport/IONDRVLibraries.cpp | 1781 ----------- iokit/Families/IONDRVSupport/IOPEFInternals.c | 2108 ------------- iokit/Families/IONDRVSupport/IOPEFInternals.h | 931 ------ iokit/Families/IONDRVSupport/IOPEFLoader.c | 600 ---- iokit/Families/IONDRVSupport/IOPEFLoader.h | 150 - .../IONetworking/IOEthernetController.cpp | 416 --- .../IONetworking/IOEthernetInterface.cpp | 922 ------ .../IONetworking/IOKernelDebugger.cpp | 688 ----- .../IONetworking/IOMbufMemoryCursor.cpp | 576 ---- iokit/Families/IONetworking/IOMbufQueue.h | 180 -- .../IONetworking/IONetworkController.cpp | 2159 -------------- iokit/Families/IONetworking/IONetworkData.cpp | 597 ---- .../IONetworking/IONetworkInterface.cpp | 1531 ---------- .../Families/IONetworking/IONetworkMedium.cpp | 383 --- .../Families/IONetworking/IONetworkStack.cpp | 1124 ------- .../IONetworking/IONetworkUserClient.cpp | 274 -- iokit/Families/IONetworking/IOOutputQueue.cpp | 899 ------ iokit/Families/IONetworking/IOPacketQueue.cpp | 267 -- iokit/Families/IOPCIBus/IOPCIBridge.cpp | 1187 -------- iokit/Families/IOPCIBus/IOPCIDevice.cpp | 473 --- iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp | 104 - iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp | 130 - .../Families/IOSCSICDDrive/IOSCSICDDrive.cpp | 747 ----- .../IOSCSICDDrive/IOSCSICDDriveNub.cpp | 250 -- .../IOSCSIDVDDrive/IOSCSIDVDDrive.cpp | 493 --- .../IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp | 264 -- iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp | 1331 --------- .../Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp | 899 ------ .../IOSCSIHDDrive/IOSCSIHDDriveNub.cpp | 184 -- .../IOSCSIParallel/IOSCSIParallelCommand.cpp | 4 +- .../IOSCSIParallel/IOSCSIParallelDevice.cpp | 20 +- .../IOStorage/IOApplePartitionScheme.cpp | 747 ----- .../IOStorage/IOBlockStorageDriver.cpp | 2338 --------------- .../IOStorage/IOFDiskPartitionScheme.cpp | 566 ---- iokit/Families/IOStorage/IOMedia.cpp | 792 ----- iokit/Families/IOStorage/IOMediaBSDClient.cpp | 2125 ------------- .../IOStorage/IONeXTPartitionScheme.cpp | 627 ---- .../Families/IOStorage/IOPartitionScheme.cpp | 418 --- iokit/Families/IOStorage/IOStorage.cpp | 194 -- iokit/IOKit/IOCatalogue.h | 2 + iokit/IOKit/IOCommandGate.h | 2 +- iokit/IOKit/IOKitKeys.h | 9 +- iokit/IOKit/IOLib.h | 3 +- iokit/IOKit/IOLocks.h | 14 +- iokit/IOKit/IOMemoryDescriptor.h | 81 +- iokit/IOKit/IOMessage.h | 2 + iokit/IOKit/IOMultiMemoryDescriptor.h | 3 + iokit/IOKit/IORegistryEntry.h | 78 +- iokit/IOKit/IOService.h | 106 +- iokit/IOKit/IOServicePM.h | 17 +- iokit/IOKit/IOWorkLoop.h | 47 +- iokit/IOKit/Makefile | 11 +- iokit/IOKit/adb/IOADBController.h | 1 + iokit/IOKit/adb/Makefile | 2 +- iokit/IOKit/ata/Makefile | 21 +- iokit/IOKit/ata/ata-device/Makefile | 14 +- iokit/IOKit/graphics/IOAccelSurfaceConnect.h | 114 - iokit/IOKit/graphics/IOAccelerator.h | 35 - iokit/IOKit/graphics/IODisplay.h | 170 -- iokit/IOKit/graphics/IOFramebuffer.h | 455 --- iokit/IOKit/graphics/IOFramebufferPrivate.h | 151 - iokit/IOKit/graphics/IOFramebufferShared.h | 145 - iokit/IOKit/graphics/IOGraphicsTypes.h | 397 --- iokit/IOKit/graphics/Makefile | 39 - iokit/IOKit/hidsystem/IOHIDDescriptorParser.h | 932 ------ iokit/IOKit/hidsystem/IOHIDParameter.h | 209 -- iokit/IOKit/hidsystem/IOHIDShared.h | 282 -- iokit/IOKit/hidsystem/IOHIDSystem.h | 498 ---- iokit/IOKit/hidsystem/IOHIDTypes.h | 170 -- iokit/IOKit/hidsystem/IOHIDUsageTables.h | 1017 ------- iokit/IOKit/hidsystem/IOHIDevice.h | 63 - iokit/IOKit/hidsystem/IOHIKeyboard.h | 187 -- iokit/IOKit/hidsystem/IOHIKeyboardMapper.h | 123 - iokit/IOKit/hidsystem/IOHIPointing.h | 137 - iokit/IOKit/hidsystem/IOHITablet.h | 78 - iokit/IOKit/hidsystem/IOHITabletPointer.h | 55 - iokit/IOKit/hidsystem/IOLLEvent.h | 351 --- iokit/IOKit/hidsystem/Makefile | 35 - iokit/IOKit/hidsystem/ev_keymap.h | 143 - iokit/IOKit/hidsystem/ev_private.h | 141 - iokit/IOKit/ndrvsupport/IOMacOSTypes.h | 394 --- iokit/IOKit/ndrvsupport/IOMacOSVideo.h | 1239 -------- iokit/IOKit/ndrvsupport/IONDRVFramebuffer.h | 309 -- iokit/IOKit/ndrvsupport/IONDRVSupport.h | 91 - iokit/IOKit/ndrvsupport/Makefile | 34 - iokit/IOKit/network/IOBasicOutputQueue.h | 301 -- iokit/IOKit/network/IOEthernetController.h | 447 --- iokit/IOKit/network/IOEthernetInterface.h | 296 -- iokit/IOKit/network/IOEthernetStats.h | 163 - iokit/IOKit/network/IOGatedOutputQueue.h | 141 - iokit/IOKit/network/IOKernelDebugger.h | 304 -- iokit/IOKit/network/IOMbufMemoryCursor.h | 438 --- iokit/IOKit/network/IONetworkController.h | 1375 --------- iokit/IOKit/network/IONetworkData.h | 462 --- iokit/IOKit/network/IONetworkInterface.h | 933 ------ iokit/IOKit/network/IONetworkLib.h | 118 - iokit/IOKit/network/IONetworkMedium.h | 411 --- iokit/IOKit/network/IONetworkStack.h | 144 - iokit/IOKit/network/IONetworkStats.h | 94 - iokit/IOKit/network/IONetworkUserClient.h | 208 -- iokit/IOKit/network/IOOutputQueue.h | 257 -- iokit/IOKit/network/IOPacketQueue.h | 271 -- iokit/IOKit/network/Makefile | 44 - iokit/IOKit/pci/IOAGPDevice.h | 1 + iokit/IOKit/pci/IOPCIBridge.h | 2 +- iokit/IOKit/pci/IOPCIDevice.h | 12 +- iokit/IOKit/ppc/IOSharedLockImp.h | 104 +- iokit/IOKit/ps2/ApplePS2Device.h | 300 -- iokit/IOKit/ps2/ApplePS2KeyboardDevice.h | 54 - iokit/IOKit/ps2/ApplePS2MouseDevice.h | 54 - iokit/IOKit/ps2/Makefile | 34 - iokit/IOKit/pwr_mgt/IOPM.h | 109 +- iokit/IOKit/pwr_mgt/IOPMLibDefs.h | 4 +- .../IOPMPagingPlexus.h} | 35 +- iokit/IOKit/pwr_mgt/IOPMchangeNoteList.h | 3 +- iokit/IOKit/pwr_mgt/IOPMpowerState.h | 3 + iokit/IOKit/pwr_mgt/IOPowerConnection.h | 61 +- iokit/IOKit/pwr_mgt/RootDomain.h | 62 +- iokit/IOKit/storage/IOApplePartitionScheme.h | 245 -- iokit/IOKit/storage/IOBlockStorageDevice.h | 411 --- iokit/IOKit/storage/IOBlockStorageDriver.h | 1320 -------- iokit/IOKit/storage/IOCDAudioControl.h | 184 -- .../storage/IOCDAudioControlUserClient.h | 159 - iokit/IOKit/storage/IOCDBlockStorageDevice.h | 105 - iokit/IOKit/storage/IOCDBlockStorageDriver.h | 189 -- iokit/IOKit/storage/IOCDMedia.h | 283 -- iokit/IOKit/storage/IOCDPartitionScheme.h | 196 -- iokit/IOKit/storage/IOCDTypes.h | 226 -- iokit/IOKit/storage/IODVDBlockStorageDevice.h | 99 - iokit/IOKit/storage/IODVDBlockStorageDriver.h | 193 -- iokit/IOKit/storage/IODVDMedia.h | 162 - iokit/IOKit/storage/IODVDTypes.h | 58 - iokit/IOKit/storage/IOFDiskPartitionScheme.h | 239 -- iokit/IOKit/storage/IOMedia.h | 527 ---- iokit/IOKit/storage/IOMediaBSDClient.h | 136 - iokit/IOKit/storage/IONeXTPartitionScheme.h | 235 -- iokit/IOKit/storage/IOPartitionScheme.h | 276 -- iokit/IOKit/storage/IOStorage.h | 390 --- iokit/IOKit/storage/Makefile | 49 - iokit/IOKit/storage/ata/IOATAHDDrive.h | 470 --- iokit/IOKit/storage/ata/IOATAHDDriveNub.h | 89 - iokit/IOKit/storage/ata/IOATAPICDDrive.h | 194 -- iokit/IOKit/storage/ata/IOATAPICDDriveNub.h | 119 - iokit/IOKit/storage/ata/IOATAPIDVDDrive.h | 265 -- iokit/IOKit/storage/ata/IOATAPIDVDDriveNub.h | 135 - iokit/IOKit/storage/ata/IOATAPIHDDrive.h | 232 -- iokit/IOKit/storage/ata/IOATAPIHDDriveNub.h | 87 - iokit/IOKit/storage/ata/Makefile | 34 - iokit/IOKit/storage/scsi/IOBasicSCSI.h | 1207 -------- iokit/IOKit/storage/scsi/IOSCSICDDrive.h | 410 --- iokit/IOKit/storage/scsi/IOSCSICDDriveNub.h | 106 - iokit/IOKit/storage/scsi/IOSCSIDVDDrive.h | 239 -- iokit/IOKit/storage/scsi/IOSCSIDVDDriveNub.h | 111 - iokit/IOKit/storage/scsi/IOSCSIHDDrive.h | 784 ----- iokit/IOKit/storage/scsi/IOSCSIHDDriveNub.h | 76 - iokit/IOKit/storage/scsi/Makefile | 34 - iokit/IOKit/system.h | 2 + iokit/Kernel/IOBufferMemoryDescriptor.cpp | 4 +- iokit/Kernel/IOCatalogue.cpp | 37 +- iokit/Kernel/IODeviceTreeSupport.cpp | 720 ++--- iokit/Kernel/IOInterruptController.cpp | 16 +- iokit/Kernel/IOKitDebug.cpp | 11 +- iokit/Kernel/IOLib.c | 61 +- iokit/Kernel/IOLocks.cpp | 8 +- iokit/Kernel/IOMemoryDescriptor.cpp | 1172 +++++--- iokit/Kernel/IOMultiMemoryDescriptor.cpp | 28 + iokit/Kernel/IOPMPagingPlexus.cpp | 235 ++ iokit/Kernel/IOPowerConnection.cpp | 79 + iokit/Kernel/IORegistryEntry.cpp | 136 +- iokit/Kernel/IOService.cpp | 1018 +++++-- iokit/Kernel/IOServicePM.cpp | 781 ++++- iokit/Kernel/IOServicePrivate.h | 18 +- iokit/Kernel/IOStartIOKit.cpp | 55 +- iokit/Kernel/IOStringFuncs.c | 167 ++ iokit/Kernel/IOUserClient.cpp | 363 ++- iokit/Kernel/IOWorkLoop.cpp | 17 +- iokit/KernelConfigTables.cpp | 550 +--- iokit/bsddev/IOBSDConsole.cpp | 216 -- iokit/bsddev/IOBSDConsole.h | 67 - iokit/bsddev/IOKitBSDInit.cpp | 133 +- iokit/conf/Makefile | 9 +- iokit/conf/Makefile.template | 3 - iokit/conf/files | 140 +- iokit/conf/files.i386 | 39 - iokit/conf/files.ppc | 49 +- iokit/conf/version.minor | 2 +- iokit/conf/version.variant | 1 - libkern/c++/OSMetaClass.cpp | 16 +- libkern/c++/OSNumber.cpp | 2 +- libkern/c++/OSUnserialize.cpp | 4 +- libkern/c++/OSUnserializeXML.cpp | 4 +- libkern/conf/Makefile | 9 +- libkern/conf/Makefile.template | 3 - libkern/conf/files.ppc | 3 + libkern/conf/version.minor | 2 +- libkern/conf/version.variant | 1 - libkern/gen/OSAtomicOperations.c | 95 +- libkern/kmod/Makefile.kmod | 2 +- libkern/libkern/OSAtomic.h | 28 +- libkern/libkern/OSBase.h | 22 + libkern/libkern/OSTypes.h | 3 - libkern/ppc/bcmp.s | 86 + libkern/ppc/memcmp.s | 100 + libkern/ppc/strlen.s | 112 + libsa/bootstrap.cpp | 26 +- libsa/catalogue.cpp | 333 ++- libsa/conf/Makefile | 9 +- libsa/conf/Makefile.template | 5 +- libsa/conf/files | 10 +- libsa/conf/version.minor | 2 +- libsa/conf/version.variant | 1 - libsa/kld_patch.c | 2124 +++++++++++++ libsa/kld_patch.h | 56 + libsa/kmod.cpp | 613 ++-- libsa/libsa/catalogue.h | 12 +- libsa/libsa/stdlib.h | 2 +- libsa/libsa/vers_rsrc.h | 2 +- libsa/mach_loader.h | 6 - libsa/strrchr.c | 77 + libsa/vers_rsrc.c | 2 +- makedefs/MakeInc.cmd | 1 + makedefs/MakeInc.def | 42 +- makedefs/MakeInc.dir | 77 +- makedefs/MakeInc.rule | 36 +- osfmk/.gdbinit | 2 +- osfmk/conf/Makefile | 9 +- osfmk/conf/Makefile.template | 4 +- osfmk/conf/files | 8 +- osfmk/conf/kernelversion.minor | 2 +- osfmk/conf/kernelversion.variant | 2 +- osfmk/conf/version.minor | 2 +- osfmk/conf/version.variant | 2 +- osfmk/ddb/db_print.c | 7 +- osfmk/default_pager/default_pager.c | 639 +--- osfmk/default_pager/default_pager_internal.h | 219 +- osfmk/default_pager/default_pager_object.defs | 5 +- osfmk/default_pager/default_pager_types.h | 5 +- osfmk/default_pager/diag.h | 50 +- osfmk/default_pager/dp_backing_store.c | 961 +++--- osfmk/default_pager/dp_memory_object.c | 811 ++--- osfmk/device/device.defs | 28 +- osfmk/device/device_port.h | 3 + osfmk/device/iokit_rpc.c | 1 + osfmk/device/subrs.c | 21 - osfmk/i386/AT386/bbclock.c | 1 + osfmk/i386/AT386/kernBootStruct.h | 204 +- osfmk/i386/AT386/model_dep.c | 54 +- osfmk/i386/AT386/video_console.c | 7 +- osfmk/i386/bsd_i386.c | 63 +- osfmk/i386/i386_lock.s | 4 +- osfmk/i386/lock.h | 37 +- osfmk/i386/loose_ends.c | 43 + osfmk/i386/misc_protos.h | 6 + osfmk/i386/pcb.c | 91 +- osfmk/i386/pmap.c | 15 + osfmk/i386/read_fault.c | 2 +- osfmk/i386/rtclock.c | 64 +- osfmk/i386/thread_act.h | 4 + osfmk/i386/trap.c | 4 +- osfmk/ipc/ipc_kmsg.c | 55 - osfmk/ipc/ipc_mqueue.c | 4 +- osfmk/ipc/ipc_port.c | 42 +- osfmk/ipc/ipc_port.h | 6 +- osfmk/ipc/mach_msg.c | 16 +- osfmk/kdp/ml/ppc/kdp_asm.s | 2 +- osfmk/kdp/ml/ppc/kdp_machdep.c | 1 + osfmk/kdp/ml/ppc/kdp_vm.c | 11 +- osfmk/kern/ast.c | 187 +- osfmk/kern/ast.h | 96 +- osfmk/kern/bsd_kern.c | 63 +- osfmk/kern/call_entry.h | 2 +- osfmk/kern/clock.c | 25 +- osfmk/kern/clock.h | 118 +- osfmk/kern/host.c | 8 +- osfmk/kern/ipc_host.c | 4 + osfmk/kern/ipc_kobject.c | 156 +- osfmk/kern/ipc_kobject.h | 9 +- osfmk/kern/ipc_mig.c | 258 +- osfmk/kern/ipc_mig.h | 27 + osfmk/kern/ipc_tt.c | 15 + osfmk/kern/ipc_tt.h | 3 + osfmk/kern/kalloc.c | 2 +- osfmk/kern/kern_types.h | 16 +- osfmk/kern/kmod.c | 39 +- osfmk/kern/lock.h | 24 +- osfmk/kern/mach_clock.c | 7 +- osfmk/kern/mach_factor.c | 11 +- osfmk/kern/machine.c | 13 +- osfmk/kern/mk_sp.c | 760 ++--- osfmk/kern/mk_sp.h | 103 +- osfmk/kern/mk_timer.c | 10 +- osfmk/kern/mk_timer.h | 4 +- osfmk/kern/priority.c | 186 +- osfmk/kern/processor.c | 117 +- osfmk/kern/processor.h | 28 +- osfmk/kern/sched.h | 49 +- osfmk/kern/sched_prim.c | 494 ++- osfmk/kern/sched_prim.h | 16 +- osfmk/kern/sf.c | 43 - osfmk/kern/sf.h | 330 -- osfmk/kern/simple_lock.h | 3 + osfmk/kern/spl.h | 14 +- osfmk/kern/startup.c | 71 +- osfmk/kern/sync_lock.c | 6 +- osfmk/kern/sync_sema.c | 6 +- osfmk/kern/syscall_subr.c | 108 +- osfmk/kern/task.c | 66 +- osfmk/kern/task.h | 15 +- osfmk/kern/task_policy.c | 142 +- osfmk/kern/thread.c | 618 ++-- osfmk/kern/thread.h | 257 +- osfmk/kern/thread_act.c | 55 +- osfmk/kern/thread_call.c | 27 +- osfmk/kern/thread_call.h | 30 +- osfmk/kern/thread_policy.c | 259 +- osfmk/kern/thread_swap.c | 119 +- osfmk/kern/thread_swap.h | 156 +- osfmk/kern/time_out.h | 15 +- osfmk/kern/timer_call.c | 17 +- osfmk/kern/timer_call.h | 8 +- osfmk/kern/wait_queue.c | 276 +- osfmk/kern/wait_queue.h | 43 +- osfmk/kern/zalloc.c | 95 +- osfmk/kern/zalloc.h | 5 +- osfmk/mach/Makefile | 2 + osfmk/mach/host_info.h | 177 -- osfmk/mach/kmod.h | 2 +- osfmk/mach/mach_port.defs | 4 +- osfmk/mach/mach_time.h | 2 - osfmk/mach/mach_types.defs | 73 +- osfmk/mach/mach_types.h | 12 +- osfmk/mach/memory_object.defs | 178 +- osfmk/mach/memory_object_control.defs | 158 +- osfmk/mach/memory_object_default.defs | 34 +- osfmk/mach/memory_object_types.h | 327 +- osfmk/mach/message.h | 4 +- osfmk/mach/mig.h | 141 +- osfmk/mach/mk_timer.h | 14 +- osfmk/mach/ppc/syscall_sw.h | 1 + osfmk/mach/shared_memory_server.h | 11 +- osfmk/mach/std_types.defs | 1 + osfmk/mach/sync_policy.h | 3 +- osfmk/mach/task.defs | 3 +- osfmk/mach/task_policy.h | 19 +- osfmk/mach/thread_policy.h | 42 +- osfmk/mach/upl.defs | 55 +- osfmk/mach/vm_map.defs | 23 +- osfmk/mach/vm_region.h | 6 +- osfmk/mach/vm_types.h | 29 +- osfmk/ppc/Diagnostics.c | 58 + osfmk/ppc/Diagnostics.h | 5 + osfmk/ppc/Firmware.h | 9 + osfmk/ppc/Firmware.s | 29 +- osfmk/ppc/POWERMAC/serial_io.c | 2 +- osfmk/ppc/POWERMAC/video_console.c | 6 +- osfmk/ppc/PPCcalls.h | 2 +- osfmk/ppc/PseudoKernel.c | 47 +- osfmk/ppc/PseudoKernel.h | 2 + osfmk/ppc/alignment.c | 18 +- osfmk/ppc/asm.h | 4 + osfmk/ppc/atomic_switch.s | 34 +- osfmk/ppc/bat_init.c | 23 - osfmk/ppc/bsd_ppc.c | 8 +- osfmk/ppc/cpu.c | 47 +- osfmk/ppc/cswtch.s | 205 +- osfmk/ppc/db_machdep.h | 2 - osfmk/ppc/exception.h | 47 +- osfmk/ppc/fpu_protos.h | 2 +- osfmk/ppc/genassym.c | 35 +- osfmk/ppc/hw_exception.s | 519 ++-- osfmk/ppc/hw_lock.s | 399 ++- osfmk/ppc/hw_vm.s | 4 +- osfmk/ppc/interrupt.c | 9 +- osfmk/ppc/lock.h | 27 +- osfmk/ppc/lowmem_vectors.s | 162 +- osfmk/ppc/machine_routines.c | 46 +- osfmk/ppc/machine_routines_asm.s | 140 +- osfmk/ppc/mappings.c | 66 +- osfmk/ppc/mappings.h | 8 + osfmk/ppc/misc.c | 39 +- osfmk/ppc/model_dep.c | 243 +- osfmk/ppc/pcb.c | 31 +- osfmk/ppc/pmap.c | 37 +- osfmk/ppc/ppc_init.c | 32 +- osfmk/ppc/ppc_vm_init.c | 14 +- osfmk/ppc/proc_reg.h | 12 - osfmk/ppc/rtclock.c | 369 +-- osfmk/ppc/savearea.h | 2 + osfmk/ppc/start.s | 59 +- osfmk/ppc/status.c | 329 +- osfmk/ppc/thread_act.h | 29 +- osfmk/ppc/trap.c | 90 +- osfmk/ppc/vmachmon.c | 349 ++- osfmk/ppc/vmachmon.h | 62 +- osfmk/ppc/vmachmon_asm.s | 77 +- osfmk/vm/bsd_vm.c | 555 ++-- osfmk/vm/device_vm.c | 475 +++ osfmk/vm/memory_object.c | 1012 +++++-- osfmk/vm/memory_object.h | 66 +- osfmk/vm/pmap.h | 5 + osfmk/vm/task_working_set.c | 1103 +++++++ osfmk/vm/task_working_set.h | 185 ++ osfmk/vm/vm_fault.c | 512 +++- osfmk/vm/vm_fault.h | 4 +- osfmk/vm/vm_init.c | 2 + osfmk/vm/vm_kern.c | 138 - osfmk/vm/vm_kern.h | 13 - osfmk/vm/vm_map.c | 1829 ++---------- osfmk/vm/vm_map.h | 150 +- osfmk/vm/vm_object.c | 1884 ++++++------ osfmk/vm/vm_object.h | 178 +- osfmk/vm/vm_page.h | 63 +- osfmk/vm/vm_pageout.c | 940 +++--- osfmk/vm/vm_pageout.h | 9 + osfmk/vm/vm_resident.c | 303 +- osfmk/vm/vm_shared_memory_server.c | 5 +- osfmk/vm/vm_user.c | 595 +--- pexpert/conf/Makefile | 9 +- pexpert/conf/Makefile.template | 2 - pexpert/conf/version.minor | 2 +- pexpert/conf/version.variant | 1 - pexpert/gen/pe_gen.c | 83 + pexpert/i386/fakePPCDeviceTree.c | 116 +- pexpert/i386/fakePPCDeviceTree.h | 45 +- pexpert/i386/fakePPCStructs.h | 53 +- pexpert/i386/kd.c | 962 +----- pexpert/i386/kd.h | 841 ------ pexpert/i386/pe_init.c | 110 +- pexpert/pexpert/i386/boot.h | 204 +- pexpert/pexpert/i386/protos.h | 13 +- 869 files changed, 36030 insertions(+), 140613 deletions(-) create mode 100644 EXTERNAL_HEADERS/mach-o/reloc.h create mode 100644 bsd/dev/random/Makefile create mode 100644 bsd/dev/random/YarrowCoreLib/include/WindowsTypesForMac.h create mode 100644 bsd/dev/random/YarrowCoreLib/include/macos_defs.h create mode 100644 bsd/dev/random/YarrowCoreLib/include/yarrow.h rename iokit/IOKit/graphics/IOAccelClientConnect.h => bsd/dev/random/YarrowCoreLib/include/yarrowUtils.h (60%) rename iokit/Drivers/network/drvMaceEnet/MaceEnetHW.cpp => bsd/dev/random/YarrowCoreLib/port/smf.c (51%) create mode 100644 bsd/dev/random/YarrowCoreLib/src/assertverify.h create mode 100644 bsd/dev/random/YarrowCoreLib/src/comp.c create mode 100644 bsd/dev/random/YarrowCoreLib/src/comp.h rename iokit/Drivers/network/AppleBPF/AppleBPF.h => bsd/dev/random/YarrowCoreLib/src/entropysources.h (59%) rename iokit/IOKit/graphics/IOGraphicsEngine.h => bsd/dev/random/YarrowCoreLib/src/macOnly.h (52%) create mode 100644 bsd/dev/random/YarrowCoreLib/src/prng.c create mode 100644 bsd/dev/random/YarrowCoreLib/src/prng.h create mode 100644 bsd/dev/random/YarrowCoreLib/src/prngpriv.h create mode 100644 bsd/dev/random/YarrowCoreLib/src/readme-prnguser.txt create mode 100644 bsd/dev/random/YarrowCoreLib/src/sha1mod.c create mode 100644 bsd/dev/random/YarrowCoreLib/src/sha1mod.h create mode 100644 bsd/dev/random/YarrowCoreLib/src/smf.h create mode 100644 bsd/dev/random/YarrowCoreLib/src/userdefines.h rename iokit/Families/IONDRVSupport/IOPEFLibraries.h => bsd/dev/random/YarrowCoreLib/src/yarrowUtils.c (55%) create mode 100644 bsd/dev/random/randomdev.c rename iokit/Families/IOHIDSystem/IOHIDDescriptorParser/PoolAlloc.c => bsd/dev/random/randomdev.h (64%) create mode 100644 bsd/hfs/hfs_encodinghint.c create mode 100644 bsd/hfs/rangelist.c rename iokit/IOKit/graphics/IOAccelTypes.h => bsd/hfs/rangelist.h (51%) delete mode 100644 bsd/netinet/fil.c delete mode 100644 bsd/netinet/ip_auth.c delete mode 100644 bsd/netinet/ip_auth.h delete mode 100644 bsd/netinet/ip_fil.h delete mode 100644 bsd/netinet/ip_frag.c delete mode 100644 bsd/netinet/ip_frag.h delete mode 100644 bsd/netinet/ip_log.c delete mode 100644 bsd/netinet/ip_nat.c delete mode 100644 bsd/netinet/ip_nat.h delete mode 100644 bsd/netinet/ip_proxy.c delete mode 100644 bsd/netinet/ip_proxy.h delete mode 100644 bsd/netinet/ip_state.c delete mode 100644 bsd/netinet/ip_state.h rename iokit/Families/IOGraphics/IOAccelerator.cpp => bsd/sys/random.h (81%) delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.cpp delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.h delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.cpp delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.h delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.cpp delete mode 100644 iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.h delete mode 100644 iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.cpp delete mode 100644 iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.h delete mode 100644 iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.cpp delete mode 100644 iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.h delete mode 100644 iokit/Drivers/network/AppleBPF/AppleBPF.cpp delete mode 100644 iokit/Drivers/network/AppleBPF/bpf.c delete mode 100644 iokit/Drivers/network/AppleBPF/bpf_filter.c delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557.cpp delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557.h delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557HW.h delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557Inline.h delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557PHY.cpp delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557PHY.h delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557Private.cpp delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp delete mode 100644 iokit/Drivers/network/drvIntel82557/i82557eeprom.h delete mode 100644 iokit/Drivers/network/drvMaceEnet/MaceEnet.cpp delete mode 100644 iokit/Drivers/network/drvMaceEnet/MaceEnet.h delete mode 100644 iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.cpp delete mode 100644 iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.h delete mode 100644 iokit/Drivers/network/drvMaceEnet/MaceEnetRegisters.h delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnet.h delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetHW.cpp delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetMII.h delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.cpp delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.h delete mode 100644 iokit/Drivers/network/drvPPCBMac/BMacEnetRegisters.h delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnet.h delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetHW.cpp delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetMII.cpp delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetMII.h delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.cpp delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.h delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNEnetRegisters.h delete mode 100644 iokit/Drivers/network/drvPPCUniN/UniNPowerSaver.cpp delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.h delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleI386PCI.h delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.cpp delete mode 100644 iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.h create mode 100644 iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.cpp create mode 100644 iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.h delete mode 100644 iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.cpp delete mode 100644 iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h delete mode 100644 iokit/Drivers/platform/drvApplePS2Controller/ApplePS2KeyboardDevice.cpp delete mode 100644 iokit/Drivers/platform/drvApplePS2Controller/ApplePS2MouseDevice.cpp rename iokit/{Drivers/hidsystem/drvAppleADBDevices => Families/IOADBBus}/IOADBDevice.cpp (97%) delete mode 100644 iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp delete mode 100644 iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp delete mode 100644 iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp delete mode 100644 iokit/Families/IOATAHDDrive/IOATAHDPower.cpp delete mode 100644 iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp delete mode 100644 iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp delete mode 100644 iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp delete mode 100644 iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp delete mode 100644 iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp delete mode 100644 iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp delete mode 100644 iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp delete mode 100644 iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp delete mode 100644 iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp delete mode 100644 iokit/Families/IOBlockStorage/IOBlockStorageDevice.cpp delete mode 100644 iokit/Families/IOCDBlockStorage/IOCDBlockStorageDevice.cpp delete mode 100644 iokit/Families/IOCDStorage/IOCDAudioControl.cpp delete mode 100644 iokit/Families/IOCDStorage/IOCDAudioControlUserClient.cpp delete mode 100644 iokit/Families/IOCDStorage/IOCDBlockStorageDriver.cpp delete mode 100644 iokit/Families/IOCDStorage/IOCDMedia.cpp delete mode 100644 iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp delete mode 100644 iokit/Families/IODVDBlockStorage/IODVDBlockStorageDevice.cpp delete mode 100644 iokit/Families/IODVDStorage/IODVDBlockStorageDriver.cpp delete mode 100644 iokit/Families/IODVDStorage/IODVDMedia.cpp delete mode 100644 iokit/Families/IOGraphics/ADBTest.m delete mode 100644 iokit/Families/IOGraphics/AppleDDCDisplay.cpp delete mode 100644 iokit/Families/IOGraphics/AppleG3SeriesDisplay.cpp delete mode 100644 iokit/Families/IOGraphics/DDCInfo.m delete mode 100644 iokit/Families/IOGraphics/IOBootFramebuffer.cpp delete mode 100644 iokit/Families/IOGraphics/IOBootFramebuffer.h delete mode 100644 iokit/Families/IOGraphics/IOCursorBlits.h delete mode 100644 iokit/Families/IOGraphics/IODisplay.cpp delete mode 100644 iokit/Families/IOGraphics/IODisplayWrangler.cpp delete mode 100644 iokit/Families/IOGraphics/IODisplayWrangler.h delete mode 100644 iokit/Families/IOGraphics/IOFramebuffer.cpp delete mode 100644 iokit/Families/IOGraphics/IOFramebufferReallyPrivate.h delete mode 100644 iokit/Families/IOGraphics/IOFramebufferUserClient.cpp delete mode 100644 iokit/Families/IOGraphics/IOFramebufferUserClient.h delete mode 100644 iokit/Families/IOGraphics/IOGraphicsDevice.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCheckReport.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCountDescriptorItems.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonCaps.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtons.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCaps.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCollectionNodes.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetData.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextButtonInfo.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextUsageValueInfo.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetReportLength.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValueArray.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetValueCaps.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDHasUsage.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDInitReport.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDIsButtonOrValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDLib.h delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDMaxUsageListLength.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDNextItem.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDOpenCloseDescriptor.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDParseDescriptor.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPostProcessRIValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPriv.h delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessCollection.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessGlobalItem.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessMainItem.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPutData.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDScaleUsageValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetButtons.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetScaledUsageValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValue.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValueArray.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageAndPageFromIndex.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageInRange.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageListDifference.c delete mode 100644 iokit/Families/IOHIDSystem/IOHIDDescriptorParser/MacTypes.h delete mode 100644 iokit/Families/IOHIDSystem/IOHIDIO.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIDSystem.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIDUserClient.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIDUserClient.h delete mode 100644 iokit/Families/IOHIDSystem/IOHIDevice.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIKeyboard.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHIPointing.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHITablet.cpp delete mode 100644 iokit/Families/IOHIDSystem/IOHITabletPointer.cpp delete mode 100644 iokit/Families/IONDRVSupport/IONDRV.cpp delete mode 100644 iokit/Families/IONDRVSupport/IONDRV.h delete mode 100644 iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp delete mode 100644 iokit/Families/IONDRVSupport/IONDRVLibraries.cpp delete mode 100644 iokit/Families/IONDRVSupport/IOPEFInternals.c delete mode 100644 iokit/Families/IONDRVSupport/IOPEFInternals.h delete mode 100644 iokit/Families/IONDRVSupport/IOPEFLoader.c delete mode 100644 iokit/Families/IONDRVSupport/IOPEFLoader.h delete mode 100644 iokit/Families/IONetworking/IOEthernetController.cpp delete mode 100644 iokit/Families/IONetworking/IOEthernetInterface.cpp delete mode 100644 iokit/Families/IONetworking/IOKernelDebugger.cpp delete mode 100644 iokit/Families/IONetworking/IOMbufMemoryCursor.cpp delete mode 100644 iokit/Families/IONetworking/IOMbufQueue.h delete mode 100644 iokit/Families/IONetworking/IONetworkController.cpp delete mode 100644 iokit/Families/IONetworking/IONetworkData.cpp delete mode 100644 iokit/Families/IONetworking/IONetworkInterface.cpp delete mode 100644 iokit/Families/IONetworking/IONetworkMedium.cpp delete mode 100644 iokit/Families/IONetworking/IONetworkStack.cpp delete mode 100644 iokit/Families/IONetworking/IONetworkUserClient.cpp delete mode 100644 iokit/Families/IONetworking/IOOutputQueue.cpp delete mode 100644 iokit/Families/IONetworking/IOPacketQueue.cpp delete mode 100644 iokit/Families/IOPCIBus/IOPCIBridge.cpp delete mode 100644 iokit/Families/IOPCIBus/IOPCIDevice.cpp delete mode 100644 iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp delete mode 100644 iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp delete mode 100644 iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp delete mode 100644 iokit/Families/IOSCSICDDrive/IOSCSICDDriveNub.cpp delete mode 100644 iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDrive.cpp delete mode 100644 iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp delete mode 100644 iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp delete mode 100644 iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp delete mode 100644 iokit/Families/IOSCSIHDDrive/IOSCSIHDDriveNub.cpp delete mode 100644 iokit/Families/IOStorage/IOApplePartitionScheme.cpp delete mode 100644 iokit/Families/IOStorage/IOBlockStorageDriver.cpp delete mode 100644 iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp delete mode 100644 iokit/Families/IOStorage/IOMedia.cpp delete mode 100644 iokit/Families/IOStorage/IOMediaBSDClient.cpp delete mode 100644 iokit/Families/IOStorage/IONeXTPartitionScheme.cpp delete mode 100644 iokit/Families/IOStorage/IOPartitionScheme.cpp delete mode 100644 iokit/Families/IOStorage/IOStorage.cpp delete mode 100644 iokit/IOKit/graphics/IOAccelSurfaceConnect.h delete mode 100644 iokit/IOKit/graphics/IOAccelerator.h delete mode 100644 iokit/IOKit/graphics/IODisplay.h delete mode 100644 iokit/IOKit/graphics/IOFramebuffer.h delete mode 100644 iokit/IOKit/graphics/IOFramebufferPrivate.h delete mode 100644 iokit/IOKit/graphics/IOFramebufferShared.h delete mode 100644 iokit/IOKit/graphics/IOGraphicsTypes.h delete mode 100644 iokit/IOKit/graphics/Makefile delete mode 100644 iokit/IOKit/hidsystem/IOHIDDescriptorParser.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDParameter.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDShared.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDSystem.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDTypes.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDUsageTables.h delete mode 100644 iokit/IOKit/hidsystem/IOHIDevice.h delete mode 100644 iokit/IOKit/hidsystem/IOHIKeyboard.h delete mode 100644 iokit/IOKit/hidsystem/IOHIKeyboardMapper.h delete mode 100644 iokit/IOKit/hidsystem/IOHIPointing.h delete mode 100644 iokit/IOKit/hidsystem/IOHITablet.h delete mode 100644 iokit/IOKit/hidsystem/IOHITabletPointer.h delete mode 100644 iokit/IOKit/hidsystem/IOLLEvent.h delete mode 100644 iokit/IOKit/hidsystem/Makefile delete mode 100644 iokit/IOKit/hidsystem/ev_keymap.h delete mode 100644 iokit/IOKit/hidsystem/ev_private.h delete mode 100644 iokit/IOKit/ndrvsupport/IOMacOSTypes.h delete mode 100644 iokit/IOKit/ndrvsupport/IOMacOSVideo.h delete mode 100644 iokit/IOKit/ndrvsupport/IONDRVFramebuffer.h delete mode 100644 iokit/IOKit/ndrvsupport/IONDRVSupport.h delete mode 100644 iokit/IOKit/ndrvsupport/Makefile delete mode 100644 iokit/IOKit/network/IOBasicOutputQueue.h delete mode 100644 iokit/IOKit/network/IOEthernetController.h delete mode 100644 iokit/IOKit/network/IOEthernetInterface.h delete mode 100644 iokit/IOKit/network/IOEthernetStats.h delete mode 100644 iokit/IOKit/network/IOGatedOutputQueue.h delete mode 100644 iokit/IOKit/network/IOKernelDebugger.h delete mode 100644 iokit/IOKit/network/IOMbufMemoryCursor.h delete mode 100644 iokit/IOKit/network/IONetworkController.h delete mode 100644 iokit/IOKit/network/IONetworkData.h delete mode 100644 iokit/IOKit/network/IONetworkInterface.h delete mode 100644 iokit/IOKit/network/IONetworkLib.h delete mode 100644 iokit/IOKit/network/IONetworkMedium.h delete mode 100644 iokit/IOKit/network/IONetworkStack.h delete mode 100644 iokit/IOKit/network/IONetworkStats.h delete mode 100644 iokit/IOKit/network/IONetworkUserClient.h delete mode 100644 iokit/IOKit/network/IOOutputQueue.h delete mode 100644 iokit/IOKit/network/IOPacketQueue.h delete mode 100644 iokit/IOKit/network/Makefile delete mode 100644 iokit/IOKit/ps2/ApplePS2Device.h delete mode 100644 iokit/IOKit/ps2/ApplePS2KeyboardDevice.h delete mode 100644 iokit/IOKit/ps2/ApplePS2MouseDevice.h delete mode 100644 iokit/IOKit/ps2/Makefile rename iokit/IOKit/{graphics/IOGraphicsDevice.h => pwr_mgt/IOPMPagingPlexus.h} (61%) delete mode 100644 iokit/IOKit/storage/IOApplePartitionScheme.h delete mode 100644 iokit/IOKit/storage/IOBlockStorageDevice.h delete mode 100644 iokit/IOKit/storage/IOBlockStorageDriver.h delete mode 100644 iokit/IOKit/storage/IOCDAudioControl.h delete mode 100644 iokit/IOKit/storage/IOCDAudioControlUserClient.h delete mode 100644 iokit/IOKit/storage/IOCDBlockStorageDevice.h delete mode 100644 iokit/IOKit/storage/IOCDBlockStorageDriver.h delete mode 100644 iokit/IOKit/storage/IOCDMedia.h delete mode 100644 iokit/IOKit/storage/IOCDPartitionScheme.h delete mode 100644 iokit/IOKit/storage/IOCDTypes.h delete mode 100644 iokit/IOKit/storage/IODVDBlockStorageDevice.h delete mode 100644 iokit/IOKit/storage/IODVDBlockStorageDriver.h delete mode 100644 iokit/IOKit/storage/IODVDMedia.h delete mode 100644 iokit/IOKit/storage/IODVDTypes.h delete mode 100644 iokit/IOKit/storage/IOFDiskPartitionScheme.h delete mode 100644 iokit/IOKit/storage/IOMedia.h delete mode 100644 iokit/IOKit/storage/IOMediaBSDClient.h delete mode 100644 iokit/IOKit/storage/IONeXTPartitionScheme.h delete mode 100644 iokit/IOKit/storage/IOPartitionScheme.h delete mode 100644 iokit/IOKit/storage/IOStorage.h delete mode 100644 iokit/IOKit/storage/Makefile delete mode 100644 iokit/IOKit/storage/ata/IOATAHDDrive.h delete mode 100644 iokit/IOKit/storage/ata/IOATAHDDriveNub.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPICDDrive.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPICDDriveNub.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPIDVDDrive.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPIDVDDriveNub.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPIHDDrive.h delete mode 100644 iokit/IOKit/storage/ata/IOATAPIHDDriveNub.h delete mode 100644 iokit/IOKit/storage/ata/Makefile delete mode 100644 iokit/IOKit/storage/scsi/IOBasicSCSI.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSICDDrive.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSICDDriveNub.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSIDVDDrive.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSIDVDDriveNub.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSIHDDrive.h delete mode 100644 iokit/IOKit/storage/scsi/IOSCSIHDDriveNub.h delete mode 100644 iokit/IOKit/storage/scsi/Makefile create mode 100644 iokit/Kernel/IOPMPagingPlexus.cpp delete mode 100644 iokit/bsddev/IOBSDConsole.cpp delete mode 100644 iokit/bsddev/IOBSDConsole.h create mode 100644 libkern/ppc/bcmp.s create mode 100644 libkern/ppc/memcmp.s create mode 100644 libkern/ppc/strlen.s create mode 100644 libsa/kld_patch.c create mode 100644 libsa/kld_patch.h create mode 100644 libsa/strrchr.c delete mode 100644 osfmk/kern/sf.c delete mode 100644 osfmk/kern/sf.h create mode 100644 osfmk/vm/device_vm.c create mode 100644 osfmk/vm/task_working_set.c create mode 100644 osfmk/vm/task_working_set.h delete mode 100644 pexpert/i386/kd.h diff --git a/EXTERNAL_HEADERS/mach-o/reloc.h b/EXTERNAL_HEADERS/mach-o/reloc.h new file mode 100644 index 000000000..8b8e29273 --- /dev/null +++ b/EXTERNAL_HEADERS/mach-o/reloc.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.1 (the "License"). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ + +/* + * Copyright (c) 1993 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _MACHO_RELOC_H_ +#define _MACHO_RELOC_H_ + +/* + * Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD + * format. The modifications from the original format were changing the value + * of the r_symbolnum field for "local" (r_extern == 0) relocation entries. + * This modification is required to support symbols in an arbitrary number of + * sections not just the three sections (text, data and bss) in a 4.3BSD file. + * Also the last 4 bits have had the r_type tag added to them. + */ +struct relocation_info { + long r_address; /* offset in the section to what is being + relocated */ + unsigned int r_symbolnum:24, /* symbol index if r_extern == 1 or section + ordinal if r_extern == 0 */ + r_pcrel:1, /* was relocated pc relative already */ + r_length:2, /* 0=byte, 1=word, 2=long */ + r_extern:1, /* does not include value of sym referenced */ + r_type:4; /* if not 0, machine specific relocation type */ +}; +#define R_ABS 0 /* absolute relocation type for Mach-O files */ + +/* + * The r_address is not really the address as it's name indicates but an offset. + * In 4.3BSD a.out objects this offset is from the start of the "segment" for + * which relocation entry is for (text or data). For Mach-O object files it is + * also an offset but from the start of the "section" for which the relocation + * entry is for. See comments in <mach-o/loader.h> about the r_address feild + * in images for used with the dynamic linker. + * + * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal + * for the segment the symbol being relocated is in. These ordinals are the + * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these + * ordinals refer to the sections in the object file in the order their section + * structures appear in the headers of the object file they are in. The first + * section has the ordinal 1, the second 2, and so on. This means that the + * same ordinal in two different object files could refer to two different + * sections. And further could have still different ordinals when combined + * by the link-editor. The value R_ABS is used for relocation entries for + * absolute symbols which need no further relocation. + */ + +/* + * For RISC machines some of the references are split across two instructions + * and the instruction does not contain the complete value of the reference. + * In these cases a second, or paired relocation entry, follows each of these + * relocation entries, using a PAIR r_type, which contains the other part of the + * reference not contained in the instruction. This other part is stored in the + * pair's r_address field. The exact number of bits of the other part of the + * reference store in the r_address field is dependent on the particular + * relocation type for the particular architecture. + */ + +/* + * To make scattered loading by the link editor work correctly "local" + * relocation entries can't be used when the item to be relocated is the value + * of a symbol plus an offset (where the resulting expresion is outside the + * block the link editor is moving, a blocks are divided at symbol addresses). + * In this case. where the item is a symbol value plus offset, the link editor + * needs to know more than just the section the symbol was defined. What is + * needed is the actual value of the symbol without the offset so it can do the + * relocation correctly based on where the value of the symbol got relocated to + * not the value of the expression (with the offset added to the symbol value). + * So for the NeXT 2.0 release no "local" relocation entries are ever used when + * there is a non-zero offset added to a symbol. The "external" and "local" + * relocation entries remain unchanged. + * + * The implemention is quite messy given the compatibility with the existing + * relocation entry format. The ASSUMPTION is that a section will never be + * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption + * allows the r_address (which is really an offset) to fit in 24 bits and high + * bit of the r_address field in the relocation_info structure to indicate + * it is really a scattered_relocation_info structure. Since these are only + * used in places where "local" relocation entries are used and not where + * "external" relocation entries are used the r_extern field has been removed. + * + * For scattered loading to work on a RISC machine where some of the references + * are split across two instructions the link editor needs to be assured that + * each reference has a unique 32 bit reference (that more than one reference is + * NOT sharing the same high 16 bits for example) so it move each referenced + * item independent of each other. Some compilers guarantees this but the + * compilers don't so scattered loading can be done on those that do guarantee + * this. + */ +#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) +/* + * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that + * when stattered relocation entries were added the mistake of using a mask + * against a structure that is made up of bit fields was used. To make this + * design work this structure must be laid out in memory the same way so the + * mask can be applied can check the same bit each time (r_scattered). + */ +#endif /* defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) */ +#define R_SCATTERED 0x80000000 /* mask to be applied to the r_address field + of a relocation_info structure to tell that + is is really a scattered_relocation_info + stucture */ +struct scattered_relocation_info { +#ifdef __BIG_ENDIAN__ + unsigned int r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */ + r_pcrel:1, /* was relocated pc relative already */ + r_length:2, /* 0=byte, 1=word, 2=long */ + r_type:4, /* if not 0, machine specific relocation type */ + r_address:24; /* offset in the section to what is being + relocated */ + long r_value; /* the value the item to be relocated is + refering to (without any offset added) */ +#endif /* __BIG_ENDIAN__ */ +#ifdef __LITTLE_ENDIAN__ + unsigned int + r_address:24, /* offset in the section to what is being + relocated */ + r_type:4, /* if not 0, machine specific relocation type */ + r_length:2, /* 0=byte, 1=word, 2=long */ + r_pcrel:1, /* was relocated pc relative already */ + r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ + long r_value; /* the value the item to be relocated is + refering to (without any offset added) */ +#endif /* __LITTLE_ENDIAN__ */ +}; + +/* + * Relocation types used in a generic implementation. Relocation entries for + * nornal things use the generic relocation as discribed above and their r_type + * is GENERIC_RELOC_VANILLA (a value of zero). + * + * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support + * the difference of two symbols defined in different sections. That is the + * expression "symbol1 - symbol2 + constant" is a relocatable expression when + * both symbols are defined in some section. For this type of relocation the + * both relocations entries are scattered relocation entries. The value of + * symbol1 is stored in the first relocation entry's r_value field and the + * value of symbol2 is stored in the pair's r_value field. + * + * A special case for a prebound lazy pointer is needed to beable to set the + * value of the lazy pointer back to its non-prebound state. This is done + * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation + * entry where the r_value feild is the value of the lazy pointer not prebound. + */ +enum reloc_type_generic +{ + GENERIC_RELOC_VANILLA, /* generic relocation as discribed above */ + GENERIC_RELOC_PAIR, /* Only follows a GENRIC_RELOC_SECTDIFF */ + GENERIC_RELOC_SECTDIFF, + GENERIC_RELOC_PB_LA_PTR /* prebound lazy pointer */ +}; + +#endif /* _MACHO_RELOC_H_ */ diff --git a/bsd/conf/MASTER b/bsd/conf/MASTER index 52e02e133..f434bfba1 100644 --- a/bsd/conf/MASTER +++ b/bsd/conf/MASTER @@ -87,6 +87,7 @@ options TIMEZONE=0, PST=0 options QUOTA # # <quota> options INET +options ABSOLUTETIME_SCALAR_TYPE options NEW_VM_CODE # # <newvm> options OLD_VM_CODE # # <!newvm> options HW_AST # Hardware ast support # <hw_ast> @@ -241,3 +242,6 @@ pseudo-device bpfilter 4 init bpf_init # # now using iokit disk shim, this is code is obsolete #pseudo-device diskshim + +pseudo-device random 1 init random_init + diff --git a/bsd/conf/Makefile b/bsd/conf/Makefile index 5a0b12a67..c2e1c4abc 100644 --- a/bsd/conf/Makefile +++ b/bsd/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(BSD_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(BSD_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(BSD_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(BSD_KERNEL_CONFIG) $(BSD_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(BSD_KERNEL_CONFIG) $(BSD_KERNEL_CONFIG); \ ); .ORDER: $(COMPOBJROOT)/$(BSD_KERNEL_CONFIG)/Makefile @@ -52,6 +52,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(BSD_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(BSD_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/bsd/conf/Makefile.template b/bsd/conf/Makefile.template index adcab81bd..235b7663f 100644 --- a/bsd/conf/Makefile.template +++ b/bsd/conf/Makefile.template @@ -28,6 +28,9 @@ include $(MakeInc_def) # CFLAGS+= -imacros meta_features.h -DARCH_PRIVATE -DKERNEL -DDRIVER_PRIVATE -D_KERNEL_BUILD -DKERNEL_BUILD -DMACH_KERNEL -DBSD_BUILD -DNCPUS=1 -Wno-four-char-constants -fpascal-strings -D__APPLE__ -I. +# XXX: ld flags for bsd.o +export LDFLAGS_COMPONENT += -keep_private_externs + # # Directories for mig generated files # @@ -98,8 +101,6 @@ do_build_all: do_depend %RULES --include Makedep - include $(MakeInc_rule) include $(MakeInc_dir) diff --git a/bsd/conf/files b/bsd/conf/files index fc46bf79f..6cb9a0e77 100644 --- a/bsd/conf/files +++ b/bsd/conf/files @@ -87,7 +87,6 @@ OPTIONS/disc optional disc OPTIONS/ether optional ether OPTIONS/fddi optional fddi -OPTIONS/ipfilter optional ipfilter OPTIONS/ipdivert optional ipdivert OPTIONS/dummynet optional dummynet OPTIONS/ipfirewall optional ipfirewall @@ -117,6 +116,13 @@ OPTIONS/volfs optional volfs OPTIONS/devfs optional devfs OPTIONS/synthfs optional synthfs +bsd/dev/random/randomdev.c standard +bsd/dev/random/YarrowCoreLib/port/smf.c standard +bsd/dev/random/YarrowCoreLib/src/comp.c standard +bsd/dev/random/YarrowCoreLib/src/prng.c standard +bsd/dev/random/YarrowCoreLib/src/sha1mod.c standard +bsd/dev/random/YarrowCoreLib/src/yarrowUtils.c standard + bsd/libkern/random.c standard bsd/libkern/scanc.c standard bsd/libkern/skpc.c standard @@ -247,7 +253,6 @@ bsd/netccitt/pk_subr.c optional ccitt bsd/netccitt/pk_timer.c optional ccitt bsd/netccitt/pk_usrreq.c optional ccitt -bsd/netinet/fil.c optional ipfilter inet bsd/netinet/if_atm.c optional atm bsd/netinet/if_ether.c optional ether bsd/netinet/igmp.c standard @@ -256,22 +261,14 @@ bsd/netinet/in_bootp.c standard bsd/netinet/in_pcb.c standard bsd/netinet/in_proto.c standard bsd/netinet/in_rmx.c standard -bsd/netinet/ip_auth.c optional ipfilter inet bsd/netinet/ip_divert.c optional ipdivert bsd/netinet/ip_dummynet.c optional dummynet -bsd/netinet/ip_fil.c optional ipfilter inet bsd/netinet/ip_flow.c standard -bsd/netinet/ip_frag.c optional ipfilter inet bsd/netinet/ip_fw.c optional ipfirewall bsd/netinet/ip_icmp.c standard bsd/netinet/ip_input.c standard -bsd/netinet/ip_log.c optional ipfilter inet bsd/netinet/ip_mroute.c standard -bsd/netinet/ip_nat.c optional ipfilter inet bsd/netinet/ip_output.c standard -bsd/netinet/ip_proxy.c optional ipfilter inet -bsd/netinet/ip_state.c optional ipfilter inet -bsd/netinet/mlf_ipl.c optional ipfilter inet bsd/netinet/raw_ip.c standard bsd/netinet/tcp_debug.c optional tcpdebug bsd/netinet/tcp_input.c standard @@ -469,6 +466,7 @@ bsd/ufs/ufs/ufs_vfsops.c standard bsd/ufs/ufs/ufs_vnops.c standard bsd/hfs/hfs_btreeio.c optional hfs +bsd/hfs/hfs_encodinghint.c optional hfs bsd/hfs/hfs_encodings.c optional hfs bsd/hfs/hfs_endian.c optional hfs bsd/hfs/hfs_link.c optional hfs @@ -481,6 +479,7 @@ bsd/hfs/hfs_vfsutils.c optional hfs bsd/hfs/hfs_vhash.c optional hfs bsd/hfs/hfs_vnodeops.c optional hfs bsd/hfs/MacOSStubs.c optional hfs +bsd/hfs/rangelist.c optional hfs bsd/hfs/hfscommon/BTree/BTree.c optional hfs bsd/hfs/hfscommon/BTree/BTreeAllocate.c optional hfs bsd/hfs/hfscommon/BTree/BTreeMiscOps.c optional hfs diff --git a/bsd/conf/version.minor b/bsd/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/bsd/conf/version.minor +++ b/bsd/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/bsd/conf/version.variant b/bsd/conf/version.variant index 7f8f011eb..e69de29bb 100644 --- a/bsd/conf/version.variant +++ b/bsd/conf/version.variant @@ -1 +0,0 @@ -7 diff --git a/bsd/dev/Makefile b/bsd/dev/Makefile index 8e8cf9321..8a11503da 100644 --- a/bsd/dev/Makefile +++ b/bsd/dev/Makefile @@ -8,6 +8,7 @@ include $(MakeInc_cmd) include $(MakeInc_def) INSTINC_SUBDIRS = \ + random INSTINC_SUBDIRS_PPC = \ diff --git a/bsd/dev/disk.h b/bsd/dev/disk.h index ef8b7504e..6431ff276 100644 --- a/bsd/dev/disk.h +++ b/bsd/dev/disk.h @@ -160,5 +160,10 @@ struct drive_location { #define DKIOCGETLOCATION DKIOCGLOCATION /* get media's location description */ #define DKIOCISFORMATTED DKIOCGFORMAT /* is media formatted? */ #define DKIOCISWRITABLE _IOR('d', 29, int) /* is media writable? */ -#endif /* _BSD_DEV_DISK_ */ +#define DKIOCGETMAXBLOCKCOUNTREAD _IOR('d', 64, u_int64_t) /* get device's maximum block count for read requests */ +#define DKIOCGETMAXBLOCKCOUNTWRITE _IOR('d', 65, u_int64_t) /* get device's maximum block count for write requests */ +#define DKIOCGETMAXSEGMENTCOUNTREAD _IOR('d', 66, u_int64_t) /* get device's maximum physical segment count for read buffers */ +#define DKIOCGETMAXSEGMENTCOUNTWRITE _IOR('d', 67, u_int64_t) /* get device's maximum physical segment count for write buffers */ + +#endif /* _BSD_DEV_DISK_ */ diff --git a/bsd/dev/i386/cons.c b/bsd/dev/i386/cons.c index 5c56556a6..118878bd1 100644 --- a/bsd/dev/i386/cons.c +++ b/bsd/dev/i386/cons.c @@ -139,9 +139,10 @@ cnioctl(dev, cmd, addr, flag, p) /*ARGSUSED*/ int -cnselect(dev, flag, p) +cnselect(dev, flag, wql, p) dev_t dev; int flag; + void * wql; struct proc *p; { dev_t device; @@ -150,7 +151,7 @@ cnselect(dev, flag, p) device = constty->t_dev; else device = cons.t_dev; - return ((*cdevsw[major(device)].d_select)(device, flag, p)); + return ((*cdevsw[major(device)].d_select)(device, flag, wql, p)); } #if 0 /* FIXME - using OSFMK console driver for the moment */ diff --git a/bsd/dev/i386/unix_startup.c b/bsd/dev/i386/unix_startup.c index 020c7c0e8..c14e2807e 100644 --- a/bsd/dev/i386/unix_startup.c +++ b/bsd/dev/i386/unix_startup.c @@ -154,3 +154,7 @@ bsd_bufferinit() bufinit(); } +void +md_prepare_for_shutdown(int paniced, int howto, char * command) +{ +} diff --git a/bsd/dev/ppc/cons.c b/bsd/dev/ppc/cons.c index 3c5c10d2b..26290d9a3 100644 --- a/bsd/dev/ppc/cons.c +++ b/bsd/dev/ppc/cons.c @@ -140,9 +140,10 @@ consioctl(dev, cmd, addr, flag, p) /*ARGSUSED*/ int -consselect(dev, flag, p) +consselect(dev, flag, wql, p) dev_t dev; int flag; + void *wql; struct proc *p; { dev_t device; @@ -151,7 +152,7 @@ consselect(dev, flag, p) device = constty->t_dev; else device = cons.t_dev; - return ((*cdevsw[major(device)].d_select)(device, flag, p)); + return ((*cdevsw[major(device)].d_select)(device, flag, wql, p)); } int diff --git a/bsd/dev/ppc/unix_startup.c b/bsd/dev/ppc/unix_startup.c index 32ba91f5c..d8dcbece8 100644 --- a/bsd/dev/ppc/unix_startup.c +++ b/bsd/dev/ppc/unix_startup.c @@ -149,3 +149,14 @@ bsd_bufferinit() bufinit(); } +void +md_prepare_for_shutdown(int paniced, int howto, char * command) +{ + extern void IOSystemShutdownNotification(); + + /* + * Temporary hack to notify the power management root domain + * that the system will shut down. + */ + IOSystemShutdownNotification(); +} diff --git a/bsd/dev/random/Makefile b/bsd/dev/random/Makefile new file mode 100644 index 000000000..a0b386718 --- /dev/null +++ b/bsd/dev/random/Makefile @@ -0,0 +1,37 @@ +export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd +export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def +export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule +export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir + + +include $(MakeInc_cmd) +include $(MakeInc_def) + +INSTINC_SUBDIRS = \ + +INSTINC_SUBDIRS_PPC = \ + +INSTINC_SUBDIRS_I386 = \ + +EXPINC_SUBDIRS = \ + +EXPINC_SUBDIRS_PPC = \ + +EXPINC_SUBDIRS_I386 = \ + +DATAFILES = \ + randomdev.h + +INSTALL_MI_LIST = ${DATAFILES} + +INSTALL_MI_DIR = dev/random + +EXPORT_MI_LIST = ${DATAFILES} + +EXPORT_MI_DIR = dev/random + + +include $(MakeInc_rule) +include $(MakeInc_dir) + + diff --git a/bsd/dev/random/YarrowCoreLib/include/WindowsTypesForMac.h b/bsd/dev/random/YarrowCoreLib/include/WindowsTypesForMac.h new file mode 100644 index 000000000..e1c4d4f4e --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/include/WindowsTypesForMac.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: WindowsTypesForMac.h + + Contains: Define common Windows data types in mac terms. + + Written by: Doug Mitchell + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created. + +*/ + +#ifndef _WINDOWS_TYPES_FOR_MAC_H_ +#define _WINDOWS_TYPES_FOR_MAC_H_ + +#include <dev/random/YarrowCoreLib/include/macos_defs.h> + +typedef UInt8 UCHAR; +typedef SInt8 CHAR; +typedef UInt8 BYTE; +typedef char TCHAR; +typedef SInt16 WORD; +typedef SInt32 DWORD; +typedef UInt16 USHORT; +typedef UInt32 ULONG; +typedef SInt32 LONG; +typedef UInt32 UINT; +typedef SInt64 LONGLONG; +typedef UInt8 *LPBYTE; +typedef SInt8 *LPSTR; +typedef SInt16 *LPWORD; +typedef SInt8 *LPCTSTR; /* ??? */ +typedef SInt8 *LPCSTR; /* ??? */ +typedef void *LPVOID; +typedef void *HINSTANCE; +typedef void *HANDLE; + +#define WINAPI + +#endif /* _WINDOWS_TYPES_FOR_MAC_H_*/ + diff --git a/bsd/dev/random/YarrowCoreLib/include/macos_defs.h b/bsd/dev/random/YarrowCoreLib/include/macos_defs.h new file mode 100644 index 000000000..73aa2ddcd --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/include/macos_defs.h @@ -0,0 +1,1658 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + File: hfs_macos_types.h + + Contains: Basic Macintosh OS data types. + + Version: System 7.5 + + DRI: Nick Kledzik + + History: + 12-Aug-1999 Scott Roberts Created from ConditionalMacros.h, MacOSStubs.h, MacOSTypes.h + + + +*/ + + +#ifndef __hfs_macos_types__ +#define __hfs_macos_types__ + + +#include <sys/param.h> + #ifdef KERNEL + #include <libkern/libkern.h> + #include <sys/systm.h> + #endif + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/lock.h> + +/****** START OF CONDITIONALMACROS *********/ + + #if defined(__ppc__) || defined(powerpc) || defined(ppc) + #define TARGET_CPU_PPC 1 + #define TARGET_CPU_68K 0 + #define TARGET_CPU_X86 0 + #define TARGET_CPU_MIPS 0 + #define TARGET_CPU_SPARC 0 + #define TARGET_CPU_ALPHA 0 + #define TARGET_RT_MAC_CFM 0 + #define TARGET_RT_MAC_MACHO 1 + #define TARGET_RT_MAC_68881 0 + #define TARGET_RT_LITTLE_ENDIAN 0 + #define TARGET_RT_BIG_ENDIAN 1 + #elif defined(m68k) + #define TARGET_CPU_PPC 0 + #define TARGET_CPU_68K 1 + #define TARGET_CPU_X86 0 + #define TARGET_CPU_MIPS 0 + #define TARGET_CPU_SPARC 0 + #define TARGET_CPU_ALPHA 0 + #define TARGET_RT_MAC_CFM 0 + #define TARGET_RT_MAC_MACHO 1 + #define TARGET_RT_MAC_68881 0 + #define TARGET_RT_LITTLE_ENDIAN 0 + #define TARGET_RT_BIG_ENDIAN 1 + #elif defined(sparc) + #define TARGET_CPU_PPC 0 + #define TARGET_CPU_68K 0 + #define TARGET_CPU_X86 0 + #define TARGET_CPU_MIPS 0 + #define TARGET_CPU_SPARC 1 + #define TARGET_CPU_ALPHA 0 + #define TARGET_RT_MAC_CFM 0 + #define TARGET_RT_MAC_MACHO 1 + #define TARGET_RT_MAC_68881 0 + #define TARGET_RT_LITTLE_ENDIAN 0 + #define TARGET_RT_BIG_ENDIAN 1 + #elif defined(__i386__) || defined(i386) || defined(intel) + #define TARGET_CPU_PPC 0 + #define TARGET_CPU_68K 0 + #define TARGET_CPU_X86 1 + #define TARGET_CPU_MIPS 0 + #define TARGET_CPU_SPARC 0 + #define TARGET_CPU_ALPHA 0 + #define TARGET_RT_MAC_CFM 0 + #define TARGET_RT_MAC_MACHO 1 + #define TARGET_RT_MAC_68881 0 + #define TARGET_RT_LITTLE_ENDIAN 1 + #define TARGET_RT_BIG_ENDIAN 0 + #else + #error unrecognized GNU C compiler + #endif + + + #define TARGET_OS_MAC 0 + #define TARGET_OS_WIN32 0 + #define TARGET_OS_UNIX 0 + + #define PRAGMA_IMPORT 0 + #define PRAGMA_STRUCT_ALIGN 1 + #define PRAGMA_ONCE 0 + #define PRAGMA_STRUCT_PACK 0 + #define PRAGMA_STRUCT_PACKPUSH 0 + #define PRAGMA_ENUM_PACK 0 + #define PRAGMA_ENUM_ALWAYSINT 0 + #define PRAGMA_ENUM_OPTIONS 0 + #define FOUR_CHAR_CODE(x) (x) + + #define TYPE_EXTENDED 0 + #if __GNUC__ >= 2 + #define TYPE_LONGLONG 1 + #else + #define TYPE_LONGLONG 0 + #endif + #ifdef __cplusplus + #define TYPE_BOOL 1 + #else + #define TYPE_BOOL 0 + #endif + + #define FUNCTION_PASCAL 0 + #define FUNCTION_DECLSPEC 0 + #define FUNCTION_WIN32CC 0 + + + #define EXTERN_API(_type) extern _type + #define EXTERN_API_C(_type) extern _type + #define EXTERN_API_STDCALL(_type) extern _type + #define EXTERN_API_C_STDCALL(_type) extern _type + + #define DEFINE_API(_type) _type + #define DEFINE_API_C(_type) _type + #define DEFINE_API_STDCALL(_type) _type + #define DEFINE_API_C_STDCALL(_type) _type + + #define CALLBACK_API(_type, _name) _type ( * _name) + #define CALLBACK_API_C(_type, _name) _type ( * _name) + #define CALLBACK_API_STDCALL(_type, _name) _type ( * _name) + #define CALLBACK_API_C_STDCALL(_type, _name) _type ( * _name) + + #define TARGET_API_MACOS_X 1 + #define TARGET_API_MAC_OS8 0 + #define TARGET_API_MAC_CARBON 0 + + #define ONEWORDINLINE(w1) + #define TWOWORDINLINE(w1,w2) + #define THREEWORDINLINE(w1,w2,w3) + #define FOURWORDINLINE(w1,w2,w3,w4) + #define FIVEWORDINLINE(w1,w2,w3,w4,w5) + #define SIXWORDINLINE(w1,w2,w3,w4,w5,w6) + #define SEVENWORDINLINE(w1,w2,w3,w4,w5,w6,w7) + #define EIGHTWORDINLINE(w1,w2,w3,w4,w5,w6,w7,w8) + #define NINEWORDINLINE(w1,w2,w3,w4,w5,w6,w7,w8,w9) + #define TENWORDINLINE(w1,w2,w3,w4,w5,w6,w7,w8,w9,w10) + #define ELEVENWORDINLINE(w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11) + #define TWELVEWORDINLINE(w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12) + + +/****** START OF MACOSTYPES *********/ + + +/* + 4.4BSD's sys/types.h defines size_t without defining __size_t__: + Things are a lot clearer from here on if we define __size_t__ now. + */ +#define __size_t__ + +/* + Convert kernel's diagnostic flag to MacOS's +*/ +#if HFS_DIAGNOSTIC + #define DEBUG_BUILD 1 +#else + #define DEBUG_BUILD 0 +#endif /* DIAGNOSTIC */ + +/******************************************************************************** + + Special values in C + + NULL The C standard for an impossible pointer value + nil A carry over from pascal, NULL is prefered for C + +*********************************************************************************/ +#ifndef NULL + #define NULL 0 +#endif + +#ifndef nil + #define nil NULL +#endif + + +/******************************************************************************** + + Base integer types for all target OS's and CPU's + + UInt8 8-bit unsigned integer + SInt8 8-bit signed integer + UInt16 16-bit unsigned integer + SInt16 16-bit signed integer + UInt32 32-bit unsigned integer + SInt32 32-bit signed integer + UInt64 64-bit unsigned integer + SInt64 64-bit signed integer + +*********************************************************************************/ +typedef u_int8_t UInt8; +typedef int8_t SInt8; +typedef u_int16_t UInt16; +typedef int16_t SInt16; +typedef u_int32_t UInt32; +typedef int32_t SInt32; +typedef u_int64_t UInt64; +typedef int64_t SInt64; + + + +/******************************************************************************** + + Base floating point types + + Float32 32 bit IEEE float: 1 sign bit, 8 exponent bits, 23 fraction bits + Float64 64 bit IEEE float: 1 sign bit, 11 exponent bits, 52 fraction bits + Float80 80 bit MacOS float: 1 sign bit, 15 exponent bits, 1 integer bit, 63 fraction bits + Float96 96 bit 68881 float: 1 sign bit, 15 exponent bits, 16 pad bits, 1 integer bit, 63 fraction bits + + Note: These are fixed size floating point types, useful when writing a floating + point value to disk. If your compiler does not support a particular size + float, a struct is used instead. + Use of of the NCEG types (e.g. double_t) or an ANSI C type (e.g. double) if + you want a floating point representation that is natural for any given + compiler, but might be a different size on different compilers. + +*********************************************************************************/ +typedef float Float32; +typedef double Float64; + +struct Float80 { + SInt16 exp; + UInt16 man[4]; +}; +typedef struct Float80 Float80; + +struct Float96 { + SInt16 exp[2]; /* the second 16-bits is always zero */ + UInt16 man[4]; +}; +typedef struct Float96 Float96; + + + +/******************************************************************************** + + MacOS Memory Manager types + + Ptr Pointer to a non-relocatable block + Handle Pointer to a master pointer to a relocatable block + Size The number of bytes in a block (signed for historical reasons) + +*********************************************************************************/ +typedef char * Ptr; +typedef Ptr * Handle; +typedef long Size; +/******************************************************************************** + + Higher level basic types + + OSErr 16-bit result error code + OSStatus 32-bit result error code + LogicalAddress Address in the clients virtual address space + ConstLogicalAddress Address in the clients virtual address space that will only be read + PhysicalAddress Real address as used on the hardware bus + BytePtr Pointer to an array of bytes + ByteCount The size of an array of bytes + ByteOffset An offset into an array of bytes + ItemCount 32-bit iteration count + OptionBits Standard 32-bit set of bit flags + PBVersion ? + Duration 32-bit millisecond timer for drivers + AbsoluteTime 64-bit clock + ScriptCode The coarse features of a written language (e.g. Roman vs Cyrillic) + LangCode A particular language (e.g. English) + RegionCode A variation of a language (British vs American English) + FourCharCode A 32-bit value made by packing four 1 byte characters together + OSType A FourCharCode used in the OS and file system (e.g. creator) + ResType A FourCharCode used to tag resources (e.g. 'DLOG') + +*********************************************************************************/ +typedef SInt16 OSErr; +typedef SInt32 OSStatus; +typedef void * LogicalAddress; +typedef const void * ConstLogicalAddress; +typedef void * PhysicalAddress; +typedef UInt8 * BytePtr; +typedef UInt32 ByteCount; +typedef UInt32 ByteOffset; +typedef SInt32 Duration; +typedef UInt64 AbsoluteTime; +typedef UInt32 OptionBits; +typedef UInt32 ItemCount; +typedef UInt32 PBVersion; +typedef SInt16 ScriptCode; +typedef SInt16 LangCode; +typedef SInt16 RegionCode; +typedef unsigned long FourCharCode; +typedef FourCharCode OSType; +typedef FourCharCode ResType; +typedef OSType * OSTypePtr; +typedef ResType * ResTypePtr; + + +/******************************************************************************** + + Boolean types and values + + Boolean A one byte value, holds "false" (0) or "true" (1) + false The Boolean value of zero (0) + true The Boolean value of one (1) + +*********************************************************************************/ +/* + The identifiers "true" and "false" are becoming keywords in C++ + and work with the new built-in type "bool" + "Boolean" will remain an unsigned char for compatibility with source + code written before "bool" existed. +*/ +#if !TYPE_BOOL + +enum { + false = 0, + true = 1 +}; + +#endif /* !TYPE_BOOL */ + +typedef unsigned char Boolean; + + +/******************************************************************************** + + Function Pointer Types + + ProcPtr Generic pointer to a function + Register68kProcPtr Pointer to a 68K function that expects parameters in registers + UniversalProcPtr Pointer to classic 68K code or a RoutineDescriptor + + ProcHandle Pointer to a ProcPtr + UniversalProcHandle Pointer to a UniversalProcPtr + +*********************************************************************************/ +typedef long (*ProcPtr)(); +typedef void (*Register68kProcPtr)(); + +typedef ProcPtr UniversalProcPtr; + +typedef ProcPtr * ProcHandle; +typedef UniversalProcPtr * UniversalProcHandle; + +/******************************************************************************** + + Quickdraw Types + + Point 2D Quickdraw coordinate, range: -32K to +32K + Rect Rectangluar Quickdraw area + Style Quickdraw font rendering styles + StyleParameter Style when used as a parameter (historical 68K convention) + StyleField Style when used as a field (historical 68K convention) + CharParameter Char when used as a parameter (historical 68K convention) + + Note: The original Macintosh toolbox in 68K Pascal defined Style as a SET. + Both Style and CHAR occupy 8-bits in packed records or 16-bits when + used as fields in non-packed records or as parameters. + +*********************************************************************************/ +struct Point { + short v; + short h; +}; +typedef struct Point Point; + +typedef Point * PointPtr; +struct Rect { + short top; + short left; + short bottom; + short right; +}; +typedef struct Rect Rect; + +typedef Rect * RectPtr; +typedef short CharParameter; + +enum { + normal = 0, + bold = 1, + italic = 2, + underline = 4, + outline = 8, + shadow = 0x10, + condense = 0x20, + extend = 0x40 +}; + +typedef unsigned char Style; +typedef short StyleParameter; +typedef Style StyleField; + + +/******************************************************************************** + + Common Constants + + noErr OSErr: function performed properly - no error + kNilOptions OptionBits: all flags false + kInvalidID KernelID: NULL is for pointers as kInvalidID is for ID's + kVariableLengthArray array bounds: variable length array + + Note: kVariableLengthArray is used in array bounds to specify a variable length array. + It is ususally used in variable length structs when the last field is an array + of any size. Before ANSI C, we used zero as the bounds of variable length + array, but zero length array are illegal in ANSI C. Example usage: + + struct FooList + { + short listLength; + Foo elements[kVariableLengthArray]; + }; + +*********************************************************************************/ + +enum { + noErr = 0 +}; + + +enum { + kNilOptions = 0 +}; + +#define kInvalidID 0 + +enum { + kVariableLengthArray = 1 +}; + + + +/******************************************************************************** + + String Types + + UniChar A single UniCode character (16-bits) + + StrNNN Pascal string holding up to NNN bytes + StringPtr Pointer to a pascal string + StringHandle Pointer to a StringPtr + ConstStrNNNParam For function parameters only - means string is const + + CStringPtr Pointer to a C string (same as: char*) + ConstCStringPtr Pointer to a const C string (same as: const char*) + + Note: The length of a pascal string is stored in the first byte. + A pascal string does not have a termination byte and can be at most 255 bytes long. + The first character in a pascal string is offset one byte from the start of the string. + + A C string is terminated with a byte of value zero. + A C string has no length limitation. + The first character in a C string is the first byte of the string. + + +*********************************************************************************/ +typedef UInt16 UniChar; +typedef unsigned char Str255[256]; +typedef unsigned char Str63[64]; +typedef unsigned char Str32[33]; +typedef unsigned char Str31[32]; +typedef unsigned char Str27[28]; +typedef unsigned char Str15[16]; +/* + The type Str32 is used in many AppleTalk based data structures. + It holds up to 32 one byte chars. The problem is that with the + length byte it is 33 bytes long. This can cause weird alignment + problems in structures. To fix this the type "Str32Field" has + been created. It should only be used to hold 32 chars, but + it is 34 bytes long so that there are no alignment problems. +*/ +typedef unsigned char Str32Field[34]; +typedef unsigned char * StringPtr; +typedef StringPtr * StringHandle; +typedef const unsigned char * ConstStr255Param; +typedef const unsigned char * ConstStr63Param; +typedef const unsigned char * ConstStr32Param; +typedef const unsigned char * ConstStr31Param; +typedef const unsigned char * ConstStr27Param; +typedef const unsigned char * ConstStr15Param; +#ifdef __cplusplus +inline unsigned char StrLength(ConstStr255Param string) { return (*string); } +#else +#define StrLength(string) (*(unsigned char *)(string)) +#endif /* defined(__cplusplus) */ + +typedef const unsigned char * ConstUTF8Param; + +/********************************************************************************* + + Old names for types + +*********************************************************************************/ +typedef UInt8 Byte; +typedef SInt8 SignedByte; +typedef SInt64 * WidePtr; +typedef UInt64 * UnsignedWidePtr; +typedef Float80 extended80; +typedef Float96 extended96; +typedef SInt8 VHSelect; + + +EXTERN_API( void ) +DebugStr (ConstStr255Param debuggerMsg); + +/********************************************************************************* + + Added types for HFSPlus MacOS X functionality. Needs to be incorporated to + other places + +*********************************************************************************/ + + typedef struct vnode* FileReference; + #define kNoFileReference NULL + + +#define HFSInstrumentation 0 + + +/***** START OF MACOSSTUBS ********/ + + +/* + SizeTDef.h -- Common definitions + + size_t - this type is defined by several ANSI headers. +*/ +#if ! defined (__size_t__) + #define __size_t__ + #if defined (__xlc) || defined (__xlC) || defined (__xlC__) || defined (__MWERKS__) + typedef unsigned long size_t; + #else /* __xlC */ + typedef unsigned int size_t; + #endif /* __xlC */ +#endif /* __size_t__ */ + + +/* + StdDef.h -- Common definitions + +*/ + +#define offsetof(structure,field) ((size_t)&((structure *) 0)->field) + + + +/* + File: Errors.h + +*/ +enum { + paramErr = -50, /*error in user parameter list*/ + noHardwareErr = -200, /*Sound Manager Error Returns*/ + notEnoughHardwareErr = -201, /*Sound Manager Error Returns*/ + userCanceledErr = -128, + qErr = -1, /*queue element not found during deletion*/ + vTypErr = -2, /*invalid queue element*/ + corErr = -3, /*core routine number out of range*/ + unimpErr = -4, /*unimplemented core routine*/ + SlpTypeErr = -5, /*invalid queue element*/ + seNoDB = -8, /*no debugger installed to handle debugger command*/ + controlErr = -17, /*I/O System Errors*/ + statusErr = -18, /*I/O System Errors*/ + readErr = -19, /*I/O System Errors*/ + writErr = -20, /*I/O System Errors*/ + badUnitErr = -21, /*I/O System Errors*/ + unitEmptyErr = -22, /*I/O System Errors*/ + openErr = -23, /*I/O System Errors*/ + closErr = -24, /*I/O System Errors*/ + dRemovErr = -25, /*tried to remove an open driver*/ + dInstErr = -26 /*DrvrInstall couldn't find driver in resources*/ +}; + +enum { /* Printing Errors */ + iMemFullErr = -108, + iIOAbort = -27, /*Scrap Manager errors*/ + noScrapErr = -100, /*No scrap exists error*/ + noTypeErr = -102, /*No object of that type in scrap*/ + memROZWarn = -99, /*soft error in ROZ*/ + memROZError = -99, /*hard error in ROZ*/ + memROZErr = -99, /*hard error in ROZ*/ + memFullErr = -108, /*Not enough room in heap zone*/ + nilHandleErr = -109, /*Master Pointer was NIL in HandleZone or other*/ + memWZErr = -111, /*WhichZone failed (applied to free block)*/ + memPurErr = -112, /*trying to purge a locked or non-purgeable block*/ + memAdrErr = -110 /*address was odd; or out of range*/ +}; + + + +enum { + abortErr = -27, /*IO call aborted by KillIO*/ + iIOAbortErr = -27, /*IO abort error (Printing Manager)*/ + notOpenErr = -28, /*Couldn't rd/wr/ctl/sts cause driver not opened*/ + unitTblFullErr = -29, /*unit table has no more entries*/ + dceExtErr = -30, /*dce extension error*/ + slotNumErr = -360, /*invalid slot # error*/ + gcrOnMFMErr = -400, /*gcr format on high density media error*/ + dirFulErr = -33, /*Directory full*/ + dskFulErr = -34, /*disk full*/ + nsvErr = -35, /*no such volume*/ + ioErr = -36, /*I/O error (bummers)*/ + bdNamErr = -37, /*there may be no bad names in the final system!*/ + fnOpnErr = -38, /*File not open*/ + eofErr = -39, /*End of file*/ + posErr = -40, /*tried to position to before start of file (r/w)*/ + mFulErr = -41, /*memory full (open) or file won't fit (load)*/ + tmfoErr = -42, /*too many files open*/ + fnfErr = -43, /*File not found*/ + wPrErr = -44, /*diskette is write protected.*/ + fLckdErr = -45 /*file is locked*/ +}; + + +enum { + vLckdErr = -46, /*volume is locked*/ + fBsyErr = -47, /*File is busy (delete)*/ + dupFNErr = -48, /*duplicate filename (rename)*/ + opWrErr = -49, /*file already open with with write permission*/ + rfNumErr = -51, /*refnum error*/ + gfpErr = -52, /*get file position error*/ + volOffLinErr = -53, /*volume not on line error (was Ejected)*/ + permErr = -54, /*permissions error (on file open)*/ + volOnLinErr = -55, /*drive volume already on-line at MountVol*/ + nsDrvErr = -56, /*no such drive (tried to mount a bad drive num)*/ + noMacDskErr = -57, /*not a mac diskette (sig bytes are wrong)*/ + extFSErr = -58, /*volume in question belongs to an external fs*/ + fsRnErr = -59, /*file system internal error:during rename the old entry was deleted but could not be restored.*/ + badMDBErr = -60, /*bad master directory block*/ + wrPermErr = -61, /*write permissions error*/ + dirNFErr = -120, /*Directory not found*/ + tmwdoErr = -121, /*No free WDCB available*/ + badMovErr = -122, /*Move into offspring error*/ + wrgVolTypErr = -123, /*Wrong volume type error [operation not supported for MFS]*/ + volGoneErr = -124 /*Server volume has been disconnected.*/ +}; + +enum { + /*Dictionary Manager errors*/ + notBTree = -410, /*The file is not a dictionary.*/ + btNoSpace = -413, /*Can't allocate disk space.*/ + btDupRecErr = -414, /*Record already exists.*/ + btRecNotFnd = -415, /*Record cannot be found.*/ + btKeyLenErr = -416, /*Maximum key length is too long or equal to zero.*/ + btKeyAttrErr = -417, /*There is no such a key attribute.*/ + unknownInsertModeErr = -20000, /*There is no such an insert mode.*/ + recordDataTooBigErr = -20001, /*The record data is bigger than buffer size (1024 bytes).*/ + invalidIndexErr = -20002 /*The recordIndex parameter is not valid.*/ +}; + + +enum { + fidNotFound = -1300, /*no file thread exists.*/ + fidExists = -1301, /*file id already exists*/ + notAFileErr = -1302, /*directory specified*/ + diffVolErr = -1303, /*files on different volumes*/ + catChangedErr = -1304, /*the catalog has been modified*/ + desktopDamagedErr = -1305, /*desktop database files are corrupted*/ + sameFileErr = -1306, /*can't exchange a file with itself*/ + badFidErr = -1307, /*file id is dangling or doesn't match with the file number*/ + notARemountErr = -1308, /*when _Mount allows only remounts and doesn't get one*/ + fileBoundsErr = -1309, /*file's EOF, offset, mark or size is too big*/ + fsDataTooBigErr = -1310, /*file or volume is too big for system*/ + volVMBusyErr = -1311, /*can't eject because volume is in use by VM*/ + envNotPresent = -5500, /*returned by glue.*/ + envBadVers = -5501, /*Version non-positive*/ + envVersTooBig = -5502, /*Version bigger than call can handle*/ + fontDecError = -64, /*error during font declaration*/ + fontNotDeclared = -65, /*font not declared*/ + fontSubErr = -66, /*font substitution occured*/ + fontNotOutlineErr = -32615, /*bitmap font passed to routine that does outlines only*/ + firstDskErr = -84, /*I/O System Errors*/ + lastDskErr = -64, /*I/O System Errors*/ + noDriveErr = -64, /*drive not installed*/ + offLinErr = -65, /*r/w requested for an off-line drive*/ + noNybErr = -66 /*couldn't find 5 nybbles in 200 tries*/ +}; + +enum { + /* general text errors*/ + kTextUnsupportedEncodingErr = -8738, /* specified encoding not supported for this operation*/ + kTextMalformedInputErr = -8739, /* in DBCS, for example, high byte followed by invalid low byte*/ + kTextUndefinedElementErr = -8740, /* text conversion errors*/ + kTECMissingTableErr = -8745, + kTECTableChecksumErr = -8746, + kTECTableFormatErr = -8747, + kTECCorruptConverterErr = -8748, /* invalid converter object reference*/ + kTECNoConversionPathErr = -8749, + kTECBufferBelowMinimumSizeErr = -8750, /* output buffer too small to allow processing of first input text element*/ + kTECArrayFullErr = -8751, /* supplied name buffer or TextRun, TextEncoding, or UnicodeMapping array is too small*/ + kTECBadTextRunErr = -8752, + kTECPartialCharErr = -8753, /* input buffer ends in the middle of a multibyte character, conversion stopped*/ + kTECUnmappableElementErr = -8754, + kTECIncompleteElementErr = -8755, /* text element may be incomplete or is too long for internal buffers*/ + kTECDirectionErr = -8756, /* direction stack overflow, etc.*/ + kTECGlobalsUnavailableErr = -8770, /* globals have already been deallocated (premature TERM)*/ + kTECItemUnavailableErr = -8771, /* item (e.g. name) not available for specified region (& encoding if relevant)*/ + /* text conversion status codes*/ + kTECUsedFallbacksStatus = -8783, + kTECNeedFlushStatus = -8784, + kTECOutputBufferFullStatus = -8785, /* output buffer has no room for conversion of next input text element (partial conversion)*/ + /* deprecated error & status codes for low-level converter*/ + unicodeChecksumErr = -8769, + unicodeNoTableErr = -8768, + unicodeVariantErr = -8767, + unicodeFallbacksErr = -8766, + unicodePartConvertErr = -8765, + unicodeBufErr = -8764, + unicodeCharErr = -8763, + unicodeElementErr = -8762, + unicodeNotFoundErr = -8761, + unicodeTableFormatErr = -8760, + unicodeDirectionErr = -8759, + unicodeContextualErr = -8758, + unicodeTextEncodingDataErr = -8757 +}; + + +/* + File: MacMemory.h + + +*/ + + +/* + File: MixedMode.h + +*/ + +/* Calling Conventions */ +typedef unsigned short CallingConventionType; + +enum { + kPascalStackBased = 0, + kCStackBased = 1, + kRegisterBased = 2, + kD0DispatchedPascalStackBased = 8, + kD1DispatchedPascalStackBased = 12, + kD0DispatchedCStackBased = 9, + kStackDispatchedPascalStackBased = 14, + kThinkCStackBased = 5 +}; + + + #define STACK_UPP_TYPE(name) name + #define REGISTER_UPP_TYPE(name) name + + +/* + File: OSUtils.h + +*/ +typedef struct QElem QElem; + +typedef QElem * QElemPtr; +struct QHdr { + short qFlags; + QElemPtr qHead; + QElemPtr qTail; +}; +typedef struct QHdr QHdr; + +typedef QHdr * QHdrPtr; + +typedef CALLBACK_API( void , DeferredTaskProcPtr )(long dtParam); +/* + WARNING: DeferredTaskProcPtr uses register based parameters under classic 68k + and cannot be written in a high-level language without + the help of mixed mode or assembly glue. +*/ +typedef REGISTER_UPP_TYPE(DeferredTaskProcPtr) DeferredTaskUPP; +enum { uppDeferredTaskProcInfo = 0x0000B802 }; /* register no_return_value Func(4_bytes:A1) */ +#define NewDeferredTaskProc(userRoutine) (DeferredTaskUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), uppDeferredTaskProcInfo, GetCurrentArchitecture()) +#define CallDeferredTaskProc(userRoutine, dtParam) CALL_ONE_PARAMETER_UPP((userRoutine), uppDeferredTaskProcInfo, (dtParam)) +struct DeferredTask { + QElemPtr qLink; + short qType; + short dtFlags; + DeferredTaskUPP dtAddr; + long dtParam; + long dtReserved; +}; +typedef struct DeferredTask DeferredTask; + +typedef DeferredTask * DeferredTaskPtr; + +/* + File: Finder.h + + +*/ + +/* + The following declerations used to be in Files.‰, + but are Finder specific and were moved here. +*/ + +enum { + /* Finder Flags */ + kIsOnDesk = 0x0001, + kColor = 0x000E, + kIsShared = 0x0040, /* bit 0x0080 is hasNoINITS */ + kHasBeenInited = 0x0100, /* bit 0x0200 was the letter bit for AOCE, but is now reserved for future use */ + kHasCustomIcon = 0x0400, + kIsStationery = 0x0800, + kNameLocked = 0x1000, + kHasBundle = 0x2000, + kIsInvisible = 0x4000, + kIsAlias = 0x8000 +}; + + +enum { + /* Finder Constants */ + fOnDesk = 1, + fHasBundle = 8192, + fTrash = -3, + fDesktop = -2, + fDisk = 0 +}; + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + + +struct FInfo { + OSType fdType; /*the type of the file*/ + OSType fdCreator; /*file's creator*/ + unsigned short fdFlags; /*flags ex. hasbundle,invisible,locked, etc.*/ + Point fdLocation; /*file's location in folder*/ + short fdFldr; /*folder containing file*/ +}; +typedef struct FInfo FInfo; + +struct FXInfo { + short fdIconID; /*Icon ID*/ + short fdUnused[3]; /*unused but reserved 6 bytes*/ + SInt8 fdScript; /*Script flag and number*/ + SInt8 fdXFlags; /*More flag bits*/ + short fdComment; /*Comment ID*/ + long fdPutAway; /*Home Dir ID*/ +}; +typedef struct FXInfo FXInfo; + +struct DInfo { + Rect frRect; /*folder rect*/ + unsigned short frFlags; /*Flags*/ + Point frLocation; /*folder location*/ + short frView; /*folder view*/ +}; +typedef struct DInfo DInfo; + +struct DXInfo { + Point frScroll; /*scroll position*/ + long frOpenChain; /*DirID chain of open folders*/ + SInt8 frScript; /*Script flag and number*/ + SInt8 frXFlags; /*More flag bits*/ + short frComment; /*comment*/ + long frPutAway; /*DirID*/ +}; +typedef struct DXInfo DXInfo; + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + + +enum { + fsRtParID = 1, + fsRtDirID = 2 +}; + + + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + + +/* + * UTGetBlock options + */ + +enum { + gbDefault = 0, /* default value - read if not found */ + /* bits and masks */ + gbReadBit = 0, /* read block from disk (forced read) */ + gbReadMask = 0x0001, + gbExistBit = 1, /* get existing cache block */ + gbExistMask = 0x0002, + gbNoReadBit = 2, /* don't read block from disk if not found in cache */ + gbNoReadMask = 0x0004, + gbReleaseBit = 3, /* release block immediately after GetBlock */ + gbReleaseMask = 0x0008 +}; + + +/* + * UTReleaseBlock options + */ + +enum { + rbDefault = 0, /* default value - just mark the buffer not in-use */ + /* bits and masks */ + rbWriteBit = 0, /* force write buffer to disk */ + rbWriteMask = 0x0001, + rbTrashBit = 1, /* trash buffer contents after release */ + rbTrashMask = 0x0002, + rbDirtyBit = 2, /* mark buffer dirty */ + rbDirtyMask = 0x0004, + rbFreeBit = 3, /* free the buffer (save in the hash) */ + rbFreeMask = 0x000A /* rbFreeMask (rbFreeBit + rbTrashBit) works as rbTrash on < System 7.0 RamCache; on >= System 7.0, rbfreeMask overrides rbTrash */ +}; + +/* + * UTFlushCache options + */ + +enum { + fcDefault = 0, /* default value - pass this fcOption to just flush any dirty buffers */ + /* bits and masks */ + fcTrashBit = 0, /* (don't pass this as fcOption, use only for testing bit) */ + fcTrashMask = 0x0001, /* pass this fcOption value to flush and trash cache blocks */ + fcFreeBit = 1, /* (don't pass this as fcOption, use only for testing bit) */ + fcFreeMask = 0x0003 /* pass this fcOption to flush and free cache blocks (Note: both fcTrash and fcFree bits are set) */ +}; + + + +/* + * FCBRec.fcbFlags bits + */ + +enum { + fcbWriteBit = 0, /* Data can be written to this file */ + fcbWriteMask = 0x01, + fcbResourceBit = 1, /* This file is a resource fork */ + fcbResourceMask = 0x02, + fcbWriteLockedBit = 2, /* File has a locked byte range */ + fcbWriteLockedMask = 0x04, + fcbSharedWriteBit = 4, /* File is open for shared write access */ + fcbSharedWriteMask = 0x10, + fcbFileLockedBit = 5, /* File is locked (write-protected) */ + fcbFileLockedMask = 0x20, + fcbOwnClumpBit = 6, /* File has clump size specified in FCB */ + fcbOwnClumpMask = 0x40, + fcbModifiedBit = 7, /* File has changed since it was last flushed */ + fcbModifiedMask = 0x80 +}; + + +/* + File: TextCommon.h + +*/ + +/* LocaleIdentifier is an obsolete Copland typedef, will be removed soon*/ +typedef UInt32 LocaleIdentifier; +/* TextEncodingBase type & values */ +/* (values 0-32 correspond to the Script Codes defined in Inside Macintosh: Text pages 6-52 and 6-53 */ +typedef UInt32 TextEncodingBase; + +enum { + /* Mac OS encodings*/ + kTextEncodingMacRoman = 0L, + kTextEncodingMacJapanese = 1, + kTextEncodingMacChineseTrad = 2, + kTextEncodingMacKorean = 3, + kTextEncodingMacArabic = 4, + kTextEncodingMacHebrew = 5, + kTextEncodingMacGreek = 6, + kTextEncodingMacCyrillic = 7, + kTextEncodingMacDevanagari = 9, + kTextEncodingMacGurmukhi = 10, + kTextEncodingMacGujarati = 11, + kTextEncodingMacOriya = 12, + kTextEncodingMacBengali = 13, + kTextEncodingMacTamil = 14, + kTextEncodingMacTelugu = 15, + kTextEncodingMacKannada = 16, + kTextEncodingMacMalayalam = 17, + kTextEncodingMacSinhalese = 18, + kTextEncodingMacBurmese = 19, + kTextEncodingMacKhmer = 20, + kTextEncodingMacThai = 21, + kTextEncodingMacLaotian = 22, + kTextEncodingMacGeorgian = 23, + kTextEncodingMacArmenian = 24, + kTextEncodingMacChineseSimp = 25, + kTextEncodingMacTibetan = 26, + kTextEncodingMacMongolian = 27, + kTextEncodingMacEthiopic = 28, + kTextEncodingMacCentralEurRoman = 29, + kTextEncodingMacVietnamese = 30, + kTextEncodingMacExtArabic = 31, /* The following use script code 0, smRoman*/ + kTextEncodingMacSymbol = 33, + kTextEncodingMacDingbats = 34, + kTextEncodingMacTurkish = 35, + kTextEncodingMacCroatian = 36, + kTextEncodingMacIcelandic = 37, + kTextEncodingMacRomanian = 38, /* The following use script code 4, smArabic*/ + kTextEncodingMacFarsi = 0x8C, /* Like MacArabic but uses Farsi digits*/ + /* The following use script code 7, smCyrillic*/ + kTextEncodingMacUkrainian = 0x98, /* The following use script code 32, smUnimplemented*/ + kTextEncodingMacVT100 = 0xFC, /* VT100/102 font from Comm Toolbox: Latin-1 repertoire + box drawing etc*/ + /* Special Mac OS encodings*/ + kTextEncodingMacHFS = 0xFF, /* Meta-value, should never appear in a table.*/ + /* Unicode & ISO UCS encodings begin at 0x100*/ + kTextEncodingUnicodeDefault = 0x0100, /* Meta-value, should never appear in a table.*/ + kTextEncodingUnicodeV1_1 = 0x0101, + kTextEncodingISO10646_1993 = 0x0101, /* Code points identical to Unicode 1.1*/ + kTextEncodingUnicodeV2_0 = 0x0103, /* New location for Korean Hangul*/ + /* ISO 8-bit and 7-bit encodings begin at 0x200*/ + kTextEncodingISOLatin1 = 0x0201, /* ISO 8859-1*/ + kTextEncodingISOLatin2 = 0x0202, /* ISO 8859-2*/ + kTextEncodingISOLatinCyrillic = 0x0205, /* ISO 8859-5*/ + kTextEncodingISOLatinArabic = 0x0206, /* ISO 8859-6, = ASMO 708, =DOS CP 708*/ + kTextEncodingISOLatinGreek = 0x0207, /* ISO 8859-7*/ + kTextEncodingISOLatinHebrew = 0x0208, /* ISO 8859-8*/ + kTextEncodingISOLatin5 = 0x0209, /* ISO 8859-9*/ + /* MS-DOS & Windows encodings begin at 0x400*/ + kTextEncodingDOSLatinUS = 0x0400, /* code page 437*/ + kTextEncodingDOSGreek = 0x0405, /* code page 737 (formerly code page 437G)*/ + kTextEncodingDOSBalticRim = 0x0406, /* code page 775*/ + kTextEncodingDOSLatin1 = 0x0410, /* code page 850, "Multilingual"*/ + kTextEncodingDOSGreek1 = 0x0411, /* code page 851*/ + kTextEncodingDOSLatin2 = 0x0412, /* code page 852, Slavic*/ + kTextEncodingDOSCyrillic = 0x0413, /* code page 855, IBM Cyrillic*/ + kTextEncodingDOSTurkish = 0x0414, /* code page 857, IBM Turkish*/ + kTextEncodingDOSPortuguese = 0x0415, /* code page 860*/ + kTextEncodingDOSIcelandic = 0x0416, /* code page 861*/ + kTextEncodingDOSHebrew = 0x0417, /* code page 862*/ + kTextEncodingDOSCanadianFrench = 0x0418, /* code page 863*/ + kTextEncodingDOSArabic = 0x0419, /* code page 864*/ + kTextEncodingDOSNordic = 0x041A, /* code page 865*/ + kTextEncodingDOSRussian = 0x041B, /* code page 866*/ + kTextEncodingDOSGreek2 = 0x041C, /* code page 869, IBM Modern Greek*/ + kTextEncodingDOSThai = 0x041D, /* code page 874, also for Windows*/ + kTextEncodingDOSJapanese = 0x0420, /* code page 932, also for Windows*/ + kTextEncodingDOSChineseSimplif = 0x0421, /* code page 936, also for Windows*/ + kTextEncodingDOSKorean = 0x0422, /* code page 949, also for Windows; Unified Hangul Code*/ + kTextEncodingDOSChineseTrad = 0x0423, /* code page 950, also for Windows*/ + kTextEncodingWindowsLatin1 = 0x0500, /* code page 1252*/ + kTextEncodingWindowsANSI = 0x0500, /* code page 1252 (alternate name)*/ + kTextEncodingWindowsLatin2 = 0x0501, /* code page 1250, Central Europe*/ + kTextEncodingWindowsCyrillic = 0x0502, /* code page 1251, Slavic Cyrillic*/ + kTextEncodingWindowsGreek = 0x0503, /* code page 1253*/ + kTextEncodingWindowsLatin5 = 0x0504, /* code page 1254, Turkish*/ + kTextEncodingWindowsHebrew = 0x0505, /* code page 1255*/ + kTextEncodingWindowsArabic = 0x0506, /* code page 1256*/ + kTextEncodingWindowsBalticRim = 0x0507, /* code page 1257*/ + kTextEncodingWindowsKoreanJohab = 0x0510, /* code page 1361, for Windows NT*/ + /* Various national standards begin at 0x600*/ + kTextEncodingUS_ASCII = 0x0600, + kTextEncodingJIS_X0201_76 = 0x0620, + kTextEncodingJIS_X0208_83 = 0x0621, + kTextEncodingJIS_X0208_90 = 0x0622, + kTextEncodingJIS_X0212_90 = 0x0623, + kTextEncodingJIS_C6226_78 = 0x0624, + kTextEncodingGB_2312_80 = 0x0630, + kTextEncodingGBK_95 = 0x0631, /* annex to GB 13000-93; for Windows 95*/ + kTextEncodingKSC_5601_87 = 0x0640, /* same as KSC 5601-92 without Johab annex*/ + kTextEncodingKSC_5601_92_Johab = 0x0641, /* KSC 5601-92 Johab annex*/ + kTextEncodingCNS_11643_92_P1 = 0x0651, /* CNS 11643-1992 plane 1*/ + kTextEncodingCNS_11643_92_P2 = 0x0652, /* CNS 11643-1992 plane 2*/ + kTextEncodingCNS_11643_92_P3 = 0x0653, /* CNS 11643-1992 plane 3 (was plane 14 in 1986 version)*/ + /* ISO 2022 collections begin at 0x800*/ + kTextEncodingISO_2022_JP = 0x0820, + kTextEncodingISO_2022_JP_2 = 0x0821, + kTextEncodingISO_2022_CN = 0x0830, + kTextEncodingISO_2022_CN_EXT = 0x0831, + kTextEncodingISO_2022_KR = 0x0840, /* EUC collections begin at 0x900*/ + kTextEncodingEUC_JP = 0x0920, /* ISO 646, 1-byte katakana, JIS 208, JIS 212*/ + kTextEncodingEUC_CN = 0x0930, /* ISO 646, GB 2312-80*/ + kTextEncodingEUC_TW = 0x0931, /* ISO 646, CNS 11643-1992 Planes 1-16*/ + kTextEncodingEUC_KR = 0x0940, /* ISO 646, KS C 5601-1987*/ + /* Misc standards begin at 0xA00*/ + kTextEncodingShiftJIS = 0x0A01, /* plain Shift-JIS*/ + kTextEncodingKOI8_R = 0x0A02, /* Russian internet standard*/ + kTextEncodingBig5 = 0x0A03, /* Big-5 (has variants)*/ + kTextEncodingMacRomanLatin1 = 0x0A04, /* Mac OS Roman permuted to align with ISO Latin-1*/ + kTextEncodingHZ_GB_2312 = 0x0A05, /* HZ (RFC 1842, for Chinese mail & news)*/ + /* Other platform encodings*/ + kTextEncodingNextStepLatin = 0x0B01, /* NextStep encoding*/ + /* EBCDIC & IBM host encodings begin at 0xC00*/ + kTextEncodingEBCDIC_US = 0x0C01, /* basic EBCDIC-US*/ + kTextEncodingEBCDIC_CP037 = 0x0C02, /* code page 037, extended EBCDIC (Latin-1 set) for US,Canada...*/ + /* Special value*/ + kTextEncodingMultiRun = 0x0FFF, /* Multi-encoding text with external run info*/ + /* The following are older names for backward compatibility*/ + kTextEncodingMacTradChinese = 2, + kTextEncodingMacRSymbol = 8, + kTextEncodingMacSimpChinese = 25, + kTextEncodingMacGeez = 28, + kTextEncodingMacEastEurRoman = 29, + kTextEncodingMacUninterp = 32 +}; + +/* TextEncodingVariant type & values */ +typedef UInt32 TextEncodingVariant; + +enum { + /* Default TextEncodingVariant, for any TextEncodingBase*/ + kTextEncodingDefaultVariant = 0, /* Variants of kTextEncodingMacIcelandic */ + kMacIcelandicStandardVariant = 0, /* 0xBB & 0xBC are fem./masc. ordinal indicators*/ + kMacIcelandicTrueTypeVariant = 1, /* 0xBB & 0xBC are fi/fl ligatures*/ + /* Variants of kTextEncodingMacJapanese*/ + kMacJapaneseStandardVariant = 0, + kMacJapaneseStdNoVerticalsVariant = 1, + kMacJapaneseBasicVariant = 2, + kMacJapanesePostScriptScrnVariant = 3, + kMacJapanesePostScriptPrintVariant = 4, + kMacJapaneseVertAtKuPlusTenVariant = 5, /* Variant options for most Japanese encodings (MacJapanese, ShiftJIS, EUC-JP, ISO 2022-JP) */ + /* These can be OR-ed into the variant value in any combination*/ + kJapaneseNoOneByteKanaOption = 0x20, + kJapaneseUseAsciiBackslashOption = 0x40, /* Variants of kTextEncodingMacArabic*/ + kMacArabicStandardVariant = 0, /* 0xC0 is 8-spoke asterisk, 0x2A & 0xAA are asterisk (e.g. Cairo)*/ + kMacArabicTrueTypeVariant = 1, /* 0xC0 is asterisk, 0x2A & 0xAA are multiply signs (e.g. Baghdad)*/ + kMacArabicThuluthVariant = 2, /* 0xC0 is Arabic five-point star, 0x2A & 0xAA are multiply signs*/ + kMacArabicAlBayanVariant = 3, /* 8-spoke asterisk, multiply sign, Koranic ligatures & parens*/ + /* Variants of kTextEncodingMacFarsi*/ + kMacFarsiStandardVariant = 0, /* 0xC0 is 8-spoke asterisk, 0x2A & 0xAA are asterisk (e.g. Tehran)*/ + kMacFarsiTrueTypeVariant = 1, /* asterisk, multiply signs, Koranic ligatures, geometric shapes*/ + /* Variants of kTextEncodingMacHebrew*/ + kMacHebrewStandardVariant = 0, + kMacHebrewFigureSpaceVariant = 1, /* Variants of Unicode & ISO 10646 encodings*/ + kUnicodeNoSubset = 0, + kUnicodeNoCompatibilityVariant = 1, + kUnicodeMaxDecomposedVariant = 2, + kUnicodeNoComposedVariant = 3, + kUnicodeNoCorporateVariant = 4, /* Variants of Big-5 encoding*/ + kBig5_BasicVariant = 0, + kBig5_StandardVariant = 1, /* 0xC6A1-0xC7FC: kana, Cyrillic, enclosed numerics*/ + kBig5_ETenVariant = 2, /* adds kana, Cyrillic, radicals, etc with hi bytes C6-C8,F9*/ + /* The following are older names for backward compatibility*/ + kJapaneseStandardVariant = 0, + kJapaneseStdNoVerticalsVariant = 1, + kJapaneseBasicVariant = 2, + kJapanesePostScriptScrnVariant = 3, + kJapanesePostScriptPrintVariant = 4, + kJapaneseVertAtKuPlusTenVariant = 5, /* kJapaneseStdNoOneByteKanaVariant = 6, // replaced by kJapaneseNoOneByteKanaOption*/ + /* kJapaneseBasicNoOneByteKanaVariant = 7, // replaced by kJapaneseNoOneByteKanaOption */ + kHebrewStandardVariant = 0, + kHebrewFigureSpaceVariant = 1 +}; + +/* TextEncodingFormat type & values */ +typedef UInt32 TextEncodingFormat; + +enum { + /* Default TextEncodingFormat for any TextEncodingBase*/ + kTextEncodingDefaultFormat = 0, /* Formats for Unicode & ISO 10646*/ + kUnicode16BitFormat = 0, + kUnicodeUTF7Format = 1, + kUnicodeUTF8Format = 2, + kUnicode32BitFormat = 3 +}; + +/* TextEncoding type */ +typedef UInt32 TextEncoding; +/* name part selector for GetTextEncodingName*/ +typedef UInt32 TextEncodingNameSelector; + +enum { + kTextEncodingFullName = 0, + kTextEncodingBaseName = 1, + kTextEncodingVariantName = 2, + kTextEncodingFormatName = 3 +}; + +/* Types used in conversion */ +struct TextEncodingRun { + ByteOffset offset; + TextEncoding textEncoding; +}; +typedef struct TextEncodingRun TextEncodingRun; + +typedef TextEncodingRun * TextEncodingRunPtr; +typedef const TextEncodingRun * ConstTextEncodingRunPtr; +struct ScriptCodeRun { + ByteOffset offset; + ScriptCode script; +}; +typedef struct ScriptCodeRun ScriptCodeRun; + +typedef ScriptCodeRun * ScriptCodeRunPtr; +typedef const ScriptCodeRun * ConstScriptCodeRunPtr; +typedef UInt8 * TextPtr; +typedef const UInt8 * ConstTextPtr; +/* Basic types for Unicode characters and strings: */ +typedef UniChar * UniCharArrayPtr; +typedef const UniChar * ConstUniCharArrayPtr; +/* enums for TextEncoding Conversion routines*/ + +enum { + kTextScriptDontCare = -128, + kTextLanguageDontCare = -128, + kTextRegionDontCare = -128 +}; + + + +/* + File: UnicodeConverter.h + + +*/ + +/* Unicode conversion contexts: */ +typedef struct OpaqueTextToUnicodeInfo* TextToUnicodeInfo; +typedef struct OpaqueUnicodeToTextInfo* UnicodeToTextInfo; +typedef struct OpaqueUnicodeToTextRunInfo* UnicodeToTextRunInfo; +typedef const TextToUnicodeInfo ConstTextToUnicodeInfo; +typedef const UnicodeToTextInfo ConstUnicodeToTextInfo; +/* UnicodeMapVersion type & values */ +typedef SInt32 UnicodeMapVersion; + +enum { + kUnicodeUseLatestMapping = -1, + kUnicodeUseHFSPlusMapping = 4 +}; + +/* Types used in conversion */ +struct UnicodeMapping { + TextEncoding unicodeEncoding; + TextEncoding otherEncoding; + UnicodeMapVersion mappingVersion; +}; +typedef struct UnicodeMapping UnicodeMapping; + +typedef UnicodeMapping * UnicodeMappingPtr; +typedef const UnicodeMapping * ConstUnicodeMappingPtr; +/* Control flags for ConvertFromUnicodeToText and ConvertFromTextToUnicode */ + +enum { + kUnicodeUseFallbacksBit = 0, + kUnicodeKeepInfoBit = 1, + kUnicodeDirectionalityBits = 2, + kUnicodeVerticalFormBit = 4, + kUnicodeLooseMappingsBit = 5, + kUnicodeStringUnterminatedBit = 6, + kUnicodeTextRunBit = 7, + kUnicodeKeepSameEncodingBit = 8 +}; + + +enum { + kUnicodeUseFallbacksMask = 1L << kUnicodeUseFallbacksBit, + kUnicodeKeepInfoMask = 1L << kUnicodeKeepInfoBit, + kUnicodeDirectionalityMask = 3L << kUnicodeDirectionalityBits, + kUnicodeVerticalFormMask = 1L << kUnicodeVerticalFormBit, + kUnicodeLooseMappingsMask = 1L << kUnicodeLooseMappingsBit, + kUnicodeStringUnterminatedMask = 1L << kUnicodeStringUnterminatedBit, + kUnicodeTextRunMask = 1L << kUnicodeTextRunBit, + kUnicodeKeepSameEncodingMask = 1L << kUnicodeKeepSameEncodingBit +}; + +/* Values for kUnicodeDirectionality field */ + +enum { + kUnicodeDefaultDirection = 0, + kUnicodeLeftToRight = 1, + kUnicodeRightToLeft = 2 +}; + +/* Directionality masks for control flags */ + +enum { + kUnicodeDefaultDirectionMask = kUnicodeDefaultDirection << kUnicodeDirectionalityBits, + kUnicodeLeftToRightMask = kUnicodeLeftToRight << kUnicodeDirectionalityBits, + kUnicodeRightToLeftMask = kUnicodeRightToLeft << kUnicodeDirectionalityBits +}; + +/* Control flags for TruncateForUnicodeToText: */ +/* + Now TruncateForUnicodeToText uses control flags from the same set as used by + ConvertFromTextToUnicode, ConvertFromUnicodeToText, etc., but only + kUnicodeStringUnterminatedMask is meaningful for TruncateForUnicodeToText. + + Previously two special control flags were defined for TruncateForUnicodeToText: + kUnicodeTextElementSafeBit = 0 + kUnicodeRestartSafeBit = 1 + However, neither of these was implemented. + Instead of implementing kUnicodeTextElementSafeBit, we now use + kUnicodeStringUnterminatedMask since it accomplishes the same thing and avoids + having special flags just for TruncateForUnicodeToText + Also, kUnicodeRestartSafeBit is unnecessary, since restart-safeness is handled by + setting kUnicodeKeepInfoBit with ConvertFromUnicodeToText. + If TruncateForUnicodeToText is called with one or both of the old special control + flags set (bits 0 or 1), it will not generate a paramErr, but the old bits have no + effect on its operation. +*/ + +/* Filter bits for filter field in QueryUnicodeMappings and CountUnicodeMappings: */ + +enum { + kUnicodeMatchUnicodeBaseBit = 0, + kUnicodeMatchUnicodeVariantBit = 1, + kUnicodeMatchUnicodeFormatBit = 2, + kUnicodeMatchOtherBaseBit = 3, + kUnicodeMatchOtherVariantBit = 4, + kUnicodeMatchOtherFormatBit = 5 +}; + + +enum { + kUnicodeMatchUnicodeBaseMask = 1L << kUnicodeMatchUnicodeBaseBit, + kUnicodeMatchUnicodeVariantMask = 1L << kUnicodeMatchUnicodeVariantBit, + kUnicodeMatchUnicodeFormatMask = 1L << kUnicodeMatchUnicodeFormatBit, + kUnicodeMatchOtherBaseMask = 1L << kUnicodeMatchOtherBaseBit, + kUnicodeMatchOtherVariantMask = 1L << kUnicodeMatchOtherVariantBit, + kUnicodeMatchOtherFormatMask = 1L << kUnicodeMatchOtherFormatBit +}; + +/* Control flags for SetFallbackUnicodeToText */ + +enum { + kUnicodeFallbackSequencingBits = 0 +}; + + +enum { + kUnicodeFallbackSequencingMask = 3L << kUnicodeFallbackSequencingBits +}; + +/* values for kUnicodeFallbackSequencing field */ + +enum { + kUnicodeFallbackDefaultOnly = 0L, + kUnicodeFallbackCustomOnly = 1L, + kUnicodeFallbackDefaultFirst = 2L, + kUnicodeFallbackCustomFirst = 3L +}; + + + +/* + File: Timer.h + + +*/ + + +enum { + /* high bit of qType is set if task is active */ + kTMTaskActive = (1L << 15) +}; + +typedef struct TMTask TMTask; +typedef TMTask * TMTaskPtr; +typedef CALLBACK_API( void , TimerProcPtr )(TMTaskPtr tmTaskPtr); +/* + WARNING: TimerProcPtr uses register based parameters under classic 68k + and cannot be written in a high-level language without + the help of mixed mode or assembly glue. +*/ +typedef REGISTER_UPP_TYPE(TimerProcPtr) TimerUPP; +struct TMTask { + QElemPtr qLink; + short qType; + TimerUPP tmAddr; + long tmCount; + long tmWakeUp; + long tmReserved; +}; + + +/* + File: TextCommonPriv.h + + +*/ + + +/* + ----------------------------------------------------------------------------------------------------------- + TextEncoding creation & extraction macros. + Current packed format: + 31 30 29 26 25 16 15 0 + |pack| format | variant | base | + |vers| | | | + |2bit| 4 bits | 10 bits | 16 bits | + Unpacked elements + base 15 0 + | 0 | 16 bits | + variant 9 0 + | 0 | 10 bits | + format 3 0 + | 0 | 4 bits | + ----------------------------------------------------------------------------------------------------------- +*/ + +enum { + kTextEncodingVersion = 0 +}; + + +enum { + kTextEncodingBaseShiftBits = 0, /* <13>*/ + kTextEncodingVariantShiftBits = 16, /* <13>*/ + kTextEncodingFormatShiftBits = 26, /* <13><16>*/ + kTextEncodingVersionShiftBits = 30 +}; + + + +enum { + kTextEncodingBaseSourceMask = 0x0000FFFF, /* 16 bits <13>*/ + kTextEncodingVariantSourceMask = 0x000003FF, /* 10 bits <13><16>*/ + kTextEncodingFormatSourceMask = 0x0000000F, /* 4 bits <13><16>*/ + kTextEncodingVersionSourceMask = 0x00000003 /* 2 bits*/ +}; + + +enum { + kTextEncodingBaseMask = kTextEncodingBaseSourceMask << kTextEncodingBaseShiftBits, + kTextEncodingVariantMask = kTextEncodingVariantSourceMask << kTextEncodingVariantShiftBits, + kTextEncodingFormatMask = kTextEncodingFormatSourceMask << kTextEncodingFormatShiftBits, + kTextEncodingVersionMask = kTextEncodingVersionSourceMask << kTextEncodingVersionShiftBits +}; + + +enum { + kTextEncodingVersionShifted = (kTextEncodingVersion & kTextEncodingVersionSourceMask) << kTextEncodingVersionShiftBits +}; + + +#define CreateTextEncodingPriv(base,variant,format) \ + ( ((base & kTextEncodingBaseSourceMask) << kTextEncodingBaseShiftBits) \ + | ((variant & kTextEncodingVariantSourceMask) << kTextEncodingVariantShiftBits) \ + | ((format & kTextEncodingFormatSourceMask) << kTextEncodingFormatShiftBits) \ + | (kTextEncodingVersionShifted) ) +#define GetTextEncodingBasePriv(encoding) \ + ((encoding & kTextEncodingBaseMask) >> kTextEncodingBaseShiftBits) +#define GetTextEncodingVariantPriv(encoding) \ + ((encoding & kTextEncodingVariantMask) >> kTextEncodingVariantShiftBits) +#define GetTextEncodingFormatPriv(encoding) \ + ((encoding & kTextEncodingFormatMask) >> kTextEncodingFormatShiftBits) +#define IsMacTextEncoding(encoding) ((encoding & 0x0000FF00L) == 0x00000000L) +#define IsUnicodeTextEncoding(encoding) ((encoding & 0x0000FF00L) == 0x00000100L) +/* TextEncoding used by HFS*/ + +enum { + kMacHFSTextEncoding = 0x000000FF +}; + + +/* + File: Instrumentation.h + + +*/ +/*******************************************************************/ +/* Types */ +/*******************************************************************/ +/* Reference to an instrumentation class */ +typedef struct InstOpaqueClassRef* InstClassRef; + +/* Aliases to the generic instrumentation class for each type of class */ +typedef InstClassRef InstPathClassRef; +typedef InstClassRef InstTraceClassRef; +typedef InstClassRef InstHistogramClassRef; +typedef InstClassRef InstSplitHistogramClassRef; +typedef InstClassRef InstMagnitudeClassRef; +typedef InstClassRef InstGrowthClassRef; +typedef InstClassRef InstTallyClassRef; + +/* Reference to a data descriptor */ +typedef struct InstOpaqueDataDescriptorRef* InstDataDescriptorRef; + + +/*******************************************************************/ +/* Constant Definitions */ +/*******************************************************************/ + +/* Reference to the root of the class hierarchy */ +#define kInstRootClassRef ( (InstClassRef) -1) + +/* Options used for creating classes */ +typedef OptionBits InstClassOptions; + + +enum { + kInstDisableClassMask = 0x00, /* Create the class disabled */ + kInstEnableClassMask = 0x01, /* Create the class enabled */ + + kInstSummaryTraceClassMask = 0x20 /* Create a summary trace class instead of a regular one */ +}; + + + +EXTERN_API( Boolean ) +EqualString (ConstStr255Param str1, + ConstStr255Param str2, + Boolean caseSensitive, + Boolean diacSensitive); + + + + +/* + File: LowMemPriv.h + + +*/ + +/* The following replace storage used in low-mem on MacOS: */ +extern struct FSVarsRec * gFSMVars; + + +#define LMGetFSMVars() gFSMVars + + + +EXTERN_API( void ) +InsTime (QElemPtr tmTaskPtr); +EXTERN_API( void ) +PrimeTime (QElemPtr tmTaskPtr, + long count); +EXTERN_API( void ) +RmvTime (QElemPtr tmTaskPtr); + + + + +/* PROTOTYPES */ + +#if HFS_DIAGNOSTIC + extern void RequireFileLock(FileReference vp, int shareable); + #define REQUIRE_FILE_LOCK(vp,s) RequireFileLock((vp),(s)) +#else + #define REQUIRE_FILE_LOCK(vp,s) +#endif + + +EXTERN_API( void ) +BlockMove (const void * srcPtr, + void * destPtr, + Size byteCount); +EXTERN_API( void ) +BlockMoveData (const void * srcPtr, + void * destPtr, + Size byteCount); + +EXTERN_API_C( void ) +BlockMoveUncached (const void * srcPtr, + void * destPtr, + Size byteCount); + +EXTERN_API_C( void ) +BlockMoveDataUncached (const void * srcPtr, + void * destPtr, + Size byteCount); + +EXTERN_API_C( void ) +BlockZero (void * destPtr, + Size byteCount); + +EXTERN_API_C( void ) +BlockZeroUncached (void * destPtr, + Size byteCount); + +EXTERN_API( Ptr ) +NewPtr (Size byteCount); + +EXTERN_API( Ptr ) +NewPtrSys (Size byteCount); + +EXTERN_API( Ptr ) +NewPtrClear (Size byteCount); + +EXTERN_API( Ptr ) +NewPtrSysClear (Size byteCount); + +EXTERN_API( OSErr ) +MemError (void); + +EXTERN_API( void ) +DisposePtr (Ptr p); + +EXTERN_API( Size ) +GetPtrSize (Ptr p); + +EXTERN_API( void ) +SetPtrSize (Ptr p, + Size newSize); + +EXTERN_API( void ) +DisposeHandle (Handle h); + +EXTERN_API( void ) +SetHandleSize (Handle h, + Size newSize); + +/* + File: DateTimeUtils.h + + +*/ +EXTERN_API( void ) +GetDateTime (unsigned long * secs); + + + +#endif /* __hfs_macos_types__ */ diff --git a/bsd/dev/random/YarrowCoreLib/include/yarrow.h b/bsd/dev/random/YarrowCoreLib/include/yarrow.h new file mode 100644 index 000000000..af6b23bf1 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/include/yarrow.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: yarrow.h + + Contains: Public header file for Counterpane's Yarrow Pseudo-random + number generator. + + Written by: Counterpane, Inc. + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created, based on Counterpane source. + +*/ +/* + yarrow.h + + Main header file for Counterpane's Yarrow Pseudo-random number generator. +*/ + +#ifndef __YARROW_H__ +#define __YARROW_H__ + +#if defined(macintosh) || defined(__APPLE__) +#include "WindowsTypesForMac.h" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Error Codes */ +typedef enum prng_error_status { + PRNG_SUCCESS = 0, + PRNG_ERR_REINIT, + PRNG_ERR_WRONG_CALLER, + PRNG_ERR_NOT_READY, + PRNG_ERR_NULL_POINTER, + PRNG_ERR_LOW_MEMORY, + PRNG_ERR_OUT_OF_BOUNDS, + PRNG_ERR_COMPRESSION, + PRNG_ERR_NOT_ENOUGH_ENTROPY, + PRNG_ERR_MUTEX, + PRNG_ERR_TIMEOUT, + PRNG_ERR_PROGRAM_FLOW +} prng_error_status; + +/* + * Entropy sources + */ +enum user_sources { + CLIENT_SOURCE = 0, + ENTROPY_FILE_SOURCE, + SYSTEM_SOURCE, + USER_SOURCES /* Leave as last source */ +}; + + +/* Declare YARROWAPI as __declspec(dllexport) before + including this file in the actual DLL */ +#ifndef YARROWAPI +#if defined(macintosh) || defined(__APPLE__) +#define YARROWAPI +#else +#define YARROWAPI __declspec(dllimport) +#endif +#endif + +/* Public function forward declarations */ + +#if defined(macintosh) || defined(__APPLE__) +/* + * Mac changes: + * 1. PrngRef context for all functions. Thus no global variables. + * 2. Strong enum typing (prng_error_status instead of int return). + */ +struct PRNG; +typedef struct PRNG *PrngRef; + +YARROWAPI prng_error_status +prngInitialize( + PrngRef *prng); +YARROWAPI prng_error_status +prngDestroy( + PrngRef prng); +YARROWAPI prng_error_status +prngOutput( + PrngRef prng, + BYTE *outbuf, + UINT outbuflen); +/* this one has no context */ +YARROWAPI prng_error_status +prngStretch( + BYTE *inbuf, + UINT inbuflen, + BYTE *outbuf, + UINT outbuflen); +YARROWAPI prng_error_status +prngInput( + PrngRef prng, + BYTE *inbuf, + UINT inbuflen, + UINT poolnum, + UINT estbits); +YARROWAPI prng_error_status +prngForceReseed( + PrngRef prng, + LONGLONG ticks); +YARROWAPI prng_error_status +prngAllowReseed( + PrngRef prng, + LONGLONG ticks); +YARROWAPI prng_error_status +prngProcessSeedBuffer( + PrngRef prng, + BYTE *buf, + LONGLONG ticks); +YARROWAPI prng_error_status +prngSlowPoll( + PrngRef prng, + UINT pollsize); +#else +/* original Counterpane API */ +YARROWAPI int prngOutput(BYTE *outbuf,UINT outbuflen); +YARROWAPI int prngStretch(BYTE *inbuf,UINT inbuflen,BYTE *outbuf,UINT outbuflen); +YARROWAPI int prngInput(BYTE *inbuf,UINT inbuflen,UINT poolnum,UINT estbits); +YARROWAPI int prngForceReseed(LONGLONG ticks); +YARROWAPI int prngAllowReseed(LONGLONG ticks); +YARROWAPI int prngProcessSeedBuffer(BYTE *buf,LONGLONG ticks); +YARROWAPI int prngSlowPoll(UINT pollsize); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/iokit/IOKit/graphics/IOAccelClientConnect.h b/bsd/dev/random/YarrowCoreLib/include/yarrowUtils.h similarity index 60% rename from iokit/IOKit/graphics/IOAccelClientConnect.h rename to bsd/dev/random/YarrowCoreLib/include/yarrowUtils.h index 9f01fac37..c25314991 100644 --- a/iokit/IOKit/graphics/IOAccelClientConnect.h +++ b/bsd/dev/random/YarrowCoreLib/include/yarrowUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,25 +20,37 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef _IOACCEL_CLIENT_CONNECT_H -#define _IOACCEL_CLIENT_CONNECT_H +/* + File: yarrowUtils.h + Contains: Misc. utility functions. -/* -** The IOAccelerator service name -*/ -#define kIOAcceleratorClassName "IOAccelerator" + Written by: Doug Mitchell + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. -/* -** IOAccelerator public client types. Private client types start with -** kIOAccelNumClientTypes. + Change History (most recent first): + + 02/29/00 dpm Created. + */ -enum eIOAcceleratorClientTypes { - kIOAccelSurfaceClientType, - kIOAccelNumClientTypes, -}; +#ifndef _YARROW_UTILS_H_ +#define _YARROW_UTILS_H_ + +#include <dev/random/YarrowCoreLib/include/yarrow.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Wipe a piece of memory clean. + */ +void trashMemory(void* mem, int len); -#endif /* _IOACCEL_CLIENT_CONNECT_H */ +#ifdef __cplusplus +} +#endif +#endif /* _YARROW_UTILS_H_*/ diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnetHW.cpp b/bsd/dev/random/YarrowCoreLib/port/smf.c similarity index 51% rename from iokit/Drivers/network/drvMaceEnet/MaceEnetHW.cpp rename to bsd/dev/random/YarrowCoreLib/port/smf.c index 68f3c05a1..838a87601 100644 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnetHW.cpp +++ b/bsd/dev/random/YarrowCoreLib/port/smf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,28 +19,51 @@ * * @APPLE_LICENSE_HEADER_END@ */ + /* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Inline definitions for the Apple Mace Ethernet Controller. - * - * HISTORY - * - * 11-Sept-97 - * Created. - */ + File: smf.c + + Contains: platform-dependent malloc/free + +*/ + +#include <dev/random/YarrowCoreLib/src/smf.h> +#include <sys/malloc.h> + -#include "MaceEnetRegisters.h" -#include "MaceEnetPrivate.h" +SMFAPI void mmInit() +{ +} + +SMFAPI MMPTR mmMalloc(DWORD request) +{ + // since kfree requires that we pass in the alloc size, add enough bytes to store a dword + void* mem; + + mem = _MALLOC (request, M_DEVBUF, M_WAITOK); + + if (mem == 0) // oops, it didn't appear to work + { + printf ("Couldn't allocate kernel memory!\n"); + return 0; + } + + return (MMPTR) mem; +} -void WriteMaceRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset, u_int8_t data ) +SMFAPI void mmFree(MMPTR ptrnum) { - *((volatile u_int8_t *)ioEnetBase + reg_offset) = data; - eieio(); + // get the size of the pointer back + _FREE (ptrnum, M_DEVBUF); } +SMFAPI LPVOID mmGetPtr(MMPTR ptrnum) +{ + return (LPVOID)ptrnum; +} -volatile u_int8_t ReadMaceRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset ) +SMFAPI void mmReturnPtr(MMPTR ptrnum) { - return ((volatile u_int8_t *)ioEnetBase)[reg_offset] ; + /* nothing */ } + diff --git a/bsd/dev/random/YarrowCoreLib/src/assertverify.h b/bsd/dev/random/YarrowCoreLib/src/assertverify.h new file mode 100644 index 000000000..feff7245c --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/assertverify.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#ifndef ASSERT_VERIFY_H +#define ASSERT_VERIFY_H + +/****************************************************************************** +Written by: Jeffrey Richter +Notices: Copyright (c) 1995-1997 Jeffrey Richter +Purpose: Common header file containing handy macros and definitions used + throughout all the applications in the book. +******************************************************************************/ + +/* These header functions were copied from the cmnhdr.h file that accompanies + Advanced Windows 3rd Edition by Jeffrey Richter */ + +//////////////////////////// Assert/Verify Macros ///////////////////////////// + +#if defined(macintosh) || defined(__APPLE__) +/* TBD */ +#define chFAIL(szMSG) +#define chASSERTFAIL(file,line,expr) +#else +#define chFAIL(szMSG) { \ + MessageBox(GetActiveWindow(), szMSG, \ + __TEXT("Assertion Failed"), MB_OK | MB_ICONERROR); \ + DebugBreak(); \ + } + +/* Put up an assertion failure message box. */ +#define chASSERTFAIL(file,line,expr) { \ + TCHAR sz[128]; \ + wsprintf(sz, __TEXT("File %hs, line %d : %hs"), file, line, expr); \ + chFAIL(sz); \ + } + +#endif /* macintosh */ + +/* Put up a message box if an assertion fails in a debug build. */ +#ifdef _DEBUG +#define chASSERT(x) if (!(x)) chASSERTFAIL(__FILE__, __LINE__, #x) +#else +#define chASSERT(x) +#endif + +/* Assert in debug builds, but don't remove the code in retail builds. */ +#ifdef _DEBUG +#define chVERIFY(x) chASSERT(x) +#else +#define chVERIFY(x) (x) +#endif + +#endif /* ASSERT_VERIFY_H */ diff --git a/bsd/dev/random/YarrowCoreLib/src/comp.c b/bsd/dev/random/YarrowCoreLib/src/comp.c new file mode 100644 index 000000000..91c1844a0 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/comp.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: comp.c + + Contains: NULL compression. Kernel version of Yarrow assumes + incoming seed data is truly random. +*/ +#include "dev/random/YarrowCoreLib/include/WindowsTypesForMac.h" +#include "comp.h" + +#ifdef YARROW_KERNEL + +/* null compression */ +comp_error_status comp_init(COMP_CTX* ctx) +{ + return COMP_SUCCESS; +} + + +comp_error_status comp_add_data(COMP_CTX* ctx,Bytef* inp,uInt inplen) +{ + return COMP_SUCCESS; +} + +comp_error_status comp_get_ratio(COMP_CTX* ctx,float* out) +{ + *out = 1.0; + return COMP_SUCCESS; +} + +comp_error_status comp_end(COMP_CTX* ctx) +{ + return COMP_SUCCESS; +} + +#else + +/* original Yarrow compression, must be linked with zlib */ + +#if defined(macintosh) || defined(__APPLE__) +#include "WindowsTypesForMac.h" +#include "yarrowUtils.h" +#include <string.h> +#include <stdlib.h> +#else +#include <windows.h> +#endif +#include <math.h> +#include "comp.h" + +/* Check that the pointer is not NULL */ +#define PCHECK(ptr) if(ptr==NULL) {return COMP_ERR_NULL_POINTER;} +#define MMPCHECK(mmptr) if(mmptr==MM_NULL) {return COMP_ERR_NULL_POINTER;} +/* Check that the important parts of the context are ok */ +#define CTXCHECK(ctx) \ +PCHECK(ctx) \ +MMPCHECK(ctx->buf) + +/* Might want to vary these by context */ +#define BUFSIZE 16384 /* 16K */ +#define OUTBUFSIZE 16800 /* = inbufsize*1.01 + 12 (See zlib docs) */ +#define SHIFTSIZE 4096 /* BUFSIZE/4 */ + +#define _MIN(a,b) (((a)<(b))?(a):(b)) + + +/* Initialize these routines */ +comp_error_status comp_init(COMP_CTX* ctx) +{ + ctx->buf = mmMalloc(BUFSIZE); + if(ctx->buf == MM_NULL) {goto cleanup_comp_init;} + ctx->spaceused = 0; + + return COMP_SUCCESS; + +cleanup_comp_init: + mmFree(ctx->buf); + + return COMP_ERR_LOW_MEMORY; +} + + +comp_error_status comp_add_data(COMP_CTX* ctx,Bytef* inp,uInt inplen) +{ + uInt shifts; + uInt blocksize; + BYTE* buf; + + CTXCHECK(ctx); + PCHECK(inp); + + buf = (BYTE*)mmGetPtr(ctx->buf); + + if(inplen+SHIFTSIZE>BUFSIZE) + { + blocksize = _MIN(inplen,BUFSIZE); + memmove(buf,inp,blocksize); + ctx->spaceused = blocksize; + } + else + { + if(inplen+ctx->spaceused>BUFSIZE) + { + shifts = (uInt)ceil((inplen+ctx->spaceused-BUFSIZE)/(float)SHIFTSIZE); + blocksize = _MIN(shifts*SHIFTSIZE,ctx->spaceused); + memmove(buf,buf+blocksize,BUFSIZE-blocksize); + ctx->spaceused = ctx->spaceused - blocksize; + } + memmove(buf+ctx->spaceused,inp,inplen); + ctx->spaceused += inplen; + } + + return COMP_SUCCESS; +} + +comp_error_status comp_get_ratio(COMP_CTX* ctx,float* out) +{ + Bytef *inbuf,*outbuf; + uLong insize,outsize; + int resp; + + *out = 0; + + CTXCHECK(ctx); + PCHECK(out); + + if(ctx->spaceused == 0) {return COMP_SUCCESS;} + + inbuf = (Bytef*)mmGetPtr(ctx->buf); + outbuf = (Bytef*)malloc(OUTBUFSIZE); + if(outbuf==NULL) {return COMP_ERR_LOW_MEMORY;} + + insize = ctx->spaceused; + outsize = OUTBUFSIZE; + + resp = compress(outbuf,&outsize,inbuf,insize); + if(resp==Z_MEM_ERROR) {return COMP_ERR_LOW_MEMORY;} + if(resp==Z_BUF_ERROR) {return COMP_ERR_LIB;} + + *out = (float)outsize/(float)insize; + + /* Thrash the memory and free it */ + trashMemory(outbuf, OUTBUFSIZE); + free(outbuf); + + return COMP_SUCCESS; +} + +comp_error_status comp_end(COMP_CTX* ctx) +{ + if(ctx == NULL) {return COMP_SUCCESS;} /* Since nothing is left undone */ + + mmFree(ctx->buf); + ctx->buf = MM_NULL; + + return COMP_SUCCESS; +} + +#endif /* YARROW_KERNEL */ + diff --git a/bsd/dev/random/YarrowCoreLib/src/comp.h b/bsd/dev/random/YarrowCoreLib/src/comp.h new file mode 100644 index 000000000..e264e2c00 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/comp.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: comp.h + + Contains: Glue between core prng code to the Zlib library. + + Written by: Counterpane, Inc. + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created, based on Counterpane source. + +*/ +/* comp.h + + Header for the compression routines added to the Counterpane PRNG. +*/ + +#ifndef __YARROW_COMP_H__ +#define __YARROW_COMP_H__ + +#include "smf.h" + +/* + * Kernel version does NULL compression.... + */ +#define YARROW_KERNEL + +#ifdef YARROW_KERNEL +/* + * Shrink this down to almost nothing to simplify kernel port; + * with additional hacking on prng.c, this could go away entirely + */ +typedef char COMP_CTX; + +/* and define some type3s normally picked up from zlib */ +typedef unsigned char Bytef; +typedef unsigned uInt; + +#else + +#include "zlib.h" + +/* Top level compression context */ +typedef struct{ + MMPTR buf; + uInt spaceused; +} COMP_CTX; +#endif /* YARROW_KERNEL */ + +typedef enum comp_error_status { + COMP_SUCCESS = 0, + COMP_ERR_NULL_POINTER, + COMP_ERR_LOW_MEMORY, + COMP_ERR_LIB +} comp_error_status; + +/* Exported functions from compress.c */ +comp_error_status comp_init(COMP_CTX* ctx); +comp_error_status comp_add_data(COMP_CTX* ctx,Bytef* inp,uInt inplen); +comp_error_status comp_end(COMP_CTX* ctx); +comp_error_status comp_get_ratio(COMP_CTX* ctx,float* out); + +#endif diff --git a/iokit/Drivers/network/AppleBPF/AppleBPF.h b/bsd/dev/random/YarrowCoreLib/src/entropysources.h similarity index 59% rename from iokit/Drivers/network/AppleBPF/AppleBPF.h rename to bsd/dev/random/YarrowCoreLib/src/entropysources.h index 410cfb77a..ad9cfb2ec 100644 --- a/iokit/Drivers/network/AppleBPF/AppleBPF.h +++ b/bsd/dev/random/YarrowCoreLib/src/entropysources.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,31 +19,29 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * AppleBPF.h - BPF driver header file. - * - */ - -#ifndef _APPLEBPF_H -#define _APPLEBPF_H -#include <IOKit/IOService.h> +/* entropysources.h */ +/* This files contain the defination of the entropy sources */ -class AppleBPF : public IOService -{ - OSDeclareDefaultStructors(AppleBPF) +#ifndef __YARROW_ENTROPY_SOURCES_H__ +#define __YARROW_ENTROPY_SOURCES_H__ -private: - -public: - virtual bool init(OSDictionary * properties); - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); +#if defined(macintosh) || defined(__APPLE__) +/* + * In our implementation, all sources are user sources. + */ +enum entropy_sources { + ENTROPY_SOURCES = 0 }; +#else +enum entropy_sources { + KEYTIMESOURCE = 0, + MOUSETIMESOURCE, + MOUSEMOVESOURCE, + SLOWPOLLSOURCE, + ENTROPY_SOURCES, /* Leave as second to last source */ + MSG_CLOSE_PIPE /* Leave as last source */ +}; +#endif -/* What you get if you don't ask */ -#define DEFAULT_BPF_DEV_COUNT 4 - -/* define this if a (loadable) kernel extension */ -/* #define BPFDRV */ -#endif /* !_APPLEBPF_H */ +#endif diff --git a/iokit/IOKit/graphics/IOGraphicsEngine.h b/bsd/dev/random/YarrowCoreLib/src/macOnly.h similarity index 52% rename from iokit/IOKit/graphics/IOGraphicsEngine.h rename to bsd/dev/random/YarrowCoreLib/src/macOnly.h index 352fdec7f..ea1d86b42 100644 --- a/iokit/IOKit/graphics/IOGraphicsEngine.h +++ b/bsd/dev/random/YarrowCoreLib/src/macOnly.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,33 +19,45 @@ * * @APPLE_LICENSE_HEADER_END@ */ + /* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * 10 Mar 99 sdouglas created. - */ + File: macOnly.h + + Contains: Mac-specific #defines for Yarrow. + + Written by: Doug Mitchell + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + 02/10/99 dpm Created. + +*/ -struct IOGraphicsEngineContext { - IOSharedLockData contextLock; - IOOptionBits state; - void * owner; - UInt32 version; - IOByteCount structSize; - UInt32 reserved[ 8 ]; -}; -#ifndef __cplusplus -typedef volatile struct IOGraphicsEngineContext IOGraphicsEngineContext; +#if !defined(macintosh) && !defined(__APPLE__) +#error Hey, why are you including macOnly for a non-Mac build!? #endif -enum { - // memory type for IOMapMemory - kIOGraphicsEngineContext = 100 -}; +#ifndef _MAC_ONLY_H_ +#define _MAC_ONLY_H_ + +#include "dev/random/YarrowCoreLib/include/WindowsTypesForMac.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * No "slow poll" for Mac. + */ +#define SLOW_POLL_ENABLE 0 +#if SLOW_POLL_ENABLE +extern DWORD prng_slow_poll(BYTE* buf,UINT bufsize); +#endif /* SLOW_POLL_ENABLE */ + +#if defined(__cplusplus) +} +#endif -enum { - // version - kIOGraphicsEngineContextVersion = 1 -}; +#endif /* _MAC_ONLY_H_*/ diff --git a/bsd/dev/random/YarrowCoreLib/src/prng.c b/bsd/dev/random/YarrowCoreLib/src/prng.c new file mode 100644 index 000000000..aa9c23d6d --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/prng.c @@ -0,0 +1,624 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: prng.c + + Contains: Core routines for the Counterpane Yarrow PRNG. + + Written by: Counterpane, Inc. + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created, based on Counterpane source. + +*/ +/* + prng.c + + Core routines for the Counterpane PRNG +*/ +#include "userdefines.h" +#include "assertverify.h" +#include "dev/random/YarrowCoreLib/include/yarrowUtils.h" + +#if defined(macintosh) || defined(__APPLE__) +/* FIXME - this file needs to be in a platform-independent place */ + +#include <dev/random/YarrowCoreLib/include/macos_defs.h> + +#include "macOnly.h" +#endif /* macintosh */ +#include "smf.h" +#include "sha1mod.h" +#include "entropysources.h" +#include "comp.h" +#include "dev/random/YarrowCoreLib/include/yarrow.h" +#include "prng.h" +#include "prngpriv.h" + + +#define _MAX(a,b) (((a)>(b))?(a):(b)) +#define _MIN(a,b) (((a)<(b))?(a):(b)) + +#if defined(macintosh) || defined(__APPLE__) +/* + * No mutexes in this module for Macintosh/OSX. We handle the + * required locking elsewhere. + */ +#define MUTEX_ENABLE 0 + +#include <string.h> /* memcpy, etc. */ +#if TARGET_API_MAC_OSX + #include <sys/time.h> /* for timespec */ +#elif TARGET_API_MAC_CARBON + #include <Timer.h> /* Microseconds */ + #include <Math64.h> +#elif KERNEL_BUILD + #include <sys/time.h> +#else + #error Unknown TARGET_API +#endif /* TARGET_API */ +#else +#define MUTEX_ENABLE 1 +#endif /* macintosh */ + +#if MUTEX_ENABLE +static HANDLE Statmutex = NULL; +static DWORD mutexCreatorId = 0; +#endif + +#pragma mark - +#pragma mark * * * Static Utility functions * * * + +/* All error checking should be done in the function that calls these */ + +/* + * out := SHA1(IV | out) + */ +static void +prng_do_SHA1(GEN_CTX *ctx) +{ + SHA1_CTX sha; + + SHA1Init(&sha); + SHA1Update(&sha,ctx->IV,20); + SHA1Update(&sha,ctx->out,20); + SHA1Final(ctx->out,&sha); + ctx->index = 0; +} + +/* + * IV := newState + * out := SHA1(IV) + * + * Called from init, prngForceReseed(), and prngOutput() + * as anti-backtracking mechanism. + */ +static void +prng_make_new_state(GEN_CTX *ctx,BYTE *newState) +{ + SHA1_CTX sha; + + memcpy(ctx->IV,newState,20); + SHA1Init(&sha); + SHA1Update(&sha,ctx->IV,20); + SHA1Final(ctx->out,&sha); + ctx->numout = 0; + ctx->index = 0; +} + +#if SLOW_POLL_ENABLE + + +/* Initialize the secret state with a slow poll */ +/* Currently only called from prngInitialize */ + +#define SPLEN 65536 /* 64K */ + +static void +prng_slow_init(PRNG *p) +/* This fails silently and must be fixed. */ +{ + SHA1_CTX* ctx = NULL; + MMPTR mmctx = MM_NULL; + BYTE* bigbuf = NULL; + MMPTR mmbigbuf = MM_NULL; + BYTE* buf = NULL; + MMPTR mmbuf = MM_NULL; + DWORD polllength; + + mmbigbuf = mmMalloc(SPLEN); + if(mmbigbuf == MM_NULL) {goto cleanup_slow_init;} + bigbuf = (BYTE*)mmGetPtr(mmbigbuf); + + mmbuf = mmMalloc(20); + if(mmbuf == MM_NULL) {goto cleanup_slow_init;} + buf = (BYTE*)mmGetPtr(mmbuf); + + mmctx = mmMalloc(sizeof(SHA1_CTX)); + if(mmctx == MM_NULL) {goto cleanup_slow_init;} + ctx = (SHA1_CTX*)mmGetPtr(mmctx); + + + /* Initialize the secret state. */ + /* Init entropy pool */ + SHA1Init(&p->pool); + /* Init output generator */ + polllength = prng_slow_poll(bigbuf,SPLEN); + SHA1Init(ctx); + SHA1Update(ctx,bigbuf,polllength); + SHA1Final(buf,ctx); + prng_make_new_state(&p->outstate, buf); + +cleanup_slow_init: + mmFree(mmctx); + mmFree(mmbigbuf); + mmFree(mmbuf); + + return; +} + +#endif /* SLOW_POLL_ENABLE */ + +/* In-place modifed bubble sort */ +static void +bubbleSort(UINT *data,UINT len) +{ + UINT i,last,newlast,temp; + + last = len-1; + while(last!=-1) + { + newlast = -1; + for(i=0;i<last;i++) + { + if(data[i+1] > data[i]) + { + newlast = i; + temp = data[i]; + data[i] = data[i+1]; + data[i+1] = temp; + } + } + last = newlast; + } +} + +#pragma mark - +#pragma mark * * * Public functions * * * + +/* Set up the PRNG */ +prng_error_status +prngInitialize(PrngRef *prng) +{ + UINT i; + comp_error_status resp; + prng_error_status retval = PRNG_ERR_LOW_MEMORY; + MMPTR mmp; + PRNG *p; + + mmInit(); + + #if MUTEX_ENABLE + /* Create the mutex */ + /* NOTE: on return the mutex should bve held, since our caller (prngInitialize) + * will release it. + */ + if(mutexCreatorId!=0) {return PRNG_ERR_REINIT;} + Statmutex = CreateMutex(NULL,TRUE,NULL); + if(Statmutex == NULL) {mutexCreatorId = 0; return PRNG_ERR_MUTEX;} + DuplicateHandle(GetCurrentProcess(),Statmutex,GetCurrentProcess(),&mutex,SYNCHRONIZE,FALSE,0); + mutexCreatorId = GetCurrentProcessId(); + #endif /* MUTEX_ENABLE */ + + /* Assign memory */ + mmp = mmMalloc(sizeof(PRNG)); + if(mmp==MM_NULL) + { + goto cleanup_init; + } + else + { + p = (PRNG*)mmGetPtr(mmp); + memset(p, 0, sizeof(PRNG)); + } + + /* Initialize Variables */ + for(i=0;i<TOTAL_SOURCES;i++) + { + p->poolSize[i] = 0; + p->poolEstBits[i] = 0; + } + +#ifdef WIN_NT + /* Setup security on the registry so that remote users cannot predict the slow pool */ + prng_set_NT_security(); +#endif + + /* Initialize the secret state. */ + /* FIXME - might want to make this an option here and have the caller + * do it after we return....? */ + SHA1Init(&p->pool); +#if SLOW_POLL_ENABLE + prng_slow_init(p); /* Does a slow poll and then calls prng_make_state(...) */ +#else + /* NULL init */ + prng_do_SHA1(&p->outstate); + prng_make_new_state(&p->outstate, p->outstate.out); +#endif /* SLOW_POLL_ENABLE */ + + /* Initialize compression routines */ + for(i=0;i<COMP_SOURCES;i++) + { + resp = comp_init((p->comp_state)+i); + if(resp!=COMP_SUCCESS) {retval = PRNG_ERR_COMPRESSION; goto cleanup_init;} + } + + p->ready = PRNG_READY; + *prng = (PrngRef)p; + + return PRNG_SUCCESS; + +cleanup_init: + /* Program failed on one of the mmmallocs */ + mmFree(mmp); + mmp = MM_NULL; + + #if MUTEX_ENABLE + CloseHandle(Statmutex); + Statmutex = NULL; + mutexCreatorId = 0; + #endif + + return retval; /* default PRNG_ERR_LOW_MEMORY */ +} + +/* Provide output */ +prng_error_status +prngOutput(PRNG *p, BYTE *outbuf,UINT outbuflen) +{ + UINT i; + GEN_CTX *ctx = &p->outstate; + + CHECKSTATE(p); + GENCHECK(p); + PCHECK(outbuf); + chASSERT(BACKTRACKLIMIT > 0); + + for(i=0;i<outbuflen;i++,ctx->index++,ctx->numout++) + { + /* Check backtracklimit */ + if(ctx->numout > BACKTRACKLIMIT) + { + prng_do_SHA1(ctx); + prng_make_new_state(ctx, ctx->out); + } + /* Check position in IV */ + if(ctx->index>=20) + { + prng_do_SHA1(ctx); + } + /* Output data */ + outbuf[i] = (ctx->out)[ctx->index]; + } + + return PRNG_SUCCESS; +} + + +/* Cause the PRNG to reseed now regardless of entropy pool */ +/* Should this be public? */ +prng_error_status +prngForceReseed(PRNG *p, LONGLONG ticks) +{ + int i; +#ifdef WIN_NT + FILETIME a,b,c,usertime; +#endif + BYTE buf[64]; + BYTE dig[20]; +#if defined(macintosh) || defined(__APPLE__) + #if (defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD)) + struct timeval tv; + int32_t endTime; + #else TARGET_API_MAC_CARBON + UnsignedWide uwide; /* struct needed for Microseconds() */ + LONGLONG start; + LONGLONG now; + #endif +#endif + + CHECKSTATE(p); + POOLCHECK(p); + ZCHECK(ticks); + + /* Set up start and end times */ + #if defined(macintosh) || defined(__APPLE__) + #if (defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD)) + /* note we can't loop for more than a million microseconds */ + #ifdef KERNEL_BUILD + microtime (&tv); + #else + gettimeofday(&tv, NULL); + #endif + endTime = tv.tv_usec + ticks; + if(endTime > 1000000) { + /* handle rollover now */ + endTime -= 1000000; + } + #else /* TARGET_API_MAC_OSX */ + Microseconds(&uwide); + start = UnsignedWideToUInt64(uwide); + #endif /* TARGET_API_xxx */ + #endif /* macintosh */ + do + { + /* Do a couple of iterations between time checks */ + prngOutput(p, buf,64); + SHA1Update(&p->pool,buf,64); + prngOutput(p, buf,64); + SHA1Update(&p->pool,buf,64); + prngOutput(p, buf,64); + SHA1Update(&p->pool,buf,64); + prngOutput(p, buf,64); + SHA1Update(&p->pool,buf,64); + prngOutput(p, buf,64); + SHA1Update(&p->pool,buf,64); + +#if defined(macintosh) || defined(__APPLE__) + #if defined(TARGET_API_MAC_OSX) || defined(KERNEL_BUILD) + #ifdef TARGET_API_MAC_OSX + gettimeofday(&tv, NULL); + #else + microtime (&tv); + #endif + } while(tv.tv_usec < endTime); + #else + Microseconds(&uwide); + now = UnsignedWideToUInt64(uwide); + } while ( (now-start) < ticks) ; + #endif +#else + } while ( (now-start) < ticks) ; +#endif + SHA1Final(dig,&p->pool); + SHA1Update(&p->pool,dig,20); + SHA1Final(dig,&p->pool); + + /* Reset secret state */ + SHA1Init(&p->pool); + prng_make_new_state(&p->outstate,dig); + + /* Clear counter variables */ + for(i=0;i<TOTAL_SOURCES;i++) + { + p->poolSize[i] = 0; + p->poolEstBits[i] = 0; + } + + /* Cleanup memory */ + trashMemory(dig,20*sizeof(char)); + trashMemory(buf,64*sizeof(char)); + + return PRNG_SUCCESS; +} + + +/* Input a state into the PRNG */ +prng_error_status +prngProcessSeedBuffer(PRNG *p, BYTE *buf,LONGLONG ticks) +{ + CHECKSTATE(p); + GENCHECK(p); + PCHECK(buf); + + /* Put the data into the entropy, add some data from the unknown state, reseed */ + SHA1Update(&p->pool,buf,20); /* Put it into the entropy pool */ + prng_do_SHA1(&p->outstate); /* Output 20 more bytes and */ + SHA1Update(&p->pool,p->outstate.out,20);/* add it to the pool as well. */ + prngForceReseed(p, ticks); /* Do a reseed */ + return prngOutput(p, buf,20); /* Return the first 20 bytes of output in buf */ +} + + +/* Take some "random" data and make more "random-looking" data from it */ +/* note: this routine has no context, no mutex wrapper */ +prng_error_status +prngStretch(BYTE *inbuf,UINT inbuflen,BYTE *outbuf,UINT outbuflen) { + long int left,prev; + SHA1_CTX ctx; + BYTE dig[20]; + + PCHECK(inbuf); + PCHECK(outbuf); + + if(inbuflen >= outbuflen) + { + memcpy(outbuf,inbuf,outbuflen); + return PRNG_SUCCESS; + } + else /* Extend using SHA1 hash of inbuf */ + { + SHA1Init(&ctx); + SHA1Update(&ctx,inbuf,inbuflen); + SHA1Final(dig,&ctx); + for(prev=0,left=outbuflen;left>0;prev+=20,left-=20) + { + SHA1Update(&ctx,dig,20); + SHA1Final(dig,&ctx); + memcpy(outbuf+prev,dig,(left>20)?20:left); + } + trashMemory(dig,20*sizeof(BYTE)); + + return PRNG_SUCCESS; + } + + return PRNG_ERR_PROGRAM_FLOW; +} + + +/* Add entropy to the PRNG from a source */ +prng_error_status +prngInput(PRNG *p, BYTE *inbuf,UINT inbuflen,UINT poolnum,UINT estbits) +{ + #ifndef YARROW_KERNEL + comp_error_status resp; + #endif + + CHECKSTATE(p); + POOLCHECK(p); + PCHECK(inbuf); + if(poolnum >= TOTAL_SOURCES) {return PRNG_ERR_OUT_OF_BOUNDS;} + + /* Add to entropy pool */ + SHA1Update(&p->pool,inbuf,inbuflen); + + #ifndef YARROW_KERNEL + /* skip this step for the kernel */ + + /* Update pool size, pool user estimate and pool compression context */ + p->poolSize[poolnum] += inbuflen; + p->poolEstBits[poolnum] += estbits; + if(poolnum<COMP_SOURCES) + { + resp = comp_add_data((p->comp_state)+poolnum,inbuf,inbuflen); + if(resp!=COMP_SUCCESS) {return PRNG_ERR_COMPRESSION;} + } + #endif /* YARROW_KERNEL */ + + return PRNG_SUCCESS; +} + + + +/* If we have enough entropy, allow a reseed of the system */ +prng_error_status +prngAllowReseed(PRNG *p, LONGLONG ticks) +{ + UINT temp[TOTAL_SOURCES]; + UINT i,sum; +#ifndef KERNEL_BUILD + float ratio; +#endif + + comp_error_status resp; + + + CHECKSTATE(p); + + for(i=0;i<ENTROPY_SOURCES;i++) + { + /* Make sure that compression-based entropy estimates are current */ +#ifndef KERNEL_BUILD // floating point in a kernel is BAD! + resp = comp_get_ratio((p->comp_state)+i,&ratio); + if(resp!=COMP_SUCCESS) {return PRNG_ERR_COMPRESSION;} + /* Use 4 instead of 8 to half compression estimate */ + temp[i] = (int)(ratio*p->poolSize[i]*4); +#else + temp[i] = p->poolSize[i] * 4; +#endif + + } + /* Use minumum of user and compression estimate for compressed sources */ + for(i=ENTROPY_SOURCES;i<COMP_SOURCES;i++) + { +#ifndef KERNEL_BUILD + /* Make sure that compression-based entropy estimates are current */ + resp = comp_get_ratio((p->comp_state)+i,&ratio); + if(resp!=COMP_SUCCESS) {return PRNG_ERR_COMPRESSION;} + /* Use 4 instead of 8 to half compression estimate */ + temp[i] = _MIN((int)(ratio*p->poolSize[i]*4),(int)p->poolEstBits[i]); +#else + temp[i] = _MIN (p->poolSize[i] * 4, p->poolEstBits[i]); +#endif + + } + /* Use user estimate for remaining sources */ + for(i=COMP_SOURCES;i<TOTAL_SOURCES;i++) {temp[i] = p->poolEstBits[i];} + + if(K > 0) { + /* pointless if we're not ignoring any sources */ + bubbleSort(temp,TOTAL_SOURCES); + } + for(i=K,sum=0;i<TOTAL_SOURCES;sum+=temp[i++]); /* Stupid C trick */ + if(sum>THRESHOLD) + return prngForceReseed(p, ticks); + else + return PRNG_ERR_NOT_ENOUGH_ENTROPY; + + return PRNG_ERR_PROGRAM_FLOW; +} + +#if SLOW_POLL_ENABLE +/* Call a slow poll and insert the data into the entropy pool */ +static prng_error_status +prngSlowPoll(PRNG *p, UINT pollsize) +{ + BYTE *buf; + DWORD len; + prng_error_status retval; + + CHECKSTATE(p); + + buf = (BYTE*)malloc(pollsize); + if(buf==NULL) {return PRNG_ERR_LOW_MEMORY;} + len = prng_slow_poll(buf,pollsize); /* OS specific call */ + retval = prngInput(p, buf,len,SLOWPOLLSOURCE, len * 8); + trashMemory(buf,pollsize); + free(buf); + + return retval; +} +#endif /* SLOW_POLL_ENABLE */ + + +/* Delete the PRNG */ +prng_error_status +prngDestroy(PRNG *p) +{ + UINT i; + + #if MUTEX_ENABLE + if(GetCurrentProcessId()!=mutexCreatorId) {return PRNG_ERR_WRONG_CALLER;} + #endif + if(p==NULL) {return PRNG_SUCCESS;} /* Well, there is nothing to destroy... */ + + p->ready = PRNG_NOT_READY; + + for(i=0;i<COMP_SOURCES;i++) + { + comp_end((p->comp_state)+i); + } + + #if MUTEX_ENABLE + CloseHandle(Statmutex); + Statmutex = NULL; + mutexCreatorId = 0; + #endif + + return PRNG_SUCCESS; +} + + diff --git a/bsd/dev/random/YarrowCoreLib/src/prng.h b/bsd/dev/random/YarrowCoreLib/src/prng.h new file mode 100644 index 000000000..8524068a6 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/prng.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: prng.h + + Contains: Core routines for the Counterpane Yarrow PRNG. + + Written by: Counterpane, Inc. + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created, based on Counterpane source. + +*/ +/* + prng.h + + Main private header for the Counterpane PRNG. Use this to be able access the + initialization and destruction routines from the DLL. +*/ + +#ifndef __YARROW_PRNG_H__ +#define __YARROW_PRNG_H__ + +#if defined(macintosh) || defined(__APPLE__) +#include "dev/random/YarrowCoreLib/include/yarrow.h" +/* Private function forward declarations */ +// this is in yarrow.h...YARROWAPI prng_error_status prngInitialize(void); +// ditto.... YARROWAPI prng_error_status prngDestroy(void); +YARROWAPI prng_error_status prngInputEntropy(PrngRef prng, BYTE *inbuf,UINT inbuflen,UINT poolnum); +#else /* original yarrow code */ +/* Declare YARROWAPI as __declspec(dllexport) before + including this file in the actual DLL */ +#ifndef YARROWAPI +#define YARROWAPI __declspec(dllimport) +#endif + +/* Private function forward declarations */ +YARROWAPI int prngInitialize(void); +YARROWAPI int prngDestroy(void); +YARROWAPI int prngInputEntropy(BYTE *inbuf,UINT inbuflen,UINT poolnum); + +#endif /* macintosh */ +#endif /* __YARROW_PRNG_H__ */ diff --git a/bsd/dev/random/YarrowCoreLib/src/prngpriv.h b/bsd/dev/random/YarrowCoreLib/src/prngpriv.h new file mode 100644 index 000000000..e2919d0d2 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/prngpriv.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: prngpriv.h + + Contains: Private typedefs and #defines for Counterpane Yarrow PRNG. + + Written by: Counterpane, Inc. + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/99 dpm Created, based on Counterpane source. + +*/ +/* + prngpriv.h + + Completely private header for the Counterpane PRNG. Should only be included by prng.c +*/ + +#ifndef __YARROW_PRNG_PRIV_H__ +#define __YARROW_PRNG_PRIV_H__ + +#include "userdefines.h" +#include "dev/random/YarrowCoreLib/include/yarrow.h" +#include "entropysources.h" +#include "comp.h" +#include "sha1mod.h" +#include "smf.h" + +#define TOTAL_SOURCES ENTROPY_SOURCES+USER_SOURCES + +#ifdef COMPRESSION_ON +#define COMP_SOURCES TOTAL_SOURCES +#else +#define COMP_SOURCES ENTROPY_SOURCES +#endif + +/* Error numbers */ +typedef enum prng_ready_status { + PRNG_READY = 33, /* Compiler will initialize to either 0 or random if allowed to */ + PRNG_NOT_READY = 0 +} prng_ready_status; + +/* Top level output state */ +typedef struct{ + BYTE IV[20]; + BYTE out[20]; + UINT index; /* current byte to output */ + UINT numout; /* bytes since last prng_make_new_state */ +} GEN_CTX; + +/* PRNG state structure */ +struct PRNG { + /* Output State */ + GEN_CTX outstate; + + /* Entropy Pools (somewhat unlike a gene pool) */ + SHA1_CTX pool; + UINT poolSize[TOTAL_SOURCES]; /* Note that size is in bytes and est in bits */ + UINT poolEstBits[TOTAL_SOURCES]; + COMP_CTX comp_state[COMP_SOURCES]; + + /* Status Flags */ + prng_ready_status ready; +}; + +/* + * Clients see an opaque PrngRef; internal code uses the + * following typedef. + */ +typedef struct PRNG PRNG; + + +/* Test Macros */ +#define CHECKSTATE(p) \ +if(p==NULL) {return PRNG_ERR_NOT_READY;} /* Does the state exist? */ \ +if(p->ready != PRNG_READY) {return PRNG_ERR_NOT_READY;} /* Set error state and return */ +/* To make sure that a pointer isn't NULL */ +#define PCHECK(ptr) if(ptr==NULL) {return PRNG_ERR_NULL_POINTER;} +/* To make sure that malloc returned a valid value */ +#define MCHECK(ptr) if(ptr==NULL) {return PRNG_ERR_LOW_MEMORY;} +/* To make sure that a given value is non-negative */ +#if defined(macintosh) || defined(__APPLE__) +/* original looks like a bogon */ +#define ZCHECK(val) if(val<0) {return PRNG_ERR_OUT_OF_BOUNDS;} +#else +#define ZCHECK(val) if(p<0) {return PRNG_ERR_OUT_OF_BOUNDS;} +#endif /* macintosh */ +/* To make sure that the generator state is valid */ +#define GENCHECK(p) if(p->outstate.index>20) {return PRNG_ERR_OUT_OF_BOUNDS;} /* index is unsigned */ +/* To make sure that the entropy pool is valid */ +#define POOLCHECK(p) /* */ + + +#endif diff --git a/bsd/dev/random/YarrowCoreLib/src/readme-prnguser.txt b/bsd/dev/random/YarrowCoreLib/src/readme-prnguser.txt new file mode 100644 index 000000000..c7b41fff8 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/readme-prnguser.txt @@ -0,0 +1,90 @@ +12345678901234567890123456789012345678901234567890123456789012345678901234567890 + +Description of User Routines in Prngcore +---------------------------------------------- + +This files describes routines in prngcore that are designed to be called by the +user (ie client apps). Those interested in the details of the library are +directed to readme-prngcoder. + +Files of interest in this directory +----------------------------------- + +yarrow.h + +Main header file (and the only one needed) for client apps. + +userdefines.h + +Header file with macros that can be defined to specify the system that this +code is being compiled on, as well as other details of the prng operation. + +usersources.h + +Header file containing the names of the various user sources of entropic data. +You can add/delete/rename sources by altering the entries in the enumeration. + + +PRNG Client Routines +-------------------- + +All major routines return the success/error value for their operation. + +prngOutput(outbuf,outbuflen) + +Writes outbuflen worth of "random" data to outbuf. This routine has +backtracking protection, but you should call prngAllowReseed whenever you can +spare the cycles to guarantee good output. + +prngStretch(inbuf,inbuflen,outbuf,outbuflen) + +Takes inbuflen bytes of data from inbuf and turns it into outbuflen bytes of +data stored in outbuf. + +prngInput(inbuf,inbuflen,poolnum,estbits) + +Takes inbuflen bytes of data from inbuf and places it in entropy pool poolnum. +The user entropy pool names can be found in usersources.h (see above). + +prngForceReseed(ticks) + +Forces a reseed that lasts about ticks ticks long. Be very careful when using +this function to ensure that you do not produce a poor output state. It is +suggested that you instead use prngAllowReseed. + +prngAllowReseed(ticks) + +Will force a reseed if there is enough entropy. A reseed (of length ticks) +will be done if the total entropy estimate, ignoring the K greatest sources, +is greater than THRESHOLD. Currently, K = 0 (a bad idea) and THRESHOLD = 100 +(likely to remain so). These values can be found and edited in userdefines.h. +Will return PRNG_ERR_NOT_ENOUGH_ENTROPY if there is not enough entropy in the +pool at this time. + +prngProcessSeedBuffer(buf,ticks) + +Takes 20 bytes of data from buf and churns it into the entropy pool, and then +forces a reseed of length ticks. The first 20 bytes of output are then +returned in buf for future use with this function. It is recommended that data +used with this function be stored very securely. + +prngSlowPoll(pollsize) + +Does a slow poll to collect a large amount of vaguely random data from the OS +itself. The poll with collect at most pollsize bytes, and this parameter can +be used to control (approximately) the length of the poll. The collected data +is fed into the entropy pool. After calling this function you may call either +allow (recommended) or force a reseed if desired. + +-------- + +Any questions can be directed to the programmer (me), Ari Benbasat, at +pigsfly@unixg.ubc.ca. Comments would be greatly appreciated. Please cc: all +e-mail to Bruce Schneier, John Kelsey and Chris Hall +{schneier,kelsey,hall}@counterpane.com. + +Thank you. + + + +i diff --git a/bsd/dev/random/YarrowCoreLib/src/sha1mod.c b/bsd/dev/random/YarrowCoreLib/src/sha1mod.c new file mode 100644 index 000000000..03dfa5a23 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/sha1mod.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* +SHA-1 in C +By Steve Reid <steve@edmweb.com> +100% Public Domain +*/ +/* Header portion split from main code for convenience (AYB 3/02/98) */ +#include "sha1mod.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* + * Apple change... + */ +#if defined(macintosh) || defined (__APPLE__) +#undef LITTLE_ENDIAN +#endif + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#ifdef LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(unsigned long state[5], unsigned char buffer[64]) +{ +unsigned long a, b, c, d, e; +typedef union { + unsigned char c[64]; + unsigned long l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) +{ +unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned long i, j; +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + + +/*************************************************************/ + +/* Test Code */ + +#if 0 + +int main(int argc, char** argv) +{ +int i, j; +SHA1_CTX context; +unsigned char digest[20], buffer[16384]; +FILE* file; + + if (argc > 2) { + puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>"); + puts("Produces the SHA-1 hash of a file, or stdin if no file is specified."); + exit(0); + } + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + exit(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + for (i = 0; i < 5; i++) { + for (j = 0; j < 4; j++) { + printf("%02X", digest[i*4+j]); + } + putchar(' '); + } + putchar('\n'); + exit(0); +} + +#endif diff --git a/bsd/dev/random/YarrowCoreLib/src/sha1mod.h b/bsd/dev/random/YarrowCoreLib/src/sha1mod.h new file mode 100644 index 000000000..839168e8b --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/sha1mod.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* +SHA-1 in C +By Steve Reid <steve@edmweb.com> +100% Public Domain +*/ +/* Header portion split from main code for convenience (AYB 3/02/98) */ + +#ifndef __SHA1_H__ + +#define __SHA1_H__ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* Apple change - define this in the source file which uses it */ +/* #define LITTLE_ENDIAN This should be #define'd if true. */ +#define SHA1HANDSOFF /* Copies data before messing with it. */ + +//Context declaration +typedef struct { + unsigned long state[5]; + unsigned long count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +//Function forward declerations +void SHA1Transform(unsigned long state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#endif /* __SHA1_H__ */ diff --git a/bsd/dev/random/YarrowCoreLib/src/smf.h b/bsd/dev/random/YarrowCoreLib/src/smf.h new file mode 100644 index 000000000..538b815f4 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/smf.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + File: smf.h + + Contains: Secure malloc/free API. + + Written by: Doug Mitchell + + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. + + Change History (most recent first): + + 02/10/00 dpm Created, based on Counterpane's Yarrow code. + +*/ + +#ifndef _YARROW_SMF_H_ +#define _YARROW_SMF_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* smf.h */ + + /* + Header file for secure malloc and free routines used by the Counterpane + PRNG. Use this code to set up a memory-mapped file out of the system + paging file, allocate and free memory from it, and then return + the memory to the system registry after having securely overwritten it. + Details of the secure overwrite can be found in Gutmann 1996 (Usenix). + Trying to explain it here will cause my head to begin to hurt. + Ari Benbasat (pigsfly@unixg.ubc.ca) + */ + + + +#if defined(macintosh) || defined(__APPLE__) +#include "macOnly.h" +#define MMPTR void * + +#ifndef SMFAPI +#define SMFAPI +#endif + +#else /* original Yarrow */ + +/* Declare HOOKSAPI as __declspec(dllexport) before + including this file in the actual DLL */ +#ifndef SMFAPI +#define SMFAPI __declspec(dllimport) +#endif +#define MMPTR BYTE + +#endif /* macintosh */ + + +#define MM_NULL 0 + +/* Function forward declarations */ +SMFAPI void mmInit(); +SMFAPI MMPTR mmMalloc(DWORD request); +SMFAPI void mmFree(MMPTR ptrnum); +SMFAPI LPVOID mmGetPtr(MMPTR ptrnum); +SMFAPI void mmReturnPtr(MMPTR ptrnum); +#if 0 +SMFAPI void mmFreePtr(LPVOID ptr); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* _YARROW_SMF_H_*/ diff --git a/bsd/dev/random/YarrowCoreLib/src/userdefines.h b/bsd/dev/random/YarrowCoreLib/src/userdefines.h new file mode 100644 index 000000000..9ca48cc25 --- /dev/null +++ b/bsd/dev/random/YarrowCoreLib/src/userdefines.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +/* + userdefines.h + + Header file that contains the major user-defineable quantities for the Counterpane PRNG. +*/ +#ifndef __YARROW_USER_DEFINES_H__ +#define __YARROW_USER_DEFINES_H__ + +/* User-alterable define statements */ +#define STRICT /* Define to force strict type checking */ +#define K 0 /* How many sources should we ignore when calculating total entropy? */ +#define THRESHOLD 100 /* Minimum amount of entropy for a reseed */ +#define BACKTRACKLIMIT 500 /* Number of outputed bytes after which to generate a new state */ +#define COMPRESSION_ON /* Define this variable to add on-the-fly compression (recommended) */ + /* for user sources */ +#if !defined(macintosh) && !defined(__APPLE__) +#define WIN_95 /* Choose an OS: WIN_95, WIN_NT */ +#endif + +/* Setup Microsoft flag for NT4.0 */ +#ifdef WIN_NT +#define _WIN32_WINNT 0x0400 +#endif + +#endif /* __YARROW_USER_DEFINES_H__ */ diff --git a/iokit/Families/IONDRVSupport/IOPEFLibraries.h b/bsd/dev/random/YarrowCoreLib/src/yarrowUtils.c similarity index 55% rename from iokit/Families/IONDRVSupport/IOPEFLibraries.h rename to bsd/dev/random/YarrowCoreLib/src/yarrowUtils.c index 897316898..a441c2780 100644 --- a/iokit/Families/IONDRVSupport/IOPEFLibraries.h +++ b/bsd/dev/random/YarrowCoreLib/src/yarrowUtils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,44 +19,38 @@ * * @APPLE_LICENSE_HEADER_END@ */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * Simon Douglas 22 Oct 97 - * - first checked in. - */ +/* + File: yarrowUtils.c -#include <IOKit/ndrvsupport/IOMacOSTypes.h> + Contains: Misc. utility functions. -#ifdef __cplusplus -extern "C" { -#endif + Written by: Doug Mitchell + Copyright: (c) 2000 by Apple Computer, Inc., all rights reserved. -struct FunctionEntry -{ - char * name; - LogicalAddress address; - LogicalAddress toc; -}; -typedef struct FunctionEntry FunctionEntry; + Change History (most recent first): -struct LibraryEntry -{ - char * name; - ItemCount numSyms; - FunctionEntry * functions; -}; -typedef struct LibraryEntry LibraryEntry; + 02/29/00 dpm Created. + +*/ -extern LibraryEntry IONDRVLibraries[]; -extern const ItemCount IONumNDRVLibraries; +#include "dev/random/YarrowCoreLib/include/yarrowUtils.h" -#ifdef __cplusplus +void +trashMemory(void* mem, int len) +/* This function should only be used on data in RAM */ +{ + if(len == 0) { + /* some memsets really don't like this */ + return; + } + + /* Cycle a bit just in case it is one of those weird memory units */ + /* No, I don't know which units those would be */ + memset(mem,0x00,len); + memset(mem,0xFF,len); + memset(mem,0x00,len); } -#endif + diff --git a/bsd/dev/random/randomdev.c b/bsd/dev/random/randomdev.c new file mode 100644 index 000000000..642add668 --- /dev/null +++ b/bsd/dev/random/randomdev.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/conf.h> +#include <sys/fcntl.h> +#include <miscfs/devfs/devfs.h> +#include <kern/lock.h> +#include <kern/task.h> +#include <kern/thread.h> +#include <sys/time.h> +#include <sys/malloc.h> + +#include <dev/random/randomdev.h> +#include <dev/random/YarrowCoreLib/include/yarrow.h> + +#define RANDOM_MAJOR -1 /* let the kernel pick the device number */ + +/* + * A struct describing which functions will get invoked for certain + * actions. + */ +static struct cdevsw random_cdevsw = +{ + random_open, /* open */ + random_close, /* close */ + random_read, /* read */ + random_write, /* write */ + eno_ioctl, /* ioctl */ + nulldev, /* stop */ + nulldev, /* reset */ + NULL, /* tty's */ + eno_select, /* select */ + eno_mmap, /* mmap */ + eno_strat, /* strategy */ + eno_getc, /* getc */ + eno_putc, /* putc */ + 0 /* type */ +}; + +/* Used to detect whether we've already been initialized */ +static int gRandomInstalled = 0; +static PrngRef gPrngRef; +static int gRandomError = 1; +static mutex_t *gYarrowMutex = 0; + +#define RESEED_TICKS 50 /* how long a reseed operation can take */ + +/* + *Initialize ONLY the Yarrow generator. + */ +void PreliminarySetup () +{ + prng_error_status perr; + struct timeval tt; + char buffer [16]; + + /* create a Yarrow object */ + perr = prngInitialize(&gPrngRef); + if (perr != 0) { + printf ("Couldn't initialize Yarrow, /dev/random will not work.\n"); + return; + } + + /* clear the error flag, reads and write should then work */ + gRandomError = 0; + + /* get a little non-deterministic data as an initial seed. */ + microtime(&tt); + + /* + * So how much of the system clock is entropic? + * It's hard to say, but assume that at least the + * least significant byte of a 64 bit structure + * is entropic. It's probably more, how can you figure + * the exact time the user turned the computer on, for example. + */ + perr = prngInput(gPrngRef, (BYTE*) &tt, sizeof (tt), SYSTEM_SOURCE, 8); + if (perr != 0) { + /* an error, complain */ + printf ("Couldn't seed Yarrow.\n"); + return; + } + + /* turn the data around */ + perr = prngOutput(gPrngRef, (BYTE*) buffer, sizeof (buffer)); + + /* and scramble it some more */ + perr = prngForceReseed(gPrngRef, RESEED_TICKS); + + /* make a mutex to control access */ + gYarrowMutex = mutex_alloc(0); +} + +/* + * Called to initialize our device, + * and to register ourselves with devfs + */ +void +random_init() +{ + int ret; + + if (gRandomInstalled) + return; + + /* install us in the file system */ + gRandomInstalled = 1; + + /* setup yarrow and the mutex */ + PreliminarySetup(); + + ret = cdevsw_add(RANDOM_MAJOR, &random_cdevsw); + if (ret < 0) { + printf("random_init: failed to allocate a major number!\n"); + gRandomInstalled = 0; + return; + } + + devfs_make_node(makedev (ret, 0), DEVFS_CHAR, + UID_ROOT, GID_WHEEL, 0644, "random", 0); + + /* + * also make urandom + * (which is exactly the same thing in our context) + */ + devfs_make_node(makedev (ret, 1), DEVFS_CHAR, + UID_ROOT, GID_WHEEL, 0644, "urandom", 0); +} + +/* + * Open the device. Make sure init happened, and make sure the caller is + * authorized. + */ + +int +random_open(dev_t dev, int flags, int devtype, struct proc *p) +{ + if (gRandomError != 0) { + /* forget it, yarrow didn't come up */ + return (ENOTSUP); + } + + /* + * if we are being opened for write, + * make sure that we have privledges do so + */ + if (flags & FWRITE) { + if (securelevel >= 2) + return (EPERM); + if ((securelevel >= 1) && suser(p->p_ucred, &p->p_acflag)) + return (EPERM); + } + + return (0); +} + + +/* + * close the device. + */ + +int +random_close(dev_t dev, int flags, int mode, struct proc *p) +{ + return (0); +} + + +/* + * Get entropic data from the Security Server, and use it to reseed the + * prng. + */ +int +random_write (dev_t dev, struct uio *uio, int ioflag) +{ + int retCode = 0; + char rdBuffer[256]; + + if (gRandomError != 0) { + return (ENOTSUP); + } + + /* get control of the Yarrow instance, Yarrow is NOT thread safe */ + mutex_lock(gYarrowMutex); + + /* Security server is sending us entropy */ + + while (uio->uio_resid > 0 && retCode == 0) { + /* get the user's data */ + int bytesToInput = min(uio->uio_resid, sizeof (rdBuffer)); + retCode = uiomove(rdBuffer, bytesToInput, uio); + if (retCode != 0) + goto /*ugh*/ error_exit; + + /* put it in Yarrow */ + if (prngInput(gPrngRef, (BYTE*) rdBuffer, + sizeof (rdBuffer), SYSTEM_SOURCE, + sizeof (rdBuffer) * 8) != 0) { + retCode = EIO; + goto error_exit; + } + } + + /* force a reseed */ + if (prngForceReseed(gPrngRef, RESEED_TICKS) != 0) { + retCode = EIO; + goto error_exit; + } + + /* retCode should be 0 at this point */ + +error_exit: /* do this to make sure the mutex unlocks. */ + mutex_unlock(gYarrowMutex); + return (retCode); +} + +/* + * return data to the caller. Results unpredictable. + */ +int +random_read(dev_t dev, struct uio *uio, int ioflag) +{ + int retCode = 0; + char wrBuffer[512]; + + if (gRandomError != 0) + return (ENOTSUP); + + /* lock down the mutex */ + mutex_lock(gYarrowMutex); + + while (uio->uio_resid > 0 && retCode == 0) { + /* get the user's data */ + int bytesToRead = min(uio->uio_resid, sizeof (wrBuffer)); + + /* get the data from Yarrow */ + if (prngOutput(gPrngRef, (BYTE *) wrBuffer, sizeof (wrBuffer)) != 0) { + printf ("Couldn't read data from Yarrow.\n"); + + /* something's really weird */ + retCode = EIO; + goto error_exit; + } + + retCode = uiomove(wrBuffer, bytesToRead, uio); + + if (retCode != 0) + goto error_exit; + } + + retCode = 0; + +error_exit: + mutex_unlock(gYarrowMutex); + return retCode; +} + +/* export good random numbers to the rest of the kernel */ +void +read_random(void* buffer, u_int numbytes) +{ + if (gYarrowMutex == 0) { /* are we initialized? */ + PreliminarySetup (); + } + + mutex_lock(gYarrowMutex); + prngOutput(gPrngRef, (BYTE *) buffer, numbytes); + mutex_unlock(gYarrowMutex); +} + +/* + * Return an unsigned long pseudo-random number. + */ +u_long +RandomULong() +{ + u_long buf; + read_random(&buf, sizeof (buf)); + return (buf); +} + diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/PoolAlloc.c b/bsd/dev/random/randomdev.h similarity index 64% rename from iokit/Families/IOHIDSystem/IOHIDDescriptorParser/PoolAlloc.c rename to bsd/dev/random/randomdev.h index 8d1c616f4..906f620b1 100644 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/PoolAlloc.c +++ b/bsd/dev/random/randomdev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -19,23 +19,17 @@ * * @APPLE_LICENSE_HEADER_END@ */ -#include <IOKit/system.h> -#include <IOKit/IOLib.h> -#include <IOKit/hidsystem/IOHIDDescriptorParser.h> -void *PoolAllocateResident (vm_size_t size, unsigned char clear) -{ - void *mem = IOMalloc(size); +#ifndef __DEV_RANDOMDEV_H__ +#define __DEV_RANDOMDEV_H__ - if (clear) { - bzero(mem, size); - } +int random_open(dev_t dev, int flags, int devtype, struct proc *pp); +int random_close(dev_t dev, int flags, int mode, struct proc *pp); +int random_read(dev_t dev, struct uio *uio, int ioflag); +int random_write(dev_t dev, struct uio *uio, int ioflag); - return mem; -} +u_long RandomULong(); +void read_random(void* buffer, u_int numBytes); + +#endif /* __DEV_RANDOMDEV_H__ */ -OSStatus PoolDeallocate (void *ptr, vm_size_t size) -{ - IOFree(ptr, size); - return noErr; -} diff --git a/bsd/hfs/MacOSStubs.c b/bsd/hfs/MacOSStubs.c index 0cca15c9e..2b8809c6b 100644 --- a/bsd/hfs/MacOSStubs.c +++ b/bsd/hfs/MacOSStubs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -254,18 +254,6 @@ Error_Exit: ; return status; } -void MarkBlock_glue (Ptr address) -{ - int err; - struct buf *bp = NULL; - int mappingEntry; - - if ((err = LookupBufferMapping(address, &bp, &mappingEntry))) { - panic("Failed to find buffer pointer for buffer in MarkBlock_glue."); - } else { - bp->b_flags |= B_DIRTY; - }; -} OSErr RelBlock_glue (Ptr address, UInt16 options ) { @@ -310,7 +298,7 @@ OSErr RelBlock_glue (Ptr address, UInt16 options ) /* Creates a new vnode to hold a psuedo file like an extents tree file */ /* */ -OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode, int init_ubc) +OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode) { struct hfsnode *hp; @@ -351,6 +339,7 @@ OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode, i hp->h_meta->h_dev = hfsmp->hfs_raw_dev; hp->h_meta->h_usecount++; hp->h_nodeflags |= IN_ACCESS | IN_CHANGE | IN_UPDATE; + rl_init(&hp->h_invalidranges); #if HFS_DIAGNOSTIC hp->h_valid = HFS_VNODE_MAGIC; #endif @@ -361,10 +350,7 @@ OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode, i * through mapped IO as will as POSIX IO APIs. * Hence we do not initialize UBC for those files */ - if (init_ubc) - ubc_info_init(vp); - else - vp->v_ubcinfo = UBC_NOINFO; + vp->v_ubcinfo = UBC_NOINFO; *tmpvnode = vp; @@ -379,24 +365,6 @@ Err_Exit: return rtn; } -OSErr GetNewFCB(ExtendedVCB *vcb, FileReference* fRefPtr) -{ - OSErr err; - - err = GetInitializedVNode( VCBTOHFS(vcb), fRefPtr, 0 ); - panic("This node is not completely initialized in GetNewFCB!"); /* XXX SER */ - - return( err ); -} - - -OSErr CheckVolumeOffLine( ExtendedVCB *vcb ) -{ - - return( 0 ); -} - - OSErr C_FlushMDB( ExtendedVCB *volume) { short err; diff --git a/bsd/hfs/Makefile b/bsd/hfs/Makefile index fe40106ac..f628fa341 100644 --- a/bsd/hfs/Makefile +++ b/bsd/hfs/Makefile @@ -25,7 +25,7 @@ DATAFILES = \ hfs_encodings.h hfs_format.h hfs_mount.h PRIVATE_DATAFILES = \ - hfs.h hfs_macos_defs.h + hfs.h hfs_macos_defs.h rangelist.h INSTALL_MI_LIST = ${DATAFILES} diff --git a/bsd/hfs/hfs.h b/bsd/hfs/hfs.h index 9c5b866e9..038327609 100644 --- a/bsd/hfs/hfs.h +++ b/bsd/hfs/hfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -27,33 +27,6 @@ * hfs.h -- constants, structures, function declarations. etc. * for Macintosh file system vfs. * -* HISTORY -* 12-Aug-1999 Scott Roberts Merge into HFSStruct, the FCB -* 6-Jun-1999 Don Brady Minor cleanup of hfsmount struct. -* 22-Mar-1999 Don Brady For POSIX delete semantics: add private metadata strings. -* 13-Jan-1999 Don Brady Add ATTR_CMN_SCRIPT to HFS_ATTR_CMN_LOOKUPMASK (radar #2296613). -* 20-Nov-1998 Don Brady Remove UFSToHFSStr and HFSToUFSStr prototypes (obsolete). -* Move filename entry from FCB to hfsfilemeta, hfsdirentry -* names are now 255 byte long. -* 10-Nov-1998 Pat Dirks Added MAXLOGBLOCKSIZE and MAXLOGBLOCKSIZEBLOCKS and RELEASE_BUFFER flag. -* Added hfsLogicalBlockTableEntry and h_logicalblocktable field in struct hfsnode. -* 4-Sep-1998 Pat Dirks Added hfs_log_block_size to hfsmount struct [again] and BestBlockSizeFit routine. -* 31-aug-1998 Don Brady Add UL to MAC_GMT_FACTOR constant. -* 04-jun-1998 Don Brady Add hfsMoveRename prototype to replace hfsMove and hfsRename. -* Add VRELE and VPUT macros to catch bad ref counts. -* 28-May-1998 Pat Dirks Move internal 'struct searchinfo' def'n here from attr.h -* 03-may-1998 Brent Knight Add gTimeZone. -* 23-apr-1998 Don Brady Add File type and creator for symbolic links. -* 22-apr-1998 Don Brady Removed kMetaFile. -* 21-apr-1998 Don Brady Add to_bsd_time and to_hfs_time prototypes. -* 20-apr-1998 Don Brady Remove course-grained hfs metadata locking. -* 15-apr-1998 Don Brady Add hasOverflowExtents and hfs_metafilelocking prototypes. Add kSysFile constant. -* 14-apr-1998 Deric Horn Added searchinfo_t, definition of search criteria used by searchfs. -* 9-apr-1998 Don Brady Added hfs_flushMDB and hfs_flushvolumeheader prototypes. -* 8-apr-1998 Don Brady Add MAKE_VREFNUM macro. -* 26-mar-1998 Don Brady Removed CloseBTreeFile and OpenBtreeFile prototypes. -* -* 12-nov-1997 Scott Roberts Added changes for HFSPlus */ #ifndef __HFS__ @@ -69,6 +42,7 @@ #include <hfs/hfs_format.h> #include <hfs/hfs_macos_defs.h> #include <hfs/hfs_encodings.h> +#include <hfs/rangelist.h> struct uio; // This is more effective than #include <sys/uio.h> in case KERNEL is undefined... @@ -99,14 +73,16 @@ enum { enum { kUndefinedFork = 0, - kAnyFork, kDataFork, kRsrcFork, kDirectory, kSysFile, - kDefault + kDefault, + kAnyFork }; +/* number of locked buffer caches to hold for b-tree meta data */ +#define kMaxLockedMetaBuffers 32 /* * File type and creator for symbolic links @@ -129,47 +105,63 @@ extern struct timezone gTimeZone; #define RELEASE_BUFFER 0x00000001 +/* How many free extents to cache per volume */ +#define kMaxFreeExtents 10 + /* Internal Data structures*/ struct vcb_t { - int16_t vcbFlags; u_int16_t vcbSigWord; - u_int32_t vcbCrDate; - u_int32_t vcbLsMod; int16_t vcbAtrb; - u_int16_t vcbNmFls; /* HFS only */ - int16_t vcbVBMSt; - int16_t vcbAlBlSt; - int32_t vcbClpSiz; - u_int32_t vcbNxtCNID; - u_int8_t vcbVN[256]; + int16_t vcbFlags; int16_t vcbVRefNum; - u_int16_t vcbVSeqNum; + + u_int32_t vcbCrDate; + u_int32_t vcbLsMod; u_int32_t vcbVolBkUp; - int32_t vcbWrCnt; - u_int16_t vcbNmRtDirs; /* HFS only */ - u_int16_t vcbReserved; + u_int32_t checkedDate; /* time of last disk check */ + int32_t vcbFilCnt; int32_t vcbDirCnt; + u_int32_t blockSize; /* size of allocation blocks */ + u_int32_t totalBlocks; /* total allocation blocks */ + u_int32_t freeBlocks; /* free allocation blocks */ + u_int32_t nextAllocation; /* start of next allocation search */ + int32_t vcbClpSiz; + u_int32_t vcbNxtCNID; + u_int32_t vcbCNIDGen; + int32_t vcbWrCnt; + int32_t vcbFndrInfo[8]; + + u_int64_t encodingsBitmap; /* HFS Plus only */ + + u_int16_t vcbNmFls; /* HFS only */ + u_int16_t vcbNmRtDirs; /* HFS only */ + int16_t vcbVBMSt; /* HFS only */ + int16_t vcbAlBlSt; /* HFS only */ + struct vnode * extentsRefNum; struct vnode * catalogRefNum; struct vnode * allocationsRefNum; - u_int32_t blockSize; /* size of allocation blocks - vcbAlBlkSiz*/ - u_int32_t totalBlocks; /* number of allocation blocks in volume */ - u_int32_t freeBlocks; /* number of unused allocation blocks - vcbFreeBks*/ - u_int32_t nextAllocation; /* start of next allocation search - vcbAllocPtr*/ + + u_int8_t vcbVN[256]; /* volume name in UTF-8 */ + u_int32_t volumeNameEncodingHint; u_int32_t altIDSector; /* location of alternate MDB/VH */ - u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */ - u_int32_t checkedDate; /* date and time of last disk check */ - u_int64_t encodingsBitmap; /* HFS Plus only*/ - u_int32_t volumeNameEncodingHint; /* Text encoding used for volume name*/ - char * hintCachePtr; /* points to this volumes heuristicHint cache*/ + u_int32_t hfsPlusIOPosOffset; /* Disk block where HFS+ starts */ + u_int32_t vcbVBMIOSize; /* volume bitmap I/O size */ + char * hintCachePtr; /* volume heuristicHint cache */ + + /* cache of largest known free extents */ + u_int32_t vcbFreeExtCnt; + HFSPlusExtentDescriptor vcbFreeExt[kMaxFreeExtents]; + u_int32_t localCreateDate; /* creation times for HFS+ volumes are in local time */ simple_lock_data_t vcbSimpleLock; /* simple lock to allow concurrent access to vcb data */ }; typedef struct vcb_t ExtendedVCB; + /* vcbFlags */ #define kHFS_DamagedVolume 0x1 /* This volume has errors, unmount dirty */ #define MARK_VOLUMEDAMAGED(fcb) FCBTOVCB((fcb))->vcbFlags |= kHFS_DamagedVolume; @@ -226,6 +218,9 @@ typedef struct hfsmount { unicode_to_hfs_func_t hfs_get_hfsname; } hfsmount_t; +#define HFSPLUS_PRIVATE_DIR \ + "\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80\xE2\x90\x80HFS+ Private Data" + /***************************************************************************** * @@ -248,15 +243,17 @@ struct hfsnode { union { struct hfslockf *hu_lockf; /* Head of byte-level lock list. */ void *hu_sysdata; /* private data for system files */ + char hu_symlinkdata[4]; /* symbolic link (4 chars or less) */ + char *hu_symlinkptr; /* symbolic link pathname */ } h_un; struct vnode * h_vp; /* vnode associated with this inode. */ struct hfsfilemeta * h_meta; /* Ptr to file meta data */ u_int16_t h_nodeflags; /* flags, see below */ u_int8_t h_type; /* Type of info: dir, data, rsrc */ int8_t fcbFlags; /* FCB flags */ + struct rl_head h_invalidranges;/* Areas of disk that should read back as zeroes */ u_int64_t fcbEOF; /* Logical length or EOF in bytes */ u_int64_t fcbPLen; /* Physical file length in bytes */ - u_int64_t fcbMaxEOF; /* Maximum logical length or EOF in bytes */ u_int32_t fcbClmpSize; /* Number of bytes per clump */ HFSPlusExtentRecord fcbExtents; /* Extents of file */ @@ -266,6 +263,8 @@ struct hfsnode { }; #define h_lockf h_un.hu_lockf #define fcbBTCBPtr h_un.hu_sysdata +#define h_symlinkptr h_un.hu_symlinkptr +#define h_symlinkdata h_un.hu_symlinkdata typedef struct hfsnode FCB; @@ -321,6 +320,9 @@ typedef struct hfsfilemeta { #define H_HINT(HP) ((HP)->h_meta->h_hint) #define H_DEV(HP) ((HP)->h_meta->h_dev) +#define H_ISBIGLINK(HP) ((HP)->fcbEOF > 4) +#define H_SYMLINK(HP) (H_ISBIGLINK((HP)) ? (HP)->h_symlinkptr : (HP)->h_symlinkdata) + /* These flags are kept in flags. */ #define IN_ACCESS 0x0001 /* Access time update request. */ #define IN_CHANGE 0x0002 /* Change time update request. */ @@ -329,6 +331,7 @@ typedef struct hfsfilemeta { #define IN_RENAME 0x0010 /* Node is being renamed. */ #define IN_SHLOCK 0x0020 /* File has shared lock. */ #define IN_EXLOCK 0x0040 /* File has exclusive lock. */ +#define IN_BYCNID 0x0100 /* Dir was found by CNID */ #define IN_ALLOCATING 0x1000 /* vnode is in transit, wait or ignore */ #define IN_WANT 0x2000 /* Its being waited for */ @@ -695,7 +698,7 @@ short hfs_flushvolumeheader(struct hfsmount *hfsmp, int waitfor); short hfs_getcatalog (ExtendedVCB *vcb, u_int32_t dirID, char *name, short len, hfsCatalogInfo *catInfo); short hfsMoveRename (ExtendedVCB *vcb, u_int32_t oldDirID, char *oldName, u_int32_t newDirID, char *newName, u_int32_t *hint); -short hfsCreate (ExtendedVCB *vcb, u_int32_t dirID, char *name, int mode); +short hfsCreate (ExtendedVCB *vcb, u_int32_t dirID, char *name, int mode, u_int32_t tehint); short hfsCreateFileID (ExtendedVCB *vcb, u_int32_t parentDirID, StringPtr name, u_int32_t catalogHint, u_int32_t *fileIDPtr); short hfs_vcreate (ExtendedVCB *vcb, hfsCatalogInfo *catInfo, u_int8_t forkType, struct vnode **vpp); short hfsDelete (ExtendedVCB *vcb, u_int32_t parentDirID, StringPtr name, short isfile, u_int32_t catalogHint); @@ -765,7 +768,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, u_long sectors, struct proc *p); OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, u_long embBlkOffset, u_long sectors, struct proc *p); -OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode, int init_ubc); +OSStatus GetInitializedVNode(struct hfsmount *hfsmp, struct vnode **tmpvnode); int hfs_getconverter(u_int32_t encoding, hfs_to_unicode_func_t *get_unicode, unicode_to_hfs_func_t *get_hfsname); @@ -783,4 +786,6 @@ int mac_roman_to_utf8(Str31 hfs_str, ByteCount maxDstLen, ByteCount *actualDstLe int utf8_to_mac_roman(ByteCount srcLen, const unsigned char* srcStr, Str31 dstStr); +u_int32_t hfs_pickencoding(const u_int16_t *src, int len); + #endif /* __HFS__ */ diff --git a/bsd/hfs/hfs_btreeio.c b/bsd/hfs/hfs_btreeio.c index 67e52e0ef..e050e8ff7 100644 --- a/bsd/hfs/hfs_btreeio.c +++ b/bsd/hfs/hfs_btreeio.c @@ -169,7 +169,6 @@ OSStatus ReleaseBTreeBlock(FileReference vp, BlockDescPtr blockPtr, ReleaseBlock VOP_BWRITE(bp); #else if (options & kLockTransaction) { - /* * * Set the B_LOCKED flag and unlock the buffer, causing brelse to move @@ -178,6 +177,10 @@ OSStatus ReleaseBTreeBlock(FileReference vp, BlockDescPtr blockPtr, ReleaseBlock * isn't going to work. * */ + extern int count_lock_queue __P((void)); + /* Don't hog all the buffers... */ + if (count_lock_queue() > kMaxLockedMetaBuffers) + hfs_fsync_transaction(vp); bp->b_flags |= B_LOCKED; }; bdwrite(bp); @@ -253,7 +256,7 @@ OSStatus ExtendBTreeFile(FileReference vp, FSSize minEOF, FSSize maxEOF) extendFlags = kEFAllMask | kEFContigMask; } - retval = ExtendFileC(vcb, filePtr, bytesToAdd, extendFlags, &actualBytesAdded ); + retval = ExtendFileC(vcb, filePtr, bytesToAdd, 0, extendFlags, &actualBytesAdded); if(H_FILEID(filePtr) != kHFSExtentsFileID) (void) hfs_metafilelocking(VTOHFS(vp), kHFSExtentsFileID, LK_RELEASE, p); diff --git a/bsd/hfs/hfs_encodinghint.c b/bsd/hfs/hfs_encodinghint.c new file mode 100644 index 000000000..776f2b361 --- /dev/null +++ b/bsd/hfs/hfs_encodinghint.c @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include <sys/param.h> +#include <hfs/hfs_macos_defs.h> + + +/* CJK Mac Encoding Bits */ +#define CJK_JAPAN 0x1 +#define CJK_KOREAN 0x2 +#define CJK_CHINESE_TRAD 0x4 +#define CJK_CHINESE_SIMP 0x8 +#define CJK_ALL 0xF + +#define CJK_CHINESE (CJK_CHINESE_TRAD | CJK_CHINESE_SIMP) +#define CJK_KATAKANA (CJK_JAPAN | CJK_CHINESE_SIMP | CJK_KOREAN) + + +/* Remeber the las unique CJK bit */ +u_int8_t cjk_lastunique = 0; + + +/* Map CJK bits to Mac encoding */ +u_int8_t cjk_encoding[] = { + /* 0000 */ kTextEncodingMacUnicode, + /* 0001 */ kTextEncodingMacJapanese, + /* 0010 */ kTextEncodingMacKorean, + /* 0011 */ kTextEncodingMacJapanese, + /* 0100 */ kTextEncodingMacChineseTrad, + /* 0101 */ kTextEncodingMacJapanese, + /* 0110 */ kTextEncodingMacKorean, + /* 0111 */ kTextEncodingMacJapanese, + /* 1000 */ kTextEncodingMacChineseSimp, + /* 1001 */ kTextEncodingMacJapanese, + /* 1010 */ kTextEncodingMacKorean, + /* 1011 */ kTextEncodingMacJapanese, + /* 1100 */ kTextEncodingMacChineseTrad, + /* 1101 */ kTextEncodingMacJapanese, + /* 1110 */ kTextEncodingMacKorean, + /* 1111 */ kTextEncodingMacJapanese +}; + +/* + * CJK Mac Encoding Bitmap + * + * Each entry in the table is 4-bits wide and represents + * every CJK codepoint (0x4E00 to 0x9FAF). + */ +static u_int8_t cjk_bitmap[] = { + 0xFF,0xF0,0x00,0xF0,0xFF,0xFF,0xFC,0x4D,0xFD,0x80,0xFF,0x1F,0xFF,0x88,0x88,0x4F, + 0x10,0x08,0x88,0x85,0x08,0xC9,0xF8,0x04,0x5C,0x4F,0x08,0x09,0xFF,0xF8,0x85,0x98, + 0x00,0xF7,0xF0,0xC0,0x8C,0xF0,0xF8,0xFF,0x08,0xCC,0x18,0x1F,0xFF,0x00,0xFC,0xFF, + 0x88,0x01,0x00,0x08,0xC0,0x20,0x20,0x00,0x98,0xF0,0x00,0x22,0x00,0x00,0x00,0x4F, + 0x01,0x47,0x14,0x0F,0x9F,0xF1,0xCF,0x8F,0xF2,0xCF,0xFF,0x00,0x5B,0xF8,0x01,0xD7, + 0xF9,0x0F,0xFF,0x8F,0x8F,0xF0,0xFF,0x0F,0x01,0xD8,0x80,0x07,0x40,0x8F,0x00,0x80, + 0xFF,0xCD,0x8F,0xFD,0xC4,0xFF,0xF0,0x19,0x80,0x80,0xFF,0xFF,0xFF,0x04,0xF4,0xFD, + 0xC0,0xF0,0xFF,0x00,0x4C,0x88,0x18,0x01,0x4F,0xCF,0xC4,0xFF,0x00,0xF0,0xC0,0xC0, + 0xF4,0x04,0x44,0x00,0xF4,0x6F,0xF0,0xFF,0xFF,0x44,0x44,0x80,0xCC,0x89,0x51,0x88, + 0x08,0x0C,0x88,0x88,0x00,0x88,0x44,0xF0,0x0D,0x48,0x0F,0x0F,0x0F,0x4F,0xFF,0x44, + 0x40,0xF0,0x00,0x7F,0x46,0x00,0xF4,0xFF,0xFF,0xD4,0xF4,0xD4,0xFC,0xFF,0xDF,0xCD, + 0x4C,0xC4,0x8C,0xC0,0xF0,0x44,0x0C,0xF4,0x0F,0xF0,0x5C,0x4F,0x44,0xD6,0x4D,0xFE, + 0x64,0xF4,0x4E,0x47,0xCF,0xF2,0xF0,0xF0,0xF4,0x04,0x4C,0xC7,0x07,0xF4,0xF4,0x04, + 0x19,0x80,0x80,0x88,0x88,0x18,0x18,0xFF,0x00,0x44,0xF0,0x47,0x40,0x44,0x00,0xF0, + 0x44,0xF7,0xCF,0x40,0x60,0x4F,0x40,0xCF,0xFD,0x60,0x07,0xF4,0x4D,0x5F,0xFC,0xFC, + 0xF6,0x90,0x11,0x08,0x88,0x08,0x84,0xFF,0xE0,0xF0,0x74,0x45,0x0F,0x0F,0x00,0x0D, + 0x04,0x02,0x50,0x47,0x70,0x70,0xFC,0xD4,0x70,0x4F,0x4D,0x47,0xFC,0x4F,0x0E,0xF6, + 0xF4,0x74,0xD3,0x6F,0xDF,0x7F,0xFF,0x48,0x44,0x40,0x40,0x41,0x10,0x28,0x0C,0x08, + 0x44,0xF0,0x40,0xF4,0x7F,0x44,0x4C,0xFC,0x41,0x40,0xF0,0x41,0x00,0x4F,0x4F,0x44, + 0x44,0x44,0xF4,0x00,0x44,0x44,0x49,0x44,0x04,0x45,0x77,0xCF,0x03,0x84,0x50,0x88, + 0x0F,0x44,0xF0,0x40,0x08,0x40,0xF4,0x04,0x70,0x04,0x44,0x04,0x77,0x45,0x44,0x04, + 0x00,0xC4,0x80,0x80,0x88,0x00,0x7F,0x44,0x44,0x7F,0x75,0x74,0x04,0xCC,0x40,0x47, + 0x40,0x05,0x74,0x44,0x74,0x47,0x10,0xF4,0x70,0x40,0x74,0x4F,0x00,0x4F,0x40,0x03, + 0x04,0x50,0x74,0xFC,0x44,0x04,0xFC,0x4D,0x44,0xC0,0xD0,0x04,0x74,0xF0,0x40,0x64, + 0x37,0x45,0x47,0xCE,0x74,0xC4,0x04,0x00,0x44,0x4F,0x55,0x41,0x05,0x05,0x04,0x70, + 0xF4,0x04,0x44,0x04,0x40,0x07,0x40,0x04,0x44,0x47,0x44,0x70,0x44,0x57,0x47,0xD0, + 0xFF,0xF0,0xFF,0x7F,0xFF,0xF0,0xF7,0x03,0x81,0x07,0xCD,0x48,0x40,0x4D,0x4F,0x44, + 0x40,0x4F,0xF0,0x60,0x7F,0xF3,0xFF,0x0F,0xF8,0x80,0xF8,0xFF,0x8F,0x80,0x8F,0x00, + 0x8F,0x09,0x90,0x43,0xD8,0x07,0xF9,0x50,0x51,0x5F,0xF4,0xF9,0x94,0x80,0x08,0x04, + 0x0F,0x0D,0xFD,0x01,0x11,0x97,0x0F,0x80,0xDD,0x99,0x91,0xFF,0x40,0x80,0xFC,0x04, + 0x08,0x00,0x5F,0x8F,0xB4,0xF4,0x7F,0x84,0x84,0x00,0x04,0x41,0x04,0x90,0xF7,0x06, + 0xFD,0x00,0x08,0x11,0x10,0x81,0x90,0x80,0x7F,0xC0,0xD0,0x0F,0xFF,0x8F,0xF8,0x81, + 0xCF,0xF8,0x01,0xFF,0x4F,0x1F,0x84,0x0F,0xF4,0x4C,0x01,0xFC,0x88,0x88,0xF4,0x04, + 0x48,0x00,0x7F,0x10,0xFC,0x87,0x80,0x0F,0x4F,0xD4,0x40,0xFF,0xBF,0xFF,0x80,0x80, + 0xC8,0xF8,0x05,0x74,0x40,0x7F,0xFF,0x14,0x88,0x04,0x4F,0x0F,0x00,0x74,0x6C,0x4D, + 0xE0,0x14,0x91,0x80,0xF0,0x4F,0x44,0xF4,0x11,0x1F,0x75,0x40,0x04,0x44,0xF4,0xF0, + 0xC4,0x7C,0x04,0x70,0x7F,0x44,0x74,0x00,0x78,0xC3,0x01,0x44,0x44,0xF0,0x80,0xF8, + 0x8F,0xF8,0x02,0x04,0xF8,0xFF,0xDD,0x04,0x90,0x88,0x11,0x00,0x10,0x40,0x05,0x8F, + 0x74,0xF4,0x30,0xF0,0xF0,0x80,0x70,0x00,0x08,0x4F,0x70,0x5E,0x7F,0x60,0x70,0xF7, + 0x01,0x77,0x0F,0x15,0x40,0x40,0x00,0x40,0x4C,0x71,0x74,0x40,0x97,0x6F,0x04,0xFF, + 0x18,0x01,0xF0,0x0D,0x4F,0x44,0xF0,0xF4,0x4F,0x04,0xF0,0xFF,0xF0,0x0D,0xD4,0x40, + 0xFF,0xF4,0x00,0x08,0x00,0x0F,0x40,0x78,0x54,0x10,0x04,0x40,0xF1,0x99,0x44,0xFC, + 0xF7,0xF0,0xD6,0xF1,0xFF,0x0F,0x74,0x88,0xF0,0xFF,0x87,0xF8,0x01,0x0F,0x0F,0x8F, + 0xCF,0xC8,0x08,0x8F,0x92,0x80,0x04,0xFD,0xFF,0xD4,0xFB,0xF0,0x4D,0x58,0x24,0xF0, + 0x00,0x0D,0x8F,0x08,0x80,0x84,0x88,0x44,0x00,0x24,0x84,0x45,0x4F,0x0F,0xC4,0xF4, + 0x03,0x88,0xF4,0x4B,0x99,0x00,0x74,0x09,0x01,0x14,0x04,0x09,0x40,0xF0,0x00,0x80, + 0x80,0x79,0x00,0x00,0xFF,0xFF,0xF9,0x01,0x80,0x00,0x0F,0xFF,0x98,0xF0,0x00,0xD0, + 0x78,0xF7,0xFF,0x0C,0xFD,0xFF,0xFF,0xFD,0xFF,0xFF,0xC0,0x99,0x8F,0xC1,0x8C,0x00, + 0xD0,0xF0,0x0F,0x4C,0xFF,0x5F,0xFF,0xFF,0xFF,0x8C,0x80,0x88,0x44,0xF0,0xF4,0xFC, + 0x8F,0x80,0x44,0xCF,0xFC,0xF4,0xDD,0x8D,0xC4,0x68,0xC8,0x45,0xFF,0xF0,0x5F,0x0F, + 0x4D,0xC7,0x40,0x4D,0x1F,0x8F,0x00,0x45,0x38,0x88,0x8C,0x88,0x88,0x80,0x08,0x10, + 0x44,0x4C,0x4C,0x4C,0x0F,0x43,0x04,0x40,0xF5,0xFC,0xF4,0xDD,0x0C,0xF4,0xFF,0x44, + 0x4F,0x0C,0x0D,0x4F,0x04,0xD0,0x4F,0x9F,0x4F,0x0D,0xC8,0x0C,0x84,0x8C,0x80,0x00, + 0x44,0x85,0x5B,0xCC,0xCF,0xFC,0xCF,0xD4,0xC4,0xF1,0x08,0x44,0x0F,0xC4,0xF5,0xC5, + 0xFF,0x4D,0x4F,0xDC,0xFF,0x00,0x88,0xCC,0x88,0x88,0x88,0x84,0x81,0x08,0x88,0x8C, + 0x74,0x05,0xF4,0xCD,0xDF,0x4C,0xF0,0x0F,0x40,0xCF,0x00,0x40,0x04,0x4F,0xDC,0xC0, + 0xC0,0x40,0x47,0xFF,0xC4,0x44,0x04,0xD6,0xCF,0x04,0x0D,0x41,0x00,0x84,0x02,0x00, + 0x08,0x88,0x08,0xC4,0x00,0x0C,0x4C,0xFD,0xFC,0xD4,0x64,0xC4,0x55,0x40,0x0C,0x8F, + 0xC5,0xC0,0x5F,0x0F,0x84,0x4C,0x41,0x74,0x4C,0x34,0xC0,0x5F,0x00,0x00,0x1D,0x46, + 0xC0,0x74,0xCC,0x8C,0x00,0x0C,0x88,0x08,0x00,0x00,0xC0,0xCC,0x08,0xD0,0x4F,0x4D, + 0xCF,0xDC,0x0F,0xF2,0xFC,0xDF,0x44,0xC4,0xC0,0x44,0x4C,0x00,0xFF,0x07,0xFF,0xD1, + 0x40,0x44,0x44,0xF4,0x35,0x77,0x47,0x07,0xC1,0xC4,0xC0,0x81,0x80,0xC0,0x80,0x48, + 0x04,0x44,0xFD,0x74,0xC4,0x44,0xCC,0x44,0xC4,0xCC,0x4F,0x0C,0x40,0x47,0xCF,0xF0, + 0xC0,0xF4,0xCF,0x4C,0x4C,0x88,0x08,0xC0,0x00,0x8C,0x80,0xD4,0x50,0x04,0xF4,0x4F, + 0xCC,0x04,0x04,0x07,0xFC,0x00,0x4C,0xCC,0x04,0x44,0x47,0x75,0x09,0xD0,0x44,0xC8, + 0x00,0x80,0x08,0xC0,0x50,0x04,0x8C,0x74,0x94,0x4F,0x4F,0x0F,0xC5,0xC4,0x40,0xC4, + 0x44,0x05,0x40,0x04,0x44,0x04,0x8D,0x0D,0x01,0x60,0x08,0xC0,0xCC,0x14,0x08,0x04, + 0x04,0x4C,0x4D,0x04,0xCF,0xFD,0x4D,0x44,0xC4,0x44,0x07,0x4C,0x45,0x81,0x08,0x44, + 0x45,0x44,0xC4,0x5F,0x00,0x01,0x44,0xDC,0x04,0xC0,0x41,0x40,0x44,0x04,0x44,0x00, + 0x01,0x81,0x70,0x44,0x04,0x44,0x46,0x87,0x00,0x44,0x47,0xC5,0x00,0x00,0x4F,0x04, + 0x55,0x55,0x40,0x04,0x45,0x4E,0x64,0x01,0x70,0x50,0x0C,0xD0,0x01,0xFF,0xC0,0xCF, + 0xCF,0x18,0x4C,0x40,0x00,0xC4,0x80,0x05,0x8F,0x11,0x88,0x40,0xF0,0x0F,0x90,0xD8, + 0x41,0xF4,0x0F,0x48,0xDF,0x7C,0x74,0x10,0x00,0x77,0x04,0x07,0x07,0x44,0x0D,0xF4, + 0x04,0xC4,0x00,0x11,0xCF,0x0C,0xFC,0xCC,0x0F,0xC0,0x04,0x10,0x81,0xF8,0x00,0x0C, + 0x4F,0x0B,0x40,0xF0,0x40,0x4F,0xEC,0xDF,0xFF,0x04,0x00,0x80,0x00,0x88,0x88,0x88, + 0xF8,0x04,0x0F,0x0F,0xDC,0xCF,0xC0,0xC2,0x46,0xC4,0x64,0xCC,0x00,0xC0,0x4E,0x10, + 0x04,0xCF,0x88,0x08,0x13,0xF0,0x0C,0x40,0x00,0xF8,0x44,0x40,0x44,0xC4,0x40,0x44, + 0x8F,0xFF,0x4D,0x88,0x80,0x81,0x80,0x0C,0x01,0x18,0x48,0x04,0x4C,0x04,0x44,0x40, + 0x41,0xFC,0x00,0x65,0x02,0xF0,0x04,0xCF,0x04,0x1D,0xCD,0x01,0x88,0x08,0x85,0xF0, + 0x4F,0x54,0x4C,0x40,0x40,0x00,0xC4,0x84,0x46,0x44,0x4F,0x74,0xFC,0x4F,0xC7,0x00, + 0x4F,0x0F,0x74,0xCF,0x66,0xD7,0xC4,0x04,0x84,0x00,0x94,0x00,0xD0,0x40,0x54,0x0E, + 0xFC,0x40,0x4F,0x60,0x44,0x0F,0x44,0x74,0x7F,0x44,0xF7,0x44,0x44,0x43,0x50,0x40, + 0x11,0x00,0x08,0x00,0x44,0x77,0xCC,0x64,0xF0,0x45,0x4F,0x70,0x5F,0x47,0x40,0x0F, + 0x20,0x47,0xC6,0x00,0x14,0xD0,0x48,0x40,0x41,0x01,0x74,0x04,0x70,0x44,0x46,0x4F, + 0xCC,0xF4,0xF0,0x44,0xE4,0x44,0x00,0x44,0x44,0xF8,0x04,0x10,0x84,0x08,0x47,0xFE, + 0x44,0x40,0x40,0x04,0xEF,0x50,0x04,0x47,0x40,0x70,0x00,0x00,0x11,0x37,0x4C,0x47, + 0xF0,0x04,0xF0,0x74,0x44,0x01,0x01,0x46,0xF0,0x74,0xF4,0x14,0x77,0x44,0x41,0x77, + 0x00,0x44,0x1F,0x40,0x44,0xF0,0x0F,0x79,0x19,0x81,0x04,0x18,0xF0,0x37,0x75,0x44, + 0x00,0x49,0x08,0x84,0x10,0x01,0xC4,0xF4,0x01,0x04,0xFE,0x4F,0xF1,0x1F,0x0F,0x80, + 0x04,0x07,0xDC,0xF0,0xF0,0xFF,0xF5,0xCF,0xF0,0x01,0x08,0xF0,0x8D,0x08,0x0C,0x07, + 0x84,0x08,0x4F,0xF0,0xFF,0x84,0x00,0xFF,0xF7,0x40,0xFF,0xF8,0x0D,0x0F,0x04,0x00, + 0x4F,0x0F,0x90,0x70,0x51,0x67,0x63,0x07,0x44,0xF4,0x0F,0x4C,0xCF,0x40,0xF4,0x44, + 0xD4,0xFF,0x4F,0x88,0x08,0x0F,0xD0,0x44,0x04,0xFC,0x00,0xEF,0xF4,0x10,0x50,0x0C, + 0x44,0xD4,0xFC,0x44,0x8F,0x88,0x03,0xCC,0x40,0x4D,0x44,0x04,0xF0,0xF4,0x44,0x0F, + 0x44,0x60,0x40,0x4F,0x34,0xFC,0x44,0x44,0xFF,0xFC,0x0F,0x84,0x3C,0x4F,0xEF,0x04, + 0x44,0xC0,0xD4,0x07,0x4F,0x17,0x4E,0x06,0x40,0x44,0x44,0x45,0x82,0xF4,0x44,0xF4, + 0xF4,0xF0,0x88,0x88,0xD8,0x04,0x0C,0x40,0xF0,0xC0,0x40,0x44,0x4F,0x61,0x0F,0xF4, + 0x0F,0xC0,0xF0,0x00,0xF0,0x00,0x40,0x14,0x80,0x48,0x58,0x4F,0x44,0x00,0x0F,0x04, + 0x7D,0x44,0x04,0x4F,0xF4,0x0C,0x44,0x00,0x44,0x44,0xC0,0x44,0x04,0x4F,0x44,0x44, + 0x04,0x0F,0x44,0xC7,0x40,0x0D,0x45,0x00,0x04,0x00,0x88,0xC8,0x04,0x4C,0x44,0xD0, + 0x00,0x40,0x04,0x00,0x00,0x44,0x04,0x44,0x04,0x4F,0x44,0x40,0x00,0xFF,0x44,0x44, + 0x00,0x04,0x42,0x44,0x40,0x08,0x04,0x44,0x44,0xCC,0xC4,0x44,0x4C,0x44,0x55,0x4D, + 0xF4,0x0F,0x06,0x44,0xF4,0x54,0x4F,0x00,0x01,0x08,0x48,0x5D,0x4C,0x44,0x4C,0x44, + 0xFC,0xD4,0x40,0x0F,0xF4,0xC4,0x44,0x04,0x80,0x40,0x44,0x44,0x44,0x51,0x40,0x40, + 0x40,0x44,0x60,0x40,0xF4,0x70,0x07,0x40,0x04,0x40,0x04,0xCF,0x40,0x44,0x40,0x04, + 0x44,0x41,0x44,0x44,0x04,0x07,0x45,0x44,0x05,0x0D,0x0C,0x81,0x04,0x00,0x44,0x45, + 0x0F,0x70,0x50,0x40,0x04,0x40,0x44,0x04,0xFF,0xC0,0xFF,0xF4,0x8F,0xDF,0xFF,0xF0, + 0x00,0xFC,0xDF,0x09,0xF0,0x78,0x0C,0x04,0xFF,0xD4,0xF0,0x40,0x07,0x4F,0xC2,0x40, + 0xC9,0xD0,0xFC,0xF0,0xFF,0xF0,0x1F,0xF4,0x00,0xE4,0xF0,0xF2,0xFF,0xFF,0x9F,0x18, + 0x88,0xFF,0xFF,0x4F,0x04,0x88,0x46,0x07,0x0F,0xF0,0xFF,0x0F,0xFF,0x00,0x80,0xF8, + 0x46,0x3F,0xFF,0xFF,0x10,0x44,0x4F,0x04,0x4F,0xFF,0x07,0x24,0x44,0x10,0x90,0xFF, + 0xF4,0x47,0xFF,0x77,0x7F,0x74,0x06,0x6F,0x4D,0x14,0x70,0x07,0x8F,0x8F,0x08,0x91, + 0xF0,0x41,0x1F,0x79,0xF7,0x7F,0x74,0xF7,0xF4,0x14,0xC8,0x0F,0x28,0x0D,0x88,0x40, + 0x01,0x0D,0xCF,0x80,0x07,0x04,0x1C,0x00,0xF4,0x40,0x08,0x40,0xFF,0xFF,0x9F,0xFF, + 0xDF,0x08,0xF4,0x47,0x8F,0xF9,0x74,0xDF,0xFD,0x10,0xF4,0x04,0xC4,0x20,0x44,0x09, + 0x9F,0xC6,0xF7,0x48,0x44,0x04,0x47,0xFD,0xF0,0x40,0x04,0x01,0xF0,0x4C,0x04,0x84, + 0x80,0x08,0x00,0x04,0x4C,0x44,0xCD,0x40,0xFF,0x44,0x4D,0x88,0x88,0x88,0x48,0x40, + 0x74,0xCC,0x44,0x44,0xF5,0xF4,0xCF,0x44,0xF4,0xF0,0xE0,0xF5,0x0F,0x12,0x81,0x83, + 0x82,0x00,0x18,0x54,0x44,0xC4,0x04,0x44,0x04,0x4C,0x04,0x44,0xF4,0x44,0x00,0x44, + 0x93,0x00,0x88,0x08,0x1F,0x0D,0xD4,0x34,0x4F,0x00,0x06,0x47,0x44,0xF1,0x70,0x40, + 0x44,0x88,0x00,0xFC,0x00,0x50,0x64,0x4F,0x70,0x04,0x1F,0x7F,0x71,0xD5,0x40,0x5C, + 0x04,0x45,0x4C,0xEC,0xF4,0x00,0x80,0x0C,0x44,0x44,0x4C,0x44,0x44,0x04,0xC4,0x48, + 0x44,0x44,0x40,0xC0,0x40,0xFC,0x0F,0x05,0x47,0x05,0x40,0x00,0x48,0x80,0x81,0x04, + 0x00,0x44,0x40,0x40,0xF4,0xC0,0x0F,0xF0,0x40,0x14,0x08,0x41,0x40,0x04,0x44,0x44, + 0x44,0x0D,0x05,0x74,0x44,0x34,0x41,0x00,0x01,0x44,0x44,0x40,0xC0,0x04,0xF4,0x44, + 0x46,0x07,0x00,0x40,0x44,0x06,0x45,0x45,0x44,0x04,0x44,0xD0,0x06,0x07,0x77,0x00, + 0x04,0x44,0x80,0x44,0x50,0x40,0xF1,0x40,0x40,0x17,0x44,0x07,0x04,0x90,0xF0,0x4F, + 0xF4,0x1E,0xF0,0xFF,0x8F,0xF0,0x00,0x8F,0xF4,0xFF,0x1F,0xF0,0x40,0x10,0xF0,0x4F, + 0x80,0xFF,0x84,0x0F,0x08,0x14,0x0F,0x84,0xF8,0x00,0xCC,0x4F,0xFC,0xFD,0xF8,0x40, + 0x44,0x44,0x74,0x88,0x44,0x70,0xF0,0x18,0x81,0x70,0x04,0xD7,0x0F,0x80,0xF8,0x24, + 0x47,0x58,0xFF,0x30,0x00,0x44,0x4F,0x45,0x00,0x40,0xFD,0x50,0x44,0xC0,0x44,0x78, + 0xF4,0x7F,0x01,0x44,0x44,0x44,0x44,0x44,0x04,0xFF,0x5F,0x2D,0x7F,0xF9,0xFF,0x97, + 0x1C,0x14,0x0F,0xF8,0x44,0xCF,0x44,0xF0,0x88,0x80,0xF8,0xFD,0x80,0x4F,0x0F,0x88, + 0x0F,0x44,0xC4,0xFF,0x04,0x74,0xF4,0x04,0x44,0xC4,0xF4,0xFF,0xCF,0x00,0x00,0x0E, + 0x50,0x17,0x44,0x44,0xF7,0x4F,0x04,0x14,0xC3,0xFC,0x44,0x4F,0x44,0xF7,0x54,0x74, + 0x57,0x77,0x40,0x44,0x5D,0x08,0x07,0x44,0x51,0x74,0x09,0xFF,0x01,0x3F,0x01,0xDD, + 0xF8,0x9C,0x4F,0x40,0x1C,0xDF,0x11,0xF0,0xB1,0xF4,0xF7,0xF1,0x0F,0xF4,0x40,0xF0, + 0x08,0x44,0x94,0xFF,0xF4,0x08,0xD0,0x94,0xF4,0x40,0x70,0x54,0x85,0x0A,0x0F,0x01, + 0x1C,0x40,0x04,0x04,0x47,0x47,0x07,0x47,0x18,0x98,0x84,0xFF,0x7C,0x20,0xD1,0x00, + 0x90,0x0F,0x4C,0x6B,0xF0,0x7F,0xFF,0x40,0xFF,0xD0,0x04,0xF4,0xF4,0x80,0x4F,0x74, + 0xFF,0x1D,0xF9,0xF4,0xCD,0xFF,0x0F,0x00,0x7F,0x1F,0x80,0xF4,0xFF,0x40,0x0C,0x47, + 0xF7,0x00,0x40,0x04,0x7F,0x4F,0xD4,0x4F,0x00,0x14,0xE1,0xE4,0x70,0x40,0xFD,0x44, + 0x44,0xF0,0xF8,0x08,0xC0,0x00,0xFF,0xC0,0xCC,0x0C,0x44,0xFF,0xFF,0x00,0xD1,0x04, + 0xCF,0x40,0x4D,0x80,0x04,0xFC,0xC0,0x4C,0xD1,0x40,0xF4,0x40,0x0D,0xD4,0xF0,0xF8, + 0x8C,0x88,0x88,0x08,0x40,0x4C,0xC4,0xFD,0x45,0x4F,0xDC,0x4F,0xD0,0xD4,0xFF,0x04, + 0xFF,0x04,0xF4,0xFD,0xDF,0xDF,0x44,0xF4,0x10,0x44,0xC4,0x40,0x40,0x81,0x08,0x80, + 0xF4,0xFF,0x44,0x45,0x40,0x91,0xF4,0x00,0x0F,0x4B,0xF4,0x00,0xF4,0x4D,0xE0,0x54, + 0x01,0xFF,0x7F,0xC4,0xFF,0xDF,0xFF,0xF4,0x0F,0x84,0x10,0x18,0x88,0x88,0x88,0xC0, + 0x54,0xD0,0x6D,0x44,0xF4,0x14,0xFF,0x04,0x04,0x0D,0x4F,0x5F,0x00,0xFF,0xC4,0xF0, + 0x0F,0xF4,0x02,0x39,0x1C,0x81,0x88,0x80,0xC6,0x3F,0x5F,0x47,0x4F,0xC4,0x7F,0x44, + 0x44,0x40,0xF4,0x7D,0x44,0xCC,0x44,0x44,0xF0,0x50,0xC4,0x00,0x4D,0x4F,0xCF,0xF0, + 0x7F,0x14,0x04,0x9C,0x89,0x80,0x88,0x88,0x7F,0xF4,0x4D,0x5F,0xF4,0x7F,0x04,0x44, + 0xFD,0x50,0x44,0x0F,0xFF,0x44,0xF0,0xFF,0x04,0x44,0xF4,0x04,0x04,0x7F,0x44,0xF0, + 0x18,0xC0,0x08,0xF8,0x45,0xC0,0x05,0x44,0x02,0x04,0x07,0x64,0x00,0x40,0x13,0xF7, + 0x44,0x03,0x47,0x74,0x4F,0x7F,0x5F,0x4D,0x80,0x74,0xF4,0x04,0x37,0x45,0xF0,0x74, + 0x40,0x7F,0x52,0xF4,0x0F,0x74,0x04,0x17,0x5F,0x54,0xD5,0xF7,0x40,0x04,0x24,0x07, + 0x24,0x47,0x00,0x10,0x40,0xC7,0x44,0x0F,0x77,0x44,0x0F,0x05,0x32,0x47,0xC0,0x40, + 0x40,0x04,0x07,0xF0,0xFC,0x74,0x4F,0x47,0x44,0x47,0x44,0x87,0x04,0x07,0x04,0x4F, + 0x40,0x7C,0x40,0x75,0x7F,0xFF,0x55,0x00,0x81,0x08,0x08,0x04,0x04,0x00,0x00,0x44, + 0x04,0x50,0x44,0x4F,0x44,0x44,0x40,0x04,0x44,0x07,0xC1,0x77,0x47,0x47,0x57,0xF5, + 0x47,0x40,0x04,0x68,0x5F,0x8F,0xFF,0x8F,0xFF,0x0F,0xC5,0x8F,0x48,0xDF,0x10,0xF1, + 0xF4,0x4C,0xCC,0x41,0x40,0x4F,0x48,0x1F,0x27,0xD5,0x0F,0x86,0x01,0x14,0xC0,0xFE, + 0xFF,0xC4,0x00,0xF4,0xFF,0xF4,0xF8,0x0D,0xC4,0xFC,0x1C,0x00,0x4F,0xD4,0x04,0x05, + 0x45,0xD4,0x44,0x8C,0x81,0x88,0xC8,0xCF,0x7C,0xC4,0x04,0x4F,0xF0,0x44,0x4F,0xFD, + 0x4F,0x51,0x0F,0x44,0xF4,0x0F,0x04,0x44,0xF0,0xDF,0xF5,0xFD,0x0F,0xB8,0x01,0x81, + 0x88,0x08,0x88,0x00,0x4C,0xF4,0x4D,0x44,0xF4,0x40,0xF4,0x04,0xF4,0xD0,0xFF,0xC4, + 0x00,0x0F,0x9C,0xFD,0xFF,0x4D,0xFF,0x7C,0x5F,0xFF,0x0F,0xFE,0xFF,0xFC,0x1F,0x80, + 0x11,0x88,0x80,0x88,0x88,0x40,0xFF,0xFF,0xF4,0xF4,0x5C,0xFD,0x44,0x44,0xCC,0xFF, + 0xF4,0x4D,0x00,0xF0,0xFD,0x40,0x45,0x4C,0xF4,0x40,0x44,0x0C,0x10,0x88,0x80,0x98, + 0x88,0x88,0x88,0x10,0x4D,0xFC,0x44,0xF0,0x00,0x4C,0x04,0x04,0xC4,0x6F,0xF4,0x17, + 0x44,0xCC,0xC4,0x4C,0xF4,0xC4,0xDF,0xFC,0x4F,0x00,0xF4,0x54,0x44,0x04,0x01,0x88, + 0x80,0x88,0x40,0xF0,0xD7,0x50,0xC0,0x4F,0xC4,0x07,0x40,0xFD,0x04,0xFF,0x44,0x20, + 0x4D,0x7C,0x44,0xC0,0xFF,0x0C,0x4F,0xDD,0x4C,0x0F,0x04,0x4F,0x4F,0x70,0x44,0x54, + 0x7F,0xDF,0xF4,0xF0,0xFF,0x5F,0xCD,0x4C,0x4C,0x81,0x19,0x80,0x08,0x18,0x48,0x0D, + 0x07,0x54,0x4F,0x4F,0xD4,0x44,0xC4,0xFC,0x0F,0x4D,0x40,0x4F,0x44,0x77,0x44,0x48, + 0xFC,0xD0,0x44,0x40,0xD4,0x4C,0xE0,0x47,0x44,0x4C,0x4F,0x2F,0x48,0x01,0x80,0x80, + 0x88,0x08,0x80,0x05,0x40,0xC4,0x7C,0xF4,0x0C,0xD4,0x4E,0x77,0x04,0xC4,0x0F,0x4C, + 0xCC,0x46,0x44,0x4D,0x05,0x4C,0xFF,0x44,0x04,0x40,0x4D,0x45,0x40,0x0B,0xC0,0xC7, + 0xC4,0x41,0x88,0x88,0x08,0x48,0x40,0x05,0x44,0x4C,0x0C,0x00,0x4F,0x40,0x44,0x4C, + 0x46,0x00,0x40,0xD4,0xF4,0x40,0xC4,0x74,0x04,0x44,0x44,0x45,0xEF,0x4F,0x40,0x40, + 0x00,0x1C,0xC8,0xC0,0x47,0x44,0x04,0x40,0xA4,0x7F,0xD0,0x4C,0xC4,0x07,0x44,0x4F, + 0x04,0x44,0x7F,0x04,0xD0,0x70,0xFC,0x0F,0x4F,0x47,0x80,0x80,0x18,0x78,0x4D,0x44, + 0x78,0x4D,0xF6,0x70,0x40,0x46,0xF0,0x4E,0x0C,0x0F,0x07,0xC4,0x4F,0x47,0x00,0x08, + 0x35,0x5F,0x2C,0x3F,0x44,0x40,0x47,0x50,0x54,0x47,0x07,0x41,0x04,0x47,0x54,0x47, + 0x4F,0x40,0x16,0x44,0xC0,0x00,0x44,0x44,0x04,0x48,0x44,0x44,0x4F,0x40,0x75,0x00, + 0x44,0x74,0xC5,0x04,0x40,0xF7,0x47,0xFC,0x00,0x44,0x99,0x7F,0xFF,0xF0,0x40,0xFF, + 0x40,0x40,0xF0,0x04,0xCF,0x04,0x38,0xF2,0xF0,0x40,0xD4,0x7F,0xD5,0x80,0xD4,0x0F, + 0x00,0xFF,0x44,0x4F,0x04,0x84,0x2F,0x40,0x09,0x4F,0x7F,0xF4,0x47,0x44,0x04,0x42, + 0x44,0x77,0x24,0xF0,0x11,0x80,0x0F,0x01,0xFF,0x84,0x44,0xF4,0xF0,0xF0,0x4F,0xF4, + 0xF4,0x04,0xFF,0xF0,0x84,0xF4,0x97,0xF4,0x0F,0x44,0x00,0x74,0xF4,0x40,0xFF,0x40, + 0xF0,0xD4,0xFD,0x0D,0x00,0xF0,0x4F,0xFC,0x04,0x4F,0x00,0xFC,0x10,0x54,0x40,0x44, + 0x5B,0x2D,0xF0,0x9F,0xFF,0x00,0xFF,0xCC,0xFC,0x44,0x46,0x88,0x00,0x7F,0x66,0x20, + 0x0C,0xDD,0x44,0x7F,0x64,0x4F,0x4F,0xFF,0x66,0xF4,0xEF,0x00,0x80,0x00,0xC5,0xF2, + 0x4F,0x04,0xF4,0xF4,0x0F,0x40,0xF0,0xF4,0xE2,0x44,0xDF,0x0F,0x40,0x26,0x09,0x18, + 0xF0,0xF7,0x43,0x40,0x70,0xB4,0x0C,0xF0,0x40,0x8D,0x88,0x88,0x60,0x6C,0x74,0xF7, + 0xC0,0x05,0x6F,0x3F,0x3F,0x24,0x04,0xFF,0x4D,0x24,0x0F,0xEF,0x46,0x4F,0x04,0x0C, + 0x14,0x18,0x0F,0xF4,0x77,0x44,0x4C,0x03,0xF6,0x00,0x44,0xFF,0x47,0x00,0xF0,0x40, + 0x46,0x07,0x00,0x81,0x4C,0x74,0x00,0x4F,0x44,0x26,0x4F,0x40,0xF5,0x64,0x41,0x0F, + 0x14,0x00,0x07,0x76,0x74,0x44,0x04,0x40,0x00,0x04,0x00,0x07,0xF4,0xC5,0xFF,0x04, + 0x07,0x40,0x04,0x0F,0xD4,0x40,0x44,0x04,0x0F,0xFF,0x1F,0xF4,0xF7,0x02,0x1F,0xFF, + 0x4F,0x70,0x44,0x00,0xFF,0xFC,0xF0,0x50,0x0C,0x44,0xFF,0xF1,0x04,0xF0,0xF0,0xF3, + 0x44,0x44,0x00,0x7F,0x0F,0xFF,0xFF,0x87,0xF0,0x40,0xCF,0x13,0x45,0x4F,0xF4,0x54, + 0x18,0x88,0x40,0x4F,0xFC,0x40,0x4C,0xFF,0xFF,0xF0,0x40,0x4F,0x50,0x04,0x4F,0xFF, + 0x9D,0x11,0x91,0x00,0x88,0x0D,0xF4,0xF0,0x7F,0xFD,0xF4,0xF4,0x44,0x64,0x4D,0xFF, + 0xC0,0x40,0x5C,0xF4,0xF0,0xF0,0x45,0x24,0x4F,0x64,0xF4,0xF0,0x4C,0x0F,0xFF,0x48, + 0x11,0x89,0x80,0x81,0x18,0x88,0x80,0xF4,0x0E,0xF4,0xC5,0xFF,0x5F,0x44,0x00,0x02, + 0xD4,0xC4,0x4F,0x05,0x44,0x45,0x44,0xF5,0xFF,0xFE,0x0F,0x00,0xCD,0x4F,0xFC,0x4D, + 0x08,0x4D,0xC5,0x54,0xF0,0x44,0x4F,0xF5,0xFE,0xF4,0x7F,0x46,0x04,0x34,0x84,0xD3, + 0x08,0x11,0x81,0x80,0x88,0x88,0x08,0x88,0x80,0xF6,0x04,0xFF,0x04,0x04,0xC4,0x41, + 0xF4,0x03,0x40,0x04,0xD4,0x5F,0x40,0x64,0x40,0xCD,0x45,0x80,0xFF,0x44,0xFF,0x08, + 0xFF,0xFF,0xCC,0x0D,0xCF,0x48,0x5C,0x4F,0xFF,0xF0,0x8F,0x00,0x10,0x00,0x11,0x10, + 0x88,0x98,0x88,0x98,0x88,0xC0,0x60,0x44,0x40,0x04,0x4D,0xDF,0x44,0x40,0x44,0x75, + 0xF4,0xD4,0xF0,0x4C,0x40,0x44,0x14,0xF0,0x44,0xF4,0x07,0xF4,0x00,0x50,0x74,0x70, + 0x65,0x4F,0x04,0xF9,0x4F,0x44,0xF4,0xF4,0x7F,0xF4,0xF4,0x03,0x10,0x01,0x01,0x00, + 0x08,0x08,0x27,0x45,0xF4,0xF1,0xF4,0x04,0x44,0x4F,0xF5,0x74,0x0F,0x0F,0x44,0x74, + 0x5F,0xD0,0x04,0x74,0x46,0x44,0x04,0x5F,0xCC,0x47,0xC4,0x44,0xF4,0x4F,0x4C,0x00, + 0x93,0x00,0xF5,0x44,0x05,0xD4,0xF5,0x5F,0x4C,0x4F,0x44,0x40,0x10,0x11,0x01,0x80, + 0x18,0x11,0x58,0x21,0x01,0x05,0x80,0x40,0x0F,0x44,0x4D,0x41,0xD4,0x40,0xF4,0xF0, + 0x44,0x0C,0x44,0x00,0x44,0x47,0x04,0x44,0x40,0x74,0x3F,0xE4,0x74,0x4F,0xD5,0x4F, + 0x3F,0xE7,0x40,0x0C,0x46,0xF5,0x74,0x7F,0xC4,0x10,0x75,0xF4,0xFF,0x44,0x19,0x01, + 0x18,0x4D,0x08,0x8C,0x88,0x01,0xC0,0x05,0x54,0x40,0xFD,0x44,0x48,0xF4,0x0F,0x04, + 0x45,0x40,0x64,0xF4,0x4C,0xC4,0xC4,0x47,0xD4,0x41,0x4F,0xC4,0x40,0xF0,0x44,0x55, + 0xF0,0x74,0x04,0x14,0x40,0x7D,0x7F,0x4D,0x0F,0x50,0x0C,0x00,0x51,0x80,0x10,0x81, + 0x08,0x04,0x44,0x54,0x07,0x52,0xD4,0x04,0x40,0x4D,0x04,0x44,0x14,0x70,0xF4,0xF4, + 0x44,0x07,0x54,0x44,0x44,0x1F,0x41,0x40,0x60,0x71,0x45,0xF4,0x7C,0x50,0x40,0xF7, + 0xF4,0x71,0x40,0x44,0x1C,0x19,0x00,0x81,0x80,0x04,0xF4,0x01,0x77,0x47,0xF4,0x4C, + 0x44,0x00,0x0F,0xD4,0x47,0x70,0x40,0x44,0x4C,0x22,0x44,0x04,0xFF,0xC4,0x40,0x74, + 0xF4,0x05,0x84,0x45,0x44,0x64,0x40,0x40,0x80,0x01,0x00,0x04,0x81,0x00,0x08,0x54, + 0x4F,0x40,0x4F,0x40,0x60,0x00,0x74,0x0F,0xCD,0x44,0x44,0xF4,0x00,0x44,0x07,0x44, + 0x4D,0x77,0x44,0x04,0x84,0x81,0x4D,0x45,0x00,0x70,0x04,0x44,0x45,0x74,0x40,0x00, + 0x10,0x77,0x40,0x44,0x00,0x40,0x44,0x40,0x54,0x70,0x00,0x00,0x40,0x77,0x44,0x55, + 0x44,0x00,0x40,0x40,0x05,0x45,0x04,0x44,0x44,0x40,0x00,0x02,0x44,0x75,0x04,0x00, + 0x04,0x44,0x17,0x00,0x44,0x47,0x02,0x40,0x44,0x47,0x00,0x47,0x44,0x04,0x10,0x14, + 0xFF,0xF8,0x48,0x90,0x04,0x00,0x44,0x40,0x40,0x4F,0x04,0xD4,0xD5,0x4F,0x74,0x4F, + 0x40,0xD4,0x40,0xFE,0xD4,0x44,0x4F,0x07,0x47,0x10,0x45,0x04,0xD0,0x50,0x04,0x74, + 0x74,0xFF,0xEF,0xCF,0x10,0x0F,0x40,0x10,0x00,0x16,0x01,0x64,0xD7,0xF0,0x08,0x74, + 0x85,0xFC,0x0F,0x8F,0xF4,0x9F,0xD4,0x44,0x40,0x88,0x54,0x4F,0x47,0xC8,0x00,0x47, + 0x84,0x44,0x45,0x44,0x00,0x5D,0x40,0x76,0x14,0xD7,0xF9,0xF4,0x00,0x17,0x47,0xF0, + 0xA5,0x48,0xF4,0x47,0x44,0xF4,0xF4,0xE1,0x04,0xFF,0x8F,0xEE,0x87,0xF4,0x00,0x14, + 0x84,0x44,0x04,0x44,0x04,0xF8,0x07,0xD0,0x04,0xD4,0x80,0x40,0xC4,0x40,0xC4,0x44, + 0x44,0x44,0xC4,0x8C,0x47,0x40,0xC4,0xF0,0xFC,0xF0,0xCD,0x1C,0xCC,0xDC,0x40,0xC0, + 0xC4,0x78,0x4D,0xCC,0x8C,0x4C,0x04,0xCC,0x0C,0x48,0x8F,0x34,0x0F,0x40,0x80,0x47, + 0xFF,0x4F,0x00,0x8C,0x80,0x4C,0x44,0x47,0x0F,0x04,0xFC,0xF0,0x40,0xC3,0xFC,0xFF, + 0xCF,0x01,0x48,0x44,0xCF,0x4F,0x60,0x40,0x4F,0x5F,0x0C,0x0E,0x84,0x47,0xF0,0x0F, + 0xF4,0xFF,0xE4,0x6E,0xCF,0x44,0x5F,0xC4,0x0F,0xF7,0x6E,0x07,0xF4,0xF7,0x44,0x80, + 0x90,0x81,0x88,0x88,0x80,0xF8,0xC4,0x0F,0xD4,0xF8,0x04,0x44,0xFF,0xF5,0xFF,0xFF, + 0x74,0x46,0xDF,0x44,0xF0,0x0F,0x4F,0x40,0x4C,0xF4,0xFC,0xFC,0x50,0xF4,0x54,0x0C, + 0xFC,0xFF,0xF0,0x40,0x4F,0xE9,0x44,0xFE,0xDF,0xF4,0xC0,0x88,0x48,0x88,0x88,0x08, + 0xC4,0x40,0x0C,0xC0,0x44,0xF4,0x4F,0x4C,0x64,0x0D,0x00,0xF4,0xF4,0xFC,0x40,0x5F, + 0x04,0x04,0xF0,0xE0,0x74,0xDF,0x44,0x4C,0xC4,0xDF,0xF4,0x47,0xE7,0xF4,0xFC,0x4F, + 0xF4,0x84,0x91,0x88,0x08,0x88,0x80,0x88,0x80,0x88,0x08,0x00,0xF4,0x0F,0x0B,0x4C, + 0x4C,0xF4,0x45,0x4F,0xF4,0x0F,0x47,0xCF,0x04,0x00,0x4F,0xF4,0x7F,0x44,0x4C,0x64, + 0x04,0x4C,0xF4,0x64,0xEF,0x44,0x6F,0x0F,0xE4,0xF4,0xFC,0x40,0x14,0x90,0x81,0x88, + 0x88,0x80,0x08,0x88,0x88,0xCC,0x04,0xFC,0x00,0x4F,0xF4,0x40,0x0D,0x44,0x45,0xC4, + 0x0F,0x24,0xFE,0xFF,0x44,0xF4,0x4D,0x60,0xF4,0x45,0x54,0x4C,0xFF,0x46,0xC4,0x4F, + 0xFC,0x44,0x4D,0x0D,0x47,0xF7,0x4D,0x4F,0xF4,0xF4,0x74,0xF4,0xF2,0xF7,0x4C,0x00, + 0x04,0x40,0xD0,0x10,0x11,0x19,0x88,0x08,0x88,0x10,0x18,0xA8,0x70,0x7F,0xD4,0x70, + 0xFF,0xF4,0xFF,0x47,0x94,0xF0,0xF7,0xF5,0x44,0x4E,0x4E,0x06,0x4F,0x4F,0x66,0x47, + 0x44,0xF0,0x4E,0x44,0x40,0x47,0xF0,0x0D,0x40,0xC4,0x4C,0x0F,0x0F,0xF4,0x46,0xF6, + 0x44,0x44,0x44,0x74,0x44,0xF0,0x00,0x7F,0x40,0x67,0x04,0x41,0x44,0x02,0x00,0x99, + 0x01,0x81,0x80,0x08,0xC4,0x00,0x41,0xD4,0x0F,0x44,0x04,0x47,0x4D,0x40,0x7F,0xF4, + 0x44,0x4F,0xF4,0xC4,0x00,0x6F,0x00,0xF4,0xE4,0x4D,0x0C,0xDF,0x40,0x8F,0xD4,0x44, + 0xC4,0x4F,0x77,0xC4,0x74,0xF4,0x47,0xC6,0xF4,0xF4,0xDF,0x84,0x04,0x08,0x14,0x89, + 0x88,0x08,0x88,0x08,0x88,0x40,0x45,0x74,0x40,0x05,0x4F,0x54,0xC7,0x40,0x44,0x77, + 0x74,0x4F,0x40,0x4F,0xD4,0x04,0x40,0xF4,0x30,0xD4,0xFF,0x00,0x44,0x04,0x04,0x44, + 0x4F,0x77,0x48,0x44,0xC0,0xFC,0xC7,0xC4,0xF4,0xC7,0x40,0x4C,0x47,0x44,0x04,0x7D, + 0x74,0x40,0x10,0x88,0x00,0x80,0x80,0x44,0x64,0x44,0x47,0x60,0x0F,0x76,0x49,0x7E, + 0x44,0x4E,0x07,0x4D,0x40,0x44,0xF4,0x5F,0x07,0x4C,0x09,0x44,0x0D,0x4F,0x6F,0x46, + 0x35,0x05,0x4F,0x45,0xCE,0x40,0xEC,0x0F,0x16,0x44,0x46,0x74,0x00,0x00,0x08,0x04, + 0xD4,0x74,0x47,0xE4,0x44,0x45,0x44,0x66,0x74,0xF4,0x04,0x0C,0xF4,0x04,0x44,0x42, + 0x7F,0x7F,0x04,0x45,0xC4,0x46,0x44,0x44,0x80,0x08,0x75,0x00,0x05,0x52,0x44,0x7C, + 0xFF,0x44,0x07,0x44,0x64,0x70,0x47,0xFD,0x74,0x14,0x04,0x41,0x00,0x45,0x04,0x47, + 0x74,0x00,0x64,0x46,0x70,0x74,0x44,0x74,0xF0,0x00,0x74,0x44,0x47,0xFF,0x76,0x73, + 0x44,0xE4,0x04,0x75,0x46,0x44,0x01,0x60,0x45,0x45,0xC4,0x60,0xC4,0x44,0x04,0x47, + 0x44,0x44,0x44,0x04,0x44,0x04,0x0F,0x80,0x72,0x04,0x40,0x44,0x07,0x44,0x60,0x4C, + 0x44,0x74,0x44,0x04,0x44,0xF4,0x88,0x90,0x4F,0x00,0x84,0x0C,0x0F,0x04,0x7F,0x88, + 0x08,0x44,0xE4,0x04,0x90,0x0F,0x00,0x0F,0x40,0x4F,0xCC,0x0C,0xF6,0x06,0x88,0x40, + 0x60,0x00,0x06,0x00,0x40,0xE0,0xFF,0xFD,0xC4,0xF0,0x44,0xE0,0xBF,0x85,0x88,0x04, + 0x88,0x88,0x40,0x44,0x0F,0x7C,0x40,0x74,0x40,0x44,0x04,0x40,0xFE,0x84,0x74,0xB4, + 0x44,0x04,0x0C,0x88,0x88,0x80,0x88,0xC0,0x34,0x40,0x04,0xC4,0xF4,0x44,0xF4,0x40, + 0x04,0x04,0x06,0x04,0xF0,0x4C,0x46,0x04,0x0C,0xC0,0x81,0x48,0xF8,0x4F,0x05,0x46, + 0x74,0x44,0x40,0x0F,0x04,0x00,0x00,0xC4,0xCE,0x04,0x00,0x0F,0x00,0x04,0x01,0x00, + 0x40,0x44,0x84,0x64,0x70,0x4A,0x4F,0x0F,0x06,0x44,0x14,0x07,0x74,0x04,0x4E,0x4E, + 0x44,0x45,0x7F,0xFF,0x7C,0x04,0x07,0x0F,0x04,0x8C,0x00,0x00,0x0C,0x48,0xF0,0x00, + 0x44,0x04,0x4F,0x44,0x61,0x0F,0x00,0xF0,0x04,0x06,0x1F,0x40,0xF8,0x44,0x44,0xF4, + 0x4C,0x02,0x44,0x40,0x4D,0x04,0x0F,0x40,0x74,0xC4,0xC0,0x00,0xF4,0x02,0x44,0x47, + 0x64,0xF4,0x44,0x44,0x77,0x44,0x00,0x4F,0x07,0x07,0xFF,0x14,0x44,0x44,0x04,0x70, + 0x4D,0x04,0xF4,0xF7,0x04,0x00,0x75,0x0F,0x44,0x04,0x14,0x00,0xD4,0x70,0x47,0x76, + 0x42,0x44,0x40,0x4F,0x00,0x04,0x54,0x00,0x07,0x40,0x04,0x00,0x40,0x74,0xC0,0x44, + 0x00,0x44,0x00,0x44,0x4D,0x0F,0x7F,0x00,0x8F,0x03,0xF0,0x8F,0xCC,0xF7,0xF1,0xD7, + 0x43,0x04,0x04,0xF7,0x4F,0x54,0x8F,0x40,0x00,0x4F,0x00,0x0C,0xF7,0xF4,0xF0,0xF4, + 0xF4,0x4F,0x00,0xF8,0xF0,0x04,0x04,0xCC,0x04,0x4F,0x85,0x44,0xF4,0x48,0x74,0xCD, + 0xFF,0x01,0x4C,0x14,0x44,0xC8,0xC4,0x84,0x44,0x4D,0x40,0x45,0x04,0x44,0x40,0x84, + 0x41,0x47,0x44,0x74,0x44,0x04,0x8F,0xF4,0x0C,0x01,0x4C,0x89,0x98,0x04,0x40,0x40, + 0xC6,0xDF,0x4F,0x05,0x48,0x44,0x84,0x0F,0x4F,0x0D,0x04,0xF4,0xF4,0x14,0x04,0x48, + 0xFD,0x41,0x04,0x04,0xFC,0x44,0x99,0x88,0x88,0xC8,0x0C,0xD4,0x7F,0xCC,0x7F,0x44, + 0xC4,0x80,0x00,0x40,0x04,0x4F,0x04,0x48,0x40,0xC4,0x80,0xDF,0x44,0xF0,0xFF,0x1C, + 0x80,0x4C,0xF0,0x44,0xF0,0xBB,0x48,0x19,0xC4,0x44,0x4D,0xF7,0x88,0x44,0x04,0xFF, + 0x04,0x44,0x77,0x00,0x40,0x04,0xC4,0x15,0x4E,0x0E,0x00,0xF0,0x44,0x44,0x40,0x44, + 0x4C,0x14,0x40,0x44,0x47,0x47,0x8C,0xC4,0x07,0x47,0x70,0x44,0x07,0x77,0x44,0x4C, + 0x44,0x44,0x4F,0xF6,0xF4,0xF4,0x00,0x0E,0x80,0x44,0x46,0x6F,0x02,0x80,0x40,0xE0, + 0x44,0x0C,0x44,0x24,0xF4,0xC0,0x64,0x88,0x08,0xFF,0x44,0xC4,0x64,0xD8,0x04,0x44, + 0x0F,0x4F,0x40,0x44,0xAD,0x4F,0xF6,0xA1,0x88,0x44,0x04,0x46,0xE4,0x44,0x64,0x0F, + 0x0F,0x60,0xF2,0xC2,0xE4,0x47,0xF0,0x05,0x10,0x08,0x44,0x24,0x25,0x04,0x64,0x47, + 0x64,0xF0,0xF4,0x6F,0xF4,0x4C,0x44,0x80,0x08,0x20,0x00,0x04,0x00,0xEC,0x40,0x00, + 0x66,0x4F,0xF4,0x0E,0x4E,0x6E,0x4E,0x6E,0x4E,0xF5,0xFF,0x0F,0x02,0x07,0x08,0x70, + 0xF6,0x24,0x06,0x04,0x00,0x64,0x40,0x44,0x44,0x04,0xF4,0xE0,0xF0,0xFF,0x0F,0xFF, + 0x03,0x56,0x27,0x40,0x72,0x07,0xC0,0x74,0x4D,0x54,0x40,0x89,0x40,0x00,0x44,0x4F, + 0xCC,0xF2,0x40,0xE4,0x64,0xF4,0x00,0x08,0x0C,0x04,0x44,0x40,0x06,0x04,0x0E,0x6F, + 0x64,0x61,0x60,0xF4,0xCE,0x46,0x40,0x40,0x47,0x06,0x60,0x44,0x24,0x4C,0x70,0x64, + 0x44,0x44,0x40,0x02,0x00,0x47,0x00,0x70,0x00,0x08,0x47,0x44,0x46,0x46,0x4F,0x4C, + 0x4F,0xFF,0x4C,0x1F,0x54,0x00,0x04,0x8F,0x11,0x01,0x4C,0xFD,0x01,0x40,0x40,0xC4, + 0x24,0x54,0x1F,0x40,0x04,0x40,0xD5,0xC1,0xF4,0xD4,0x74,0x44,0x8F,0x2F,0x4D,0xF1, + 0x40,0x34,0xF0,0x07,0xCF,0xF4,0xCF,0xC4,0xFF,0xFF,0x80,0xF0,0x4F,0x9F,0x41,0x4C, + 0x0C,0x00,0x81,0x61,0x1C,0xD1,0x1F,0xFC,0x30,0x20,0x0F,0x00,0xF0,0xFD,0x7F,0x40, + 0x01,0x47,0xF5,0x1F,0x10,0x5F,0x14,0x60,0x07,0x18,0x29,0x57,0xCF,0x02,0x40,0xF4, + 0x04,0x81,0x04,0x7F,0x10,0xF7,0x04,0xF3,0xF4,0x08,0x4D,0x88,0xC4,0x0D,0xF0,0x80, + 0x88,0xD4,0xFC,0x40,0x00,0xF4,0x08,0x88,0xBC,0xFF,0xF8,0x04,0xFF,0x44,0xFF,0x4F, + 0x44,0x9F,0xFC,0xF0,0x88,0x4D,0xF4,0x44,0x44,0x0F,0xFF,0x48,0x7F,0xF4,0x40,0x4D, + 0x44,0xDF,0x0C,0xCC,0x18,0x88,0x40,0x40,0xCF,0x57,0x4F,0x44,0xC4,0x47,0x4F,0xD5, + 0xDE,0xC0,0x80,0x00,0x54,0x5C,0x7C,0x40,0x4C,0x40,0xC4,0x84,0xE8,0xC4,0x44,0xF4, + 0x7F,0x4F,0xCF,0x5E,0xC4,0x88,0xC0,0x40,0x4D,0xC4,0xCD,0x00,0x0C,0x34,0x4C,0x88, + 0x08,0xC7,0x00,0x55,0x45,0x00,0x8F,0x02,0x04,0x47,0x08,0x4F,0x45,0x04,0x0D,0x48, + 0x74,0x85,0x46,0x10,0x71,0x85,0x47,0x84,0x47,0x07,0x40,0x01,0x4F,0xF1,0xF7,0x4F, + 0x41,0x1C,0x0F,0xFF,0x4D,0xD4,0x00,0x4F,0x83,0xF4,0x40,0x0D,0xD0,0x45,0x44,0x04, + 0x00,0x00,0x0C,0x04,0x00,0x44,0x40,0x4F,0x85,0x08,0x4D,0x10,0x15,0x47,0x40,0xF4, + 0x00,0x7F,0xC4,0x0F,0x4F,0x0F,0xD0,0x8C,0x88,0x4F,0x0C,0x9B,0x08,0xF4,0x47,0xF7, + 0x70,0x70,0xD7,0x74,0x40,0x05,0x44,0xCF,0xC4,0x4F,0x4F,0x40,0xCF,0x54,0x0E,0x0F, + 0xF0,0x40,0x4F,0xD0,0xFF,0xF4,0x81,0x00,0x44,0x44,0x40,0x00,0xC0,0x5C,0x40,0xD3, + 0x0F,0x4C,0x51,0x49,0xFC,0x00,0xC0,0xC0,0x40,0x44,0xC4,0xFC,0x4F,0x4F,0x4F,0x04, + 0x8B,0x80,0x44,0xD4,0x00,0x44,0x64,0x44,0x88,0x04,0x44,0x04,0x40,0xFD,0x04,0x44, + 0xF4,0xFC,0xD0,0x4F,0x4D,0xF4,0x4C,0x44,0x00,0x00,0x00,0x00,0xF0,0x00,0xC4,0xFF, + 0x4C,0x44,0xCC,0x40,0x44,0x70,0xCC,0x4D,0xF0,0x08,0x40,0x40,0x40,0x44,0x44,0xC7, + 0x4D,0x4C,0xF0,0xC0,0x84,0x4C,0x7F,0x00,0x4F,0xF4,0xC4,0x45,0x10,0xF4,0xD7,0xF0, + 0x00,0x04,0x04,0x50,0x40,0x04,0xD4,0x44,0x04,0x40,0x44,0xF0,0x44,0xF5,0x0F,0x04, + 0x04,0xFF,0xF0,0xD0,0xF4,0x80,0xFC,0x7F,0x44,0xF4,0x00,0x48,0x4C,0x44,0xC5,0x88, + 0x88,0x4F,0x40,0x04,0xC0,0x00,0xCD,0x44,0xC4,0x4F,0x1D,0x88,0x08,0x08,0xC8,0xC0, + 0x45,0xC4,0xF0,0xFF,0xC4,0x44,0xCE,0x44,0x4C,0x47,0x4F,0xC0,0x8C,0x89,0x08,0x18, + 0x08,0x40,0xF0,0x80,0x44,0x04,0x4C,0x2C,0x0C,0x0C,0x80,0x88,0x00,0x00,0xF4,0x04, + 0x04,0x04,0x44,0x00,0x44,0xFC,0xCF,0x7C,0x44,0x01,0x01,0x80,0x40,0x40,0x0F,0x44, + 0x34,0x40,0x44,0xF5,0xC0,0x00,0xBF,0x4F,0xF0,0xD0,0x54,0xF4,0x4C,0x8D,0x08,0xC4, + 0xC4,0xF4,0xC4,0xF0,0x74,0x45,0x44,0x10,0x8C,0xCC,0x1C,0x00,0x80,0x67,0x07,0x0D, + 0xF0,0x40,0xF4,0x01,0xC4,0xFF,0x44,0x46,0x5F,0x00,0xCD,0x00,0x80,0x45,0x40,0x44, + 0x44,0x44,0x40,0x50,0x4F,0x04,0x4F,0x70,0x00,0x4C,0x2D,0xC0,0x40,0x6C,0x54,0x44, + 0xF0,0x04,0xC4,0x10,0x40,0x00,0x04,0x07,0x54,0xC5,0x04,0x42,0x50,0x40,0x44,0x0C, + 0x40,0x40,0x4C,0x45,0x44,0x77,0x47,0x40,0x40,0x00,0x48,0x00,0x44,0x8F,0x49,0x4F, + 0xFF,0x04,0x44,0x7C,0xFF,0x44,0x04,0x40,0x47,0xD4,0x54,0xFF,0x00,0xEF,0xFE,0xDF, + 0x4F,0x49,0xF4,0xC0,0x4F,0x44,0xF0,0x80,0x04,0x44,0x04,0x90,0x48,0x0F,0x44,0x70, + 0xF9,0x04,0x99,0x00,0x04,0x4D,0x70,0xF7,0x24,0x44,0x44,0x44,0x04,0x4C,0x14,0x00, + 0x44,0x04,0x04,0xF7,0x04,0x47,0x44,0x07,0x65,0xF4,0x04,0x44,0xF4,0xCD,0xF0,0x7F, + 0xFF,0x80,0x40,0x08,0xF4,0xF2,0xC0,0x44,0xF0,0x0F,0xF0,0x04,0x0F,0x00,0x44,0xF4, + 0x14,0xD0,0x0F,0xFF,0xF0,0xC4,0xC5,0x84,0x09,0x00,0x00,0x44,0x0C,0xF4,0x80,0x00, + 0x0F,0xCC,0x64,0x08,0x07,0xF4,0xF4,0x09,0x44,0x44,0x4F,0xF0,0x75,0x4F,0x07,0x7C, + 0x0F,0x84,0x00,0x04,0x04,0x40,0x00,0x47,0x74,0x81,0x00,0xF2,0xC0,0xF0,0xFF,0xF1, + 0x07,0x11,0x04,0x4F,0x34,0x44,0x74,0x17,0x81,0x00,0x04,0xF4,0x04,0x44,0x04,0x40, + 0x74,0x17,0x00,0x40,0x74,0x70,0x44,0x04,0x4F,0x00,0x4F,0x8F,0xFC,0x4F,0x30,0xF4, + 0xFC,0x90,0x4F,0x4C,0x4F,0x44,0x84,0x40,0x84,0x3F,0xF4,0xDD,0x4F,0x00,0x88,0xF4, + 0x0C,0x44,0x80,0x08,0x7C,0x47,0x8C,0x77,0x41,0xC4,0x44,0x45,0x04,0x07,0x00,0xD4, + 0x44,0x10,0x77,0x70,0x01,0xF7,0x10,0x10,0x40,0x11,0x10,0x28,0xF4,0x01,0x31,0xF8, + 0x1F,0xF1,0xF4,0x0D,0x00,0x43,0xF0,0xF4,0x01,0x00,0x00,0x47,0xF1,0x4F,0xC0,0xF0, + 0x44,0x81,0x4D,0x0D,0x4D,0x9D,0x00,0xF4,0xF4,0x44,0x88,0x00,0xF5,0xF4,0x40,0x0F, + 0x0F,0x44,0xDC,0x0F,0x0D,0xCC,0x6F,0x4C,0xC4,0xD4,0x54,0x01,0x3C,0x48,0x08,0x08, + 0x04,0x00,0xD4,0xC7,0xF5,0xF4,0x7F,0xF4,0xFF,0x0F,0x0F,0x0F,0x0C,0x88,0x90,0x00, + 0x4E,0x48,0x54,0x54,0x40,0x00,0x43,0x0F,0xD5,0x4C,0xF5,0xC4,0x84,0x81,0x20,0x08, + 0x08,0x04,0xC4,0x71,0x04,0x74,0xD4,0x74,0x4C,0x01,0xFF,0xF4,0x55,0x43,0xFD,0x10, + 0xF4,0x08,0x04,0x88,0x88,0x89,0xFC,0x40,0xF0,0x00,0x4F,0x40,0x4F,0x00,0x00,0x04, + 0xF7,0x00,0x07,0xFF,0x70,0x54,0x0D,0x14,0x80,0x82,0x44,0x00,0xC4,0x4C,0xD4,0x44, + 0xC7,0x44,0xD7,0x4D,0x74,0x4C,0x10,0x08,0xC4,0x54,0x04,0xD1,0x44,0x40,0x48,0x4C, + 0x45,0x44,0x40,0xF4,0x40,0xC4,0x5C,0xC4,0x54,0x13,0x01,0x18,0x40,0x00,0x44,0xD6, + 0x74,0x54,0x40,0xFC,0x44,0x7F,0x44,0x00,0x04,0x40,0x00,0x50,0x4D,0x40,0x74,0xF7, + 0x8D,0x70,0x40,0x40,0x44,0x04,0xF7,0x10,0x05,0x40,0x05,0x41,0x41,0x44,0x04,0x50, + 0x07,0x40,0x57,0x44,0x40,0x44,0x07,0x44,0x00,0xF4,0x58,0x00,0x44,0x84,0xC8,0x41, + 0x54,0x31,0x44,0x00,0xF4,0x14,0x54,0x00,0xC1,0x0F,0xF4,0xF4,0x0F,0x10,0x88,0xFC, + 0x50,0x4D,0xF9,0x30,0x05,0x18,0x10,0x4B,0xF0,0xFF,0x44,0x00,0xF0,0x44,0xDC,0x4F, + 0x81,0x01,0xD0,0x80,0x0C,0x4F,0x8C,0x05,0x44,0x05,0xC4,0xCF,0xC1,0x00,0x4D,0xF7, + 0x0F,0x05,0x00,0x70,0x0C,0x04,0x04,0xD4,0x44,0x05,0x05,0x45,0x0D,0xF1,0x40,0x07, + 0x47,0x47,0x77,0x67,0x46,0x7F,0x74,0x44,0x47,0x44,0x57,0x74,0x77,0x77,0x45,0x44, + 0x7F,0x0F,0x00,0x80,0x44,0xF0,0x07,0xF7,0x47,0x75,0x70,0x04,0x74,0x47,0x44,0x54, + 0x44,0x77,0x77,0x47,0x00,0x14,0x01,0x55,0x47,0x44,0x44,0x05,0x04,0x50,0x04,0x47, + 0x70,0x57,0x00,0x47,0x47,0x46,0x40,0x4F,0x74,0x77,0x10,0x83,0x70,0x44,0x54,0x60, + 0x44,0x40,0x44,0x04,0x14,0x00,0x44,0x76,0x40,0x74,0x04,0x04,0x10,0x11,0x47,0x54, + 0x46,0x57,0x00,0x4C,0x40,0x14,0x77,0x5D,0x75,0x07,0x77,0x40,0x47,0x77,0x74,0x77, + 0x44,0x04,0x44,0x74,0x40,0x77,0x04,0x14,0x10,0x05,0x10,0x42,0x47,0x47,0x71,0x47, + 0x77,0x60,0x01,0x44,0x77,0x04,0x07,0x74,0x44,0x45,0x07,0x44,0x40,0x74,0x00,0x00, + 0x10,0x40,0x11,0x00,0x74,0x57,0x44,0x44,0x44,0x45,0x64,0x44,0x00,0x74,0x64,0x77, + 0x74,0x75,0x44,0x01,0x40,0x74,0x40,0x67,0x74,0x45,0x54,0x74,0x54,0xD5,0x74,0x47, + 0xF4,0x74,0x44,0xE7,0x44,0x11,0x14,0x00,0x44,0x46,0x77,0x45,0x54,0x05,0x14,0x47, + 0x64,0x44,0x00,0x11,0x74,0x67,0x70,0x40,0x07,0x44,0x44,0x44,0x74,0x54,0x57,0x14, + 0x44,0x1F,0x00,0x44,0x15,0x44,0x47,0x71,0x41,0x71,0x45,0x47,0x46,0xF4,0x07,0x80, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x80,0x88,0x88,0x08,0x80,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88, + 0x88,0x88,0x80,0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x80, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x0F,0x4F,0x0F,0x40,0x44, + 0x00,0x48,0xDC,0x00,0x04,0x44,0x57,0x41,0xDF,0x00,0xFF,0x80,0x0D,0x48,0x44,0xD4, + 0xC5,0x48,0x40,0x54,0xDD,0x7F,0x44,0x0F,0x87,0x4F,0x78,0x74,0xF1,0x44,0x44,0x4C, + 0x80,0x51,0x70,0x55,0x47,0x4F,0x4F,0x0F,0x40,0x04,0x4F,0x04,0x00,0x4F,0xD4,0x8F, + 0xC4,0x14,0x4F,0xC4,0x77,0x00,0x44,0xD1,0x4C,0x4F,0x40,0x45,0xFF,0x44,0xFC,0xC4, + 0xF4,0x44,0xF0,0x41,0x40,0x4F,0x4F,0x4E,0x44,0x07,0xFF,0x40,0x08,0x40,0x04,0xE4, + 0xFF,0x44,0xC0,0x0D,0xF4,0x74,0x44,0x4C,0xCF,0xD4,0x44,0x40,0x74,0xD0,0x4F,0x44, + 0xFF,0xF0,0xFD,0x4F,0x20,0xD0,0xCF,0x44,0x4F,0x0D,0xFC,0xFC,0xDF,0x40,0x0D,0x44, + 0x58,0x08,0x84,0x8C,0xCD,0x0C,0x24,0x00,0x84,0xF0,0xC4,0xCF,0x48,0x90,0xF0,0xF4, + 0x00,0xE8,0x00,0x4F,0x04,0x8F,0x88,0x40,0x44,0x0D,0x08,0x07,0x0F,0x0F,0x44,0x17, + 0x10,0x01,0x04,0x40,0x81,0x08,0x04,0x70,0xC7,0x77,0x41,0x75,0x54,0x00,0x70,0xF7, + 0x08,0x84,0x7F,0xFF,0xF0,0xF4,0x0F,0x40,0x04,0xD4,0x40,0x0F,0x4D,0xFD,0xFC,0x80, + 0xF8,0x4F,0xF8,0x00,0xF0,0xCF,0xD1,0xFC,0xF0,0x0F,0x4F,0x80,0x04,0x0F,0x88,0x88, + 0x88,0xFC,0x4F,0x49,0x44,0x04,0xCF,0x4F,0x44,0x00,0x44,0xCD,0xD4,0xFF,0xDC,0x0F, + 0xF4,0x40,0xFF,0x84,0x88,0x88,0xC8,0xD0,0xFC,0xCC,0x4F,0x08,0x4F,0x4C,0xFD,0x04, + 0x44,0x0F,0x70,0x3F,0x97,0x0F,0x80,0x88,0x88,0x88,0x48,0x0C,0x4E,0x7B,0x40,0x4C, + 0x40,0x74,0x44,0x40,0x70,0x60,0x4C,0xF0,0x94,0x18,0x00,0x08,0x78,0x04,0x40,0x0F, + 0x00,0x40,0x04,0x4D,0x08,0xFC,0x4C,0x47,0xFF,0xD4,0xFF,0x00,0x80,0x48,0x04,0x14, + 0x4C,0x04,0xF4,0xC7,0xC0,0x70,0x80,0x4D,0xFF,0x44,0x0D,0x44,0xF7,0x8F,0x88,0xF8, + 0x0F,0x5D,0x00,0x44,0x4F,0x4F,0x44,0xF0,0x80,0x10,0x50,0x40,0x4C,0xC7,0xFF,0x44, + 0x07,0xF4,0x01,0x4C,0x5F,0x48,0x04,0x04,0x45,0xF4,0x74,0x40,0x41,0xCF,0x74,0x77, + 0x8F,0xCF,0x44,0x4F,0x51,0x0C,0x7C,0x40,0x54,0x14,0x40,0x40,0x57,0x45,0x40,0x74, + 0x45,0xF4,0x70,0xF4,0x47,0x0F,0xFC,0x04,0x00,0xF4,0x0F,0x40,0x44,0xF7,0x0F,0x4F, + 0xDC,0x0D,0xFC,0x78,0x57,0x47,0xFF,0x01,0x4D,0x0F,0x4C,0x15,0x01,0xF0,0x4F,0xFF, + 0xE4,0x8C,0x40,0x00,0x1C,0xFF,0x8F,0xC1,0x88,0xD4,0xFC,0xFF,0xFD,0x84,0x44,0x48, + 0x07,0x04,0x6C,0xF0,0xC0,0xC0,0x00,0xC4,0x44,0x44,0x40,0x44,0x7D,0x4D,0x14,0xD4, + 0x40,0x41,0x07,0x07,0x4D,0x51,0x44,0xFF,0x78,0x8F,0x4C,0x53,0x87,0x08,0xC4,0xCF, + 0x04,0x48,0x4C,0x00,0x08,0xFC,0xF0,0xCE,0xC4,0x4F,0x04,0x80,0xFC,0x46,0xF8,0xF4, + 0xC4,0x44,0xFC,0x4B,0xEC,0xD8,0xFF,0xFE,0xFC,0xF0,0x4C,0xE4,0xFF,0x74,0xF6,0x2C, + 0x84,0x44,0x18,0x80,0x08,0x88,0x88,0x88,0xF0,0xDF,0xEF,0xF4,0x58,0xF0,0x0D,0xFF, + 0xFC,0xD0,0xFC,0x7F,0x04,0xD4,0x44,0xC0,0xF4,0x54,0x4D,0x84,0xD0,0xD5,0x20,0x06, + 0xE4,0xFF,0xFF,0xCD,0xFC,0x00,0x4C,0x89,0x80,0x00,0x88,0xF5,0x41,0xC8,0x0D,0x04, + 0x04,0x14,0x44,0xC4,0x4F,0xF4,0xCC,0xF0,0xF0,0xC5,0xFF,0x4F,0xFF,0x4C,0x0C,0x40, + 0x4F,0xC4,0x54,0xE8,0xF4,0x47,0x44,0xF4,0xED,0x4F,0x0C,0x04,0x01,0x88,0x08,0x88, + 0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x00,0x70,0x54,0xF4,0x0C,0xF4,0xCD,0x44, + 0x40,0x40,0x90,0x5C,0xF4,0x47,0x44,0x4F,0x04,0xDC,0x44,0x47,0x4E,0xC5,0x48,0x1F, + 0x0D,0x47,0x44,0x44,0xED,0xFF,0x00,0x44,0x9C,0x88,0x18,0x88,0x88,0x08,0xF8,0x40, + 0xFC,0x44,0xF4,0xC4,0x64,0x4F,0x0F,0xC5,0x40,0x30,0x4C,0x4F,0x4D,0x40,0xCF,0xD4, + 0xCD,0x44,0xC4,0x40,0xF4,0x7C,0x04,0x74,0xFF,0x4F,0x47,0x14,0xEC,0x54,0xF4,0x44, + 0xC0,0xF0,0x0F,0x5C,0x40,0xD6,0xFF,0xCF,0xC4,0x54,0x00,0x00,0x08,0x40,0x88,0x00, + 0x01,0x41,0x88,0x88,0x78,0x41,0x47,0x40,0xF4,0x44,0x54,0x44,0x4F,0x44,0xFD,0x40, + 0x04,0x44,0x44,0x4D,0x70,0x40,0x44,0x05,0xC4,0x04,0x04,0xF4,0xC0,0xFC,0x48,0x44, + 0xF4,0xF1,0x40,0x47,0xD4,0xF0,0xDF,0x75,0x94,0xC0,0xF4,0x5C,0x5C,0x0F,0x40,0x04, + 0x00,0x0D,0x01,0x84,0x88,0x90,0x48,0x4C,0x47,0x00,0x07,0xC0,0xF4,0x44,0x4F,0x54, + 0xF4,0x04,0x04,0x40,0x44,0x44,0x14,0xC4,0x44,0x0F,0x0C,0x04,0xDF,0x7C,0x87,0xF0, + 0xD6,0x06,0x4F,0x47,0xF0,0x7D,0xF4,0x44,0xFD,0xC4,0x04,0x4D,0x10,0x43,0x80,0x80, + 0x08,0x80,0x80,0x48,0x44,0x44,0x0F,0x47,0x4C,0x44,0x07,0x44,0x40,0x44,0x4F,0xD4, + 0x05,0x04,0x00,0x45,0x44,0x44,0x4C,0x44,0xF0,0xF4,0x57,0xF4,0x47,0x0F,0x44,0xD6, + 0xF4,0x60,0x64,0x45,0x44,0xC4,0x7F,0x64,0x44,0x00,0x10,0x80,0x88,0xC8,0xF8,0x24, + 0x75,0xF0,0x44,0x44,0xFD,0x1D,0x40,0x07,0x40,0x60,0x54,0x5C,0xE5,0x41,0x40,0x0C, + 0x44,0x74,0x4C,0x44,0x7F,0x47,0x74,0x04,0x40,0x08,0x48,0x54,0xC4,0xCC,0x04,0x0D, + 0x45,0x44,0xCF,0xF4,0x45,0x45,0x44,0xE4,0x75,0x00,0x47,0x14,0x54,0xF4,0x4D,0x44, + 0x44,0x44,0x0D,0x47,0x7F,0x1F,0x01,0xF9,0x4E,0x40,0x44,0xC4,0xD4,0x07,0x40,0x44, + 0xB4,0x44,0x44,0x44,0xF4,0x40,0x70,0xF6,0x4D,0x84,0xF0,0x40,0x44,0x04,0x7F,0x44, + 0x40,0x44,0x7F,0x04,0xF4,0x47,0x44,0x40,0x44,0x04,0x00,0x74,0x54,0xF7,0x40,0xE5, + 0x44,0x03,0xC4,0x77,0x40,0x57,0x04,0x00,0xC0,0x10,0x00,0x7B,0x44,0x47,0x04,0x44, + 0x44,0x45,0x44,0xC4,0xC0,0x04,0x74,0x14,0x41,0x44,0x44,0x04,0x4C,0x44,0x0C,0x74, + 0x04,0x40,0x00,0x44,0x04,0x40,0xD4,0x8F,0x8F,0x44,0x7F,0x04,0x40,0x69,0x07,0x7F, + 0x40,0x4C,0x44,0x70,0x44,0xD4,0x48,0x4C,0xD4,0x40,0x04,0x40,0xF0,0xDC,0x8C,0x88, + 0x88,0x08,0x40,0x44,0x00,0xDF,0xCF,0x04,0x44,0xF0,0xD4,0x44,0x44,0x04,0xCC,0x04, + 0x40,0xF4,0x4F,0xC0,0xFC,0x1D,0x08,0xD0,0xCD,0x40,0xCC,0x4D,0x44,0x4C,0x44,0x44, + 0x4C,0x44,0x4D,0xFD,0xD4,0xF8,0x14,0x89,0xCC,0x40,0x0F,0x44,0xFC,0xF4,0x44,0xFD, + 0x00,0x44,0x0F,0x04,0xD4,0x44,0xF5,0x19,0x88,0x88,0x48,0x44,0xDD,0x54,0x00,0x0F, + 0x4F,0xFF,0x44,0xC5,0xDF,0x4D,0xD4,0x04,0x50,0xCD,0x80,0x80,0x4F,0x4F,0x0F,0x0C, + 0xC4,0xCC,0xD4,0x44,0xD4,0x04,0x44,0x0C,0xC4,0x44,0x4D,0xD0,0x04,0xD4,0x04,0xDC, + 0x44,0x44,0x00,0x84,0x98,0x10,0x4D,0x4F,0x44,0xD4,0x74,0xF4,0xD4,0x44,0x44,0x74, + 0x4D,0xD4,0xCC,0x47,0x47,0x45,0x44,0x4D,0x08,0x40,0x4F,0x4F,0x47,0xC4,0x88,0x18, + 0x40,0xCF,0xC4,0x40,0x4C,0x80,0xF0,0x40,0x44,0xC4,0x04,0xC4,0x04,0x44,0x44,0xF4, + 0x00,0x47,0x04,0x00,0x08,0xD4,0xCC,0xD4,0x04,0xF4,0xC4,0x44,0x44,0x5F,0xD4,0x44, + 0x0D,0x44,0x47,0x1D,0x44,0xDC,0x04,0x00,0xC1,0xCD,0x04,0x40,0x44,0xC0,0x44,0x44, + 0x4F,0x44,0xC4,0x44,0x04,0x4C,0x46,0x78,0x00,0x47,0x04,0x55,0xF0,0x74,0x04,0x4F, + 0x44,0xC4,0x70,0x04,0x44,0x4C,0x54,0x11,0x54,0xC0,0xD4,0x4D,0x40,0xC0,0x44,0x60, + 0xD4,0x7F,0x44,0x14,0x44,0x44,0x04,0x44,0x74,0x4C,0x40,0x47,0xD4,0x70,0x4C,0x44, + 0x4F,0x41,0x8D,0x03,0x04,0x44,0xFF,0x04,0x00,0x77,0x48,0xF4,0xF0,0x74,0x70,0x01, + 0xF0,0xFF,0x88,0x40,0xCF,0xF4,0x48,0x48,0x4F,0x0F,0x54,0xF4,0x40,0x00,0xD4,0xFF, + 0xF4,0x4F,0x88,0x00,0x4F,0xF0,0xF4,0x04,0x40,0x4F,0x40,0x7F,0x54,0x44,0x08,0x47, + 0x40,0x0D,0x0D,0x40,0x04,0xF4,0x84,0x01,0xD1,0x04,0x13,0xD4,0x44,0x04,0x4C,0x14, + 0xF4,0x1F,0x91,0x08,0xC0,0x44,0x44,0x3C,0x04,0x0C,0xFF,0x44,0xFD,0x44,0x77,0xF4, + 0x70,0x88,0x88,0x40,0x0F,0x40,0x04,0x44,0xCC,0xF5,0x2F,0x44,0xDF,0x44,0x7D,0x0D, + 0x40,0x0D,0x41,0x74,0x40,0x4D,0x05,0x04,0x4F,0xFF,0x44,0x44,0xE6,0x8C,0x10,0x45, + 0xC0,0x44,0xF0,0x44,0x40,0xDF,0x44,0x44,0x4C,0x44,0x48,0x4F,0x07,0x70,0x44,0x04, + 0xF0,0x14,0x0F,0x04,0x40,0x40,0x15,0x40,0x44,0x44,0x00,0x45,0x44,0x44,0x44,0xFD, + 0x45,0x44,0x07,0x0D,0x40,0x47,0x54,0x54,0x40,0x47,0x05,0x14,0x40,0xC4,0x04,0xF5, + 0xF0,0xF4,0x40,0x3F,0x05,0x71,0x00,0x70,0x00,0x70,0x40,0x57,0x05,0x41,0x44,0x44, + 0x70,0x44,0x04,0x15,0x30,0x07,0x45,0x54,0x00,0x17,0x00,0x44,0x40,0x07,0x70,0x54, + 0x87,0x08,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x4F,0x44,0x0C,0x40,0x4D,0x5D,0x48, + 0x44,0xF4,0xC4,0x1D,0x44,0xC0,0x44,0x80,0x44,0xC4,0x07,0x44,0x07,0x44,0x04,0x44, + 0x0F,0x77,0x04,0xC0,0x07,0x07,0x07,0x47,0x45,0x74,0x40,0x77,0x07,0x70,0x70,0x74, + 0x00,0x74,0x70,0x40,0x00,0x07,0x74,0x00,0x74,0x10,0x07,0x07,0x40,0x77,0x05,0x4C, + 0x54,0x00,0x44,0x05,0x0D,0x04,0x44,0x44,0x57,0x05,0x77,0x44,0x44,0x70,0x00,0x07, + 0x47,0x77,0x00,0x07,0x74,0x50,0x75,0x07,0x77,0x77,0x64,0x44,0xE0,0x44,0x05,0x40, + 0x40,0x45,0x75,0x74,0x90,0x48,0x77,0x40,0x50,0xF4,0x70,0x04,0x47,0x05,0x00,0x07, + 0x77,0x70,0x77,0x47,0x07,0x46,0x11,0x00,0x07,0x07,0x00,0x04,0x74,0x44,0x47,0x76, + 0x04,0x47,0x47,0x74,0x44,0x70,0x71,0x70,0x40,0x47,0x44,0x47,0x44,0x71,0x47,0x45, + 0x75,0x05,0x05,0x77,0x04,0x72,0x70,0x47,0x74,0x54,0x44,0x76,0x07,0x47,0x04,0x47, + 0x77,0x07,0x47,0xD4,0x04,0x44,0x41,0x47,0x47,0x44,0x47,0x77,0x74,0x77,0x74,0x04, + 0x17,0x44,0x44,0x4D,0x07,0x74,0x07,0x44,0x44,0x70,0x40,0x44,0x70,0x44,0x44,0x05, + 0x74,0x04,0x40,0x44,0x74,0x44,0x01,0x77,0x44,0x44,0x44,0x45,0x47,0x17,0x47,0x50, + 0x04,0x40,0x40,0x4F,0x04,0x54,0x4F,0x70,0x17,0x01,0x07,0x70,0x44,0x44,0x70,0x44, + 0x07,0x14,0x44,0x04,0x04,0x47,0x05,0x05,0x03,0x77,0x44,0x07,0x54,0x07,0x04,0x44, + 0x88,0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x08,0x88,0x88,0x88,0x88,0x08,0x88,0x88, + 0x88,0x88,0x88,0x08,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x80, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0xF8,0x40,0x41,0x44,0x74, + 0xF0,0x44,0x40,0xCF,0xC7,0x47,0x4F,0x45,0x05,0x00,0xF4,0x44,0x00,0x0F,0x44,0x40, + 0xF0,0x0D,0x44,0x04,0x44,0xFF,0x45,0x40,0x44,0xC4,0x40,0x44,0xFD,0x4F,0x41,0x00, + 0x44,0x0F,0xD4,0x04,0xD0,0x0F,0x5F,0x41,0x44,0x44,0x4D,0x40,0x4D,0x04,0x74,0x07, + 0x77,0x47,0x44,0x70,0x77,0x77,0x17,0x71,0x07,0x75,0x47,0x77,0x47,0x74,0x77,0x74, + 0x77,0x77,0x47,0x70,0x07,0x07,0x14,0x41,0x70,0x74,0x40,0x40,0x40,0x17,0x47,0x47, + 0x47,0x77,0x47,0x47,0x04,0x07,0x74,0x04,0x44,0x40,0x46,0x00,0x44,0x75,0x77,0x04, + 0x04,0x04,0x77,0x74,0x47,0x17,0x70,0x50,0x05,0x70,0x45,0x47,0x40,0x40,0x80,0x88, + 0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x08,0x80,0x88,0x08,0x88,0x88,0x88,0x08, + 0x88,0x88,0x0F,0xDF,0x44,0xF0,0xD4,0x44,0x1F,0xF4,0x8F,0xFC,0x44,0x40,0x40,0x00, + 0xD4,0x00,0xFC,0x00,0x40,0x8F,0x44,0x44,0xC4,0x44,0x4C,0x04,0x70,0x40,0x04,0xC0, + 0x44,0xF0,0x40,0x40,0x07,0x44,0x44,0x44,0x80,0xF4,0xCC,0x44,0x48,0x0F,0x0C,0xCF, + 0x40,0x85,0x48,0x4E,0x04,0xF0,0x4F,0xFC,0xC4,0x40,0x40,0xCD,0x44,0xFD,0xF4,0xD8, + 0x74,0xF4,0x0C,0x44,0x4F,0xDD,0x0C,0xF4,0x44,0xF4,0x94,0x80,0x88,0x8C,0xC5,0x54, + 0x04,0x44,0xC4,0x44,0xD1,0x0F,0x48,0xF0,0x47,0x44,0x4C,0x44,0x44,0x44,0xD4,0xDF, + 0x44,0xCC,0x44,0x44,0xC0,0x4B,0x08,0x8C,0xC7,0x40,0xF5,0x04,0xC4,0x08,0xC4,0x44, + 0xCC,0x0F,0x4F,0xF0,0xFF,0xCF,0x45,0x04,0x85,0x48,0x54,0x44,0xF0,0x44,0x44,0x74, + 0x47,0x54,0x45,0x4C,0xC0,0x04,0xCC,0xC0,0x08,0x4D,0x0F,0x0F,0x04,0x44,0x0D,0x80, + 0xF0,0x04,0xD5,0xF4,0x44,0x57,0x74,0x84,0x5C,0x54,0x4D,0x44,0x14,0x04,0x48,0x4C, + 0x54,0x40,0x44,0x04,0x44,0xF7,0x0F,0x90,0x11,0x0C,0x00,0x00,0x00,0x0C,0x40,0x01, + 0x06,0x04,0x10,0x01,0x41,0x77,0x77,0x48,0x40,0x47,0x04,0x40,0x04,0x50,0x44,0x74, + 0x44,0x11,0x40,0x44,0x44,0x70,0x04,0x44,0x40,0x00,0x44,0x44,0x47,0x74,0x15,0x47, + 0x44,0x74,0x70,0x44,0x74,0x45,0x41,0x04,0x44,0x77,0x77,0x44,0x14,0x74,0x77,0x76, + 0x04,0x40,0x44,0x27,0x70,0x07,0x04,0x74,0x00,0x74,0x44,0x44,0x77,0x70,0x00,0x77, + 0x04,0x45,0x77,0x45,0x74,0x40,0x71,0x47,0x44,0x44,0x44,0x54,0x44,0x44,0x61,0x74, + 0x54,0x57,0x05,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x80,0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x80,0x88,0x88,0x88,0xF8,0x0F,0xD9, + 0x00,0xF0,0x00,0x16,0x8F,0x80,0x70,0x75,0xFF,0x07,0x04,0x18,0x80,0x11,0x81,0x58, + 0x80,0x0F,0xFD,0x84,0x48,0x40,0x40,0x0F,0xF8,0xC4,0xCF,0x44,0x88,0x81,0x88,0x88, + 0x44,0x4D,0xDC,0x0F,0x9C,0xFF,0xF0,0x1C,0x0F,0x82,0x45,0xF4,0xBD,0x45,0xF4,0x44, + 0xFF,0xFE,0xFC,0x0F,0x82,0xF8,0xF4,0xF1,0xFF,0x18,0x7F,0xFD,0x70,0xCF,0xF4,0xFF, + 0xFF,0x7F,0x04,0x18,0x00,0x00,0xC0,0xCF,0x70,0x07,0xF4,0x0D,0x1F,0x80,0x4F,0x4F, + 0xF0,0x0F,0x1C,0xF0,0x50,0x77,0xF0,0xD7,0xFF,0xFD,0x77,0x81,0x7D,0xC0,0x67,0x07, + 0x37,0xFC,0x90,0x40,0x7D,0x40,0xF0,0x7F,0x04,0x47,0xFC,0x75,0x47,0x47,0xF7,0xF4, + 0x7F,0xFF,0x47,0x74,0x1E,0xC7,0x40,0x70,0xF4,0x80,0xE4,0xC0,0xE4,0xC0,0x80,0x44, + 0xC4,0xFE,0x40,0x4F,0x03,0x0F,0x08,0xF8,0xFE,0xC4,0xFC,0x0C,0x8F,0x88,0x40,0x4C, + 0xF0,0x40,0xC8,0xC0,0x04,0x4F,0x00,0x8D,0x88,0x80,0x44,0xC4,0x44,0xD4,0xCC,0x42, + 0xF4,0x4D,0x45,0x88,0x4F,0xC4,0xF4,0xC0,0x44,0x44,0x7C,0x10,0x48,0x44,0xF4,0x4C, + 0x44,0x4F,0x4C,0x44,0x44,0x40,0x40,0x44,0x44,0x07,0x24,0x44,0xF4,0x44,0x44,0x4C, + 0x44,0xCC,0x04,0x64,0x44,0x44,0x74,0xC4,0xC5,0x47,0x44,0x04,0xC4,0x44,0x00,0x44, + 0x44,0xC0,0x44,0x4C,0xF4,0xFF,0xFF,0xCF,0x0C,0x4F,0x41,0xC5,0x05,0x0C,0x80,0x48, + 0xC4,0xDF,0xDC,0x00,0xF4,0x0F,0x0F,0xCC,0x88,0x5D,0xFC,0xF8,0xCF,0x04,0x80,0x88, + 0x44,0x45,0xC4,0xF4,0xF0,0xF4,0xF8,0x40,0xCD,0x4F,0x00,0x10,0x40,0xCC,0x47,0x44, + 0x44,0xCD,0x41,0x40,0x04,0x7D,0xC6,0xFE,0x64,0x44,0xFF,0x40,0x41,0x0D,0x44,0x04, + 0x57,0x44,0x40,0xF5,0xF1,0x78,0xFF,0xFF,0xF7,0x40,0x44,0x61,0x47,0x14,0x7F,0x10, + 0x10,0x74,0x04,0x75,0x44,0x46,0x44,0x04,0x40,0x40,0x74,0x41,0x44,0x00,0x41,0x50, + 0x44,0x44,0x44,0x44,0x40,0x04,0x74,0x41,0x76,0x06,0x55,0x64,0x40,0x04,0x04,0x07, + 0x00,0x40,0x44,0x44,0x10,0x00,0x41,0x04,0x44,0x44,0x07,0x54,0x44,0x06,0x40,0x74, + 0x06,0x00,0x71,0x04,0x75,0x54,0x44,0x44,0x45,0x44,0x04,0x74,0x00,0x75,0x00,0x07, + 0x44,0x43,0x67,0x47,0x00,0x00,0x44,0x40,0x14,0x04,0x08,0x04,0x44,0x44,0x44,0x45, + 0x07,0x74,0x70,0x44,0x04,0x44,0x44,0x0C,0x70,0x70,0x54,0x47,0x47,0x55,0x47,0x00, + 0x44,0x44,0x44,0x44,0x44,0x44,0x14,0x08,0x00,0x64,0x44,0x76,0x30,0x40,0x04,0x00, + 0x44,0x44,0x44,0x44,0x4C,0x44,0x46,0x74,0x44,0x47,0x40,0x40,0x44,0x00,0x40,0x44, + 0x44,0x00,0x07,0x44,0x54,0x07,0x10,0x44,0x44,0x11,0x00,0x40,0x47,0x45,0x07,0x44, + 0x44,0x04,0x06,0x05,0x44,0x40,0x44,0x54,0x07,0x44,0x44,0x04,0x57,0x47,0x40,0x66, + 0x67,0x57,0x46,0x47,0x47,0x74,0x41,0x77,0x00,0x41,0x54,0x04,0x44,0x11,0x04,0x08, + 0x00,0x00,0x01,0x44,0x42,0x76,0x74,0x44,0x44,0x04,0x47,0x45,0x44,0x74,0x05,0x04, + 0x45,0x40,0x44,0x40,0x00,0x0C,0x45,0x03,0x44,0x00,0x70,0x44,0x40,0x44,0x07,0x07, + 0x04,0x44,0x00,0x00,0x44,0x04,0x47,0xC4,0x40,0x04,0x47,0x57,0x44,0x47,0x40,0x44, + 0x40,0x64,0x44,0x74,0x44,0x04,0x37,0x45,0x47,0x44,0x44,0x40,0x10,0x00,0x00,0x00, + 0x04,0x74,0x04,0x40,0x05,0x0C,0x44,0x44,0x75,0x04,0x44,0x5D,0x45,0x04,0x54,0x46, + 0x70,0x44,0x17,0x44,0x05,0x00,0x04,0x04,0x00,0x00,0x40,0x46,0x44,0x44,0x44,0x44, + 0x04,0x50,0x02,0x54,0x40,0x44,0x44,0x44,0x45,0x54,0x45,0x04,0x57,0x01,0x00,0x00, + 0x14,0x00,0x20,0x00,0x44,0x74,0x04,0x04,0x44,0x44,0x70,0x45,0x47,0x45,0x44,0x48, + 0x14,0x00,0x47,0x44,0x44,0x44,0x04,0x40,0x74,0x17,0x40,0x40,0x00,0x31,0x40,0x05, + 0x05,0x45,0x04,0x00,0x44,0xC5,0x40,0x44,0x45,0x44,0x54,0x54,0x04,0x00,0x75,0x75, + 0x54,0x44,0x80,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x80,0x80,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x08,0x88,0x88,0x88,0x08,0x88,0x08,0x80,0x88,0x88,0x80,0x88,0x88, + 0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x80,0x88, + 0x80,0x88,0x88,0x08,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x88,0x88,0x08,0x88, + 0x88,0x08,0x88,0x88,0x80,0x08,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x80,0x88,0x88, + 0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x80,0x88,0x88,0x00,0x78,0x00,0x44,0x44,0x80, + 0x07,0x75,0x00,0x14,0x74,0x71,0x44,0x74,0x74,0x76,0x07,0x01,0x17,0x40,0x04,0x44, + 0x41,0x71,0x77,0x10,0x47,0x40,0x74,0x04,0x64,0x01,0x40,0x44,0x50,0x74,0x47,0x45, + 0x04,0x50,0x40,0x74,0x44,0x47,0x55,0x00,0x44,0x44,0x77,0x07,0x01,0x44,0x07,0x44, + 0x74,0x47,0x54,0x00,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x08, + 0x88,0x88,0x88,0x08,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x80,0x08,0x8F,0x84, + 0xF4,0x4C,0x04,0x00,0x05,0x0F,0x44,0x5F,0xC4,0x8F,0x88,0x08,0x40,0xF4,0xCC,0xF0, + 0x0F,0x4F,0x8F,0x88,0x88,0xF4,0xFF,0x54,0x4F,0x40,0x8C,0x00,0x04,0xF0,0x77,0xF7, + 0xC0,0x7F,0x1F,0x81,0x88,0x4F,0x4D,0x40,0x47,0x7D,0xFC,0xFF,0x07,0x01,0x74,0x04, + 0x04,0x40,0xF4,0x4F,0x4D,0xF7,0xF0,0x97,0x48,0x44,0x7F,0xD0,0xFF,0x70,0x0F,0x04, + 0x41,0x34,0x04,0xF0,0x47,0x07,0x04,0x04,0x7D,0xC1,0x05,0x39,0xD5,0x70,0x8D,0x48, + 0xFF,0x44,0xFF,0xFF,0xF4,0x74,0xFF,0x8F,0x10,0x4C,0xF4,0x47,0x74,0x74,0x47,0x44, + 0x48,0x77,0x40,0x00,0xEF,0x1F,0x00,0xE0,0x47,0x87,0x40,0xFF,0xF4,0x74,0x40,0x48, + 0x8F,0x04,0x4D,0xFF,0xCD,0x41,0xD0,0xDD,0x74,0xF4,0x00,0x0F,0x74,0x00,0x4F,0x4F, + 0x04,0x44,0x45,0x74,0x44,0x4D,0x84,0x44,0x0F,0x0F,0x40,0x00,0xFD,0x04,0x70,0x4D, + 0x00,0x47,0x07,0x45,0x57,0x40,0x00,0x00,0x20,0x8D,0x00,0x0F,0x94,0xC4,0x07,0x0F, + 0xFD,0x0F,0x81,0x05,0xF5,0x14,0x34,0x04,0x14,0xC4,0x0F,0x6C,0x14,0x47,0x4D,0x44, + 0x54,0x44,0xD5,0x01,0x04,0xF4,0xF0,0x74,0x81,0x08,0x0C,0x40,0x4D,0x04,0x45,0x04, + 0x4F,0xD4,0x44,0x05,0x07,0xF4,0xF4,0x84,0x00,0x58,0x09,0x44,0x40,0x40,0x00,0x40, + 0x40,0x50,0x44,0x47,0x41,0x70,0x44,0x44,0x04,0x70,0x44,0x44,0x44,0x00,0x47,0x44, + 0x40,0x40,0x40,0x88,0x80,0x88,0xD8,0x01,0x44,0xF1,0x90,0x0F,0x44,0x74,0x40,0x74, + 0x76,0x77,0x74,0x47,0x07,0x06,0x47,0x54,0x77,0x77,0x00,0x74,0x07,0x41,0x44,0x04, + 0x54,0x00,0x05,0x44,0x44,0x40,0x71,0x40,0x06,0x04,0x41,0x50,0x67,0x70,0x11,0x00, + 0x40,0x40,0x44,0x07,0x44,0x14,0x77,0x57,0x44,0x44,0x13,0x40,0x47,0x52,0x44,0x47, + 0x04,0x44,0x64,0x70,0x40,0x74,0x00,0x70,0x55,0x54,0x85,0x88,0x88,0x88,0x88,0x88, + 0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x80,0x88,0x80,0x08,0x88,0x08,0x88,0x88,0x88, + 0x88,0x08,0x88,0x88,0x47,0x01,0x44,0x74,0x70,0x44,0x00,0x05,0x04,0x44,0x44,0x44, + 0x44,0x14,0x07,0x25,0x40,0x40,0x04,0x08,0x80,0x88,0x80,0x00,0x88,0x78,0x03,0xF8, + 0x20,0x47,0x40,0xC0,0x58,0x54,0x70,0x73,0x00,0x05,0x07,0x04,0x40,0x04,0x77,0x07, + 0x04,0x74,0x50,0x40,0x74,0x07,0x87,0x00,0x4F,0x75,0x45,0x44,0x07,0x44,0x10,0x47, + 0x53,0x00,0x45,0x40,0x47,0x44,0x45,0x4D,0x44,0x44,0x40,0x00,0x00,0x04,0x54,0x45, + 0x40,0x41,0x70,0x40,0x74,0x70,0x27,0x04,0x75,0x47,0xDE,0x74,0x44,0x40,0x04,0x44, + 0x40,0x80,0x80,0x80,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x00,0x08,0x88,0x80, + 0x88,0x00,0x88,0x88,0x08,0x88,0x80,0x80,0x88,0x88,0x88,0xDF,0xFD,0x00,0x64,0x04, + 0x40,0x40,0xF0,0x44,0x0F,0x40,0x77,0x47,0x64,0x74,0x47,0x00,0x60,0x44,0x41,0x00, + 0x70,0x44,0x11,0x41,0x41,0x40,0x44,0x44,0x77,0x47,0x74,0x44,0x65,0x50,0x74,0x70, + 0x00,0x45,0x44,0x40,0x40,0x04,0x74,0x05,0x74,0x01,0x04,0x44,0x45,0x54,0x44,0x74, + 0x70,0x44,0x54,0x44,0x42,0x44,0x40,0x77,0x40,0x11,0x44,0x04,0x70,0x44,0x44,0x04, + 0x04,0x44,0x44,0x40,0x41,0x74,0x44,0x04,0x47,0x04,0x44,0x76,0x44,0x04,0x40,0x45, + 0x47,0x75,0x74,0x04,0x44,0x04,0x74,0x44,0x04,0x44,0x74,0x74,0x40,0x77,0x00,0x74, + 0x04,0x07,0x75,0x44,0x74,0x57,0x88,0x88,0x88,0x80,0x88,0x88,0x88,0x88,0x88,0x88, + 0x88,0x08,0x88,0x88,0x08,0x88,0x08,0x80,0x88,0x88,0x00,0x88,0x08,0x88,0x88,0x88, + 0x88,0x88,0x88,0x80,0x0F,0x40,0x50,0x40,0xCD,0x40,0x04,0xC8,0x4F,0x48,0x0D,0x44, + 0xCD,0x0C,0x81,0x44,0x00,0x84,0x48,0x50,0xD4,0xF4,0x47,0x04,0x0F,0x00,0x04,0xD1, + 0xC0,0x51,0x20,0x4D,0x00,0xD1,0xD4,0xD7,0x50,0x44,0x01,0x54,0xC0,0xD4,0x44,0x04, + 0x40,0xC0,0x44,0x05,0x0C,0x44,0x44,0x84,0x44,0x84,0x40,0x44,0x45,0x07,0x00,0xD4, + 0x04,0xD5,0x54,0x70,0x55,0x43,0x00,0xD5,0x70,0x4D,0x40,0x40,0x00,0xD4,0x0F,0x44, + 0xF0,0xFF,0xFF,0x84,0x8C,0x44,0xD4,0xF5,0xD0,0x04,0x4F,0x04,0x45,0x47,0x00,0x40, + 0x44,0x00,0x04,0x44,0x04,0x00,0x04,0x70,0x44,0x00,0x45,0x44,0x00,0x44,0x44,0x04, + 0x04,0x14,0x40,0x44,0x04,0x00,0x00,0x03,0x74,0x55,0x40,0x11,0x00,0x44,0x00,0x34, + 0x45,0x04,0x44,0x04,0x05,0x75,0x50,0x47,0x00,0x00,0x41,0x04,0x54,0x00,0x40,0x40, + 0x45,0x40,0x04,0x45,0x74,0x05,0x00,0x10,0x10,0x41,0x45,0x47,0x40,0x54,0x04,0x04, + 0x54,0x15,0x47,0x44,0x07,0x44,0x04,0x00,0x15,0x01,0x10,0x40,0x04,0x00,0x40,0x00, + 0x00,0x00,0x41,0x45,0x55,0x41,0x71,0x04,0x03,0x57,0x35,0x40,0x00,0x10,0x44,0x00, + 0x50,0x40,0x75,0x00,0x44,0x40,0x54,0x11,0x41,0x47,0x04,0x44,0x50,0x71,0x44,0x45, + 0x44,0x00,0x04,0x35,0x65,0x44,0x44,0x04,0x04,0x05,0x44,0x74,0x44,0x01,0x00,0x44, + 0x05,0x44,0x00,0x54,0x04,0x00,0x40,0x04,0x40,0x40,0x44,0x41,0x45,0x04,0x08,0x80, + 0x80,0x08,0x80,0x88,0x08,0x80,0x80,0x08,0x88,0x08,0x88,0x00,0x00,0x88,0x08,0x88, + 0x88,0x88,0x88,0x88,0x88,0x80,0x80,0x08,0x88,0x88,0x88,0x88,0x08,0x88,0x88,0x00, + 0x00,0x80,0x88,0x88,0x00,0x88,0x88,0x88,0x08,0x80,0x88,0x88,0x88,0x00,0x88,0x88, + 0x00,0x08,0x70,0x74,0x70,0x14,0x41,0x00,0x41,0x74,0x47,0x47,0x40,0x44,0x44,0x40, + 0x04,0x50,0x44,0x55,0x75,0x00,0x00,0x01,0x04,0x05,0x54,0x40,0x44,0x70,0x40,0x54, + 0x04,0x54,0x40,0x07,0x47,0x11,0x41,0x44,0x44,0x40,0x00,0x44,0x04,0x70,0x40,0x55, + 0x54,0x44,0x41,0x01,0x01,0x44,0x04,0x40,0x71,0x44,0x04,0x44,0x54,0x44,0x75,0x41, + 0x77,0x00,0x01,0x40,0x44,0x44,0x07,0x50,0x44,0x47,0x44,0x40,0x44,0x41,0x40,0x40, + 0x44,0x04,0x44,0x54,0x54,0x44,0x04,0x10,0x04,0x04,0x04,0x44,0x44,0x45,0x44,0x44, + 0x44,0x44,0x05,0x44,0x74,0x14,0x44,0x70,0x40,0x45,0x47,0x44,0x45,0x55,0x04,0x44, + 0x50,0x45,0x43,0x41,0x04,0x44,0x44,0x54,0x44,0x54,0x40,0x64,0x54,0x44,0x44,0x44, + 0x40,0x44,0x44,0x05,0x44,0x40,0x54,0x54,0x04,0x47,0x44,0x44,0x77,0x47,0x50,0x44, + 0x44,0x44,0x44,0x44,0x40,0x40,0x40,0x40,0x44,0x44,0x44,0x40,0x40,0x57,0x40,0x87, + 0x88,0x88,0x80,0x08,0x88,0x88,0x88,0x80,0x80,0x88,0x80,0x88,0x88,0x08,0x80,0x88, + 0x80,0x88,0x88,0x88,0x88,0x88,0x08,0x88,0x80,0x00,0x80,0x80,0x08,0x88,0x08,0x08, + 0x00,0x80,0x08,0x88,0x88,0x88,0x88,0x00,0x88,0x80,0x70,0x00,0x71,0x04,0x74,0xF8, + 0x14,0x4C,0x00,0xC4,0x4D,0xD4,0x45,0x04,0x50,0xFF,0x14,0x70,0x40,0x44,0xF4,0xF0, + 0x44,0x00,0x74,0x49,0x50,0x01,0x50,0x04,0x04,0x00,0x6E,0x44,0x19,0xF1,0x85,0x1F, + 0x04,0x64,0x09,0x00,0x84,0x00,0xF5,0xDF,0xE5,0x41,0x4F,0x04,0x1F,0xF4,0xDF,0xC7, + 0x0D,0x08,0xD4,0xC4,0x87,0x48,0x40,0xD4,0x04,0x44,0x47,0x55,0xD0,0xD4,0x5D,0x48, + 0x44,0x00,0x00,0x74,0x43,0x84,0x80,0x4F,0x0C,0xF4,0x50,0x84,0xC4,0x44,0x04,0x04, + 0x1F,0x4C,0x44,0x00,0x44,0x44,0x4D,0xC4,0x44,0x44,0x44,0xC4,0x84,0xF0,0xC0,0x0D, + 0x44,0x44,0x08,0x44,0x44,0x77,0x44,0x57,0x88,0x07,0x45,0x44,0x44,0x40,0x44,0x74, + 0x75,0x51,0x44,0x75,0x00,0x47,0x07,0x44,0x44,0x05,0x44,0x75,0x44,0x44,0x00,0x84, + 0x08,0x80,0x88,0x88,0x88,0x88,0x78,0x00,0x46,0x04,0x74,0x00,0x84,0x88,0x17,0x80, + 0x0D,0x04,0x04,0x00,0x00,0x00,0x00,0x00, +}; + +/* + * Pick a suitable Mac encoding value for a Unicode string. + * + * This routine is only used during file creation and renaming. + */ +u_int32_t +hfs_pickencoding(const u_int16_t *src, int len) +{ + u_int32_t guess; + u_int16_t ch; + u_int8_t bits; + u_int8_t cjkstate; + + cjkstate = 0; + guess = kTextEncodingMacRoman; + + while (len--) { + ch = *src++; + if (ch < 0x0080) /* ASCII */ + continue; + + if (ch >= 0x4E00 && ch <= 0x9FAF) { /* CJK */ + bits = cjk_bitmap[(ch - 0x4E00) >> 1]; + if (ch & 1) + bits = bits >> 4; + bits &= 0x0F; + if (bits) { + if (cjkstate) { + bits &= cjkstate; + if (bits) + cjkstate = bits; + } else + cjkstate = bits; + } + continue; + } + if (ch >= 0x3041 && ch <= 0x30FE) { /* Hiragana & Katakana */ + if (cjkstate) { + bits = cjkstate & CJK_KATAKANA; + if (bits) + cjkstate = bits; + } else + cjkstate = CJK_KATAKANA; + continue; + } + if ((ch >= 0x1100 && ch <= 0x11F9) || /* Hangul Jamo */ + (ch >= 0x3131 && ch <= 0x318E) || /* Hangul Compatibility Jamo */ + (ch >= 0xF900 && ch <= 0xFA0B)) { /* CJK Compatibility Ideographs */ + cjk_lastunique = CJK_KOREAN; + return kTextEncodingMacKorean; + } + if (ch >= 0x3105 && ch <= 0x3129) { /* Bopomofo */ + if (cjkstate) { + bits = cjkstate & CJK_CHINESE; + if (bits) + cjkstate = bits; + } else + cjkstate = CJK_CHINESE; + continue; + } + if (ch >= 0xFF01 && ch <= 0xFFE6) { /* Halfwidth and Fullwidth */ + if (cjkstate == 0) + cjkstate = CJK_ALL; + continue; + } + if (ch <= 0x0491 && ch >= 0x0401) { + guess = kTextEncodingMacCyrillic; + continue; + } + if (ch >= 0x05B0 && ch <= 0x05EA) { + return kTextEncodingMacHebrew; + } + if (ch >= 0x060C && ch <= 0x06d5) { + return kTextEncodingMacArabic; + } + if (ch >= 0x0E00 && ch <= 0x0E5B) { + return kTextEncodingMacThai; + } + if (guess == 0 && ch > 0x2122) { + guess = kTextEncodingMacUnicode; + } + } /* end while */ + + if (cjkstate) { + if (powerof2(cjkstate)) { + cjk_lastunique = cjkstate; + } else if (cjk_lastunique) { + if (cjkstate & cjk_lastunique) + cjkstate = cjk_lastunique; + else + cjk_lastunique = 0; + } + return ((u_int32_t)cjk_encoding[cjkstate]); + } + + return guess; +} + + diff --git a/bsd/hfs/hfs_link.c b/bsd/hfs/hfs_link.c index b3e91dfdd..f31f86495 100644 --- a/bsd/hfs/hfs_link.c +++ b/bsd/hfs/hfs_link.c @@ -53,7 +53,7 @@ createindirectlink(struct hfsnode *dnhp, UInt32 linkPID, char *linkName) vcb = HTOVCB(dnhp); /* Create the indirect link directly in the catalog */ - result = hfsCreate(vcb, linkPID, linkName, IFREG); + result = hfsCreate(vcb, linkPID, linkName, IFREG, 0); if (result) return (result); /* diff --git a/bsd/hfs/hfs_lookup.c b/bsd/hfs/hfs_lookup.c index d627217ca..821bd1b66 100644 --- a/bsd/hfs/hfs_lookup.c +++ b/bsd/hfs/hfs_lookup.c @@ -379,7 +379,7 @@ hfs_lookup(ap) goto Err_Exit; } else { - retval = hfs_vget_catinfo(parent_vp, &catInfo, kAnyFork, &target_vp); + retval = hfs_vget_catinfo(parent_vp, &catInfo, kDefault, &target_vp); if (retval) goto Err_Exit; CLEAN_CATALOGDATA(&catInfo.nodeData); @@ -439,19 +439,8 @@ hfs_lookup(ap) goto Err_Exit; } else { - /* If then name differs in case, then act like it does not exist - * This allows renaming foo->Foo - * Exclude length difference due to compose/decompe issues. - */ - if ((cnp->cn_namelen == catInfo.nodeData.cnm_length) && - strncmp(cnp->cn_nameptr, catInfo.nodeData.cnm_nameptr, targetLen)) { - if (!lockparent) - VOP_UNLOCK(parent_vp, 0, p); - retval = EJUSTRETURN; - goto Err_Exit; - }; - retval = hfs_vget_catinfo(parent_vp, &catInfo, kAnyFork, &target_vp); + retval = hfs_vget_catinfo(parent_vp, &catInfo, kDefault, &target_vp); if (retval) goto Err_Exit; @@ -465,7 +454,7 @@ hfs_lookup(ap) goto Err_Exit; /* Finished...all is well, goto the end */ }; - + /* * Step through the translation in the name. We do not `vput' the * directory because we may need it again if a symbolic link @@ -548,7 +537,7 @@ hfs_lookup(ap) /* If couldn't determine what type of fork, leave */ if (forkType == kUndefinedFork) { - retval = EISDIR; + retval = ENOTDIR; goto Err_Exit; }; @@ -640,11 +629,11 @@ hfs_cache_lookup(ap) int lockparent; int error; struct vnode **vpp = ap->a_vpp; - struct componentname *cnp = ap->a_cnp; - struct ucred *cred = cnp->cn_cred; + struct componentname *cnp = ap->a_cnp; + struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; - struct proc *p = cnp->cn_proc; - struct hfsnode *hp; + struct proc *p = cnp->cn_proc; + struct hfsnode *hp; u_int32_t vpid; /* capability number of vnode */ DBG_FUNC_NAME("cache_lookup"); DBG_VOP_LOCKS_DECL(2); @@ -659,7 +648,7 @@ hfs_cache_lookup(ap) lockparent = flags & LOCKPARENT; if (vdp->v_type != VDIR) - return (ENOTDIR); + return (ENOTDIR); if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) @@ -737,55 +726,17 @@ hfs_cache_lookup(ap) error = vget(vdp, LK_EXCLUSIVE, p); if (!error && lockparent && (flags & ISLASTCN)) error = vn_lock(pdp, LK_EXCLUSIVE, p); - } else { + } else if ((! (flags & ISLASTCN)) && (vdp->v_type == VREG) && + (GetForkFromName(cnp) != kDataFork)) { /* - * Check to see if a specific fork is not being requested. - * - * If it is a file and not the last path item - * then check if its a proper fork - * If it is, check to see if the matched vnode is the same fork - * else see if the proper fork exists. - * If it does, return that one, else do VOP_CACHEDLOOKUP() - * Notice that nothing is done if an undefined fork is named. Just leave and let lookup() - * handle strange cases. - * - * XXX SER Notice that when the target is not what was in the name cache, - * it is locked, before trying to get its sibling. Could this be a problem since both - * siblings can be locked, but not in a determinalistic order???? - */ - u_int16_t forkType; - + * We only store data forks in the name cache. + */ + goto finished; + } else { error = vget(vdp, LK_EXCLUSIVE, p); - if ((! error) && (vdp->v_type == VREG) && (vpid == vdp->v_id)) { - if (!(flags & ISLASTCN)) { - forkType = GetForkFromName(cnp); - if (forkType != kUndefinedFork) { - flags |= ISLASTCN; - if (H_FORKTYPE(VTOH(vdp)) != forkType) { - error = hfs_vget_sibling(vdp, forkType, vpp); - vput(vdp); - if (! error) { - vdp = *vpp; - vpid = vdp->v_id; - } - } - } - } - else { - /* Its the last item, so we want the data fork */ - if (H_FORKTYPE(VTOH(vdp)) != kDataFork) { - error = hfs_vget_sibling(vdp, kDataFork, vpp); - vput(vdp); - if (! error) { - vdp = *vpp; - vpid = vdp->v_id; - } - } - }; - }; if (!lockparent || error || !(flags & ISLASTCN)) VOP_UNLOCK(pdp, 0, p); - }; + } /* * Check that the capability number did not change * while we were waiting for the lock. @@ -804,6 +755,9 @@ hfs_cache_lookup(ap) error = vn_lock(pdp, LK_EXCLUSIVE, p); if (error) return (error); + +finished: + return (hfs_lookup(ap)); } diff --git a/bsd/hfs/hfs_macos_defs.h b/bsd/hfs/hfs_macos_defs.h index 73aa2ddcd..917613810 100644 --- a/bsd/hfs/hfs_macos_defs.h +++ b/bsd/hfs/hfs_macos_defs.h @@ -28,11 +28,6 @@ DRI: Nick Kledzik - History: - 12-Aug-1999 Scott Roberts Created from ConditionalMacros.h, MacOSStubs.h, MacOSTypes.h - - - */ @@ -1051,10 +1046,12 @@ enum { kTextEncodingMacTurkish = 35, kTextEncodingMacCroatian = 36, kTextEncodingMacIcelandic = 37, - kTextEncodingMacRomanian = 38, /* The following use script code 4, smArabic*/ - kTextEncodingMacFarsi = 0x8C, /* Like MacArabic but uses Farsi digits*/ - /* The following use script code 7, smCyrillic*/ - kTextEncodingMacUkrainian = 0x98, /* The following use script code 32, smUnimplemented*/ + kTextEncodingMacRomanian = 38, + kTextEncodingMacUnicode = 0x7E, + /* The following use script code 4, smArabic */ + kTextEncodingMacFarsi = 0x8C, /* Like MacArabic but uses Farsi digits */ + /* The following use script code 7, smCyrillic */ + kTextEncodingMacUkrainian = 0x98, /* The following use script code 32, smUnimplemented */ kTextEncodingMacVT100 = 0xFC, /* VT100/102 font from Comm Toolbox: Latin-1 repertoire + box drawing etc*/ /* Special Mac OS encodings*/ kTextEncodingMacHFS = 0xFF, /* Meta-value, should never appear in a table.*/ @@ -1557,13 +1554,6 @@ EqualString (ConstStr255Param str1, */ -/* The following replace storage used in low-mem on MacOS: */ -extern struct FSVarsRec * gFSMVars; - - -#define LMGetFSMVars() gFSMVars - - EXTERN_API( void ) InsTime (QElemPtr tmTaskPtr); diff --git a/bsd/hfs/hfs_readwrite.c b/bsd/hfs/hfs_readwrite.c index dcb0fe1e5..035cd80f3 100644 --- a/bsd/hfs/hfs_readwrite.c +++ b/bsd/hfs/hfs_readwrite.c @@ -67,11 +67,9 @@ #include <miscfs/specfs/specdev.h> - #include <sys/ubc.h> #include <vm/vm_pageout.h> - #include <sys/kdebug.h> #include "hfs.h" @@ -129,7 +127,7 @@ struct vop_read_args /* { struct buf *bp; daddr_t logBlockNo; u_long fragSize, moveSize, startOffset, ioxfersize; - long devBlockSize = 0; + int devBlockSize = 0; off_t bytesRemaining; int retval; u_short mode; @@ -343,7 +341,7 @@ struct vop_write_args /* { struct timeval tv; FCB *fcb = HTOFCB(hp); ExtendedVCB *vcb = HTOVCB(hp); - long devBlockSize = 0; + int devBlockSize = 0; daddr_t logBlockNo; long fragSize; off_t origFileSize, currOffset, writelimit, bytesToAdd; @@ -390,8 +388,7 @@ struct vop_write_args /* { uio = ap->a_uio; vp = ap->a_vp; - if (ioflag & IO_APPEND) - uio->uio_offset = fcb->fcbEOF; + if (ioflag & IO_APPEND) uio->uio_offset = fcb->fcbEOF; if ((hp->h_meta->h_pflags & APPEND) && uio->uio_offset != fcb->fcbEOF) return (EPERM); @@ -410,7 +407,7 @@ struct vop_write_args /* { VOP_DEVBLOCKSIZE(hp->h_meta->h_devvp, &devBlockSize); resid = uio->uio_resid; - origFileSize = fcb->fcbPLen; + origFileSize = fcb->fcbEOF; flags = ioflag & IO_SYNC ? B_SYNC : 0; DBG_RW(("\tLEOF is 0x%lX, PEOF is 0x%lX.\n", fcb->fcbEOF, fcb->fcbPLen)); @@ -436,9 +433,6 @@ struct vop_write_args /* { (int)uio->uio_offset, uio->uio_resid, (int)fcb->fcbEOF, (int)fcb->fcbPLen, 0); retval = 0; - if (fcb->fcbEOF > fcb->fcbMaxEOF) - fcb->fcbMaxEOF = fcb->fcbEOF; - /* Now test if we need to extend the file */ /* Doing so will adjust the fcbPLen for us */ @@ -457,60 +451,144 @@ struct vop_write_args /* { ExtendFileC (vcb, fcb, bytesToAdd, + 0, kEFContigBit, &actualBytesAdded)); (void) hfs_metafilelocking(HTOHFS(hp), kHFSExtentsFileID, LK_RELEASE, cp); DBG_VOP_CONT(("\tactual bytes added = 0x%lX bytes, retval = %d...\n", actualBytesAdded, retval)); - if ((actualBytesAdded == 0) && (retval == E_NONE)) - retval = ENOSPC; - if (retval != E_NONE) - break; + if ((actualBytesAdded == 0) && (retval == E_NONE)) retval = ENOSPC; + if (retval != E_NONE) break; KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 0)) | DBG_FUNC_NONE, (int)uio->uio_offset, uio->uio_resid, (int)fcb->fcbEOF, (int)fcb->fcbPLen, 0); }; - if (UBCISVALID(vp) && retval == E_NONE) { - off_t filesize; - off_t zero_off; - int lflag; - - if (writelimit > fcb->fcbEOF) - filesize = writelimit; - else - filesize = fcb->fcbEOF; - - lflag = (ioflag & IO_SYNC); - - if (uio->uio_offset > fcb->fcbMaxEOF) { - zero_off = fcb->fcbMaxEOF; - lflag |= IO_HEADZEROFILL; - } else - zero_off = 0; + if (UBCISVALID(vp) && retval == E_NONE) { + off_t filesize; + off_t zero_off; + off_t tail_off; + off_t inval_start; + off_t inval_end; + off_t io_start, io_end; + int lflag; + struct rl_entry *invalid_range; + + if (writelimit > fcb->fcbEOF) + filesize = writelimit; + else + filesize = fcb->fcbEOF; - /* - * if the write starts beyond the current EOF then - * we we'll zero fill from the current EOF to where the write begins - */ - retval = cluster_write(vp, uio, fcb->fcbEOF, filesize, zero_off, - (off_t)0, devBlockSize, lflag); + lflag = (ioflag & IO_SYNC); - if (uio->uio_offset > fcb->fcbEOF) { - fcb->fcbEOF = uio->uio_offset; + if (uio->uio_offset <= fcb->fcbEOF) { + zero_off = uio->uio_offset & ~PAGE_MASK_64; + + /* Check to see whether the area between the zero_offset and the start + of the transfer to see whether is invalid and should be zero-filled + as part of the transfer: + */ + if (rl_scan(&hp->h_invalidranges, zero_off, uio->uio_offset - 1, &invalid_range) != RL_NOOVERLAP) { + lflag |= IO_HEADZEROFILL; + }; + } else { + off_t eof_page_base = fcb->fcbEOF & ~PAGE_MASK_64; + + /* The bytes between fcb->fcbEOF and uio->uio_offset must never be + read without being zeroed. The current last block is filled with zeroes + if it holds valid data but in all cases merely do a little bookkeeping + to track the area from the end of the current last page to the start of + the area actually written. For the same reason only the bytes up to the + start of the page where this write will start is invalidated; any remainder + before uio->uio_offset is explicitly zeroed as part of the cluster_write. + + Note that inval_start, the start of the page after the current EOF, + may be past the start of the write, in which case the zeroing + will be handled by the cluser_write of the actual data. + */ + inval_start = (fcb->fcbEOF + (PAGE_SIZE_64 - 1)) & ~PAGE_MASK_64; + inval_end = uio->uio_offset & ~PAGE_MASK_64; + zero_off = fcb->fcbEOF; + + if ((fcb->fcbEOF & PAGE_MASK_64) && + (rl_scan(&hp->h_invalidranges, + eof_page_base, + fcb->fcbEOF - 1, + &invalid_range) != RL_NOOVERLAP)) { + /* The page containing the EOF is not valid, so the + entire page must be made inaccessible now. If the write + starts on a page beyond the page containing the eof + (inval_end > eof_page_base), add the + whole page to the range to be invalidated. Otherwise + (i.e. if the write starts on the same page), zero-fill + the entire page explicitly now: + */ + if (inval_end > eof_page_base) { + inval_start = eof_page_base; + } else { + zero_off = eof_page_base; + }; + }; + + if (inval_start < inval_end) { + /* There's some range of data that's going to be marked invalid */ + + if (zero_off < inval_start) { + /* The pages between inval_start and inval_end are going to be invalidated, + and the actual write will start on a page past inval_end. Now's the last + chance to zero-fill the page containing the EOF: + */ + retval = cluster_write(vp, (struct uio *) 0, fcb->fcbEOF, inval_start, + zero_off, (off_t)0, devBlockSize, lflag | IO_HEADZEROFILL); + if (retval) goto ioerr_exit; + }; + + /* Mark the remaining area of the newly allocated space as invalid: */ + rl_add(inval_start, inval_end - 1 , &hp->h_invalidranges); + zero_off = fcb->fcbEOF = inval_end; + }; + + if (uio->uio_offset > zero_off) lflag |= IO_HEADZEROFILL; + }; - if (fcb->fcbEOF > fcb->fcbMaxEOF) - fcb->fcbMaxEOF = fcb->fcbEOF; + /* Check to see whether the area between the end of the write and the end of + the page it falls in is invalid and should be zero-filled as part of the transfer: + */ + tail_off = (writelimit + (PAGE_SIZE_64 - 1)) & ~PAGE_MASK_64; + if (tail_off > filesize) tail_off = filesize; + if (tail_off > writelimit) { + if (rl_scan(&hp->h_invalidranges, writelimit, tail_off - 1, &invalid_range) != RL_NOOVERLAP) { + lflag |= IO_TAILZEROFILL; + }; + }; + + /* + * if the write starts beyond the current EOF (possibly advanced in the + * zeroing of the last block, above), then we'll zero fill from the current EOF + * to where the write begins: + * + * NOTE: If (and ONLY if) the portion of the file about to be written is + * before the current EOF it might be marked as invalid now and must be + * made readable (removed from the invalid ranges) before cluster_write + * tries to write it: + */ + io_start = (lflag & IO_HEADZEROFILL) ? zero_off : uio->uio_offset; + io_end = (lflag & IO_TAILZEROFILL) ? tail_off : writelimit; + if (io_start < fcb->fcbEOF) { + rl_remove(io_start, io_end - 1, &hp->h_invalidranges); + }; + retval = cluster_write(vp, uio, fcb->fcbEOF, filesize, zero_off, tail_off, devBlockSize, lflag); + + if (uio->uio_offset > fcb->fcbEOF) { + fcb->fcbEOF = uio->uio_offset; - ubc_setsize(vp, (off_t)fcb->fcbEOF); /* XXX check errors */ - } - if (resid > uio->uio_resid) - hp->h_nodeflags |= IN_CHANGE | IN_UPDATE; + ubc_setsize(vp, (off_t)fcb->fcbEOF); /* XXX check errors */ + } + if (resid > uio->uio_resid) hp->h_nodeflags |= IN_CHANGE | IN_UPDATE; } else { while (retval == E_NONE && uio->uio_resid > 0) { - logBlockNo = currOffset / PAGE_SIZE; blkoffset = currOffset & PAGE_MASK; @@ -614,9 +692,6 @@ struct vop_write_args /* { DBG_VOP(("\textending EOF to 0x%lX...\n", (UInt32)fcb->fcbEOF)); fcb->fcbEOF = currOffset; - if (fcb->fcbEOF > fcb->fcbMaxEOF) - fcb->fcbMaxEOF = fcb->fcbEOF; - if (UBCISVALID(vp)) ubc_setsize(vp, (off_t)fcb->fcbEOF); /* XXX check errors */ }; @@ -626,11 +701,13 @@ struct vop_write_args /* { hp->h_nodeflags |= IN_CHANGE | IN_UPDATE; }; }; + +ioerr_exit: /* - * If we successfully wrote any data, and we are not the superuser - * we clear the setuid and setgid bits as a precaution against - * tampering. - */ + * If we successfully wrote any data, and we are not the superuser + * we clear the setuid and setgid bits as a precaution against + * tampering. + */ if (resid > uio->uio_resid && ap->a_cred && ap->a_cred->cr_uid != 0) hp->h_meta->h_mode &= ~(ISUID | ISGID); @@ -694,9 +771,9 @@ struct vop_ioctl_args /* { switch (ap->a_command) { - case 1: + case 1: { register struct hfsnode *hp; - register struct vnode *vp; + register struct vnode *vp; register struct radvisory *ra; FCB *fcb; int devBlockSize = 0; @@ -724,15 +801,15 @@ struct vop_ioctl_args /* { DBG_VOP_LOCKS_TEST(error); return (error); - } + } - case 2: /* F_READBOOTBLOCKS */ - case 3: /* F_WRITEBOOTBLOCKS */ - { + case 2: /* F_READBOOTBLOCKS */ + case 3: /* F_WRITEBOOTBLOCKS */ + { struct vnode *vp = ap->a_vp; struct hfsnode *hp = VTOH(vp); struct fbootstraptransfer *btd = (struct fbootstraptransfer *)ap->a_data; - u_long devBlockSize; + int devBlockSize; int error; struct iovec aiov; struct uio auio; @@ -741,8 +818,8 @@ struct vop_ioctl_args /* { u_long xfersize; struct buf *bp; - if ((vp->v_flag & VROOT) == 0) return EINVAL; - if (btd->fbt_offset + btd->fbt_length > 1024) return EINVAL; + if ((vp->v_flag & VROOT) == 0) return EINVAL; + if (btd->fbt_offset + btd->fbt_length > 1024) return EINVAL; aiov.iov_base = btd->fbt_buffer; aiov.iov_len = btd->fbt_length; @@ -761,33 +838,40 @@ struct vop_ioctl_args /* { blockNumber = auio.uio_offset / devBlockSize; error = bread(hp->h_meta->h_devvp, blockNumber, devBlockSize, ap->a_cred, &bp); if (error) { - if (bp) brelse(bp); - return error; - }; + if (bp) brelse(bp); + return error; + }; - blockOffset = auio.uio_offset % devBlockSize; + blockOffset = auio.uio_offset % devBlockSize; xfersize = devBlockSize - blockOffset; error = uiomove((caddr_t)bp->b_data + blockOffset, (int)xfersize, &auio); - if (error) { - brelse(bp); - return error; - }; - if (auio.uio_rw == UIO_WRITE) { - error = VOP_BWRITE(bp); - if (error) return error; - } else { - brelse(bp); - }; + if (error) { + brelse(bp); + return error; + }; + if (auio.uio_rw == UIO_WRITE) { + error = VOP_BWRITE(bp); + if (error) return error; + } else { + brelse(bp); + }; + }; }; - }; - return 0; + return 0; + + case _IOC(IOC_OUT,'h', 4, 0): /* Create date in local time */ + { + *(time_t *)(ap->a_data) = to_bsd_time(VTOVCB(ap->a_vp)->localCreateDate); + return 0; + } - default: - DBG_VOP_LOCKS_TEST(ENOTTY); - return (ENOTTY); + default: + DBG_VOP_LOCKS_TEST(ENOTTY); + return (ENOTTY); } - return 0; + /* Should never get here */ + return 0; } /* ARGSUSED */ @@ -798,6 +882,7 @@ struct vop_select_args /* { int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { @@ -933,8 +1018,11 @@ struct vop_bmap_args /* { int retval = E_NONE; daddr_t logBlockSize; size_t bytesContAvail = 0; + off_t blockposition; struct proc *p = NULL; int lockExtBtree; + struct rl_entry *invalid_range; + enum rl_overlaptype overlaptype; #define DEBUG_BMAP 0 #if DEBUG_BMAP @@ -961,6 +1049,9 @@ struct vop_bmap_args /* { if (ap->a_bnp == NULL) return (0); + logBlockSize = GetLogicalBlockSize(ap->a_vp); + blockposition = (off_t)(ap->a_bn * logBlockSize); + lockExtBtree = hasOverflowExtents(hp); if (lockExtBtree) { @@ -970,19 +1061,50 @@ struct vop_bmap_args /* { return (retval); } - logBlockSize = GetLogicalBlockSize(ap->a_vp); - - retval = MacToVFSError( - MapFileBlockC (HFSTOVCB(hfsmp), - HTOFCB(hp), - MAXPHYSIO, - (off_t)(ap->a_bn * logBlockSize), - ap->a_bnp, - &bytesContAvail)); + retval = MacToVFSError( + MapFileBlockC (HFSTOVCB(hfsmp), + HTOFCB(hp), + MAXPHYSIO, + blockposition, + ap->a_bnp, + &bytesContAvail)); if (lockExtBtree) (void) hfs_metafilelocking(hfsmp, kHFSExtentsFileID, LK_RELEASE, p); if (retval == E_NONE) { + /* Adjust the mapping information for invalid file ranges: */ + overlaptype = rl_scan(&hp->h_invalidranges, + blockposition, + blockposition + MAXPHYSIO - 1, + &invalid_range); + if (overlaptype != RL_NOOVERLAP) { + switch(overlaptype) { + case RL_MATCHINGOVERLAP: + case RL_OVERLAPCONTAINSRANGE: + case RL_OVERLAPSTARTSBEFORE: + /* There's no valid block for this byte offset: */ + *ap->a_bnp = (daddr_t)-1; + bytesContAvail = invalid_range->rl_end + 1 - blockposition; + break; + + case RL_OVERLAPISCONTAINED: + case RL_OVERLAPENDSAFTER: + /* The range of interest hits an invalid block before the end: */ + if (invalid_range->rl_start == blockposition) { + /* There's actually no valid information to be had starting here: */ + *ap->a_bnp = (daddr_t)-1; + if ((HTOFCB(hp)->fcbEOF > (invalid_range->rl_end + 1)) && + (invalid_range->rl_end + 1 - blockposition < bytesContAvail)) { + bytesContAvail = invalid_range->rl_end + 1 - blockposition; + }; + } else { + bytesContAvail = invalid_range->rl_start - blockposition; + }; + break; + }; + if (bytesContAvail > MAXPHYSIO) bytesContAvail = MAXPHYSIO; + }; + /* Figure out how many read ahead blocks there are */ if (ap->a_runp != NULL) { if (can_cluster(logBlockSize)) { @@ -1059,10 +1181,14 @@ struct vop_cmap_args /* { { struct hfsnode *hp = VTOH(ap->a_vp); struct hfsmount *hfsmp = VTOHFS(ap->a_vp); + FCB *fcb = HTOFCB(hp); size_t bytesContAvail = 0; int retval = E_NONE; int lockExtBtree; struct proc *p = NULL; + struct rl_entry *invalid_range; + enum rl_overlaptype overlaptype; + off_t limit; #define DEBUG_CMAP 0 #if DEBUG_CMAP @@ -1079,18 +1205,20 @@ struct vop_cmap_args /* { * Check for underlying vnode requests and ensure that logical * to physical mapping is requested. */ - if (ap->a_bpn == NULL) + if (ap->a_bpn == NULL) { return (0); + }; if (lockExtBtree = hasOverflowExtents(hp)) { p = current_proc(); - if (retval = hfs_metafilelocking(hfsmp, kHFSExtentsFileID, LK_EXCLUSIVE | LK_CANRECURSE, p)) + if (retval = hfs_metafilelocking(hfsmp, kHFSExtentsFileID, LK_EXCLUSIVE | LK_CANRECURSE, p)) { return (retval); + }; } retval = MacToVFSError( MapFileBlockC (HFSTOVCB(hfsmp), - HTOFCB(hp), + fcb, ap->a_size, ap->a_foffset, ap->a_bpn, @@ -1098,11 +1226,53 @@ struct vop_cmap_args /* { if (lockExtBtree) (void) hfs_metafilelocking(hfsmp, kHFSExtentsFileID, LK_RELEASE, p); - if ((retval == E_NONE) && (ap->a_run)) - *ap->a_run = bytesContAvail; + if (retval == E_NONE) { + /* Adjust the mapping information for invalid file ranges: */ + overlaptype = rl_scan(&hp->h_invalidranges, + ap->a_foffset, + ap->a_foffset + (off_t)bytesContAvail - 1, + &invalid_range); + if (overlaptype != RL_NOOVERLAP) { + switch(overlaptype) { + case RL_MATCHINGOVERLAP: + case RL_OVERLAPCONTAINSRANGE: + case RL_OVERLAPSTARTSBEFORE: + /* There's no valid block for this byte offset: */ + *ap->a_bpn = (daddr_t)-1; + + /* There's no point limiting the amount to be returned if the + invalid range that was hit extends all the way to the EOF + (i.e. there's no valid bytes between the end of this range + and the file's EOF): + */ + if ((fcb->fcbEOF > (invalid_range->rl_end + 1)) && + (invalid_range->rl_end + 1 - ap->a_foffset < bytesContAvail)) { + bytesContAvail = invalid_range->rl_end + 1 - ap->a_foffset; + }; + break; + + case RL_OVERLAPISCONTAINED: + case RL_OVERLAPENDSAFTER: + /* The range of interest hits an invalid block before the end: */ + if (invalid_range->rl_start == ap->a_foffset) { + /* There's actually no valid information to be had starting here: */ + *ap->a_bpn = (daddr_t)-1; + if ((fcb->fcbEOF > (invalid_range->rl_end + 1)) && + (invalid_range->rl_end + 1 - ap->a_foffset < bytesContAvail)) { + bytesContAvail = invalid_range->rl_end + 1 - ap->a_foffset; + }; + } else { + bytesContAvail = invalid_range->rl_start - ap->a_foffset; + }; + break; + }; + if (bytesContAvail > ap->a_size) bytesContAvail = ap->a_size; + }; + + if (ap->a_run) *ap->a_run = bytesContAvail; + }; - if (ap->a_poff) - *(int *)ap->a_poff = 0; + if (ap->a_poff) *(int *)ap->a_poff = 0; DBG_IO(("%d:%d.\n", *ap->a_bpn, bytesContAvail)); @@ -1147,7 +1317,7 @@ struct vop_strategy_args /* { if (bp->b_flags & B_PAGELIST) { /* * if we have a page list associated with this bp, - * then go through cluste_bp since it knows how to + * then go through cluster_bp since it knows how to * deal with a page request that might span non-contiguous * physical blocks on the disk... */ @@ -1160,8 +1330,10 @@ struct vop_strategy_args /* { /* * If we don't already know the filesystem relative block number * then get it using VOP_BMAP(). If VOP_BMAP() returns the block - * number as -1 then we've got a hole in the file. HFS filesystems - * don't allow files with holes, so we shouldn't ever see this. + * number as -1 then we've got a hole in the file. Although HFS + * filesystems don't create files with holes, invalidating of + * subranges of the file (lazy zero filling) may create such a + * situation. */ if (bp->b_blkno == bp->b_lblkno) { if ((retval = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL))) { @@ -1294,22 +1466,19 @@ int hfs_truncate(ap) * since there may be extra physical blocks that also need truncation */ - if (fcb->fcbEOF > fcb->fcbMaxEOF) - fcb->fcbMaxEOF = fcb->fcbEOF; - /* * Lengthen the size of the file. We must ensure that the * last byte of the file is allocated. Since the smallest * value of fcbEOF is 0, length will be at least 1. */ if (length > fcb->fcbEOF) { - off_t filePosition; - daddr_t logBlockNo; - long logBlockSize; - long blkOffset; - off_t bytestoclear; - int blockZeroCount; - struct buf *bp=NULL; + off_t filePosition; + daddr_t logBlockNo; + long logBlockSize; + long blkOffset; + off_t bytestoclear; + int blockZeroCount; + struct buf *bp=NULL; /* * If we don't have enough physical space then @@ -1327,6 +1496,7 @@ int hfs_truncate(ap) ExtendFileC (HTOVCB(hp), fcb, bytesToAdd, + 0, kEFAllMask, /* allocate all requested bytes or none */ &actualBytesAdded)); @@ -1348,72 +1518,96 @@ int hfs_truncate(ap) if (! (ap->a_flags & IO_NOZEROFILL)) { if (UBCISVALID(vp) && retval == E_NONE) { - u_long devBlockSize; - - if (length > fcb->fcbMaxEOF) { - - VOP_DEVBLOCKSIZE(hp->h_meta->h_devvp, &devBlockSize); - - retval = cluster_write(vp, (struct uio *) 0, fcb->fcbEOF, length, fcb->fcbMaxEOF, - (off_t)0, devBlockSize, ((ap->a_flags & IO_SYNC) | IO_HEADZEROFILL)); - - if (retval) - goto Err_Exit; - } + struct rl_entry *invalid_range; + int devBlockSize; + off_t zero_limit; + + zero_limit = (fcb->fcbEOF + (PAGE_SIZE_64 - 1)) & ~PAGE_MASK_64; + if (length < zero_limit) zero_limit = length; + + if (length > fcb->fcbEOF) { + /* Extending the file: time to fill out the current last page w. zeroes? */ + if ((fcb->fcbEOF & PAGE_MASK_64) && + (rl_scan(&hp->h_invalidranges, + fcb->fcbEOF & ~PAGE_MASK_64, + fcb->fcbEOF - 1, + &invalid_range) == RL_NOOVERLAP)) { + + /* There's some valid data at the start of the (current) last page + of the file, so zero out the remainder of that page to ensure the + entire page contains valid data. Since there is no invalid range + possible past the (current) eof, there's no need to remove anything + from the invalid range list before calling cluster_write(): */ + VOP_DEVBLOCKSIZE(hp->h_meta->h_devvp, &devBlockSize); + retval = cluster_write(vp, (struct uio *) 0, fcb->fcbEOF, zero_limit, + fcb->fcbEOF, (off_t)0, devBlockSize, (ap->a_flags & IO_SYNC) | IO_HEADZEROFILL); + if (retval) goto Err_Exit; + + /* Merely invalidate the remaining area, if necessary: */ + if (length > zero_limit) rl_add(zero_limit, length - 1, &hp->h_invalidranges); + } else { + /* The page containing the (current) eof is invalid: just add the + remainder of the page to the invalid list, along with the area + being newly allocated: + */ + rl_add(fcb->fcbEOF, length - 1, &hp->h_invalidranges); + }; + } } else { - /* - * zero out any new logical space... - */ - bytestoclear = length - fcb->fcbEOF; - filePosition = fcb->fcbEOF; - - while (bytestoclear > 0) { - logBlockNo = (daddr_t)(filePosition / PAGE_SIZE_64); - blkOffset = (long)(filePosition & PAGE_MASK_64); - - if (((off_t)(fcb->fcbPLen) - ((off_t)logBlockNo * (off_t)PAGE_SIZE)) < PAGE_SIZE_64) - logBlockSize = (off_t)(fcb->fcbPLen) - ((off_t)logBlockNo * PAGE_SIZE_64); - else - logBlockSize = PAGE_SIZE; - - if (logBlockSize < blkOffset) - panic("hfs_truncate: bad logBlockSize computed\n"); - - blockZeroCount = MIN(bytestoclear, logBlockSize - blkOffset); - - if (blkOffset == 0 && ((bytestoclear >= logBlockSize) || filePosition >= fcb->fcbEOF)) { - bp = getblk(vp, logBlockNo, logBlockSize, 0, 0, BLK_WRITE); - retval = 0; - - } else { - retval = bread(vp, logBlockNo, logBlockSize, ap->a_cred, &bp); - if (retval) { - brelse(bp); - goto Err_Exit; +#if 0 + /* + * zero out any new logical space... + */ + bytestoclear = length - fcb->fcbEOF; + filePosition = fcb->fcbEOF; + + while (bytestoclear > 0) { + logBlockNo = (daddr_t)(filePosition / PAGE_SIZE_64); + blkOffset = (long)(filePosition & PAGE_MASK_64); + + if (((off_t)(fcb->fcbPLen) - ((off_t)logBlockNo * (off_t)PAGE_SIZE)) < PAGE_SIZE_64) + logBlockSize = (off_t)(fcb->fcbPLen) - ((off_t)logBlockNo * PAGE_SIZE_64); + else + logBlockSize = PAGE_SIZE; + + if (logBlockSize < blkOffset) + panic("hfs_truncate: bad logBlockSize computed\n"); + + blockZeroCount = MIN(bytestoclear, logBlockSize - blkOffset); + + if (blkOffset == 0 && ((bytestoclear >= logBlockSize) || filePosition >= fcb->fcbEOF)) { + bp = getblk(vp, logBlockNo, logBlockSize, 0, 0, BLK_WRITE); + retval = 0; + + } else { + retval = bread(vp, logBlockNo, logBlockSize, ap->a_cred, &bp); + if (retval) { + brelse(bp); + goto Err_Exit; + } + } + bzero((char *)bp->b_data + blkOffset, blockZeroCount); + + bp->b_flags |= B_DIRTY | B_AGE; + + if (ap->a_flags & IO_SYNC) + VOP_BWRITE(bp); + else if (logBlockNo % 32) + bawrite(bp); + else + VOP_BWRITE(bp); /* wait after we issue 32 requests */ + + bytestoclear -= blockZeroCount; + filePosition += blockZeroCount; } - } - bzero((char *)bp->b_data + blkOffset, blockZeroCount); - - bp->b_flags |= B_DIRTY | B_AGE; - - if (ap->a_flags & IO_SYNC) - VOP_BWRITE(bp); - else if (logBlockNo % 32) - bawrite(bp); - else - VOP_BWRITE(bp); /* wait after we issue 32 requests */ - - bytestoclear -= blockZeroCount; - filePosition += blockZeroCount; - } +#else + panic("hfs_truncate: invoked on non-UBC object?!"); +#endif }; } fcb->fcbEOF = length; - if (fcb->fcbEOF > fcb->fcbMaxEOF) - fcb->fcbMaxEOF = fcb->fcbEOF; - if (UBCISVALID(vp)) ubc_setsize(vp, (off_t)fcb->fcbEOF); /* XXX check errors */ @@ -1430,6 +1624,9 @@ int hfs_truncate(ap) vflags = ((length > 0) ? V_SAVE : 0) | V_SAVEMETA; retval = vinvalbuf(vp, vflags, ap->a_cred, ap->a_p, 0, 0); + + /* Any space previously marked as invalid is now irrelevant: */ + rl_remove(length, fcb->fcbEOF - 1, &hp->h_invalidranges); } /* @@ -1453,8 +1650,6 @@ int hfs_truncate(ap) (void) hfs_metafilelocking(HTOHFS(hp), kHFSExtentsFileID, LK_RELEASE, ap->a_p); if (retval) goto Err_Exit; - - fcb->fcbMaxEOF = length; } fcb->fcbEOF = length; @@ -1465,8 +1660,7 @@ int hfs_truncate(ap) retval = VOP_UPDATE(vp, &tv, &tv, MNT_WAIT); if (retval) { DBG_ERR(("Could not update truncate")); - - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 7)) | DBG_FUNC_NONE, + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 7)) | DBG_FUNC_NONE, -1, -1, -1, retval, 0); } Err_Exit:; @@ -1489,11 +1683,13 @@ Err_Exit:; #% allocate vp L L L # vop_allocate { - IN struct vnode *vp; - IN off_t length; - IN int flags; - IN struct ucred *cred; - IN struct proc *p; + IN struct vnode *vp; + IN off_t length; + IN int flags; + OUT off_t *bytesallocated; + IN off_t offset; + IN struct ucred *cred; + IN struct proc *p; }; * allocate the hfsnode hp to at most length size */ @@ -1502,7 +1698,8 @@ int hfs_allocate(ap) struct vnode *a_vp; off_t a_length; u_int32_t a_flags; - off_t *a_bytesallocated; + off_t *a_bytesallocated; + off_t a_offset; struct ucred *a_cred; struct proc *a_p; } */ *ap; @@ -1517,6 +1714,7 @@ int hfs_allocate(ap) struct timeval tv; int retval, retval2; FCB *fcb; + UInt32 blockHint; UInt32 extendFlags =0; /* For call to ExtendFileC */ DBG_FUNC_NAME("hfs_allocate"); DBG_VOP_LOCKS_DECL(1); @@ -1528,6 +1726,7 @@ int hfs_allocate(ap) did nothing. ExtendFileC will fill this in for us if we actually allocate space */ *(ap->a_bytesallocated) = 0; + fcb = HTOFCB(hp); /* Now for some error checking */ @@ -1541,6 +1740,9 @@ int hfs_allocate(ap) return (EISDIR); /* hfs doesn't support truncating of directories */ } + if ((ap->a_flags & ALLOCATEFROMVOL) && (length <= fcb->fcbPLen)) + return (EINVAL); + /* Fill in the flags word for the call to Extend the file */ if (ap->a_flags & ALLOCATECONTIG) { @@ -1551,16 +1753,17 @@ int hfs_allocate(ap) extendFlags |= kEFAllMask; } - fcb = HTOFCB(hp); tv = time; retval = E_NONE; + blockHint = 0; startingPEOF = fcb->fcbPLen; if (ap->a_flags & ALLOCATEFROMPEOF) { length += fcb->fcbPLen; } - DBG_RW(("%s: allocate from Ox%lX to Ox%X bytes\n", funcname, fcb->fcbPLen, (u_int)length)); + if (ap->a_flags & ALLOCATEFROMVOL) + blockHint = ap->a_offset / HTOVCB(hp)->blockSize; /* If no changes are necesary, then we're done */ if (fcb->fcbPLen == length) @@ -1582,6 +1785,7 @@ int hfs_allocate(ap) ExtendFileC(HTOVCB(hp), fcb, moreBytesRequested, + blockHint, extendFlags, &actualBytesAdded)); @@ -1605,16 +1809,9 @@ int hfs_allocate(ap) * block size. */ - if ((actualBytesAdded != 0) && (moreBytesRequested < actualBytesAdded)) { - u_long blks, blocksize; - - blocksize = VTOVCB(vp)->blockSize; - blks = moreBytesRequested / blocksize; - if ((blks * blocksize) != moreBytesRequested) - blks++; - - *(ap->a_bytesallocated) = blks * blocksize; - } + if ((actualBytesAdded != 0) && (moreBytesRequested < actualBytesAdded)) + *(ap->a_bytesallocated) = + roundup(moreBytesRequested, (off_t)VTOVCB(vp)->blockSize); } else { /* Shorten the size of the file */ @@ -1652,7 +1849,6 @@ int hfs_allocate(ap) if (fcb->fcbEOF > fcb->fcbPLen) { fcb->fcbEOF = fcb->fcbPLen; - fcb->fcbMaxEOF = fcb->fcbPLen; if (UBCISVALID(vp)) ubc_setsize(vp, (off_t)fcb->fcbEOF); /* XXX check errors */ @@ -1689,7 +1885,7 @@ hfs_pagein(ap) register struct vnode *vp; struct hfsnode *hp; FCB *fcb; - long devBlockSize = 0; + int devBlockSize = 0; int retval; DBG_FUNC_NAME("hfs_pagein"); @@ -1745,7 +1941,8 @@ hfs_pageout(ap) struct hfsnode *hp = VTOH(vp); FCB *fcb = HTOFCB(hp); int retval; - long devBlockSize = 0; + int devBlockSize = 0; + off_t end_of_range; DBG_FUNC_NAME("hfs_pageout"); DBG_VOP_LOCKS_DECL(1); @@ -1767,8 +1964,17 @@ hfs_pageout(ap) VOP_DEVBLOCKSIZE(hp->h_meta->h_devvp, &devBlockSize); + end_of_range = ap->a_f_offset + ap->a_size - 1; + + if (end_of_range >= (off_t)fcb->fcbEOF) + end_of_range = (off_t)(fcb->fcbEOF - 1); + + if (ap->a_f_offset < (off_t)fcb->fcbEOF) + rl_remove(ap->a_f_offset, end_of_range, &hp->h_invalidranges); + retval = cluster_pageout(vp, ap->a_pl, ap->a_pl_offset, ap->a_f_offset, ap->a_size, (off_t)fcb->fcbEOF, devBlockSize, ap->a_flags); + /* * If we successfully wrote any data, and we are not the superuser * we clear the setuid and setgid bits as a precaution against diff --git a/bsd/hfs/hfs_vfsops.c b/bsd/hfs/hfs_vfsops.c index b3b2e8f1a..001c0f600 100644 --- a/bsd/hfs/hfs_vfsops.c +++ b/bsd/hfs/hfs_vfsops.c @@ -145,9 +145,6 @@ simple_lock_data_t gBufferPtrListLock; //static char hfs_fs_name[MFSNAMELEN] = "hfs"; -/* The following represent information held in low-memory on the MacOS: */ - -struct FSVarsRec *gFSMVars; /* * Global variables defined in other modules: @@ -211,8 +208,10 @@ hfs_mountroot() /* Init hfsmp */ hfsmp = VFSTOHFS(mp); - hfsmp->hfs_dir_mask = (S_IRWXU|S_IRWXG|S_IRWXO); /* 0777 */ - hfsmp->hfs_file_mask = (S_IRWXU|S_IRWXG|S_IRWXO); /* 0777 */ + hfsmp->hfs_uid = UNKNOWNUID; + hfsmp->hfs_gid = UNKNOWNGID; + hfsmp->hfs_dir_mask = (S_IRWXU | S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH); /* 0755 */ + hfsmp->hfs_file_mask = (S_IRWXU | S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH); /* 0755 */ (void)hfs_statfs(mp, &mp->mnt_stat, p); @@ -253,7 +252,7 @@ hfs_mount (mp, path, data, ndp, p) * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { - + hfsmp = VFSTOHFS(mp); if ((hfsmp->hfs_fs_ronly == 0) && (mp->mnt_flag & MNT_RDONLY)) { @@ -429,6 +428,11 @@ hfs_changefs(mp, args, p) vcb = HFSTOVCB(hfsmp); permswitch = (((hfsmp->hfs_unknownpermissions != 0) && ((mp->mnt_flag & MNT_UNKNOWNPERMISSIONS) == 0)) || ((hfsmp->hfs_unknownpermissions == 0) && ((mp->mnt_flag & MNT_UNKNOWNPERMISSIONS) != 0))); + /* The root filesystem must operate with actual permissions: */ + if (permswitch && (mp->mnt_flag & MNT_ROOTFS) && (mp->mnt_flag & MNT_UNKNOWNPERMISSIONS)) { + mp->mnt_flag &= ~MNT_UNKNOWNPERMISSIONS; /* Just say "No". */ + return EINVAL; + }; hfsmp->hfs_unknownpermissions = ((mp->mnt_flag & MNT_UNKNOWNPERMISSIONS) != 0); namefix = permfix = 0; @@ -556,12 +560,13 @@ loop: hp->h_meta->h_gid = VTOHFS(vp)->hfs_gid; /* Default access is full read/write/execute: */ - hp->h_meta->h_mode = ACCESSPERMS; /* 0777: rwxrwxrwx */ + hp->h_meta->h_mode &= IFMT; + hp->h_meta->h_mode |= ACCESSPERMS; /* 0777: rwxrwxrwx */ /* ... but no more than that permitted by the mount point's: */ if ((hp->h_meta->h_mode & IFMT) == IFDIR) { - hp->h_meta->h_mode &= VTOHFS(vp)->hfs_dir_mask; + hp->h_meta->h_mode &= IFMT | VTOHFS(vp)->hfs_dir_mask; } else { - hp->h_meta->h_mode &= VTOHFS(vp)->hfs_file_mask; + hp->h_meta->h_mode &= IFMT | VTOHFS(vp)->hfs_file_mask; } }; }; @@ -873,6 +878,13 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct proc *p, struct hfs_mo if (retval) return retval; devvp->v_specsize = blksize; + /* cache the IO attributes */ + if ((retval = vfs_init_io_attributes(devvp, mp))) { + printf("hfs_mountfs: vfs_init_io_attributes returned %d\n", + retval); + return (retval); + } + DBG_VFS(("hfs_mountfs: reading MDB [block no. %d + %d bytes, size %d bytes]...\n", IOBLKNOFORBLK(kMasterDirectoryBlock, blksize), IOBYTEOFFSETFORBLK(kMasterDirectoryBlock, blksize), @@ -1260,6 +1272,7 @@ loop:; for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { + int didhold; /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. @@ -1289,12 +1302,16 @@ loop:; continue; } + didhold = ubc_hold(vp); if ((error = VOP_FSYNC(vp, cred, waitfor, p))) { DBG_ERR(("hfs_sync: error %d calling fsync on vnode 0x%X.\n", error, (u_int)vp)); allerror = error; }; DBG_ASSERT(*((volatile int *)(&(vp)->v_interlock))==0); - vput(vp); + VOP_UNLOCK(vp, 0, p); + if (didhold) + ubc_rele(vp); + vrele(vp); simple_lock(&mntvnode_slock); }; @@ -1398,7 +1415,18 @@ struct ucred **credanonp; if (result) return result; if (nvp == NULL) return ESTALE; - if ((hfsfhp->hfsfid_gen != VTOH(nvp)->h_meta->h_crtime)) { + /* The createtime can be changed by hfs_setattr or hfs_setattrlist. + * For NFS, we are assuming that only if the createtime was moved + * forward would it mean the fileID got reused in that session by + * wrapping. We don't have a volume ID or other unique identifier to + * to use here for a generation ID across reboots, crashes where + * metadata noting lastFileID didn't make it to disk but client has + * it, or volume erasures where fileIDs start over again. Lastly, + * with HFS allowing "wraps" of fileIDs now, this becomes more + * error prone. Future, would be change the "wrap bit" to a unique + * wrap number and use that for generation number. For now do this. + */ + if ((hfsfhp->hfsfid_gen < VTOH(nvp)->h_meta->h_crtime)) { vput(nvp); return ESTALE; }; @@ -1484,25 +1512,10 @@ struct vfsconf *vfsp; }; gBufferListIndex = 0; - /* - * Do any initialization that the MacOS/MacOS X shared code relies on - * (normally done as part of MacOS's startup): - */ - MALLOC(gFSMVars, FSVarsRec *, sizeof(FSVarsRec), M_TEMP, M_WAITOK); - bzero(gFSMVars, sizeof(FSVarsRec)); - /* * Allocate Catalog Iterator cache... */ err = InitCatalogCache(); -#if HFS_DIAGNOSTIC - if (err) panic("hfs_init: Error returned from InitCatalogCache() call."); -#endif - /* - * XXX do we need to setup the following? - * - * GMT offset, Unicode globals, CatSearch Buffers, BTSscanner - */ return E_NONE; } @@ -1619,12 +1632,10 @@ Lookup_Err_Exit: Err_Exit: - if (retval != E_NONE) { - DBG_VFS(("hfs_vget: Error returned of %d\n", retval)); - } - else { - DBG_VFS(("hfs_vget: vp = 0x%x\n", (u_int)*vpp)); - } + /* rember if a parent directory was looked up by CNID */ + if (retval == 0 && ((*vpp)->v_type == VDIR) + && lockstatus(&mp->mnt_lock) != LK_SHARED) + VTOH(*vpp)->h_nodeflags |= IN_BYCNID; return (retval); @@ -1690,7 +1701,6 @@ short hfs_flushMDB(struct hfsmount *hfsmp, int waitfor) retval = utf8_to_mac_roman(namelen, vcb->vcbVN, mdb->drVN); mdb->drVolBkUp = SWAP_BE32 (UTCToLocal(vcb->vcbVolBkUp)); - mdb->drVSeqNum = SWAP_BE16 (vcb->vcbVSeqNum); mdb->drWrCnt = SWAP_BE32 (vcb->vcbWrCnt); mdb->drNmRtDirs = SWAP_BE16 (vcb->vcbNmRtDirs); mdb->drFilCnt = SWAP_BE32 (vcb->vcbFilCnt); diff --git a/bsd/hfs/hfs_vfsutils.c b/bsd/hfs/hfs_vfsutils.c index 36c3e550e..077b9a13a 100644 --- a/bsd/hfs/hfs_vfsutils.c +++ b/bsd/hfs/hfs_vfsutils.c @@ -133,8 +133,6 @@ #define BYPASSBLOCKINGOPTIMIZATION 0 -#define kMaxLockedMetaBuffers 32 /* number of locked buffer caches to hold for meta data */ - extern int (**hfs_vnodeop_p)(void *); extern int (**hfs_specop_p)(void *); extern int (**hfs_fifoop_p)(void *); @@ -142,7 +140,6 @@ extern int count_lock_queue __P((void)); extern uid_t console_user; OSErr ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb ); -UInt16 DivUp( UInt32 byteRun, UInt32 blockSize ); /* Externs from vhash */ extern void hfs_vhashins_sibling(dev_t dev, UInt32 nodeID, struct hfsnode *hp, struct hfsfilemeta **fm); @@ -151,7 +148,6 @@ extern struct vnode *hfs_vhashget(dev_t dev, UInt32 nodeID, UInt8 forkType); extern int hfs_vinit( struct mount *mntp, int (**specops)(void *), int (**fifoops)(), struct vnode **vpp); -extern UInt16 CountRootFiles(ExtendedVCB *vcb); extern OSErr GetVolumeNameFromCatalog(ExtendedVCB *vcb); static int InitMetaFileVNode(struct vnode *vp, off_t eof, u_long clumpSize, const HFSPlusExtentRecord extents, @@ -215,6 +211,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, vcb->vcbSigWord = SWAP_BE16 (mdb->drSigWord); vcb->vcbCrDate = LocalToUTC (SWAP_BE32 (mdb->drCrDate)); + vcb->localCreateDate = SWAP_BE32 (mdb->drCrDate); vcb->vcbLsMod = LocalToUTC (SWAP_BE32 (mdb->drLsMod)); vcb->vcbAtrb = SWAP_BE16 (mdb->drAtrb); vcb->vcbNmFls = SWAP_BE16 (mdb->drNmFls); @@ -227,7 +224,6 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, vcb->vcbNxtCNID = SWAP_BE32 (mdb->drNxtCNID); vcb->freeBlocks = SWAP_BE16 (mdb->drFreeBks); vcb->vcbVolBkUp = LocalToUTC (SWAP_BE32 (mdb->drVolBkUp)); - vcb->vcbVSeqNum = SWAP_BE16 (mdb->drVSeqNum); vcb->vcbWrCnt = SWAP_BE32 (mdb->drWrCnt); vcb->vcbNmRtDirs = SWAP_BE16 (mdb->drNmRtDirs); vcb->vcbFilCnt = SWAP_BE32 (mdb->drFilCnt); @@ -256,6 +252,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, ReturnIfError( err ); hfsmp->hfs_logBlockSize = BestBlockSizeFit(vcb->blockSize, MAXBSIZE, hfsmp->hfs_phys_block_size); + vcb->vcbVBMIOSize = kHFSBlockSize; // XXX PPD: Should check here for hardware lock flag and set flags in VCB/MP appropriately VCB_LOCK_INIT(vcb); @@ -263,7 +260,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, /* * Set up Extents B-tree vnode... */ - err = GetInitializedVNode(hfsmp, &tmpvnode, 0); + err = GetInitializedVNode(hfsmp, &tmpvnode); if (err) goto MtVolErr; /* HFSToHFSPlusExtents(mdb->drXTExtRec, extents); */ /* ASDFADSFSD */ extents[0].startBlock = SWAP_BE16 (mdb->drXTExtRec[0].startBlock); @@ -280,7 +277,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, /* * Set up Catalog B-tree vnode... */ - err = GetInitializedVNode(hfsmp, &tmpvnode, 0); + err = GetInitializedVNode(hfsmp, &tmpvnode); if (err) goto MtVolErr; /* HFSToHFSPlusExtents(mdb->drCTExtRec, extents); */ extents[0].startBlock = SWAP_BE16 (mdb->drCTExtRec[0].startBlock); @@ -399,6 +396,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, /* Update the logical block size in the mount struct (currently set up from the wrapper MDB) using the new blocksize value: */ hfsmp->hfs_logBlockSize = BestBlockSizeFit(vcb->blockSize, MAXBSIZE, hfsmp->hfs_phys_block_size); + vcb->vcbVBMIOSize = min(vcb->blockSize, MAXPHYSIO); // XXX PPD: Should check here for hardware lock flag and set flags in VCB/MP appropriately // vcb->vcbAtrb |= kVolumeHardwareLockMask; // XXX this line for debugging only!!!! @@ -410,7 +408,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, /* * Set up Extents B-tree vnode... */ - retval = GetInitializedVNode(hfsmp, &tmpvnode, 0); + retval = GetInitializedVNode(hfsmp, &tmpvnode); if (retval) goto ErrorExit; fdp = &vhp->extentsFile; SWAP_HFS_PLUS_FORK_DATA (fdp); @@ -422,7 +420,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, /* * Set up Catalog B-tree vnode... */ - retval = GetInitializedVNode(hfsmp, &tmpvnode, 0); + retval = GetInitializedVNode(hfsmp, &tmpvnode); if (retval) goto ErrorExit; fdp = &vhp->catalogFile; SWAP_HFS_PLUS_FORK_DATA (fdp); @@ -434,7 +432,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, /* * Set up Allocation file vnode... */ - retval = GetInitializedVNode(hfsmp, &tmpvnode, 0); + retval = GetInitializedVNode(hfsmp, &tmpvnode); if (retval) goto ErrorExit; fdp = &vhp->allocationFile; SWAP_HFS_PLUS_FORK_DATA (fdp); @@ -613,6 +611,53 @@ short hfsUnmount( register struct hfsmount *hfsmp, struct proc *p) } +/* + * hfs_resolvelink - auto resolve HFS+ hardlinks + * + * Used after calling GetCatalogNode or GetCatalogOffspring + */ +void hfs_resolvelink(ExtendedVCB *vcb, CatalogNodeData *cndp) +{ + struct FInfo *fip; + char iNodeName[32]; + UInt32 hint; + UInt32 indlinkno; + OSErr result; + + fip = (struct FInfo *) &cndp->cnd_finderInfo; + + /* + * if this is an indirect link (hardlink) then auto resolve it... + */ + if ((vcb->vcbSigWord == kHFSPlusSigWord) + && (cndp->cnd_type == kCatalogFileNode) + && (fip->fdType == kHardLinkFileType) + && (fip->fdCreator == kHFSPlusCreator) + && ((cndp->cnd_createDate == vcb->vcbCrDate) || + (cndp->cnd_createDate == VCBTOHFS(vcb)->hfs_metadata_createdate))) { + + indlinkno = cndp->cnd_iNodeNum; + MAKE_INODE_NAME(iNodeName, indlinkno); + /* + * Get nodeData from the data node file. + * Flag the node data to NOT copy the name (ie preserve the original) + */ + cndp->cnm_flags |= kCatNameNoCopyName; + result = GetCatalogNode(vcb, VCBTOHFS(vcb)->hfs_private_metadata_dir, + iNodeName, 0, 0, cndp, &hint); + cndp->cnm_flags &= ~kCatNameNoCopyName; + + /* Make sure there's a reference */ + if (result == 0) { + if (cndp->cnd_linkCount == 0) cndp->cnd_linkCount = 2; + + /* Keep a copy of iNodeNum to put into h_indnodeno */ + cndp->cnd_iNodeNumCopy = indlinkno; + } + } +} + + /* * Performs a lookup on the given dirID, name. Returns the catalog info * @@ -623,7 +668,6 @@ short hfs_getcatalog (ExtendedVCB *vcb, UInt32 parentDirID, char *name, short le { OSErr result; UInt32 length; - struct FInfo *fip; if (len == -1 ) { /* Convert it to MacOS terms */ if (name) @@ -642,56 +686,8 @@ short hfs_getcatalog (ExtendedVCB *vcb, UInt32 parentDirID, char *name, short le } #endif -#if HFS_HARDLINKS - if (result) - goto exit; - - fip = (struct FInfo *) &catInfo->nodeData.cnd_finderInfo; - - /* - * if we encounter an indirect link (hardlink) then auto resolve it... - */ - if ((catInfo->nodeData.cnd_type == kCatalogFileNode) && - (fip->fdType == kHardLinkFileType) && - (fip->fdCreator == kHFSPlusCreator) && - ((catInfo->nodeData.cnd_createDate == vcb->vcbCrDate) || - (catInfo->nodeData.cnd_createDate == VCBTOHFS(vcb)->hfs_metadata_createdate))) { - - u_int32_t indlinkno; - char iNodeName[32]; - UInt32 privDir = VCBTOHFS(vcb)->hfs_private_metadata_dir; - - indlinkno = catInfo->nodeData.cnd_iNodeNum; - MAKE_INODE_NAME(iNodeName, indlinkno); - - /* - * Get nodeData from the data node file. - * Flag the node data to NOT copy the name, perserver the original - */ - catInfo->nodeData.cnm_flags |= kCatNameNoCopyName; - result = GetCatalogNode(vcb, privDir, iNodeName, 0, 0, &catInfo->nodeData, &catInfo->hint); - catInfo->nodeData.cnm_flags &= ~kCatNameNoCopyName; /* Just to keep things like they should be */ - - /* make sure there's at lease 1 reference */ - if (result == 0) { - if (catInfo->nodeData.cnd_linkCount == 0) - catInfo->nodeData.cnd_linkCount = 2; - /* keep a copy of iNodeNum to put into h_indnodeno */ - catInfo->nodeData.cnd_iNodeNumCopy = indlinkno; - } - - /* if we can not resolve the link, allow the link to be - * exposed (as an empty file) so it can be deleted - */ - if (result == cmNotFound) - result = 0; - } - -exit: -#endif - - if (result) - DBG_ERR(("on Lookup, GetCatalogNode returned: %d: dirid: %ld name: %s\n", result, parentDirID, name)); + if (result == 0) + hfs_resolvelink(vcb, &catInfo->nodeData); return MacToVFSError(result); } @@ -724,7 +720,7 @@ short hfsMoveRename (ExtendedVCB *vcb, UInt32 oldDirID, char *oldName, UInt32 ne { OSErr result = noErr; - result = MoveRenameCatalogNode(vcb, oldDirID,oldName, *hint, newDirID, newName, hint); + result = MoveRenameCatalogNode(vcb, oldDirID,oldName, *hint, newDirID, newName, hint, 0); if (result) DBG_ERR(("on hfsMoveRename, MoveRenameCatalogNode returned: %d: newdirid: %ld newname: %s\n", result, newDirID, newName)); @@ -736,7 +732,7 @@ short hfsMoveRename (ExtendedVCB *vcb, UInt32 oldDirID, char *oldName, UInt32 ne /* XXX SER pass back the hint so other people can use it */ -short hfsCreate(ExtendedVCB *vcb, UInt32 dirID, char *name, int mode) +short hfsCreate(ExtendedVCB *vcb, UInt32 dirID, char *name, int mode, UInt32 tehint) { OSErr result = noErr; HFSCatalogNodeID catalogNodeID; @@ -749,7 +745,7 @@ short hfsCreate(ExtendedVCB *vcb, UInt32 dirID, char *name, int mode) else type = kCatalogFileNode; - result = CreateCatalogNode (vcb, dirID, name, type, &catalogNodeID, &catalogHint); + result = CreateCatalogNode (vcb, dirID, name, type, &catalogNodeID, &catalogHint, tehint); return MacToVFSError(result); } @@ -771,83 +767,23 @@ int hfs_vget_catinfo(struct vnode *parent_vp, struct hfsCatalogInfo *catInfo, u_ { int retval = E_NONE; - + if (forkType == kDefault) { + if (catInfo->nodeData.cnd_type == kCatalogFolderNode) + forkType = kDirectory; + else + forkType = kDataFork; + } + *target_vp = hfs_vhashget(H_DEV(VTOH(parent_vp)), catInfo->nodeData.cnd_nodeID, forkType); - if (*target_vp == NULL) { - if (forkType == kAnyFork) - if (catInfo->nodeData.cnd_type == kCatalogFolderNode) - forkType = kDirectory; - else - forkType = kDataFork; - + if (*target_vp == NULL) retval = hfs_vcreate( VTOVCB(parent_vp), catInfo, forkType, target_vp); - }; return (retval); } -/********************************************************************************/ -/* */ -/* hfs_vget_fork - Returns a vnode derived from a sibling */ -/* vp is locked */ -/* */ -/********************************************************************************/ - -int hfs_vget_sibling(struct vnode *vp, u_int16_t forkType, struct vnode **vpp) -{ - struct vnode * target_vp = NULL; - int retval = E_NONE; - - - DBG_ASSERT(vp != NULL); - DBG_ASSERT(VTOH(vp) != NULL); - DBG_ASSERT(VTOH(vp)->h_meta != NULL); - DBG_ASSERT(forkType==kDataFork || forkType==kRsrcFork); - - target_vp = hfs_vhashget(H_DEV(VTOH(vp)), H_FILEID(VTOH(vp)), forkType); - - /* - * If not in the hash, then we have to create it - */ - if (target_vp == NULL) { - struct proc *p = current_proc(); - hfsCatalogInfo catInfo; - - INIT_CATALOGDATA(&catInfo.nodeData, 0); - catInfo.hint = H_HINT(VTOH(vp)); - - /* lock catalog b-tree */ - retval = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_SHARED, p); - if (retval) goto GetCatErr_Exit; - - retval = hfs_getcatalog (VTOVCB(vp), H_DIRID(VTOH(vp)), H_NAME(VTOH(vp)), VTOH(vp)->h_meta->h_namelen, &catInfo); - - /* unlock catalog b-tree */ - (void) hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_RELEASE, p); - if (retval) goto GetCatErr_Exit; - - retval = hfs_vcreate( VTOVCB(vp), &catInfo, forkType, &target_vp); - -GetCatErr_Exit: - CLEAN_CATALOGDATA(&catInfo.nodeData); - }; - -Err_Exit: - - if (!retval) { - DBG_ASSERT(target_vp!=NULL); - } else { - DBG_ASSERT(target_vp==NULL); - } - - *vpp = target_vp; - return (retval); -} - - /************************************************************************/ /* hfs_vcreate - Returns a vnode derived from hfs */ /* */ @@ -882,6 +818,16 @@ short hfs_vcreate(ExtendedVCB *vcb, hfsCatalogInfo *catInfo, UInt8 forkType, str } #endif + if ( ! ((forkType == kDirectory) || (forkType == kDataFork) || (forkType == kRsrcFork))) + panic("Bad fork type"); + if (catInfo->nodeData.cnd_type == kCatalogFolderNode) { + if (forkType != kDirectory) + panic("non directory type"); + } else { + if (forkType != kDataFork && forkType != kRsrcFork) + panic("non fork type"); + } + hfsmp = VCBTOHFS(vcb); mp = HFSTOVFS(hfsmp); dev = hfsmp->hfs_raw_dev; @@ -922,6 +868,7 @@ short hfs_vcreate(ExtendedVCB *vcb, hfsCatalogInfo *catInfo, UInt8 forkType, str hp->h_vp = vp; /* Make HFSTOV work */ vp->v_data = hp; /* Make VTOH work */ H_FORKTYPE(hp) = forkType; + rl_init(&hp->h_invalidranges); fm = NULL; /* @@ -1345,7 +1292,9 @@ int hfs_metafilelocking(struct hfsmount *hfsmp, u_long fileID, u_int flags, stru * * 1. (a) Your UID matches the UID of the vnode * (b) The object in question is owned by "unknown" and your UID matches the console user's UID - * 2. Permissions on the filesystem are being ignored and your UID matches the replacement UID + * 2. (a) Permissions on the filesystem are being ignored and your UID matches the replacement UID + * (b) Permissions on the filesystem are being ignored and the replacement UID is "unknown" and + * your UID matches the console user UID * 3. You are root * */ @@ -1353,7 +1302,8 @@ int hfs_owner_rights(struct vnode *vp, struct ucred *cred, struct proc *p, Boole return ((cred->cr_uid == VTOH(vp)->h_meta->h_uid) || /* [1a] */ ((VTOH(vp)->h_meta->h_uid == UNKNOWNUID) && (cred->cr_uid == console_user)) || /* [1b] */ ((VTOVFS(vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) && /* [2] */ - (cred->cr_uid == VTOHFS(vp)->hfs_uid)) || /* [2] */ + ((cred->cr_uid == VTOHFS(vp)->hfs_uid) || /* [2a] */ + ((VTOHFS(vp)->hfs_uid == UNKNOWNUID) && (cred->cr_uid == console_user)))) || /* [2b] */ (invokesuperuserstatus && (suser(cred, &p->p_acflag) == 0))) ? 0 : EPERM; } @@ -1361,9 +1311,10 @@ int hfs_owner_rights(struct vnode *vp, struct ucred *cred, struct proc *p, Boole int hfs_catalogentry_owner_rights(uid_t obj_uid, struct mount *mp, struct ucred *cred, struct proc *p, Boolean invokesuperuserstatus) { return ((cred->cr_uid == obj_uid) || /* [1a] */ - ((VFSTOHFS(mp)->hfs_uid == UNKNOWNUID) && (cred->cr_uid == console_user)) || /* [1b] */ + ((obj_uid == UNKNOWNUID) && (cred->cr_uid == console_user)) || /* [1b] */ ((mp->mnt_flag & MNT_UNKNOWNPERMISSIONS) && /* [2] */ - (cred->cr_uid == VFSTOHFS(mp)->hfs_uid)) || /* [2] */ + ((cred->cr_uid == VFSTOHFS(mp)->hfs_uid) || /* [2a] */ + ((VFSTOHFS(mp)->hfs_uid == UNKNOWNUID) && (cred->cr_uid == console_user)))) || /* [2b] */ (invokesuperuserstatus && (suser(cred, &p->p_acflag) == 0))) ? 0 : EPERM; } @@ -1376,6 +1327,7 @@ void CopyVNodeToCatalogNode (struct vnode *vp, struct CatalogNodeData *nodeData) struct hfsnode *hp; Boolean isHFSPlus, isResource; HFSPlusExtentDescriptor *extents; + off_t fileReadLimit; hp = VTOH(vp); vcb = HTOVCB(hp); @@ -1423,13 +1375,18 @@ void CopyVNodeToCatalogNode (struct vnode *vp, struct CatalogNodeData *nodeData) /* The file is unlocked: make sure the locked bit in the catalog is clear. */ nodeData->cnd_flags &= ~kHFSFileLockedMask; }; + if (CIRCLEQ_EMPTY(&hp->h_invalidranges)) { + fileReadLimit = fcb->fcbEOF; + } else { + fileReadLimit = CIRCLEQ_FIRST(&hp->h_invalidranges)->rl_start; + }; if (isResource) { extents = nodeData->cnd_rsrcfork.extents; - nodeData->cnd_rsrcfork.logicalSize = fcb->fcbEOF; + nodeData->cnd_rsrcfork.logicalSize = fileReadLimit; nodeData->cnd_rsrcfork.totalBlocks = fcb->fcbPLen / vcb->blockSize; } else { extents = nodeData->cnd_datafork.extents; - nodeData->cnd_datafork.logicalSize = fcb->fcbEOF; + nodeData->cnd_datafork.logicalSize = fileReadLimit; nodeData->cnd_datafork.totalBlocks = fcb->fcbPLen / vcb->blockSize; }; @@ -1870,7 +1827,7 @@ void PackVolCommonAttributes(struct attrlist *alist, if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = vcb->volumeNameEncodingHint; /* NOTE: all VCB dates are in Mac OS time */ if (a & ATTR_CMN_CRTIME) { - ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(LocalToUTC(vcb->localCreateDate)); + ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(vcb->vcbCrDate); ((struct timespec *)attrbufptr)->tv_nsec = 0; ++((struct timespec *)attrbufptr); }; @@ -2020,17 +1977,22 @@ void PackVolAttributeBlock(struct attrlist *alist, }; if (a & ATTR_VOL_ENCODINGSUSED) *((unsigned long long *)attrbufptr)++ = (unsigned long long)vcb->encodingsBitmap; if (a & ATTR_VOL_CAPABILITIES) { - ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_FORMAT] = - VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_SYMBOLICLINKS | VOL_CAP_FMT_HARDLINKS; + if (vcb->vcbSigWord == kHFSPlusSigWord) { + ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_FORMAT] = + VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_SYMBOLICLINKS | VOL_CAP_FMT_HARDLINKS; + } else { /* Plain HFS */ + ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_FORMAT] = + VOL_CAP_FMT_PERSISTENTOBJECTIDS; + } ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_INTERFACES] = - VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT; + VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT | VOL_CAP_INT_READDIRATTR; ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED1] = 0; ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED2] = 0; ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_SYMBOLICLINKS | VOL_CAP_FMT_HARDLINKS; ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_INTERFACES] = - VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT; + VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT | VOL_CAP_INT_READDIRATTR; ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED1] = 0; ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED2] = 0; @@ -2083,10 +2045,12 @@ void PackCommonCatalogInfoAttributeBlock(struct attrlist *alist, void *varbufptr; attrgroup_t a; u_long attrlength; + Boolean isHFSPlus; hp = VTOH(root_vp); attrbufptr = *attrbufptrptr; varbufptr = *varbufptrptr; + isHFSPlus = (VTOVCB(root_vp)->vcbSigWord == kHFSPlusSigWord); if ((a = alist->commonattr) != 0) { @@ -2193,7 +2157,8 @@ void PackCommonCatalogInfoAttributeBlock(struct attrlist *alist, (char *)attrbufptr += sizeof(catalogInfo->nodeData.cnd_finderInfo); }; if (a & ATTR_CMN_OWNERID) { - if (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) { + if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) || + ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) { *((uid_t *)attrbufptr)++ = (VTOHFS(root_vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(root_vp)->hfs_uid; } else { @@ -2202,34 +2167,37 @@ void PackCommonCatalogInfoAttributeBlock(struct attrlist *alist, }; } if (a & ATTR_CMN_GRPID) { - if (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) { + if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) || + ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) { *((gid_t *)attrbufptr)++ = VTOHFS(root_vp)->hfs_gid; } else { *((gid_t *)attrbufptr)++ = catalogInfo->nodeData.cnd_groupID; }; } if (a & ATTR_CMN_ACCESSMASK) { + if (((catalogInfo->nodeData.cnd_mode & IFMT) == 0) #if OVERRIDE_UNKNOWN_PERMISSIONS - if (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) { + || (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) +#endif + ) { switch (catalogInfo->nodeData.cnd_type) { case kCatalogFileNode: /* Files in an HFS+ catalog can represent many things (regular files, symlinks, block/character devices, ...) */ - *((fsobj_type_t *)attrbufptr)++ = (u_long)(VTOHFS(root_vp)->hfs_file_mask); + *((u_long *)attrbufptr)++ = (u_long)(IFREG | (ACCESSPERMS & (u_long)(VTOHFS(root_vp)->hfs_file_mask))); break; case kCatalogFolderNode: - /* Fall through to default case */ + *((u_long *)attrbufptr)++ = (u_long)(IFDIR | (ACCESSPERMS & (u_long)(VTOHFS(root_vp)->hfs_dir_mask))); + break; default: - *((u_long *)attrbufptr)++ = (u_long)(VTOHFS(root_vp)->hfs_dir_mask); + *((u_long *)attrbufptr)++ = (u_long)((catalogInfo->nodeData.cnd_mode & IFMT) | + VTOHFS(root_vp)->hfs_dir_mask); }; } else { -#endif *((u_long *)attrbufptr)++ = (u_long)catalogInfo->nodeData.cnd_mode; -#if OVERRIDE_UNKNOWN_PERMISSIONS }; -#endif } if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0; /* XXX PPD TBC */ if (a & ATTR_CMN_NAMEDATTRLIST) @@ -2242,16 +2210,39 @@ void PackCommonCatalogInfoAttributeBlock(struct attrlist *alist, (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3); ++((struct attrreference *)attrbufptr); }; - if (a & ATTR_CMN_FLAGS) - *((u_long *)attrbufptr)++ = - (u_long) (catalogInfo->nodeData.cnd_ownerFlags | - (catalogInfo->nodeData.cnd_adminFlags << 16)); + if (a & ATTR_CMN_FLAGS) { + if (catalogInfo->nodeData.cnd_mode & IFMT) { + if (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask) { + *((u_long *)attrbufptr)++ = + (u_long) (catalogInfo->nodeData.cnd_ownerFlags | + (catalogInfo->nodeData.cnd_adminFlags << 16)) | + UF_IMMUTABLE; + } else { + *((u_long *)attrbufptr)++ = + (u_long) (catalogInfo->nodeData.cnd_ownerFlags | + (catalogInfo->nodeData.cnd_adminFlags << 16)) & ~UF_IMMUTABLE; + } + } else { + /* The information in the node flag fields is not valid: */ + *((u_long *)attrbufptr)++ = + (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask) ? UF_IMMUTABLE : 0; + }; + }; if (a & ATTR_CMN_USERACCESS) { - if (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) { + if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) || + ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) { *((u_long *)attrbufptr)++ = DerivePermissionSummary((VTOHFS(root_vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(root_vp)->hfs_uid, VTOHFS(root_vp)->hfs_gid, +#if OVERRIDE_UNKNOWN_PERMISSIONS (catalogInfo->nodeData.cnd_type == kCatalogFileNode) ? VTOHFS(root_vp)->hfs_file_mask : VTOHFS(root_vp)->hfs_dir_mask, +#else + (catalogInfo->nodeData.cnd_mode & IFMT) ? + (u_long)catalogInfo->nodeData.cnd_mode : + ((catalogInfo->nodeData.cnd_type == kCatalogFileNode) ? + VTOHFS(root_vp)->hfs_file_mask : + VTOHFS(root_vp)->hfs_dir_mask), +#endif VTOVFS(root_vp), current_proc()->p_ucred, current_proc()); @@ -2787,7 +2778,9 @@ void UnpackVolumeAttributeBlock(struct attrlist *alist, #endif }; if (a & ATTR_CMN_CRTIME) { - vcb->localCreateDate = UTCToLocal(to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec)); + vcb->vcbCrDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec); + /* Need to update the local time also */ + vcb->localCreateDate = UTCToLocal(vcb->vcbCrDate); ++((struct timespec *)attrbufptr); #if HFS_DIAGNOSTIC a &= ~ATTR_CMN_CRTIME; @@ -2850,6 +2843,7 @@ void UnpackCommonAttributeBlock(struct attrlist *alist, a = alist->commonattr; if (a & ATTR_CMN_SCRIPT) { catInfo->nodeData.cnd_textEncoding = (u_int32_t)*((text_encoding_t *)attrbufptr)++; + UpdateVolumeEncodings(VTOVCB(vp), catInfo->nodeData.cnd_textEncoding); /* Update the volume encoding */ #if HFS_DIAGNOSTIC a &= ~ATTR_CMN_SCRIPT; #endif @@ -3140,7 +3134,7 @@ FindMetaDataDirectory(ExtendedVCB *vcb) dirID = 0; metadata_createdate = 0; - strncpy(namep, HFSPLUSMETADATAFOLDER, sizeof(namep)); + strncpy(namep, HFSPLUS_PRIVATE_DIR, sizeof(namep)); INIT_CATALOGDATA(&catInfo.nodeData, kCatNameNoCopyName); catInfo.hint = kNoHint; @@ -3152,7 +3146,7 @@ FindMetaDataDirectory(ExtendedVCB *vcb) dirID = catInfo.nodeData.cnd_nodeID; metadata_createdate = catInfo.nodeData.cnd_createDate; } else if (VCBTOHFS(vcb)->hfs_fs_ronly == 0) { - if (CreateCatalogNode(vcb, kRootDirID, namep, kCatalogFolderNode, &dirID, &catInfo.hint) == 0) { + if (CreateCatalogNode(vcb, kRootDirID, namep, kCatalogFolderNode, &dirID, &catInfo.hint, 0) == 0) { catInfo.hint = kNoHint; if (hfs_getcatalog(vcb, kRootDirID, namep, -1, &catInfo) == 0) { @@ -3192,7 +3186,7 @@ RemovedMetaDataDirectory(ExtendedVCB *vcb) hfsCatalogInfo catInfo; int retval; - strncpy(name, HFSPLUSMETADATAFOLDER, sizeof(name)); + strncpy(name, HFSPLUS_PRIVATE_DIR, sizeof(name)); INIT_CATALOGDATA(&catInfo.nodeData, kCatNameNoCopyName); /* lock catalog b-tree */ @@ -3226,26 +3220,30 @@ u_int32_t logBlockSize; DBG_ASSERT(vp != NULL); - if ((vp->v_flag & VSYSTEM) && (VTOH(vp)->fcbBTCBPtr!=NULL)) { - BTreeInfoRec bTreeInfo; - int retval; + /* start with default */ + logBlockSize = VTOHFS(vp)->hfs_logBlockSize; - /* - * We do not lock the BTrees, because if we are getting block..then the tree - * should be locked in the first place. - * We just want the nodeSize wich will NEVER change..so even if the world - * is changing..the nodeSize should remain the same. Which argues why lock - * it in the first place?? - */ - - (void) BTGetInformation (VTOFCB(vp), kBTreeInfoVersion, &bTreeInfo); - - logBlockSize = bTreeInfo.nodeSize; + if (vp->v_flag & VSYSTEM) { + if (VTOH(vp)->fcbBTCBPtr != NULL) { + BTreeInfoRec bTreeInfo; + + /* + * We do not lock the BTrees, because if we are getting block..then the tree + * should be locked in the first place. + * We just want the nodeSize wich will NEVER change..so even if the world + * is changing..the nodeSize should remain the same. Which argues why lock + * it in the first place?? + */ + + (void) BTGetInformation (VTOFCB(vp), kBTreeInfoVersion, &bTreeInfo); + + logBlockSize = bTreeInfo.nodeSize; + + } else if (H_FILEID(VTOH(vp)) == kHFSAllocationFileID) { + logBlockSize = VTOVCB(vp)->vcbVBMIOSize; } - else - logBlockSize = VTOHFS(vp)->hfs_logBlockSize; - - + } + DBG_ASSERT(logBlockSize > 0); return logBlockSize; diff --git a/bsd/hfs/hfs_vhash.c b/bsd/hfs/hfs_vhash.c index 1c7a54e7a..b6ccc2445 100644 --- a/bsd/hfs/hfs_vhash.c +++ b/bsd/hfs/hfs_vhash.c @@ -128,9 +128,9 @@ loop: (H_DEV(hp) == dev) && !(hp->h_meta->h_metaflags & IN_NOEXISTS)) { /* SER XXX kDefault of meta data (ksysfile) is not assumed here */ - if ((H_FORKTYPE(hp) == forkType) || - (forkType == kAnyFork) || - ((forkType == kDefault) && ((H_FORKTYPE(hp) == kDirectory) + if ( (forkType == kAnyFork) || + (H_FORKTYPE(hp) == forkType) || + ((forkType == kDefault) && ((H_FORKTYPE(hp) == kDirectory) || (H_FORKTYPE(hp) == kDataFork)))) { vp = HTOV(hp); simple_lock(&vp->v_interlock); diff --git a/bsd/hfs/hfs_vnodeops.c b/bsd/hfs/hfs_vnodeops.c index e451aaab2..7e910c4ff 100644 --- a/bsd/hfs/hfs_vnodeops.c +++ b/bsd/hfs/hfs_vnodeops.c @@ -179,6 +179,8 @@ extern void hfs_name_CatToMeta(CatalogNodeData *nodeData, struct hfsfilemeta *fm extern groupmember(gid_t gid, struct ucred *cred); +extern void hfs_resolvelink(ExtendedVCB *vcb, CatalogNodeData *cndp); + static int hfs_makenode( int mode, dev_t rawdev, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct proc *p); @@ -484,6 +486,8 @@ struct vop_close_args /* { off_t leof; u_long blks, blocksize; int retval = E_NONE; + int devBlockSize; + int forceUpdate = 0; DBG_FUNC_NAME("close"); DBG_VOP_LOCKS_DECL(1); @@ -518,7 +522,7 @@ struct vop_close_args /* { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* - * Since we can contact switch in vn_lock our vnode + * Since we can context switch in vn_lock our vnode * could get recycled (eg umount -f). Double check * that its still ours. */ @@ -528,6 +532,26 @@ struct vop_close_args /* { return(E_NONE); } + /* Last chance to explicitly zero out the areas that are currently marked invalid: */ + VOP_DEVBLOCKSIZE(hp->h_meta->h_devvp, &devBlockSize); + while (!CIRCLEQ_EMPTY(&hp->h_invalidranges)) { + struct rl_entry *invalid_range = CIRCLEQ_FIRST(&hp->h_invalidranges); + off_t start = invalid_range->rl_start; + off_t end = invalid_range->rl_end; + + /* The range about to be written must be validated first, so that + VOP_CMAP() will return the appropriate mapping for the cluster code: */ + rl_remove(start, end, &hp->h_invalidranges); + + retval = cluster_write(vp, (struct uio *) 0, fcb->fcbEOF, invalid_range->rl_end + 1, invalid_range->rl_start, + (off_t)0, devBlockSize, IO_HEADZEROFILL | 0x8000); + + forceUpdate = 1; + }; + /* Make sure the EOF gets written out at least once more + now that all invalid ranges have been zero-filled and validated: */ + if (forceUpdate) hp->h_nodeflags |= IN_MODIFIED; + blocksize = HTOVCB(hp)->blockSize; blks = leof / blocksize; if (((off_t)blks * (off_t)blocksize) != leof) @@ -540,6 +564,13 @@ struct vop_close_args /* { retval = VOP_TRUNCATE(vp, leof, IO_NDELAY, ap->a_cred, p); } cluster_push(vp); + + /* If the VOP_TRUNCATE didn't happen to flush the vnode's information out to + disk, force it to be updated now that all invalid ranges have been zero-filled + and validated: + */ + if (hp->h_nodeflags & IN_MODIFIED) VOP_UPDATE(vp, &time, &time, 0); + VOP_UNLOCK(vp, 0, p); } @@ -1276,12 +1307,6 @@ struct proc *a_p; INIT_CATALOGDATA(&catInfo.nodeData, kCatNameNoCopyName); catInfo.hint = kNoHint; - - /* lock catalog b-tree */ - error = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_EXCLUSIVE, p); - if (error != E_NONE) { - goto FreeBuffer; - }; filename = H_NAME(hp); pid = H_DIRID(hp); @@ -1298,12 +1323,18 @@ struct proc *a_p; } #endif + /* lock catalog b-tree */ + error = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_EXCLUSIVE, p); + if (error != E_NONE) + goto ErrorExit; error = hfs_getcatalog(VTOVCB(vp), pid, filename, -1, &catInfo); - if (error != E_NONE) { - DBG_ERR(("%s: Lookup failed on file '%s'\n", funcname, filename)); - goto ErrorExit; - }; + + /* unlock catalog b-tree */ + (void) hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_RELEASE, p); + if (error != E_NONE) + goto ErrorExit; + H_HINT(hp) = catInfo.hint; /* Remember the last valid hint */ error = uiomove((caddr_t)attrbufptr, attrblocksize, ap->a_uio); @@ -1339,9 +1370,13 @@ struct proc *a_p; } simple_unlock(&hp->h_meta->h_siblinglock); - /* The only error that vget returns is when the vnode is going away, so ignore the vnode */ + /* + * The only error that vget returns is when the vnode is going away, + * so ignore the vnode + */ if (sib_vp && vget(sib_vp, LK_EXCLUSIVE | LK_RETRY, p) == 0) { - if (VTOH(sib_vp)->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { + if ((sib_vp->v_tag == VT_HFS) + && VTOH(sib_vp)->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) { if (alist->commonattr & ATTR_CMN_MODTIME) VTOH(sib_vp)->h_nodeflags &= ~IN_UPDATE; if (alist->commonattr & ATTR_CMN_CHGTIME) @@ -1350,8 +1385,8 @@ struct proc *a_p; VTOH(sib_vp)->h_nodeflags &= ~IN_ACCESS; } vput(sib_vp); - } /* vget() */ - } /* h_use_count > 1 */ + } + } } /* save these in case hfs_chown() or hfs_chmod() fail */ @@ -1397,6 +1432,11 @@ struct proc *a_p; }; + /* lock catalog b-tree */ + error = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_EXCLUSIVE, p); + if (error != E_NONE) + goto ErrorExit; + /* Update Catalog Tree */ if (alist->volattr == 0) { error = MacToVFSError( UpdateCatalogNode(HTOVCB(hp), pid, filename, H_HINT(hp), &catInfo.nodeData)); @@ -1407,36 +1447,46 @@ struct proc *a_p; ExtendedVCB *vcb = VTOVCB(vp); int namelen = strlen(vcb->vcbVN); - if (vcb->vcbVN[0] == 0) { - /* + if (vcb->vcbVN[0] == 0) { + /* * Ignore attempts to rename a volume to a zero-length name: * restore the original name from the metadata. - */ - copystr(H_NAME(hp), vcb->vcbVN, sizeof(vcb->vcbVN), NULL); - } else { + */ + copystr(H_NAME(hp), vcb->vcbVN, sizeof(vcb->vcbVN), NULL); + } else { + UInt32 tehint = 0; + + /* + * Force Carbon renames to have MacUnicode encoding + */ + if ((hp->h_nodeflags & IN_BYCNID) && (!ISSET(p->p_flag, P_TBE))) { + tehint = kTextEncodingMacUnicode; + } + error = MoveRenameCatalogNode(vcb, kRootParID, H_NAME(hp), H_HINT(hp), - kRootParID, vcb->vcbVN, &H_HINT(hp)); - if (error) { + kRootParID, vcb->vcbVN, &H_HINT(hp), tehint); + if (error) { VCB_LOCK(vcb); copystr(H_NAME(hp), vcb->vcbVN, sizeof(vcb->vcbVN), NULL); /* Restore the old name in the VCB */ vcb->vcbFlags |= 0xFF00; // Mark the VCB dirty VCB_UNLOCK(vcb); - goto ErrorExit; - }; - - hfs_set_metaname(vcb->vcbVN, hp->h_meta, HTOHFS(hp)); - hp->h_nodeflags |= IN_CHANGE; + goto UnlockExit; + }; + hfs_set_metaname(vcb->vcbVN, hp->h_meta, HTOHFS(hp)); + hp->h_nodeflags |= IN_CHANGE; + } /* vcb->vcbVN[0] == 0 ... else ... */ } /* alist->volattr & ATTR_VOL_NAME */ +UnlockExit: + /* unlock catalog b-tree */ + (void) hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_RELEASE, p); + ErrorExit: - /* unlock catalog b-tree */ - (void) hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_RELEASE, p); CLEAN_CATALOGDATA(&catInfo.nodeData); -FreeBuffer: if (attrbufptr) FREE(attrbufptr, M_TEMP); DBG_VOP_LOCKS_TEST(error); @@ -2159,6 +2209,7 @@ struct vop_remove_args /* { struct timeval tv; int retval, use_count; int filebusy = 0; + int uncache = 0; DBG_FUNC_NAME("remove"); DBG_VOP_LOCKS_DECL(2); DBG_VOP_PRINT_FUNCNAME(); @@ -2336,7 +2387,14 @@ hfs_nobusy2: if ((ap->a_cnp->cn_flags & (HASBUF | SAVENAME)) == (HASBUF | SAVENAME)) FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI); - + /* + * This is a deleted file no new clients + * would be able to look it up. Maked the VM object + * not cachable so that it dies as soon as the last + * mapping disappears. This will reclaim the disk + * space as soon as possible. + */ + uncache = 1; goto out2; /* link deleted, all done */ } #endif @@ -2364,6 +2422,14 @@ hfs_nobusy2: H_DIRID(hp) = hfsmp->hfs_private_metadata_dir; hfs_set_metaname(nodeName, hp->h_meta, HTOHFS(hp)); + /* + * This is an open deleted file no new clients + * would be able to look it up. Maked the VM object + * not cachable so that it dies as soon as the last + * mapping disappears. This will reclaim the disk + * space as soon as possible. + */ + uncache = 1; goto out2; /* all done, unlock the catalog */ } @@ -2409,37 +2475,27 @@ hfs_nobusy2: VTOH(dvp)->h_nodeflags |= IN_CHANGE | IN_UPDATE; - if (dvp == vp) { - vrele(vp); - } else { - vput(vp); - }; - - vput(dvp); - DBG_VOP_LOCKS_TEST(retval); - - if (UBCINFOEXISTS(vp)) { - (void) ubc_uncache(vp); - ubc_release(vp); - /* WARNING vp may not be valid after this */ - } - return (retval); + uncache = 1; + goto done; out2: (void) hfs_metafilelocking(hfsmp, kHFSCatalogFileID, LK_RELEASE, p); -out:; +out: if (! retval) VTOH(dvp)->h_nodeflags |= IN_CHANGE | IN_UPDATE; - if (dvp == vp) { - vrele(vp); - } else { - vput(vp); - }; +done: + if (dvp != vp) + VOP_UNLOCK(vp, 0, p); + + if (uncache) + ubc_uncache(vp); + vrele(vp); vput(dvp); + DBG_VOP_LOCKS_TEST(retval); return (retval); } @@ -2498,6 +2554,7 @@ struct vop_rename_args /* { int retval = 0; struct timeval tv; struct hfsCatalogInfo catInfo; + u_int32_t tehint = 0; DBG_VOP_LOCKS_DECL(4); DBG_FUNC_NAME("rename");DBG_VOP_PRINT_FUNCNAME();DBG_VOP_CONT(("\n")); @@ -2524,6 +2581,15 @@ struct vop_rename_args /* { DBG_ASSERT((ap->a_fdvp->v_type == VDIR) && (ap->a_tdvp->v_type == VDIR)); target_hp = targetPar_hp = source_hp = sourcePar_hp = 0; + /* If fvp is the same as tvp...then we are just changing case, ignore target_vp */ + /* + * This must be done now, since the value of target_vp is used to + * determine wether to unlock it (for instance, goto abortit). + * In this case, target_vp comes in unlocked + */ + if (source_vp == target_vp) + target_vp = NULL; + /* * Check for cross-device rename. */ @@ -2542,6 +2608,13 @@ struct vop_rename_args /* { goto abortit; } + /* + * Force Carbon renames to have MacUnicode encoding + */ + if ((VTOH(targetPar_vp)->h_nodeflags & IN_BYCNID) && (!ISSET(p->p_flag, P_TBE))) { + tehint = kTextEncodingMacUnicode; + } + if ((retval = vn_lock(source_vp, LK_EXCLUSIVE, p))) goto abortit; @@ -2664,10 +2737,13 @@ struct vop_rename_args /* { VOP_UNLOCK(sourcePar_vp, 0, p); goto bad; }; - + /* use source_cnp instead of H_NAME(source_hp) in case source is a hard link */ - retval = hfsMoveRename( HTOVCB(source_hp), H_DIRID(source_hp), source_cnp->cn_nameptr, - H_FILEID(VTOH(targetPar_vp)), target_cnp->cn_nameptr, &H_HINT(source_hp)); + retval = MoveRenameCatalogNode(HTOVCB(source_hp), H_DIRID(source_hp), + source_cnp->cn_nameptr, H_HINT(source_hp), + H_FILEID(VTOH(targetPar_vp)), + target_cnp->cn_nameptr, &H_HINT(source_hp), tehint); + retval = MacToVFSError(retval); if (retval == 0) { /* Look up the catalog entry just renamed since it might have been auto-decomposed */ @@ -2942,47 +3018,52 @@ hfs_symlink(ap) register struct vnode *vp, **vpp = ap->a_vpp; struct proc *p = current_proc(); struct hfsnode *hp; - u_int32_t dfltClump; int len, retval; - DBG_FUNC_NAME("symlink"); - DBG_VOP_LOCKS_DECL(2); - DBG_VOP_PRINT_FUNCNAME(); - DBG_VOP_LOCKS_INIT(0,ap->a_dvp, VOPDBG_LOCKED, VOPDBG_UNLOCKED, VOPDBG_UNLOCKED, VOPDBG_POS); - DBG_VOP_LOCKS_INIT(1,*ap->a_vpp, VOPDBG_IGNORE, VOPDBG_UNLOCKED, VOPDBG_IGNORE, VOPDBG_POS); + struct buf *bp = NULL; + /* HFS standard disks don't support symbolic links */ if (VTOVCB(ap->a_dvp)->vcbSigWord != kHFSPlusSigWord) { VOP_ABORTOP(ap->a_dvp, ap->a_cnp); vput(ap->a_dvp); - DBG_VOP((" ...sorry HFS disks don't support symbolic links.\n")); - DBG_VOP_LOCKS_TEST(EOPNOTSUPP); return (EOPNOTSUPP); } + /* Check for empty target name */ + if (ap->a_target[0] == 0) { + VOP_ABORTOP(ap->a_dvp, ap->a_cnp); + vput(ap->a_dvp); + return (EINVAL); + } + /* Create the vnode */ retval = hfs_makenode(IFLNK | ap->a_vap->va_mode, 0, ap->a_dvp, vpp, ap->a_cnp, p); DBG_VOP_UPDATE_VP(1, *ap->a_vpp); if (retval != E_NONE) { - DBG_VOP_LOCKS_TEST(retval); return (retval); } - vp = *vpp; len = strlen(ap->a_target); hp = VTOH(vp); - dfltClump = hp->fcbClmpSize; - /* make clump size minimal */ hp->fcbClmpSize = VTOVCB(vp)->blockSize; - retval = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, - UIO_SYSSPACE, IO_NODELOCKED, ap->a_cnp->cn_cred, (int *)0, - (struct proc *)0); - hp->fcbClmpSize = dfltClump; + /* Allocate space for the link */ + retval = VOP_TRUNCATE(vp, len, IO_NOZEROFILL, + ap->a_cnp->cn_cred, ap->a_cnp->cn_proc); + if (retval) + goto out; + + /* Write the link to disk */ + bp = getblk(vp, 0, roundup((int)hp->fcbEOF, kHFSBlockSize), 0, 0, BLK_META); + bzero(bp->b_data, bp->b_bufsize); + bcopy(ap->a_target, bp->b_data, len); + bp->b_flags |= B_DIRTY; + bawrite(bp); +out: vput(vp); - DBG_VOP_LOCKS_TEST(retval); return (retval); } @@ -3429,9 +3510,7 @@ struct vop_readdirattr_args /* { u_long currattrbufsize; void *attrbufptr = NULL; void *attrptr; - void *varptr; - struct vnode *entryvnode; - + void *varptr; *(ap->a_actualcount) = 0; *(ap->a_eofflag) = 0; @@ -3477,9 +3556,6 @@ struct vop_readdirattr_args /* { index = (uio->uio_offset / sizeof(struct dirent)) + 1; INIT_CATALOGDATA(&catInfo.nodeData, 0); - /* Lock catalog b-tree */ - if ((retval = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_SHARED, proc)) != E_NONE) - goto exit; /* HFS Catalog does not have a bulk directory enumeration call. Do it one at * time, using hints. GetCatalogOffspring takes care of hfsplus and name issues @@ -3492,7 +3568,20 @@ struct vop_readdirattr_args /* { * Thus fixedblocksize is too large in some cases.Also, the variable * part (like name) could be between fixedblocksize and the max. */ - OSErr result = GetCatalogOffspring(vcb, dirID, index, &catInfo.nodeData, NULL, NULL); + OSErr result; + + /* Lock catalog b-tree */ + if ((retval = hfs_metafilelocking(VTOHFS(vp), kHFSCatalogFileID, LK_SHARED, proc)) != E_NONE) + goto exit; + + catInfo.nodeData.cnd_iNodeNumCopy = 0; + result = GetCatalogOffspring(vcb, dirID, index, &catInfo.nodeData, NULL, NULL); + if (result == 0) + hfs_resolvelink(vcb, &catInfo.nodeData); + + /* Unlock catalog b-tree, unconditionally . Ties up the everything during enumeration */ + (void) hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, proc ); + if (result != noErr) { if (result == cmNotFound) { *(ap->a_eofflag) = TRUE; @@ -3508,26 +3597,64 @@ struct vop_readdirattr_args /* { catInfo.nodeData.cnd_type == kCatalogFolderNode) { ++index; + CLEAN_CATALOGDATA(&catInfo.nodeData); continue; } *((u_long *)attrptr)++ = 0; /* move it past length */ - if (ap->a_options & FSOPT_NOINMEMUPDATE) { - /* vp okay to use instead of root vp */ - PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr); - } else { - /* Check to see if there's a vnode for this item in the cache: */ - entryvnode = hfs_vhashget(H_DEV(VTOH(vp)), catInfo.nodeData.cnd_nodeID, kDefault); - if (entryvnode != NULL) { - PackAttributeBlock(alist, entryvnode, &catInfo, &attrptr, &varptr); - vput(entryvnode); - } else { - /* vp okay to use instead of root vp */ - PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr); - }; - }; - currattrbufsize = *((u_long *)attrbufptr) = ((char *)varptr - (char *)attrbufptr); + /* + * Don't use data from cached vnodes when FSOPT_NOINMEMUPDATE + * option is active or if this entry is a hard link. + */ + if ((ap->a_options & FSOPT_NOINMEMUPDATE) + || (catInfo.nodeData.cnd_iNodeNumCopy != 0)) { + /* vp okay to use instead of root vp */ + PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr); + } else { + struct vnode *entry_vp = NULL; + struct vnode *rsrc_vp = NULL; + int nodetype; + UInt32 nodeid; + + /* + * Flush out any in-memory state to the catalog record. + * + * In the HFS locking hierarchy, the data fork vnode must + * be acquired before the resource fork vnode. + */ + nodeid = catInfo.nodeData.cnd_nodeID; + if (catInfo.nodeData.cnd_type == kCatalogFolderNode) + nodetype = kDirectory; + else + nodetype = kDataFork; + + /* Check for this entry's cached vnode: */ + entry_vp = hfs_vhashget(H_DEV(VTOH(vp)), nodeid, nodetype); + + /* Also check for a cached resource fork vnode: */ + if (nodetype == kDataFork) { + rsrc_vp = hfs_vhashget(H_DEV(VTOH(vp)), nodeid, kRsrcFork); + if ((rsrc_vp != NULL) + && (VTOH(rsrc_vp)->h_nodeflags & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE))) { + /* Pick up resource fork info */ + CopyVNodeToCatalogNode(rsrc_vp, &catInfo.nodeData); + } + } + + if (entry_vp != NULL) + PackAttributeBlock(alist, entry_vp, &catInfo, &attrptr, &varptr); + else if (rsrc_vp != NULL) + PackAttributeBlock(alist, rsrc_vp, &catInfo, &attrptr, &varptr); + else + PackCatalogInfoAttributeBlock(alist, vp, &catInfo, &attrptr, &varptr); + + if (rsrc_vp) + vput(rsrc_vp); + if (entry_vp) + vput(entry_vp); + } + currattrbufsize = *((u_long *)attrbufptr) = ((char *)varptr - (char *)attrbufptr); /* now check if we can't fit in the buffer space remaining */ if (currattrbufsize > uio->uio_resid) @@ -3542,10 +3669,10 @@ struct vop_readdirattr_args /* { *ap->a_actualcount += 1; maxcount--; } + /* Clean for the next loop */ + CLEAN_CATALOGDATA(&catInfo.nodeData); }; *ap->a_newstate = VTOH(vp)->h_meta->h_mtime;/* before we unlock, know the mod date */ - /* Unlock catalog b-tree, finally. Ties up the everything during enumeration */ - (void) hfs_metafilelocking( VTOHFS(ap->a_vp), kHFSCatalogFileID, LK_RELEASE, proc ); CLEAN_CATALOGDATA(&catInfo.nodeData); @@ -3600,20 +3727,48 @@ struct uio *a_uio; struct ucred *a_cred; } */ *ap; { - int retval; - DBG_FUNC_NAME("readlink"); - DBG_VOP_LOCKS_DECL(1); - DBG_VOP_PRINT_FUNCNAME(); - DBG_VOP_PRINT_VNODE_INFO(ap->a_vp);DBG_VOP_CONT(("\n")); + int retval; + struct vnode *vp = ap->a_vp; + struct hfsnode *hp = VTOH(vp); - DBG_VOP_LOCKS_INIT(0,ap->a_vp, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_LOCKED, VOPDBG_POS); - retval = VOP_READ(ap->a_vp, ap->a_uio, 0, ap->a_cred); - /* clear IN_ACCESS to prevent needless update of symlink vnode */ - VTOH(ap->a_vp)->h_nodeflags &= ~IN_ACCESS; + if (vp->v_type != VLNK) + return (EINVAL); + + /* Zero length sym links are not allowed */ + if (hp->fcbEOF == 0) { + VTOVCB(vp)->vcbFlags |= kHFS_DamagedVolume; + return (EINVAL); + } + + /* Cache the path so we don't waste buffer cache resources */ + if (hp->h_symlinkptr == NULL) { + struct buf *bp = NULL; + + if (H_ISBIGLINK(hp)) + MALLOC(hp->h_symlinkptr, char *, hp->fcbEOF, M_TEMP, M_WAITOK); + + retval = meta_bread(vp, 0, roundup((int)hp->fcbEOF, kHFSBlockSize), ap->a_cred, &bp); + if (retval) { + if (bp) + brelse(bp); + if (hp->h_symlinkptr) { + FREE(hp->h_symlinkptr, M_TEMP); + hp->h_symlinkptr = NULL; + } + return (retval); + } + + bcopy(bp->b_data, H_SYMLINK(hp), (size_t)hp->fcbEOF); - DBG_VOP_LOCKS_TEST(retval); - return (retval); + if (bp) { + bp->b_flags |= B_INVAL; /* data no longer needed */ + brelse(bp); + } + } + + retval = uiomove((caddr_t)H_SYMLINK(hp), (int)hp->fcbEOF, ap->a_uio); + return (retval); } @@ -3845,7 +4000,13 @@ struct vop_reclaim_args /* { } else DBG_ASSERT(hp->h_meta->h_usecount == 1); - + + /* Dump cached symlink data */ + if ((vp->v_type == VLNK) && (hp->h_symlinkptr != NULL)) { + if (H_ISBIGLINK(hp)) + FREE(hp->h_symlinkptr, M_TEMP); + hp->h_symlinkptr = NULL; + } /* * Purge old data structures associated with the inode. @@ -3899,6 +4060,9 @@ struct vop_lock_args /* { goto Err_Exit; }; + if (vp->v_type == VDIR) + hp->h_nodeflags &= ~IN_BYCNID; + Err_Exit:; DBG_ASSERT(*((int*)&vp->v_interlock) == 0); DBG_VOP_LOCKS_TEST(retval); @@ -3933,6 +4097,8 @@ struct vop_unlock_args /* { DBG_VOP_PRINT_VNODE_INFO(vp);DBG_VOP_CONT((" flags = 0x%08X.\n", ap->a_flags)); DBG_VOP_LOCKS_INIT(0,vp, VOPDBG_LOCKED, VOPDBG_UNLOCKED, VOPDBG_LOCKED, VOPDBG_ZERO); + if (vp->v_type == VDIR) + hp->h_nodeflags &= ~IN_BYCNID; DBG_ASSERT((ap->a_flags & (LK_EXCLUSIVE|LK_SHARED)) == 0); retval = lockmgr(&hp->h_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock, ap->a_p); @@ -4055,6 +4221,15 @@ struct vop_pathconf_args /* { case _PC_NO_TRUNC: *ap->a_retval = 0; break; + case _PC_NAME_CHARS_MAX: + *ap->a_retval = kHFSPlusMaxFileNameChars; + break; + case _PC_CASE_SENSITIVE: + *ap->a_retval = 0; + break; + case _PC_CASE_PRESERVING: + *ap->a_retval = 1; + break; default: retval = EINVAL; } @@ -4427,6 +4602,7 @@ hfs_makenode(mode, rawdev, dvp, vpp, cnp, p) UInt8 forkType; int retval; int hasmetalock = 0; + u_int32_t tehint = 0; DBG_FUNC_NAME("makenode"); parhp = VTOH(dvp); @@ -4449,8 +4625,15 @@ hfs_makenode(mode, rawdev, dvp, vpp, cnp, p) else hasmetalock = 1; + /* + * Force Carbon creates to have MacUnicode encoding + */ + if ((parhp->h_nodeflags & IN_BYCNID) && (!ISSET(p->p_flag, P_TBE))) { + tehint = kTextEncodingMacUnicode; + } + /* Create the Catalog B*-Tree entry */ - retval = hfsCreate(vcb, H_FILEID(parhp), cnp->cn_nameptr, mode); + retval = hfsCreate(vcb, H_FILEID(parhp), cnp->cn_nameptr, mode, tehint); if (retval != E_NONE) { DBG_ERR(("%s: hfsCreate FAILED: %s, %s\n", funcname, cnp->cn_nameptr, H_NAME(parhp))); goto bad1; diff --git a/bsd/hfs/hfscommon/Catalog/Catalog.c b/bsd/hfs/hfscommon/Catalog/Catalog.c index 0e94bef13..63950007d 100644 --- a/bsd/hfs/hfscommon/Catalog/Catalog.c +++ b/bsd/hfs/hfscommon/Catalog/Catalog.c @@ -236,7 +236,8 @@ void InitCatalogRecord(ExtendedVCB *volume, UInt32 nodeType, UInt32 textEncoding OSErr CreateCatalogNode ( ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param name, - UInt32 nodeType, HFSCatalogNodeID *catalogNodeID, UInt32 *catalogHint) + UInt32 nodeType, HFSCatalogNodeID *catalogNodeID, UInt32 *catalogHint, + UInt32 teHint) { CatalogKey *nodeKey; CatalogRecord nodeData; // 520 bytes @@ -291,6 +292,7 @@ CreateCatalogNode ( ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Par InvalidateCatalogNodeCache(volume, parentsParentID); //--- build key for new catalog node + textEncoding = teHint; result = BuildCatalogKeyUTF8(volume, parentID, name, kUndefinedStrLen, nodeKey, &textEncoding); ReturnIfError(result); @@ -512,6 +514,18 @@ DeleteCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param // if we did not find it by name, then look for an embedded file ID in a mangled name if ( (result == cmNotFound) && isHFSPlus ) result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, &key, &data, &nodeHint); + + /* + * In Mac OS X there can also be HFS filenames that + * could not be encoded using the default encoding. + */ + if (result == cmNotFound && !isHFSPlus && VCBTOHFS(volume)->hfs_encoding != 0) { + Str31 hfsName; + + utf8_to_mac_roman(strlen(name), name, hfsName); + result = LocateCatalogNode(volume, parentID, (CatalogName*)hfsName, + 0, &key, &data, &nodeHint); + } ReturnIfError(result); nodeParentID = isHFSPlus ? key.hfsPlus.parentID : key.hfs.parentID; // establish real parent cnid @@ -695,7 +709,7 @@ GetCatalogNode( ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param n * could not be encoded using the default encoding. * In which case they were encoded as MacRoman. */ - if (result == cmNotFound && !isHFSPlus) { + if (result == cmNotFound && !isHFSPlus && VCBTOHFS(volume)->hfs_encoding != 0) { Str31 hfsName; utf8_to_mac_roman(nameLen, name, hfsName); @@ -801,7 +815,14 @@ GetDirEntrySize(BTreeIterator *bip, ExtendedVCB * vol) cnp = (CatalogName*) ckp->hfs.nodeName; result = hfs_to_utf8(vol, cnp->pstr, kdirentMaxNameBytes + 1, &utf8chars, name); - /*XXX ignoring error */ + if (result) { + /* + * When an HFS name cannot be encoded with the current + * volume encoding we use MacRoman as a fallback. + */ + result = mac_roman_to_utf8(cnp->pstr, MAXHFSVNODELEN + 1, + &utf8chars, name); + } } return DIRENTRY_SIZE(utf8chars); @@ -1148,6 +1169,13 @@ IterateCatalogNode( ExtendedVCB *volume, CatalogIterator *catalogIterator, UInt1 nodeData->cnm_nameptr = NewPtr(utf8len+1); nodeData->cnm_flags |= kCatNameIsAllocated; result = hfs_to_utf8(volume, offspringName->pstr, utf8len + 1, &utf8len, nodeData->cnm_nameptr); + } else if (result) { + /* + * When an HFS name cannot be encoded with the current + * volume encoding we use MacRoman as a fallback. + */ + result = mac_roman_to_utf8(offspringName->pstr, MAXHFSVNODELEN + 1, + &utf8len, nodeData->cnm_namespace); } } else { @@ -1180,7 +1208,8 @@ ErrorExit: OSErr MoveRenameCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID srcParentID, ConstUTF8Param srcName, - UInt32 srcHint, HFSCatalogNodeID dstParentID, ConstUTF8Param dstName, UInt32 *newHint) + UInt32 srcHint, HFSCatalogNodeID dstParentID, ConstUTF8Param dstName, + UInt32 *newHint, UInt32 teHint) { CatalogKey srcKey; // 518 bytes CatalogRecord srcRecord; // 520 bytes @@ -1199,7 +1228,7 @@ MoveRenameCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID srcParentID, ConstUT short srcNameLen; short dstNameLen; - + textEncoding = teHint; result = BuildCatalogKeyUTF8(volume, srcParentID, srcName, kUndefinedStrLen, &srcKey, &textEncoding); ReturnIfError(result); @@ -1235,6 +1264,17 @@ MoveRenameCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID srcParentID, ConstUT // if we did not find it by name, then look for an embedded file ID in a mangled name if ( (result == cmNotFound) && isHFSPlus ) result = LocateCatalogNodeByMangledName(volume, srcParentID, srcName, kUndefinedStrLen, &srcKey, &srcRecord, &srcHint); + /* + * In Mac OS X there can also be HFS filenames that + * could not be encoded using the default encoding. + */ + if (result == cmNotFound && !isHFSPlus && VCBTOHFS(volume)->hfs_encoding != 0) { + Str31 hfsName; + + utf8_to_mac_roman(strlen(srcName), srcName, hfsName); + result = LocateCatalogNode(volume, srcParentID, (CatalogName*)hfsName, + 0, &srcKey, &srcRecord, &srcHint); + } ReturnIfError(result); srcParentID = (isHFSPlus ? srcKey.hfsPlus.parentID : srcKey.hfs.parentID); @@ -1530,6 +1570,17 @@ UpdateCatalogNode(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param if ( (result == cmNotFound) && isHFSPlus ) result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, key, record, &hint); + /* + * In Mac OS X there can also be HFS filenames that + * could not be encoded using the default encoding. + */ + if (result == cmNotFound && !isHFSPlus && VCBTOHFS(volume)->hfs_encoding != 0) { + Str31 hfsName; + + utf8_to_mac_roman(strlen(name), name, hfsName); + result = LocateCatalogNode(volume, parentID, (CatalogName*)hfsName, + 0, key, record, &hint); + } if (result == btNotFound) result = cmNotFound; @@ -1722,6 +1773,17 @@ CreateFileIDRef(ExtendedVCB *volume, HFSCatalogNodeID parentID, ConstUTF8Param n // if we did not find it by name, then look for an embedded file ID in a mangled name if ( (result == cmNotFound) && isHFSPlus ) result = LocateCatalogNodeByMangledName(volume, parentID, name, kUndefinedStrLen, &nodeKey, &nodeData, &nodeHint); + /* + * In Mac OS X there can also be HFS filenames that + * could not be encoded using the default encoding. + */ + if ((result == cmNotFound) && !isHFSPlus && VCBTOHFS(volume)->hfs_encoding != 0) { + Str31 hfsName; + + utf8_to_mac_roman(strlen(name), name, hfsName); + result = LocateCatalogNode(volume, parentID, (CatalogName*)hfsName, + 0, &nodeKey, &nodeData, &nodeHint); + } ReturnIfError(result); if (nodeData.recordType == kHFSPlusFileRecord) diff --git a/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c b/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c index 15ff358a9..a966d7ab4 100644 --- a/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c +++ b/bsd/hfs/hfscommon/Catalog/CatalogUtilities.c @@ -89,6 +89,7 @@ */ #include <sys/param.h> #include <sys/utfconv.h> +#include <sys/stat.h> #include "../headers/FileMgrInternal.h" #include "../headers/BTreesInternal.h" @@ -96,7 +97,6 @@ #include "../headers/HFSUnicodeWrappers.h" #include <string.h> -static void ExtractTextEncoding (ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding); //******************************************************************************* // Routine: LocateCatalogNode @@ -472,9 +472,6 @@ BuildCatalogKey(HFSCatalogNodeID parentID, const CatalogName *cName, Boolean isH } } -/* - * for HFS, only MacRoman is supported. If a non-MacRoman character is found, an error is returned - */ OSErr BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char *name, UInt32 nameLength, CatalogKey *key, UInt32 *textEncoding) @@ -499,8 +496,9 @@ BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char * key->hfsPlus.keyLength += unicodeBytes; } - if (textEncoding) - ExtractTextEncoding(key->hfsPlus.nodeName.length, key->hfsPlus.nodeName.unicode, textEncoding); + if (textEncoding && (*textEncoding != kTextEncodingMacUnicode)) + *textEncoding = hfs_pickencoding(key->hfsPlus.nodeName.unicode, + key->hfsPlus.nodeName.length); } else { key->hfs.keyLength = kHFSCatalogKeyMinimumLength; // initial key length (1 + 4 + 1) @@ -533,36 +531,6 @@ BuildCatalogKeyUTF8(ExtendedVCB *volume, HFSCatalogNodeID parentID, const char * } -/* - * make a guess at the text encoding value that coresponds to the Unicode characters - */ -static void -ExtractTextEncoding(ItemCount length, ConstUniCharArrayPtr string, UInt32 * textEncoding) -{ - int i; - UniChar ch; - - *textEncoding = 0; - - for (i = 0; i < length; ++i) { - ch = string[i]; - /* CJK codepoints are 0x3000 thru 0x9FFF */ - if (ch >= 0x3000) { - if (ch < 0xa000) { - *textEncoding = kTextEncodingMacJapanese; - break; - } - - /* fullwidth character codepoints are 0xFF00 thru 0xFFEF */ - if (ch >= 0xff00 && ch <= 0xffef) { - *textEncoding = kTextEncodingMacJapanese; - break; - } - } - } -} - - //******************************************************************************* // Routine: FlushCatalog // @@ -798,7 +766,14 @@ CopyCatalogNodeData(const ExtendedVCB *volume, const CatalogRecord *dataPtr, Cat nodeData->cnd_nodeID = dataPtr->hfsFolder.folderID; nodeData->cnd_createDate = LocalToUTC(dataPtr->hfsFolder.createDate); nodeData->cnd_contentModDate = LocalToUTC(dataPtr->hfsFolder.modifyDate); + nodeData->cnd_attributeModDate = LocalToUTC(dataPtr->hfsFolder.modifyDate); + nodeData->cnd_accessDate = LocalToUTC(dataPtr->hfsFolder.modifyDate); nodeData->cnd_backupDate = LocalToUTC(dataPtr->hfsFolder.backupDate); + nodeData->cnd_ownerID = VCBTOHFS(volume)->hfs_uid; + nodeData->cnd_groupID = VCBTOHFS(volume)->hfs_gid; + nodeData->cnd_adminFlags = 0; + nodeData->cnd_ownerFlags = 0; /* HFS directories cannot be locked */ + nodeData->cnd_mode = IFDIR | (ACCESSPERMS & VCBTOHFS(volume)->hfs_dir_mask); nodeData->cnd_valence = dataPtr->hfsFolder.valence; BlockMoveData(&dataPtr->hfsFolder.userInfo, &nodeData->cnd_finderInfo, 32); @@ -810,7 +785,14 @@ CopyCatalogNodeData(const ExtendedVCB *volume, const CatalogRecord *dataPtr, Cat nodeData->cnd_nodeID = dataPtr->hfsFile.fileID; nodeData->cnd_createDate = LocalToUTC(dataPtr->hfsFile.createDate); nodeData->cnd_contentModDate = LocalToUTC(dataPtr->hfsFile.modifyDate); + nodeData->cnd_attributeModDate = LocalToUTC(dataPtr->hfsFolder.modifyDate); + nodeData->cnd_accessDate = LocalToUTC(dataPtr->hfsFolder.modifyDate); nodeData->cnd_backupDate = LocalToUTC(dataPtr->hfsFile.backupDate); + nodeData->cnd_ownerID = VCBTOHFS(volume)->hfs_uid; + nodeData->cnd_groupID = VCBTOHFS(volume)->hfs_gid; + nodeData->cnd_adminFlags = 0; + nodeData->cnd_ownerFlags = (nodeData->cnd_flags & kHFSFileLockedMask) ? UF_IMMUTABLE : 0; + nodeData->cnd_mode = IFREG | (ACCESSPERMS & VCBTOHFS(volume)->hfs_file_mask); nodeData->cnd_linkCount = 0; BlockMoveData(&dataPtr->hfsFile.userInfo, &nodeData->cnd_finderInfo, 16); diff --git a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c index 4e7a2d0f9..43cdd2a22 100644 --- a/bsd/hfs/hfscommon/Catalog/FileIDsServices.c +++ b/bsd/hfs/hfscommon/Catalog/FileIDsServices.c @@ -158,17 +158,16 @@ OSErr ExchangeFileIDs( ExtendedVCB *vcb, ConstUTF8Param srcName, ConstUTF8Param CatalogRecord swapData; // 520 bytes SInt16 numSrcExtentBlocks; SInt16 numDestExtentBlocks; - UInt32 textEncoding; OSErr err; Boolean isHFSPlus = ( vcb->vcbSigWord == kHFSPlusSigWord ); TrashCatalogIterator(vcb, srcID); // invalidate any iterators for this parentID TrashCatalogIterator(vcb, destID); // invalidate any iterators for this parentID - err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, &textEncoding); + err = BuildCatalogKeyUTF8(vcb, srcID, srcName, kUndefinedStrLen, &srcKey, NULL); ReturnIfError(err); - err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, &textEncoding); + err = BuildCatalogKeyUTF8(vcb, destID, destName, kUndefinedStrLen, &destKey, NULL); ReturnIfError(err); if ( isHFSPlus ) diff --git a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c index 92ae16ad6..3f17d760e 100644 --- a/bsd/hfs/hfscommon/Misc/FileExtentMapping.c +++ b/bsd/hfs/hfscommon/Misc/FileExtentMapping.c @@ -159,8 +159,6 @@ #include "../headers/BTreesInternal.h" #include "../headers/CatalogPrivate.h" // calling a private catalog routine (LocateCatalogNode) -#include "../headers/HFSInstrumentation.h" - #include <sys/malloc.h> /* @@ -332,14 +330,6 @@ static OSErr UpdateExtentRecord ( const HFSPlusExtentRecord extentData, UInt32 extentBTreeHint); -static OSErr MapFileBlockFromFCB( - const ExtendedVCB *vcb, - const FCB *fcb, - SInt64 offset, // Desired offset in bytes from start of file - UInt32 *firstFABN, // FABN of first block of found extent - UInt32 *firstBlock, // Corresponding allocation block number - UInt32 *nextFABN); // FABN of block after end of extent - static Boolean ExtentsAreIntegral( const HFSPlusExtentRecord extentRecord, UInt32 mask, @@ -625,25 +615,17 @@ OSErr MapFileBlockC ( UInt32 startBlock; // volume allocation block corresponding to firstFABN daddr_t temp; off_t tmpOff; - - - LogStartTime(kTraceMapFileBlock); allocBlockSize = vcb->blockSize; - err = MapFileBlockFromFCB(vcb, fcb, offset, &firstFABN, &startBlock, &nextFABN); - if (err != noErr) { - err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN); - if (err == noErr) { - startBlock = foundData[foundIndex].startBlock; - firstFABN = nextFABN - foundData[foundIndex].blockCount; - } + err = SearchExtentFile(vcb, fcb, offset, &foundKey, foundData, &foundIndex, &hint, &nextFABN); + if (err == noErr) { + startBlock = foundData[foundIndex].startBlock; + firstFABN = nextFABN - foundData[foundIndex].blockCount; } if (err != noErr) { - LogEndTime(kTraceMapFileBlock, err); - return err; } @@ -680,7 +662,6 @@ OSErr MapFileBlockC ( *availableBytes = numberOfBytes; // more there than they asked for, so pin the output else *availableBytes = tmpOff; - LogEndTime(kTraceMapFileBlock, noErr); return noErr; } @@ -1060,6 +1041,7 @@ OSErr ExtendFileC ( ExtendedVCB *vcb, // volume that file resides on FCB *fcb, // FCB of file to truncate SInt64 bytesToAdd, // number of bytes to allocate + UInt32 blockHint, // desired starting allocation block UInt32 flags, // EFContig and/or EFAll SInt64 *actualBytesAdded) // number of bytes actually allocated { @@ -1085,21 +1067,6 @@ OSErr ExtendFileC ( SInt64 previousPEOF; -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - InstDataDescriptorRef traceDescriptor; - FSVarsRec *fsVars = (FSVarsRec *) LMGetFSMVars(); - - traceDescriptor = (InstDataDescriptorRef) fsVars->later[2]; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:Extents:ExtendFileC", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif - needsFlush = false; *actualBytesAdded = 0; volumeBlockSize = vcb->blockSize; @@ -1197,8 +1164,12 @@ OSErr ExtendFileC ( // else, keep getting bits and pieces (non-contig) err = noErr; wantContig = true; + vcb->vcbFreeExtCnt = 0; /* For now, force rebuild of free extent list */ do { - startBlock = foundData[foundIndex].startBlock + foundData[foundIndex].blockCount; + if (blockHint != 0) + startBlock = blockHint; + else + startBlock = foundData[foundIndex].startBlock + foundData[foundIndex].blockCount; err = BlockAllocate(vcb, startBlock, bytesToAdd, maximumBytes, wantContig, &actualStartBlock, &actualNumBlocks); if (err == dskFulErr) { if (forceContig) @@ -1213,26 +1184,8 @@ OSErr ExtendFileC ( err = noErr; } if (err == noErr) { -#if HFSInstrumentation - { - struct { - UInt32 fileID; - UInt32 start; - UInt32 count; - UInt32 fabn; - } x; - - x.fileID = H_FILEID(fcb); - x.start = actualStartBlock; - x.count = actualNumBlocks; - x.fabn = nextBlock; - - InstLogTraceEventWithDataStructure( trace, eventTag, kInstMiddleEvent, traceDescriptor, - (UInt8 *) &x, sizeof(x)); - } -#endif // Add the new extent to the existing extent record, or create a new one. - if (actualStartBlock == startBlock) { + if ((actualStartBlock == startBlock) && (blockHint == 0)) { // We grew the file's last extent, so just adjust the number of blocks. foundData[foundIndex].blockCount += actualNumBlocks; err = UpdateExtentRecord(vcb, fcb, &foundKey, foundData, hint); @@ -1247,7 +1200,8 @@ OSErr ExtendFileC ( if (foundIndex == numExtentsPerRecord) { // This record is full. Need to create a new one. if (H_FILEID(fcb) == kHFSExtentsFileID) { - err = fxOvFlErr; // Oops. Can't extend extents file (?? really ??) + (void) BlockDeallocate(vcb, actualStartBlock, actualNumBlocks); + err = dskFulErr; // Oops. Can't extend extents file past first record. break; } @@ -1326,10 +1280,6 @@ Exit: if (needsFlush) (void) FlushExtentFile(vcb); -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; Overflow: @@ -1384,20 +1334,6 @@ OSErr TruncateFileC ( Boolean extentChanged; // true if we actually changed an extent Boolean recordDeleted; // true if an extent record got deleted -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - InstDataDescriptorRef traceDescriptor; - FSVarsRec *fsVars = (FSVarsRec *) LMGetFSMVars(); - - traceDescriptor = (InstDataDescriptorRef) fsVars->later[2]; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:Extents:TruncateFileC", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif recordDeleted = false; @@ -1538,10 +1474,6 @@ ErrorExit: if (recordDeleted) (void) FlushExtentFile(vcb); -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; } @@ -1909,104 +1841,6 @@ OSErr GetFCBExtentRecord( } - -//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ -// Routine: MapFileBlockFromFCB -// -// Function: Determine if the given file offset is within the set of extents -// stored in the FCB. If so, return the file allocation -// block number of the start of the extent, volume allocation block number -// of the start of the extent, and file allocation block number immediately -// following the extent. -// -// Input: vcb - the volume containing the extents -// fcb - the file that owns the extents -// offset - desired offset in bytes -// -// Output: firstFABN - file alloc block number of start of extent -// firstBlock - volume alloc block number of start of extent -// nextFABN - file alloc block number of next extent -// -// Result: noErr = ok -// fxRangeErr = beyond FCB's extents -//ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ -static OSErr MapFileBlockFromFCB( - const ExtendedVCB *vcb, - const FCB *fcb, - SInt64 offset, // Desired offset in bytes from start of file - UInt32 *firstFABN, // FABN of first block of found extent - UInt32 *firstBlock, // Corresponding allocation block number - UInt32 *nextFABN) // FABN of block after end of extent -{ - UInt32 index; - UInt32 offsetBlocks; - SInt64 temp64; - - temp64 = offset / (SInt64)vcb->blockSize; - offsetBlocks = (UInt32)temp64; - - if (vcb->vcbSigWord == kHFSSigWord) { - /* XXX SER Do we need to test for overflow values ??? */ - UInt16 blockCount; - UInt16 currentFABN; - - currentFABN = 0; - - for (index=0; index<kHFSExtentDensity; index++) { - - blockCount = fcb->fcbExtents[index].blockCount; - - if (blockCount == 0) - return fxRangeErr; // ran out of extents! - - // Is it in this extent? - if (offsetBlocks < blockCount) { - *firstFABN = currentFABN; - *firstBlock = fcb->fcbExtents[index].startBlock; - currentFABN += blockCount; // faster to add these as UInt16 first, then extend to UInt32 - *nextFABN = currentFABN; - return noErr; // found the right extent - } - - // Not in current extent, so adjust counters and loop again - offsetBlocks -= blockCount; - currentFABN += blockCount; - } - } - else { - UInt32 blockCount; - UInt32 currentFABN; - - currentFABN = 0; - - for (index=0; index<kHFSPlusExtentDensity; index++) { - - blockCount = fcb->fcbExtents[index].blockCount; - - if (blockCount == 0) - return fxRangeErr; // ran out of extents! - - // Is it in this extent? - if (offsetBlocks < blockCount) { - *firstFABN = currentFABN; - *firstBlock = fcb->fcbExtents[index].startBlock; - *nextFABN = currentFABN + blockCount; - return noErr; // found the right extent - } - - // Not in current extent, so adjust counters and loop again - offsetBlocks -= blockCount; - currentFABN += blockCount; - } - } - - // If we fall through here, the extent record was full, but the offset was - // beyond those extents. - - return fxRangeErr; -} - - //_________________________________________________________________________________ // // Routine: ExtentsAreIntegral diff --git a/bsd/hfs/hfscommon/Misc/VolumeAllocation.c b/bsd/hfs/hfscommon/Misc/VolumeAllocation.c index 7a6417dd7..e8006d107 100644 --- a/bsd/hfs/hfscommon/Misc/VolumeAllocation.c +++ b/bsd/hfs/hfscommon/Misc/VolumeAllocation.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,88 +26,8 @@ Version: HFS Plus 1.0 - Copyright: © 1996-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: Mark Day - - Other Contact: Greg Parks - - Technology: HFS+ - - Writers: - - (djb) Don Brady - (DSH) Deric Horn - (msd) Mark Day - - Change History (most recent first): - <MacOSX> 1/22/2000 djb Removed unused BlockCheck and BlockVerifyAllocated routines. - <MacOSX> 4/27/98 djb Remove references to unused/legacy vcbFreeBks. - <MacOSX> 4/27/98 djb Remove unneccessary DebugStr in BlockVerifyAllocated. - <MacOSX> 4/17/98 djb Add VCB locking. - <MacOSX> 4/13/98 djb Add RequireFileLock checking to ReadBitmapBlock. - <MacOSX> 3/31/98 djb Sync up with final HFSVolumes.h header file. - - <12> 1 0/31/97 DSH Modify BlockVerifyAllocated() so DFA can call without actually - writing to the disk. - <CS11> 10/20/97 msd The way BlockAllocate rounds up to a multiple of the clump size - is wrong. ExtendFileC should do the round-up and pass the result - into BlockAllocate. Removed the fcb parameter to BlockAllocate; - added a bytesMaximum parameter. - <CS10> 10/17/97 msd Conditionalize DebugStrs. - <CS9> 9/4/97 djb Add logging to BlockAllocate. - <CS8> 9/4/97 msd Add a histogram of allocation sizes. Use DEBUG_BUILD instead of - VSM_DEBUG to generate DebugStr messages. - <CS7> 8/14/97 msd Bug 1662332. Don't mark blocks dirty in UpdateFreeCount. In - BlockVerifyAllocated, only mark blocks dirty if they've actually - changed. - <CS6> 7/16/97 DSH FilesInternal.i renamed FileMgrInternal.i to avoid name - collision - <CS5> 7/8/97 DSH Loading PrecompiledHeaders from define passed in on C line - <CS4> 6/12/97 msd Export BlockAllocateAny and UpdateVCBFreeBlks. - <3> 5/8/97 DSH Added comments and ascii diagram of new BlockFindContiguous() - algorithm. - <2> 5/7/97 DSH New faster BlockFindContiguous algorithm. It searches backwards - until a dirty bit is found instead of forwards. - <CS1> 4/25/97 djb first checked in - - <HFS21> 4/14/97 msd Fix UpdateVCBFreeBlks so free space calculation doesn't overflow - on volumes bigger than 4GB. - <HFS20> 4/4/97 djb Get in sync with volume format changes. - <HFS19> 1/27/97 msd Speed up BlockCheck and UpdateFreeCount. Removed DebugStr from - BlockCheck; there are now DebugStr's in BlockVerifyAllocated, - before the bitmap gets fixed (so potential problems can be - debugged easier). Adjusted comments about internal routines. - Changed names of "Fast" routines back to their original names - (since the originals are now removed). - <HFS18> 1/24/97 msd Speed up allocation and deallocation. - <HFS17> 1/21/97 msd Add instrumentation for function entry/exit. BlockAllocate and - ReadBitMapBlock use the event tag to log bytes requested and - block number (respectively). - <HFS16> 1/15/97 djb Add HFS+ supprt to BlockCheck (for MountCheck). - <HFS15> 1/13/97 DSH Use vcb->nextAllocation instead of vcbAllocPtr. - <HFS14> 1/9/97 djb UpdateVCBFreeBlks is not converting correctly. - <HFS13> 1/6/97 djb Use vcb's allocationsRefNum to access allocation file. - <HFS12> 1/2/97 DSH Added UpdateVCBFreeBlks() to update vcbFreeBks whenever we - update vcb->freeblocks. - <HFS11> 12/19/96 DSH All refs to VCB are now refs to ExtendedVCB - <HFS10> 12/12/96 msd DivideAndRoundUp should not be declared as static. - <HFS9> 12/10/96 msd Check PRAGMA_LOAD_SUPPORTED before loading precompiled headers. - <HFS8> 12/4/96 DSH PrecompiledHeaders - <HFS7> 11/27/96 djb Added AllocateFreeSpace for HFS wrapper support. - <HFS6> 11/27/96 msd Changed ReadBitmapBlock to read from HFS+ allocation file. - Temporarily uses the vcbVBMSt field of the VCB as the allocation - file's refnum until extended VCB changes are checked in. - <HFS5> 11/26/96 msd VSM and FileExtentMapping routines use FCB instead of FCBRec. - <HFS4> 11/20/96 DSH Changed a parameter in GetBlock_glue, so I also changed the - caller. - <HFS3> 11/20/96 msd Include FilesInternal.h. Remove definition of MarkVCBDirty - (since it is now in FilesInternal.h). - <HFS2> 11/12/96 msd Need to bound allocations to be within the last allocation block - of the volume (function AllocateAt). - <HFS1> 11/11/96 msd first checked in + Copyright: © 1996-2001 by Apple Computer, Inc., all rights reserved. + */ /* @@ -119,22 +39,7 @@ Public routines: blocks. (Will only do a single extent???) BlockDeallocate Deallocate a contiguous run of allocation blocks. - UpdateFreeCount - Computes the number of free allocation blocks on a volume. - The vcb's free block count is updated. - - AllocateFreeSpace - Allocates all the remaining free space (used for embedding HFS+ volumes). - - BlockAllocateAny - Find and allocate a contiguous range of blocks up to a given size. The - first range of contiguous free blocks found are allocated, even if there - are fewer blocks than requested (and even if a contiguous range of blocks - of the given size exists elsewhere). - UpdateVCBFreeBlks - Given an ExtenddVCB, calculate the vcbFreeBks value - so that vcbFreeBks*vcbAlBlkSiz == freeBlocks*blockSize. Internal routines: BlockMarkFree @@ -148,13 +53,26 @@ Internal routines: Find a contiguous range of blocks of a given size. The caller specifies where to begin the search (by block number). The block number of the first block in the range is returned. + BlockAllocateAny + Find and allocate a contiguous range of blocks up to a given size. The + first range of contiguous free blocks found are allocated, even if there + are fewer blocks than requested (and even if a contiguous range of blocks + of the given size exists elsewhere). BlockAllocateContig Find and allocate a contiguous range of blocks of a given size. If a contiguous range of free blocks of the given size isn't found, then the allocation fails (i.e. it is "all or nothing"). + + BlockAllocateKnown + Try to allocate space from known free space in the volume's + free extent cache. + ReadBitmapBlock Given an allocation block number, read the bitmap block that contains that allocation block into a caller-supplied buffer. + + ReleaseBitmapBlock + Release a bitmap block back into the buffer cache. */ #include "../../hfs_macos_defs.h" @@ -170,22 +88,13 @@ Internal routines: #include "../headers/FileMgrInternal.h" -#include "../headers/HFSInstrumentation.h" - -#define EXPLICIT_BUFFER_RELEASES 1 enum { + kBytesPerWord = 4, kBitsPerByte = 8, kBitsPerWord = 32, - kWordsPerBlock = 128, - kBytesPerBlock = 512, - kBitsPerBlock = 4096, - - kBitsWithinWordMask = kBitsPerWord-1, - kBitsWithinBlockMask = kBitsPerBlock-1, - kWordsWithinBlockMask = kWordsPerBlock-1, - - kExtentsPerRecord = 3 + + kBitsWithinWordMask = kBitsPerWord-1 }; #define kLowBitInWordMask 0x00000001ul @@ -195,8 +104,22 @@ enum { static OSErr ReadBitmapBlock( ExtendedVCB *vcb, - UInt32 block, - UInt32 **buffer); + UInt32 bit, + UInt32 **buffer, + UInt32 *blockRef); + +static OSErr ReleaseBitmapBlock( + ExtendedVCB *vcb, + UInt32 blockRef, + Boolean dirty); + +static OSErr BlockAllocateAny( + ExtendedVCB *vcb, + UInt32 startingBlock, + UInt32 endingBlock, + UInt32 maxBlocks, + UInt32 *actualStartBlock, + UInt32 *actualNumBlocks); static OSErr BlockAllocateContig( ExtendedVCB *vcb, @@ -225,6 +148,12 @@ static OSErr BlockMarkFree( UInt32 startingBlock, UInt32 numBlocks); +static OSErr BlockAllocateKnown( + ExtendedVCB *vcb, + UInt32 maxBlocks, + UInt32 *actualStartBlock, + UInt32 *actualNumBlocks); + /* ;________________________________________________________________________________ @@ -266,13 +195,6 @@ static OSErr BlockMarkFree( ; ; Side effects: ; The volume bitmap is read and updated; the volume bitmap cache may be changed. -; -; Modification history: -; <06Oct85> PWD Changed to check for errors after calls to ReadBM and NextWord -; Relocated call to MarkBlock in allocation loop -; Changed to call NextBit -; <21Oct85> PWD Changed to check VCBFreeBks before attempting to allocate any block. -; Speed up scan for free space by checking for all 1's. ;________________________________________________________________________________ */ @@ -293,25 +215,6 @@ OSErr BlockAllocate ( UInt32 maxBlocks; // number of allocation blocks requested, rounded to clump size Boolean updateAllocPtr = false; // true if nextAllocation needs to be updated - LogStartTime(kTraceBlockAllocate); - -#if HFSInstrumentation - InstSplitHistogramClassRef histogram; - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:BlockAllocate", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - err = InstCreateSplitHistogramClass(kInstRootClassRef, "HFS:VSM:BlockAllocate size", 0, 512, 16384, 262144, 16384, - kInstEnableClassMask, &histogram); - if (err != noErr) DebugStr("\pError from InstCreateHistogramClass"); - - eventTag = bytesRequested; // a cheap way to get bytesRequested into the log - InstLogTraceEvent( trace, eventTag, kInstStartEvent); - InstUpdateHistogram( histogram, bytesRequested, 1); -#endif - // // Initialize outputs in case we get an error // @@ -346,7 +249,7 @@ OSErr BlockAllocate ( VCB_UNLOCK(vcb); updateAllocPtr = true; } - + // // If the request must be contiguous, then find a sequence of free blocks // that is long enough. Otherwise, find the first free block. @@ -354,10 +257,18 @@ OSErr BlockAllocate ( if (forceContiguous) { err = BlockAllocateContig(vcb, startingBlock, minBlocks, maxBlocks, actualStartBlock, actualNumBlocks); } else { - err = BlockAllocateAny(vcb, startingBlock, vcb->totalBlocks, maxBlocks, actualStartBlock, actualNumBlocks); - if (err == dskFulErr) { + /* + * Scan the bitmap once, gather the N largest free extents, then + * allocate from these largest extents. Repeat as needed until + * we get all the space we needed. We could probably build up + * that list when the higher level caller tried (and failed) a + * contiguous allocation first. + */ + err = BlockAllocateKnown(vcb, maxBlocks, actualStartBlock, actualNumBlocks); + if (err == dskFulErr) + err = BlockAllocateAny(vcb, startingBlock, vcb->totalBlocks, maxBlocks, actualStartBlock, actualNumBlocks); + if (err == dskFulErr) err = BlockAllocateAny(vcb, 0, startingBlock, maxBlocks, actualStartBlock, actualNumBlocks); - }; } if (err == noErr) { @@ -380,43 +291,15 @@ OSErr BlockAllocate ( vcb->freeBlocks -= *actualNumBlocks; VCB_UNLOCK(vcb); - UpdateVCBFreeBlks( vcb ); MarkVCBDirty(vcb); } Exit: -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - LogEndTime(kTraceBlockAllocate, err); - return err; } -/* -;________________________________________________________________________________ -; -; Routine: UpdateVCBFreeBlks -; -; Function: Whenever the freeBlocks field in the ExtendedVCB is updated, -; we must also recalculate the (UInt16) vcbFreeBks field in the -; traditional HFS VCB structure. -; -; Input Arguments: -; vcb - Pointer to ExtendedVCB for the volume to free space on -;________________________________________________________________________________ -*/ -void UpdateVCBFreeBlks( ExtendedVCB *vcb ) -{ - #if DEBUG_BUILD - if ( vcb->vcbSigWord == kHFSSigWord && vcb->freeBlocks > 0xFFFF ) - DebugStr("\p UpdateVCBFreeBlks: freeBlocks overflow!"); - #endif -} - - /* ;________________________________________________________________________________ ; @@ -434,11 +317,6 @@ void UpdateVCBFreeBlks( ExtendedVCB *vcb ) ; ; Side effects: ; The volume bitmap is read and updated; the volume bitmap cache may be changed. -; -; Modification history: -; -; <06Oct85> PWD Changed to check for error after calls to ReadBM and NextWord -; Now calls NextBit to read successive bits from the bitmap ;________________________________________________________________________________ */ @@ -449,17 +327,6 @@ OSErr BlockDeallocate ( { OSErr err; -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:BlockDeallocate", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif - // // If no blocks to deallocate, then exit early // @@ -481,197 +348,14 @@ OSErr BlockDeallocate ( VCB_LOCK(vcb); vcb->freeBlocks += numBlocks; VCB_UNLOCK(vcb); - UpdateVCBFreeBlks( vcb ); MarkVCBDirty(vcb); Exit: -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; } -/* -;_______________________________________________________________________ -; -; Routine: UpdateFree -; Arguments: vcb -- ExtendedVCB for volume -; -; Called By: MountVol -; Function: This routine is used as part of the MountVol consistency check -; to figure out the number of free allocation blocks in the volume. -; -; Modification History: -; <08Sep85> LAK New today. -; <06Oct85> PWD Added explicit check for errors after calls to ReadBM, NextWord -; Now calls NextBit. -;_______________________________________________________________________ -*/ - -OSErr UpdateFreeCount ( - ExtendedVCB *vcb) // Volume whose free block count should be updated -{ - OSErr err; - register UInt32 wordsLeft; // Number of words left in this bitmap block - register UInt32 numBlocks; // Number of blocks left to scan - register UInt32 freeCount; // Running count of free blocks found so far - register UInt32 temp; - UInt32 blockNum; // Block number of first block in this bitmap block - UInt32 *buffer = NULL; // Pointer to bitmap block - register UInt32 *currentWord; // Pointer to current word in bitmap block - -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:UpdateFreeCount", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif - - // - // Pre-read the first bitmap block - // - - err = ReadBitmapBlock(vcb, 0, &buffer); - if (err != noErr) goto Exit; - - // - // Initialize buffer stuff - // - currentWord = buffer; - wordsLeft = kWordsPerBlock; - numBlocks = vcb->totalBlocks; - freeCount = 0; - blockNum = 0; - - // - // Scan whole words first - // - - while (numBlocks >= kBitsPerWord) { - // See if it's time to move to the next bitmap block - if (wordsLeft == 0) { - // Read in the next bitmap block - blockNum += kBitsPerBlock; // generate a block number in the next bitmap block - -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; - buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, blockNum, &buffer); - if (err != noErr) goto Exit; - - // Readjust currentWord, wordsLeft - currentWord = buffer; - wordsLeft = kWordsPerBlock; - } - - // We count free blocks by inverting the word in the bitmap and counting set bits. - temp = ~(*currentWord); - while (temp) { - ++freeCount; - temp &= temp-1; // this clears least significant bit that is currently set - } - - numBlocks -= kBitsPerWord; - ++currentWord; // move to next word - --wordsLeft; // one less word left in this block - } - - // - // Check any remaining blocks. - // - - if (numBlocks != 0) { - if (wordsLeft == 0) { - // Read in the next bitmap block - blockNum += kBitsPerBlock; // generate a block number in the next bitmap block - -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; - buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, blockNum, &buffer); - if (err != noErr) goto Exit; - - // Readjust currentWord, wordsLeft - currentWord = buffer; - wordsLeft = kWordsPerBlock; - } - - // We count free blocks by inverting the word in the bitmap and counting set bits. - temp = SWAP_BE32 (~(*currentWord)); - while (numBlocks != 0) { - if (temp & kHighBitInWordMask) - ++freeCount; - temp <<= 1; - --numBlocks; - } - } - - VCB_LOCK(vcb); - vcb->freeBlocks = freeCount; - VCB_UNLOCK(vcb); - UpdateVCBFreeBlks( vcb ); - -Exit: - -#if EXPLICIT_BUFFER_RELEASES - if (buffer) { - (void)RelBlock_glue((Ptr)buffer, rbDefault); /* Ignore any additional errors */ - }; -#endif - -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - - return err; -} - - - -/* -;_______________________________________________________________________ -; -; Routine: AllocateFreeSpace -; Arguments: vcb -- ExtendedVCB for volume -; -; Called By: HFSDiskInitComponent -; Function: This routine is used as part of DiskInit to create an -; embedded HFS+ volume. -; -; Note: Assumes that the free space is contiguous (true for a freshly erased disk) -;_______________________________________________________________________ -*/ - -OSErr AllocateFreeSpace ( - ExtendedVCB *vcb, // Volume whose free space is about to be expropriated - UInt32 *startBlock, // return where free space starts - UInt32 *actualBlocks) // return the number of blocks in free space -{ - OSErr err; - - err = BlockAllocateAny(vcb, 0, vcb->totalBlocks, vcb->freeBlocks, startBlock, actualBlocks); - - if (err == noErr) { - VCB_LOCK(vcb); - vcb->freeBlocks = 0; // sorry, no more blocks left! - VCB_UNLOCK(vcb); - MarkVCBDirty(vcb); - } - - return err; -} - /* ;_______________________________________________________________________ ; @@ -706,87 +390,94 @@ UInt32 FileBytesToBlocks( ; Routine: ReadBitmapBlock ; ; Function: Read in a bitmap block corresponding to a given allocation -; block. Return a pointer to the bitmap block. +; block (bit). Return a pointer to the bitmap block. ; ; Inputs: ; vcb -- Pointer to ExtendedVCB -; block -- Allocation block whose bitmap block is desired +; bit -- Allocation block whose bitmap block is desired ; ; Outputs: ; buffer -- Pointer to bitmap block corresonding to "block" +; blockRef ;_______________________________________________________________________ */ static OSErr ReadBitmapBlock( ExtendedVCB *vcb, - UInt32 block, - UInt32 **buffer) + UInt32 bit, + UInt32 **buffer, + UInt32 *blockRef) { OSErr err; + struct buf *bp = NULL; + struct vnode *vp = NULL; + UInt32 block; + UInt32 blockSize; -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:ReadBitmapBlock", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = block; // a cheap way to get the block number into the log - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif + /* + * volume bitmap blocks are protected by the Extents B-tree lock + */ + REQUIRE_FILE_LOCK(vcb->extentsRefNum, false); - err = noErr; + blockSize = (UInt32)vcb->vcbVBMIOSize; + block = bit / (blockSize * kBitsPerByte); - REQUIRE_FILE_LOCK(vcb->extentsRefNum, false); /* bitmap blocks are covered by the Extents B-tree lock */ + if (vcb->vcbSigWord == kHFSPlusSigWord) { + vp = vcb->allocationsRefNum; /* use allocation file vnode */ - if (vcb->vcbSigWord == kHFSSigWord) { - // - // HFS: Turn block number into physical block offset within the - // bitmap, and then the physical block within the volume. - // - block /= kBitsPerBlock; // block offset within bitmap - block += vcb->vcbVBMSt; // block within whole volume + } else /* hfs */ { + vp = VCBTOHFS(vcb)->hfs_devvp; /* use device I/O vnode */ + block += vcb->vcbVBMSt; /* map to physical block */ } - else { - FCB *allocFile; - daddr_t startBlock; - size_t availableBytes; - - // - // HFS+: Read from allocation file. We simply convert the block number into a byte - // offset within the allocation file and then determine which block that byte is in. - // - allocFile = GetFileControlBlock(vcb->allocationsRefNum); - // - // Find out which physical block holds byte #offset in allocation file. Note that we - // map only 1 byte (the one we asked for). - // - err = MapFileBlockC(vcb, allocFile, (size_t)1, (off_t)(block/kBitsPerByte), &startBlock, &availableBytes); - block = startBlock; - } + err = meta_bread(vp, block, blockSize, NOCRED, &bp); - if (err == noErr) { - err = GetBlock_glue( -#if EXPLICIT_BUFFER_RELEASES - 0, // No options -#else - gbReleaseMask, // Release block immediately. We only work on one - // block at a time. Call MarkBlock later if dirty. -#endif - block, // Physical block on volume - (Ptr *) buffer, // A place to return the buffer pointer - kNoFileReference, // Not a file read - vcb); // Volume to read from + if (bp) { + if (err) { + brelse(bp); + *blockRef = NULL; + *buffer = NULL; + } else { + *blockRef = (UInt32)bp; + *buffer = (UInt32 *)bp->b_data; + } } -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif - return err; } +/* +;_______________________________________________________________________ +; +; Routine: ReleaseBitmapBlock +; +; Function: Relase a bitmap block. +; +; Inputs: +; vcb +; blockRef +; dirty +;_______________________________________________________________________ +*/ +static OSErr ReleaseBitmapBlock( + ExtendedVCB *vcb, + UInt32 blockRef, + Boolean dirty) +{ + struct buf *bp = (struct buf *)blockRef; + + if (bp) { + if (dirty) { + bp->b_flags |= B_DIRTY; + bdwrite(bp); + } else { + brelse(bp); + } + } + + return (0); +} + /* _______________________________________________________________________ @@ -824,12 +515,23 @@ static OSErr BlockAllocateContig( // Determine the number of contiguous blocks available (up // to maxBlocks). // + + /* + * NOTE: If the only contiguous free extent of at least minBlocks + * crosses startingBlock (i.e. starts before, ends after), then we + * won't find it. Earlier versions *did* find this case by letting + * the second search look past startingBlock by minBlocks. But + * with the free extent cache, this can lead to duplicate entries + * in the cache, causing the same blocks to be allocated twice. + */ err = BlockFindContiguous(vcb, startingBlock, vcb->totalBlocks, minBlocks, maxBlocks, actualStartBlock, actualNumBlocks); - if (err == dskFulErr) { - //€€ Should constrain the endingBlock here, so we don't bother looking for ranges - //€€ that start after startingBlock, since we already checked those. - err = BlockFindContiguous(vcb, 0, vcb->totalBlocks, minBlocks, maxBlocks, + if (err == dskFulErr && startingBlock != 0) { + /* + * Constrain the endingBlock so we don't bother looking for ranges + * that would overlap those found in the previous call. + */ + err = BlockFindContiguous(vcb, 0, startingBlock, minBlocks, maxBlocks, actualStartBlock, actualNumBlocks); } if (err != noErr) goto Exit; @@ -871,7 +573,7 @@ Outputs: actualNumBlocks Number of blocks allocated, or 0 if error _______________________________________________________________________ */ -OSErr BlockAllocateAny( +static OSErr BlockAllocateAny( ExtendedVCB *vcb, UInt32 startingBlock, register UInt32 endingBlock, @@ -886,37 +588,35 @@ OSErr BlockAllocateAny( register UInt32 wordsLeft; // Number of words left in this bitmap block UInt32 *buffer = NULL; UInt32 *currCache = NULL; - -#if HFS_DIAGNOSTIC - struct buf *bp = NULL; - int mappingEntry; -#endif + UInt32 blockRef; + UInt32 bitsPerBlock; + UInt32 wordsPerBlock; + Boolean dirty = false; // Since this routine doesn't wrap around if (maxBlocks > (endingBlock - startingBlock)) { maxBlocks = endingBlock - startingBlock; } - DBG_TREE (("\nAllocating starting at %ld, maxblocks %ld\n", startingBlock, maxBlocks)); // // Pre-read the first bitmap block // - err = ReadBitmapBlock(vcb, startingBlock, &currCache); - DBG_TREE (("\n1. Read bit map at %ld, buffer is 0x%x\n", startingBlock, (int)currCache)); + err = ReadBitmapBlock(vcb, startingBlock, &currCache, &blockRef); if (err != noErr) goto Exit; buffer = currCache; - MarkBlock_glue((Ptr) currCache); // this block will be dirty - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); // // Set up the current position within the block // { UInt32 wordIndexInBlock; + + bitsPerBlock = vcb->vcbVBMIOSize * kBitsPerByte; + wordsPerBlock = vcb->vcbVBMIOSize / kBytesPerWord; - wordIndexInBlock = (startingBlock & kBitsWithinBlockMask) / kBitsPerWord; + wordIndexInBlock = (startingBlock & (bitsPerBlock-1)) / kBitsPerWord; buffer += wordIndexInBlock; - wordsLeft = kWordsPerBlock - wordIndexInBlock; + wordsLeft = wordsPerBlock - wordIndexInBlock; currentWord = SWAP_BE32 (*buffer); bitMask = kHighBitInWordMask >> (startingBlock & kBitsWithinWordMask); } @@ -939,20 +639,15 @@ OSErr BlockAllocateAny( if (--wordsLeft == 0) { // Next block -#if EXPLICIT_BUFFER_RELEASES - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); - err = RelBlock_glue((Ptr)currCache, rbDefault); - if (err != noErr) goto Exit; buffer = currCache = NULL; -#endif - err = ReadBitmapBlock(vcb, block, &currCache); + err = ReleaseBitmapBlock(vcb, blockRef, false); + if (err != noErr) goto Exit; + + err = ReadBitmapBlock(vcb, block, &currCache, &blockRef); if (err != noErr) goto Exit; buffer = currCache; - DBG_TREE (("\n2. Read bit map at %ld, buffer is 0x%x\n", block, (int)currCache)); - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); - MarkBlock_glue((Ptr) currCache); // this block will be dirty - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } currentWord = SWAP_BE32 (*buffer); @@ -968,6 +663,7 @@ OSErr BlockAllocateAny( // Return the first block in the allocated range *actualStartBlock = block; + dirty = true; // If we could get the desired number of blocks before hitting endingBlock, // then adjust endingBlock so we won't keep looking. Ideally, the comparison @@ -1000,20 +696,15 @@ OSErr BlockAllocateAny( if (--wordsLeft == 0) { // Next block -#if EXPLICIT_BUFFER_RELEASES - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); - err = RelBlock_glue((Ptr)currCache, rbDefault); - if (err != noErr) goto Exit; buffer = currCache = NULL; -#endif - err = ReadBitmapBlock(vcb, block, &currCache); + err = ReleaseBitmapBlock(vcb, blockRef, true); + if (err != noErr) goto Exit; + + err = ReadBitmapBlock(vcb, block, &currCache, &blockRef); if (err != noErr) goto Exit; buffer = currCache; - DBG_TREE (("\n3. Read bit map at %ld, buffer is 0x%x\n", block, (int)currCache)); - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); - MarkBlock_glue((Ptr) currCache); // this block will be dirty - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } currentWord = SWAP_BE32 (*buffer); @@ -1030,17 +721,94 @@ Exit: *actualNumBlocks = 0; } -#if EXPLICIT_BUFFER_RELEASES - if (currCache) { - DBG_ASSERT(! LookupBufferMapping((caddr_t)currCache, &bp, &mappingEntry)); - (void)RelBlock_glue((Ptr)currCache, rbDefault); /* Ignore any additional errors */ - }; -#endif + if (currCache) + (void) ReleaseBitmapBlock(vcb, blockRef, dirty); return err; } +/* +_______________________________________________________________________ + +Routine: BlockAllocateKnown + +Function: Try to allocate space from known free space in the free + extent cache. + +Inputs: + vcb Pointer to volume where space is to be allocated + maxBlocks Maximum number of contiguous blocks to allocate + +Outputs: + actualStartBlock First block of range allocated, or 0 if error + actualNumBlocks Number of blocks allocated, or 0 if error + +Returns: + dskFulErr Free extent cache is empty +_______________________________________________________________________ +*/ +static OSErr BlockAllocateKnown( + ExtendedVCB *vcb, + UInt32 maxBlocks, + UInt32 *actualStartBlock, + UInt32 *actualNumBlocks) +{ + UInt32 i; + UInt32 foundBlocks; + UInt32 newStartBlock, newBlockCount; + + if (vcb->vcbFreeExtCnt == 0) + return dskFulErr; + + // Just grab up to maxBlocks of the first (largest) free exent. + *actualStartBlock = vcb->vcbFreeExt[0].startBlock; + foundBlocks = vcb->vcbFreeExt[0].blockCount; + if (foundBlocks > maxBlocks) + foundBlocks = maxBlocks; + *actualNumBlocks = foundBlocks; + + // Adjust the start and length of that extent. + newStartBlock = vcb->vcbFreeExt[0].startBlock + foundBlocks; + newBlockCount = vcb->vcbFreeExt[0].blockCount - foundBlocks; + + // The first extent might not be the largest anymore. Bubble up any + // (now larger) extents to the top of the list. + for (i=1; i<vcb->vcbFreeExtCnt; ++i) + { + if (vcb->vcbFreeExt[i].blockCount > newBlockCount) + { + vcb->vcbFreeExt[i-1].startBlock = vcb->vcbFreeExt[i].startBlock; + vcb->vcbFreeExt[i-1].blockCount = vcb->vcbFreeExt[i].blockCount; + } + else + { + break; + } + } + + // If this is now the smallest known free extent, then it might be smaller than + // other extents we didn't keep track of. So, just forget about this extent. + // After the previous loop, (i-1) is the index of the extent we just allocated from. + if (i == vcb->vcbFreeExtCnt) + { + // It's now the smallest extent, so forget about it + --vcb->vcbFreeExtCnt; + } + else + { + // It's not the smallest, so store it in its proper place + vcb->vcbFreeExt[i-1].startBlock = newStartBlock; + vcb->vcbFreeExt[i-1].blockCount = newBlockCount; + } + + // + // Now mark the found extent in the bitmap + // + return BlockMarkAllocated(vcb, *actualStartBlock, *actualNumBlocks); +} + + /* _______________________________________________________________________ @@ -1069,35 +837,28 @@ static OSErr BlockMarkAllocated( UInt32 firstBit; // Bit index within word of first bit to allocate UInt32 numBits; // Number of bits in word to allocate UInt32 *buffer = NULL; - -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:BlockMarkAllocated", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif + UInt32 blockRef; + UInt32 bitsPerBlock; + UInt32 wordsPerBlock; // // Pre-read the bitmap block containing the first word of allocation // - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - // // Initialize currentWord, and wordsLeft. // { UInt32 wordIndexInBlock; + + bitsPerBlock = vcb->vcbVBMIOSize * kBitsPerByte; + wordsPerBlock = vcb->vcbVBMIOSize / kBytesPerWord; - wordIndexInBlock = (startingBlock & kBitsWithinBlockMask) / kBitsPerWord; + wordIndexInBlock = (startingBlock & (bitsPerBlock-1)) / kBitsPerWord; currentWord = buffer + wordIndexInBlock; - wordsLeft = kWordsPerBlock - wordIndexInBlock; + wordsLeft = wordsPerBlock - wordIndexInBlock; } // @@ -1116,9 +877,7 @@ static OSErr BlockMarkAllocated( } #if DEBUG_BUILD if ((*currentWord & SWAP_BE32 (bitMask)) != 0) { - DebugStr("\pFATAL: blocks already allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkAllocated: blocks already allocated!"); } #endif *currentWord |= SWAP_BE32 (bitMask); // set the bits in the bitmap @@ -1136,26 +895,22 @@ static OSErr BlockMarkAllocated( while (numBlocks >= kBitsPerWord) { if (wordsLeft == 0) { // Read in the next bitmap block - startingBlock += kBitsPerBlock; // generate a block number in the next bitmap block + startingBlock += bitsPerBlock; // generate a block number in the next bitmap block -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReleaseBitmapBlock(vcb, blockRef, true); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - + + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); + if (err != noErr) goto Exit; + // Readjust currentWord and wordsLeft currentWord = buffer; - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } #if DEBUG_BUILD if (*currentWord != 0) { - DebugStr("\pFATAL: blocks already allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkAllocated: blocks already allocated!"); } #endif *currentWord = SWAP_BE32 (bitMask); @@ -1173,26 +928,22 @@ static OSErr BlockMarkAllocated( bitMask = ~(kAllBitsSetInWord >> numBlocks); // set first numBlocks bits if (wordsLeft == 0) { // Read in the next bitmap block - startingBlock += kBitsPerBlock; // generate a block number in the next bitmap block + startingBlock += bitsPerBlock; // generate a block number in the next bitmap block -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReleaseBitmapBlock(vcb, blockRef, true); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - + + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); + if (err != noErr) goto Exit; + // Readjust currentWord and wordsLeft currentWord = buffer; - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } #if DEBUG_BUILD if ((*currentWord & SWAP_BE32 (bitMask)) != 0) { - DebugStr("\pFATAL: blocks already allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkAllocated: blocks already allocated!"); } #endif *currentWord |= SWAP_BE32 (bitMask); // set the bits in the bitmap @@ -1202,21 +953,13 @@ static OSErr BlockMarkAllocated( Exit: -#if EXPLICIT_BUFFER_RELEASES - if (buffer) { - (void)RelBlock_glue((Ptr)buffer, rbDefault); /* Ignore any additional errors */ - }; -#endif - -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif + if (buffer) + (void)ReleaseBitmapBlock(vcb, blockRef, true); return err; } - /* _______________________________________________________________________ @@ -1244,35 +987,28 @@ static OSErr BlockMarkFree( UInt32 firstBit; // Bit index within word of first bit to allocate UInt32 numBits; // Number of bits in word to allocate UInt32 *buffer = NULL; - -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:BlockMarkFree", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif + UInt32 blockRef; + UInt32 bitsPerBlock; + UInt32 wordsPerBlock; // // Pre-read the bitmap block containing the first word of allocation // - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - // // Initialize currentWord, and wordsLeft. // { UInt32 wordIndexInBlock; + + bitsPerBlock = vcb->vcbVBMIOSize * kBitsPerByte; + wordsPerBlock = vcb->vcbVBMIOSize / kBytesPerWord; - wordIndexInBlock = (startingBlock & kBitsWithinBlockMask) / kBitsPerWord; + wordIndexInBlock = (startingBlock & (bitsPerBlock-1)) / kBitsPerWord; currentWord = buffer + wordIndexInBlock; - wordsLeft = kWordsPerBlock - wordIndexInBlock; + wordsLeft = wordsPerBlock - wordIndexInBlock; } // @@ -1291,9 +1027,7 @@ static OSErr BlockMarkFree( } #if DEBUG_BUILD if ((*currentWord & SWAP_BE32 (bitMask)) != SWAP_BE32 (bitMask)) { - DebugStr("\pFATAL: blocks not allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkFree: blocks not allocated!"); } #endif *currentWord &= SWAP_BE32 (~bitMask); // clear the bits in the bitmap @@ -1304,33 +1038,29 @@ static OSErr BlockMarkFree( } // - // Allocate whole words (32 blocks) at a time. + // Free whole words (32 blocks) at a time. // while (numBlocks >= kBitsPerWord) { if (wordsLeft == 0) { // Read in the next bitmap block - startingBlock += kBitsPerBlock; // generate a block number in the next bitmap block + startingBlock += bitsPerBlock; // generate a block number in the next bitmap block -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReleaseBitmapBlock(vcb, blockRef, true); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - + + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); + if (err != noErr) goto Exit; + // Readjust currentWord and wordsLeft currentWord = buffer; - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } #if DEBUG_BUILD if (*currentWord != SWAP_BE32 (kAllBitsSetInWord)) { - DebugStr("\pFATAL: blocks not allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkFree: blocks not allocated!"); } #endif *currentWord = 0; // clear the entire word @@ -1341,33 +1071,29 @@ static OSErr BlockMarkFree( } // - // Allocate any remaining blocks. + // Free any remaining blocks. // if (numBlocks != 0) { bitMask = ~(kAllBitsSetInWord >> numBlocks); // set first numBlocks bits if (wordsLeft == 0) { // Read in the next bitmap block - startingBlock += kBitsPerBlock; // generate a block number in the next bitmap block + startingBlock += bitsPerBlock; // generate a block number in the next bitmap block -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, startingBlock, &buffer); + err = ReleaseBitmapBlock(vcb, blockRef, true); if (err != noErr) goto Exit; - MarkBlock_glue((Ptr) buffer); // this block will be dirty - + + err = ReadBitmapBlock(vcb, startingBlock, &buffer, &blockRef); + if (err != noErr) goto Exit; + // Readjust currentWord and wordsLeft currentWord = buffer; - wordsLeft = kWordsPerBlock; + wordsLeft = wordsPerBlock; } #if DEBUG_BUILD if ((*currentWord & SWAP_BE32 (bitMask)) != SWAP_BE32 (bitMask)) { - DebugStr("\pFATAL: blocks not allocated!"); - //err = fsDSIntErr; - //goto Exit; + panic("BlockMarkFree: blocks not allocated!"); } #endif *currentWord &= SWAP_BE32 (~bitMask); // clear the bits in the bitmap @@ -1377,15 +1103,8 @@ static OSErr BlockMarkFree( Exit: -#if EXPLICIT_BUFFER_RELEASES - if (buffer) { - (void)RelBlock_glue((Ptr)buffer, rbDefault); /* Ignore any additional errors */ - }; -#endif - -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif + if (buffer) + (void)ReleaseBitmapBlock(vcb, blockRef, true); return err; } @@ -1399,13 +1118,6 @@ Routine: BlockFindContiguous Function: Find a contiguous range of blocks that are free (bits clear in the bitmap). If a contiguous range of the minimum size can't be found, an error will be returned. - - €€ It would be nice if we could skip over whole words - €€ with all bits set. - - €€ When we find a bit set, and are about to set freeBlocks - €€ to 0, we should check to see whether there are still - €€ minBlocks bits left in the bitmap. Inputs: vcb Pointer to volume where space is to be allocated @@ -1417,340 +1129,264 @@ Inputs: Outputs: actualStartBlock First block of range found, or 0 if error actualNumBlocks Number of blocks found, or 0 if error -_______________________________________________________________________ -*/ -/* -_________________________________________________________________________________________ - (DSH) 5/8/97 Description of BlockFindContiguous() algorithm - Finds a contiguous range of free blocks by searching back to front. This - allows us to skip ranges of bits knowing that they are not candidates for - a match because they are too small. The below ascii diagrams illustrate - the algorithm in action. - - Representation of a piece of a volume bitmap file - If BlockFindContiguous() is called with minBlocks == 10, maxBlocks == 20 - - -Fig. 1 initialization of variables, "<--" represents direction of travel - -startingBlock (passed in) - | - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - | <--| -stopBlock currentBlock freeBlocks == 0 - countedFreeBlocks == 0 - -Fig. 2 dirty bit found - - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - | | -stopBlock currentBlock freeBlocks == 3 - countedFreeBlocks == 0 - -Fig. 3 reset variables to search for remainder of minBlocks - - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - |_________________| | | - Unsearched stopBlock currentBlock freeBlocks == 0 - countedFreeBlocks == 3 -Fig. 4 minBlocks contiguous blocks found, *actualStartBlock is set - - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - |_________________| | - Unsearched stopBlock freeBlocks == 7 - currentBlock countedFreeBlocks == 3 - -Fig. 5 Now run it forwards trying to accumalate up to maxBlocks if possible - - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - |_________________| | --> - Unsearched currentBlock - *actualNumBlocks == 10 - -Fig. 6 Dirty bit is found, return actual number of contiguous blocks found - - 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 - |_________________| | - Unsearched currentBlock - *actualNumBlocks == 16 -_________________________________________________________________________________________ +Returns: + noErr Found at least minBlocks contiguous + dskFulErr No contiguous space found, or all less than minBlocks +_______________________________________________________________________ */ static OSErr BlockFindContiguous( ExtendedVCB *vcb, UInt32 startingBlock, - register UInt32 endingBlock, + UInt32 endingBlock, UInt32 minBlocks, UInt32 maxBlocks, UInt32 *actualStartBlock, UInt32 *actualNumBlocks) { OSErr err; - register UInt32 bitMask; // mask of bit within word for currentBlock - register UInt32 tempWord; // bitmap word currently being examined - register UInt32 freeBlocks; // number of contiguous free blocks so far - register UInt32 currentBlock; // block number we're currently examining - UInt32 wordsLeft; // words remaining in bitmap block + register UInt32 currentBlock; // Block we're currently looking at. + UInt32 firstBlock; // First free block in current extent. + UInt32 stopBlock; // If we get to this block, stop searching for first free block. + UInt32 foundBlocks; // Number of contiguous free blocks in current extent. UInt32 *buffer = NULL; register UInt32 *currentWord; - - UInt32 stopBlock; // when all blocks until stopBlock are free, we found enough - UInt32 countedFreeBlocks; // how many contiguous free block behind stopBlock - UInt32 currentSector; // which allocations file sector - -#if HFSInstrumentation - InstTraceClassRef trace; - InstEventTag eventTag; - - err = InstCreateTraceClass(kInstRootClassRef, "HFS:VSM:BlockFindContiguous", 'hfs+', kInstEnableClassMask, &trace); - if (err != noErr) DebugStr("\pError from InstCreateTraceClass"); - - eventTag = InstCreateEventTag(); - InstLogTraceEvent( trace, eventTag, kInstStartEvent); -#endif + register UInt32 bitMask; + register UInt32 wordsLeft; + register UInt32 tempWord; + UInt32 blockRef; + UInt32 wordsPerBlock; - if ((endingBlock - startingBlock) < minBlocks) { + if ((endingBlock - startingBlock) < minBlocks) + { // The set of blocks we're checking is smaller than the minimum number // of blocks, so we couldn't possibly find a good range. - err = dskFulErr; - goto Exit; + goto DiskFull; } - - // Search for min blocks from back to front. - // If min blocks is found, advance the allocation pointer up to max blocks - - // - // Pre-read the bitmap block containing currentBlock - // - stopBlock = startingBlock; - currentBlock = startingBlock + minBlocks - 1; // (-1) to include startingBlock - - err = ReadBitmapBlock( vcb, currentBlock, &buffer ); - if ( err != noErr ) goto Exit; + + stopBlock = endingBlock - minBlocks + 1; + currentBlock = startingBlock; // - // Init buffer, currentWord, wordsLeft, and bitMask + // Pre-read the first bitmap block. // - { - UInt32 wordIndexInBlock; + err = ReadBitmapBlock(vcb, currentBlock, &buffer, &blockRef); + if ( err != noErr ) goto ErrorExit; - wordIndexInBlock = ( currentBlock & kBitsWithinBlockMask ) / kBitsPerWord; - currentWord = buffer + wordIndexInBlock; - - wordsLeft = wordIndexInBlock; - tempWord = SWAP_BE32 (*currentWord); - bitMask = kHighBitInWordMask >> ( currentBlock & kBitsWithinWordMask ); - currentSector = currentBlock / kBitsPerBlock; - } - // - // Look for maxBlocks free blocks. If we find an allocated block, - // see if we've found minBlocks. + // Figure out where currentBlock is within the buffer. // - freeBlocks = 0; - countedFreeBlocks = 0; + wordsPerBlock = vcb->vcbVBMIOSize / kBytesPerWord; - while ( currentBlock >= stopBlock ) + wordsLeft = (startingBlock / kBitsPerWord) & (wordsPerBlock-1); // Current index into buffer + currentWord = buffer + wordsLeft; + wordsLeft = wordsPerBlock - wordsLeft; + + do { - // Check current bit - if ((tempWord & bitMask) == 0) - { - ++freeBlocks; - } - else // Used bitmap block found - { - if ( ( freeBlocks + countedFreeBlocks ) >= minBlocks ) + foundBlocks = 0; + + //============================================================ + // Look for a free block, skipping over allocated blocks. + //============================================================ + + // + // Check an initial partial word (if any) + // + bitMask = currentBlock & kBitsWithinWordMask; + if (bitMask) + { + tempWord = *currentWord; // Fetch the current word only once + bitMask = kHighBitInWordMask >> bitMask; + while (tempWord & bitMask) { - break; // Found enough + bitMask >>= 1; + ++currentBlock; } - else - { - // We found a dirty bit, so we want to check if the next (minBlocks-freeBlocks) blocks - // are free beyond what we have already checked. At Fig.2 setting up for Fig.3 - - stopBlock = currentBlock + 1 + freeBlocks; // Advance stop condition - currentBlock += minBlocks; - if ( currentBlock >= endingBlock ) break; - countedFreeBlocks = freeBlocks; - freeBlocks = 0; // Not enough; look for another range - if ( currentSector != currentBlock / kBitsPerBlock ) - { -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; - buffer = NULL; -#endif - err = ReadBitmapBlock( vcb, currentBlock, &buffer ); - if (err != noErr) goto Exit; - currentSector = currentBlock / kBitsPerBlock; - } - - wordsLeft = ( currentBlock & kBitsWithinBlockMask ) / kBitsPerWord; - currentWord = buffer + wordsLeft; - tempWord = SWAP_BE32 (*currentWord); - bitMask = kHighBitInWordMask >> ( currentBlock & kBitsWithinWordMask ); + // Did we find an unused bit (bitMask != 0), or run out of bits (bitMask == 0)? + if (bitMask) + goto FoundUnused; - continue; // Back to the while loop - } + // Didn't find any unused bits, so we're done with this word. + ++currentWord; + --wordsLeft; } - - // Move to next bit - --currentBlock; - bitMask <<= 1; - if (bitMask == 0) // On a word boundry, start masking words - { - bitMask = kLowBitInWordMask; - // Move to next word -NextWord: - if ( wordsLeft != 0 ) - { - --currentWord; - --wordsLeft; - } - else + // + // Check whole words + // + while (currentBlock < stopBlock) + { + // See if it's time to read another block. + if (wordsLeft == 0) { - // Read in the next bitmap block -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; buffer = NULL; -#endif - err = ReadBitmapBlock( vcb, currentBlock, &buffer ); - if (err != noErr) goto Exit; + err = ReleaseBitmapBlock(vcb, blockRef, false); + if (err != noErr) goto ErrorExit; + + err = ReadBitmapBlock(vcb, currentBlock, &buffer, &blockRef); + if ( err != noErr ) goto ErrorExit; - // Adjust currentWord, wordsLeft, currentSector - currentSector = currentBlock / kBitsPerBlock; - currentWord = buffer + kWordsPerBlock - 1; // Last word in buffer - wordsLeft = kWordsPerBlock - 1; + currentWord = buffer; + wordsLeft = wordsPerBlock; } - tempWord = SWAP_BE32 (*currentWord); // Grab the current word - - // - // If we found a whole word of free blocks, quickly skip over it. - // NOTE: we could actually go beyond the end of the bitmap if the - // number of allocation blocks on the volume is not a multiple of - // 32. If this happens, we'll adjust currentBlock and freeBlocks - // after the loop. - // - if ( tempWord == 0 ) + // See if any of the bits are clear + if ((tempWord=*currentWord) + 1) // non-zero if any bits were clear { - freeBlocks += kBitsPerWord; - currentBlock -= kBitsPerWord; - if ( freeBlocks + countedFreeBlocks >= minBlocks ) - break; // Found enough - goto NextWord; + // Figure out which bit is clear + bitMask = kHighBitInWordMask; + while (tempWord & bitMask) + { + bitMask >>= 1; + ++currentBlock; + } + + break; // Found the free bit; break out to FoundUnused. } - } - } - if ( freeBlocks + countedFreeBlocks < minBlocks ) - { - *actualStartBlock = 0; - *actualNumBlocks = 0; - err = dskFulErr; - goto Exit; - } + // Keep looking at the next word + currentBlock += kBitsPerWord; + ++currentWord; + --wordsLeft; + } - // - // When we get here, we know we've found minBlocks continuous space. - // At Fig.4, setting up for Fig.5 - // From here we do a forward search accumalating additional free blocks. - // - - *actualNumBlocks = minBlocks; - *actualStartBlock = stopBlock - countedFreeBlocks; // ActualStartBlock is set to return to the user - currentBlock = *actualStartBlock + minBlocks; // Right after found free space - - // Now lets see if we can run the actualNumBlocks number all the way up to maxBlocks - if ( currentSector != currentBlock / kBitsPerBlock ) - { -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; - buffer = NULL; -#endif - err = ReadBitmapBlock( vcb, currentBlock, &buffer ); - if (err != noErr) +FoundUnused: + // Make sure the unused bit is early enough to use + if (currentBlock >= stopBlock) { - err = noErr; // We already found the space - goto Exit; + break; } - - currentSector = currentBlock / kBitsPerBlock; - } - // - // Init buffer, currentWord, wordsLeft, and bitMask - // - { - UInt32 wordIndexInBlock; + // Remember the start of the extent + firstBlock = currentBlock; - wordIndexInBlock = (currentBlock & kBitsWithinBlockMask) / kBitsPerWord; - currentWord = buffer + wordIndexInBlock; - tempWord = SWAP_BE32 (*currentWord); - wordsLeft = kWordsPerBlock - wordIndexInBlock; - bitMask = kHighBitInWordMask >> (currentBlock & kBitsWithinWordMask); - } + //============================================================ + // Count the number of contiguous free blocks. + //============================================================ - if ( *actualNumBlocks < maxBlocks ) - { - while ( currentBlock < endingBlock ) + // + // Check an initial partial word (if any) + // + bitMask = currentBlock & kBitsWithinWordMask; + if (bitMask) { - - if ( (tempWord & bitMask) == 0 ) + tempWord = *currentWord; // Fetch the current word only once + bitMask = kHighBitInWordMask >> bitMask; + while (bitMask && !(tempWord & bitMask)) { - *actualNumBlocks += 1; - - if ( *actualNumBlocks == maxBlocks ) - break; + bitMask >>= 1; + ++currentBlock; } - else + + // Did we find a used bit (bitMask != 0), or run out of bits (bitMask == 0)? + if (bitMask) + goto FoundUsed; + + // Didn't find any used bits, so we're done with this word. + ++currentWord; + --wordsLeft; + } + + // + // Check whole words + // + while (currentBlock < endingBlock) + { + // See if it's time to read another block. + if (wordsLeft == 0) { - break; + buffer = NULL; + err = ReleaseBitmapBlock(vcb, blockRef, false); + if (err != noErr) goto ErrorExit; + + err = ReadBitmapBlock(vcb, currentBlock, &buffer, &blockRef); + if ( err != noErr ) goto ErrorExit; + + currentWord = buffer; + wordsLeft = wordsPerBlock; } - - // Move to next bit - ++currentBlock; - bitMask >>= 1; - if (bitMask == 0) + + // See if any of the bits are set + if ((tempWord=*currentWord) != 0) { + // Figure out which bit is set bitMask = kHighBitInWordMask; - ++currentWord; - - if ( --wordsLeft == 0) + while (!(tempWord & bitMask)) { -#if EXPLICIT_BUFFER_RELEASES - err = RelBlock_glue((Ptr)buffer, rbDefault); - if (err != noErr) goto Exit; - buffer = NULL; -#endif - err = ReadBitmapBlock(vcb, currentBlock, &buffer); - if (err != noErr) break; - - // Adjust currentWord, wordsLeft - currentWord = buffer; - wordsLeft = kWordsPerBlock; + bitMask >>= 1; + ++currentBlock; } - tempWord = SWAP_BE32 (*currentWord); // grab the current word + + break; // Found the used bit; break out to FoundUsed. } + + // Keep looking at the next word + currentBlock += kBitsPerWord; + ++currentWord; + --wordsLeft; + + // If we found at least maxBlocks, we can quit early. + if ((currentBlock - firstBlock) >= maxBlocks) + break; } - } - -Exit: -#if EXPLICIT_BUFFER_RELEASES - if (buffer) { - (void)RelBlock_glue((Ptr)buffer, rbDefault); /* Ignore any additional errors */ - }; -#endif +FoundUsed: + // Make sure we didn't run out of bitmap looking for a used block. + // If so, pin to the end of the bitmap. + if (currentBlock > endingBlock) + currentBlock = endingBlock; + + // Figure out how many contiguous free blocks there were. + // Pin the answer to maxBlocks. + foundBlocks = currentBlock - firstBlock; + if (foundBlocks > maxBlocks) + foundBlocks = maxBlocks; + if (foundBlocks >= minBlocks) + break; // Found what we needed! + + // This free chunk wasn't big enough. Try inserting it into the free extent cache in case + // the allocation wasn't forced contiguous. + tempWord = vcb->vcbFreeExtCnt; + if (tempWord == kMaxFreeExtents && vcb->vcbFreeExt[kMaxFreeExtents-1].blockCount < foundBlocks) + --tempWord; + if (tempWord < kMaxFreeExtents) + { + // We're going to add this extent. Bubble any smaller extents down in the list. + while (tempWord && vcb->vcbFreeExt[tempWord-1].blockCount < foundBlocks) + { + vcb->vcbFreeExt[tempWord] = vcb->vcbFreeExt[tempWord-1]; + --tempWord; + } + vcb->vcbFreeExt[tempWord].startBlock = firstBlock; + vcb->vcbFreeExt[tempWord].blockCount = foundBlocks; + + if (vcb->vcbFreeExtCnt < kMaxFreeExtents) + ++vcb->vcbFreeExtCnt; + } + } while (currentBlock < stopBlock); -#if HFSInstrumentation - InstLogTraceEvent( trace, eventTag, kInstEndEvent); -#endif + + // Return the outputs. + if (foundBlocks < minBlocks) + { +DiskFull: + err = dskFulErr; +ErrorExit: + *actualStartBlock = 0; + *actualNumBlocks = 0; + } + else + { + err = noErr; + *actualStartBlock = firstBlock; + *actualNumBlocks = foundBlocks; + } + + if (buffer) + (void) ReleaseBitmapBlock(vcb, blockRef, false); return err; } diff --git a/bsd/hfs/hfscommon/Misc/VolumeRequests.c b/bsd/hfs/hfscommon/Misc/VolumeRequests.c index 96de58244..18c6eb6b4 100644 --- a/bsd/hfs/hfscommon/Misc/VolumeRequests.c +++ b/bsd/hfs/hfscommon/Misc/VolumeRequests.c @@ -206,59 +206,15 @@ #include "../headers/FileMgrInternal.h" -#define kIDSectorOffset 2 - -OSErr GetNewFCB( ExtendedVCB *vcb, FileReference* fRefPtr); - -OSErr AccessBTree( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize, void *CompareRoutine ); - -UInt16 DivUp( UInt32 byteRun, UInt32 blockSize ); - -Boolean IsARamDiskDriver( void ); - -OSErr GetVCBRefNum( ExtendedVCB **vcb, short vRefNum ); OSErr ValidMasterDirectoryBlock( HFSMasterDirectoryBlock *mdb ); -void RenameWrapperVolume( Str27 newVolumeName, UInt16 driveNumber ); - -OSErr CheckExternalFileSystem( ExtendedVCB *vcb ); - -OSErr FlushVolume( ExtendedVCB *vcb ); - -FCB *SetupFCB( ExtendedVCB *vcb, FileReference refNum, UInt32 fileID, UInt32 fileClumpSize ); - -void AddVCB( ExtendedVCB *vcb, short driveNumber, short ioDRefNum ); - -short IsPressed( unsigned short k ); - -FileReference GetNewVRefNum(); - OSErr GetVolumeNameFromCatalog(ExtendedVCB *vcb); -#if TARGET_API_MAC_OS8 -static UInt16 CountRootFiles(ExtendedVCB *vcb); -#endif /* TARGET_API_MAC_OS8 */ - - -#if ( hasHFSManualEject ) -static void SetVCBManEject(ExtendedVCB *vcb); -#endif - // External routines extern OSErr C_FlushMDB( ExtendedVCB *volume ); -extern OSErr DisposeVolumeCacheBlocks( ExtendedVCB *vcb ); - -extern void DisposeVolumeControlBlock( ExtendedVCB *vcb ); - -extern OSErr FlushVolumeBuffers( ExtendedVCB *vcb ); - -extern void MultiplyUInt32IntoUInt64( UInt64 *wideResult, UInt32 num1, UInt32 num2 ); - -extern void TrashCatalogNodeCache( void ); - //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ // Routine: VolumeWritable Asm: CVFlgs @@ -282,55 +238,6 @@ OSErr VolumeWritable( ExtendedVCB *vcb ) } -//‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ -// Routine: DivUp from Asm: DivUp -// -// Function: Given a number of bytes and block size, calculate the number of -// blocks needd to hold all the bytes. -// -// Result: Number of physical blocks needed -//‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ -UInt16 DivUp( UInt32 byteRun, UInt32 blockSize ) -{ - UInt32 blocks; - - blocks = (byteRun + blockSize - 1) / blockSize; // Divide up, remember this is integer math. - - if ( blocks > 0xffff ) // maximum 16 bit value - blocks = 0xffff; - - return( (UInt16) blocks ); -} - - - - -//‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ -// Routine: HFSBlocksFromTotalSectors -// -// Function: Given the total number of sectors on the volume, calculate -// the 16Bit number of allocation blocks, and allocation block size. -// -// Result: none -//‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ -void HFSBlocksFromTotalSectors( UInt32 totalSectors, UInt32 *blockSize, UInt16 *blockCount ) -{ - UInt16 newBlockSizeInSectors = 1; - UInt32 newBlockCount = totalSectors; - - while ( newBlockCount > 0XFFFF ) - { - newBlockSizeInSectors++; - newBlockCount = totalSectors / newBlockSizeInSectors; - } - - *blockSize = newBlockSizeInSectors * 512; - *blockCount = newBlockCount; -} - - - - //‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹‹ // Routine: ValidMasterDirectoryBlock // @@ -385,52 +292,6 @@ OSErr ValidVolumeHeader( HFSPlusVolumeHeader *volumeHeader ) } - - -//_______________________________________________________________________ -// -// Routine: CountRootFiles -// -// Input: pointer to VCB -// -// Function: Return a count of the number of files and folders in -// the root directory of a volume. For HFS volumes, this -// is maintained in the VCB (and MDB). For HFS Plus volumes, -// we get the valence of the root directory from its catalog -// record. -//_______________________________________________________________________ -UInt16 CountRootFiles(ExtendedVCB *vcb) -{ - OSErr err; - CatalogNodeData catNodeData; - UInt32 hint; - UInt16 rootCount; - -// if (vcb->vcbSigWord == kHFSSigWord || vcb->vcbFSID != 0) { -// return vcb->vcbNmFls; -// } - - // Here, it's an HFS Plus volume, so get the valence from the root - // directory's catalog record. - - rootCount = 0; - - INIT_CATALOGDATA(&catNodeData, kCatNameNoCopyName); - - err = GetCatalogNode( vcb, kHFSRootFolderID, nil, kUndefinedStrLen, kNoHint, &catNodeData, &hint ); - if ( err == noErr ) { - if (catNodeData.cnd_valence < 65536) - rootCount = catNodeData.cnd_valence; - else - rootCount = 65535; // if the value is too large, pin it - } - CLEAN_CATALOGDATA(&catNodeData); - - return rootCount; -} - - - //_______________________________________________________________________ // // Routine: FlushVolumeControlBlock diff --git a/bsd/hfs/hfscommon/headers/FileMgrInternal.h b/bsd/hfs/hfscommon/headers/FileMgrInternal.h index 24c46bc56..370dca4e9 100644 --- a/bsd/hfs/hfscommon/headers/FileMgrInternal.h +++ b/bsd/hfs/hfscommon/headers/FileMgrInternal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,136 +26,7 @@ Version: HFS Plus 1.0 - Copyright: © 1996-1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: Don Brady - - Other Contacts: Mark Day, Deric horn, Jim Luther - - Technology: File Systems - - Writers: - - (JL) Jim Luther - (msd) Mark Day - (djb) Don Brady - (DSH) Deric Horn - - Change History (most recent first): - <MOSXS> 9/12/99 ser Removed FCBs. - <MOSX> 9/9/99 pwd Fixed some VCB fields to be unsigned instead of signed to align - the definitions with the MDB/volume header and actual use [#2355889]. - <MOSXS> 9/3/99 ser Added kUndefinedStrLen. - <MOSXS> 6/3/99 djb Removed unused/legacy vcb fields from ExtendedVCB. - <MOSXS> 11/20/98 djb Add support for UTF-8 names. - <MOSXS> 8/31/98 djb Added boolean flag to GetTimeLocal prototype. - <MOSXS> 6/30/98 djb Add NodesAreContiguous prototype (for radar #2249539). - <MOSXS> 6/22/98 djb Add ERR_BASE to error codes to make them negative (for MacOS X only). - Replace DeallocFile prototype with DeleteFile prototype. - <MOSXS> 6/5/98 djb Added CreateFileIDRef prototype; - <MOSXS> 6/3/98 djb Add MoveRenameCatalogNode prototype (replaces seperate Move and Rename). - <MOSXS> 4/17/98 djb Add VCB locking. - <MOSXS> 4/6/98 djb Removed CreateVolumeCatalogCache and DisposeVolumeCatalogCache (obsolete). - <MOSXS> 4/2/98 djb UpdateCatalogNode now takes parID and name as input. - <MOSXS> 3/31/98 djb Sync up with final HFSVolumes.h header file. - <MOSXS> 3/17/98 djb Fixed CreateCatalogNode interface to take kCatalogFolderNode and - kCatalogFileNode as type input. - - <CS30> 1/29/98 DSH Added TrashVolumeDiskCache prototype for TrashAllFSCaches API - support. - <CS29> 12/10/97 DSH 2201501, Overload the NodeData valence field for over 2 Gig file - support. - <CS28> 11/18/97 DSH Conditionalize ou BlockCameFromDisk() macro for DFA - <CS27> 11/16/97 djb LockMappingTable is now defined in UnicodeConverterPriv.i. - <CS26> 11/13/97 djb Move CatalogIterator struct to CatalogPrivate.h. Include - UnicodeConverter.i instead of Unicode.i. - <CS25> 11/3/97 JL #2001483 - changed UnMountVolume's prototype. - <24> 10/31/97 DSH Added consistencyStatus parameter to MountCheck. - <CS23> 10/21/97 DSH Interfacer tweak - <CS22> 10/21/97 DSH Conditionalize LMGetFCBTable, LMGetFSVars for DFA to call - through DFAs LowMem accessors. - <CS21> 10/20/97 msd Add a bytesMaximum parameter to BlockAllocate; removed fcb - parameter. - <CS20> 10/19/97 msd Bug 1684586. Remove the modifyDate field from CatalogNodeDate. - GetCatInfo and SetCatInfo use only contentModDate. - <CS19> 10/16/97 djb Add LMGetFSVars and LMGetFCBTable macros, add gBlockCacheDirty - to FSVars, simplified HFS Stack swapping macros. - <CS18> 10/13/97 DSH Added InitBTreeHeader prototype - <CS17> 10/13/97 djb Add volumeNameEncodingHint to VCB, add textEncoding to - CatalogNodeData, add gTextEncodingFontName to FSVars. - <CS16> 10/1/97 DSH Added CheckVolumeConsistency() for 1682475. - <CS15> 10/1/97 djb New Catalog iterators and Catalog node cache SPI. - <CS14> 9/17/97 DSH Moved prototype HFSBlocksFromTotalSectors() here for DFA - wrapperless volume support. - <CS13> 9/16/97 msd Add a field to FSVarsRec to store old WriteXParam address. - <CS12> 9/15/97 djb Add gBootPToUTable to FSVars (used to bootstrap Unicode). - <CS11> 9/7/97 djb Add FlushBlockCache prototype. - <CS10> 9/4/97 djb Add cmParentNotFound error code and reportMissingParent bit. - <CS9> 9/4/97 msd Remove unused attributes calls. Rename PropertyCloseVolume to - AttributesCloseVolume. In CatalogNodeData, replace - attributeModDate with modifyDate. Remove macro LatestModDate. - <CS8> 8/22/97 djb Add readFromDisk flag to GetCacheBlock and BlockCameFromDisk - macro. - <CS7> 8/18/97 DSH Override ASM cache accessing routines for DFA to use DFA cache. - <CS6> 7/28/97 msd Add prototypes for CacheReadInPlace, RemountWrappedVolumes. - <CS5> 7/25/97 DSH Added GenericMRUCache Routines - <CS4> 7/22/97 msd In CatalogNodeData, move attributeModDate after backupDate; this - allows SetCatInfo to manipulate the rest of the dates in one - block, the same as in the parameter block. - <CS3> 7/21/97 djb Add more instrumentation globals (CallProfile). Reallign FSVars. - <CS2> 7/18/97 msd Selector for PBCreateAttribute conflicts with PBGetXCatInfo. The - attribute calls now have selectors in the range $65..$69. - <CS1> 7/16/97 DSH first checked in - <CS23> 7/8/97 DSH Added LockMappingTable() until its moved into the Unicode header - files. - <CS22> 7/7/97 DSH Taking out changes made in HFS <45> for greater compatability - with the Tempo installer. - <CS21> 6/27/97 msd Add PBLongRename SPI. Add prototype for - RenameCatalogNodeUnicode. - <CS20> 6/26/97 DSH Conditionalized macro LocalToUTC to not look at FSVars for DFA. - <CS19> 6/25/97 msd Add prototype for HFSCommunicationProc. - <CS18> 6/24/97 DSH Adding runtime flags to deturmine unicode usage and installation - status. - <CS17> 6/24/97 djb Add linkCount to CatalogNodeData. Add LinkCatalogNode prototype. - Move Private Catalog Manager prototypes to CatalogPrivate.h. - <CS16> 6/20/97 msd Add prototype for CopyCatalogNodeData. In CatalogNodeData, - replaced modifyDate with contentModDate and attributeModDate. - Added a LatestModDate macro. - <15> 6/18/97 djb Add mask to ConversionContext. Add encodingsBitmap to VCB (and - reallign some fields). Add gInstalledEncodings to FSVars. - <CS14> 6/17/97 msd The conversions between local time and UTC have the sign of the - offset backwards. - <CS13> 6/13/97 djb Removed PrepareOutputName. Changed parameters for - DeleteCatalogNode, MoveCatalogNode, PrepareInputName. Add - private catalog macros. - <CS12> 6/12/97 msd Export BlockAllocateAny and UpdateVCBFreeBlks. - <CS11> 6/12/97 msd Add a parameter block and prototype for an SPI to create very - large files. - <CS10> 6/9/97 msd Add an offsetToUTC field to FSVarsRec. Add prototypes for - GetTimeUTC and GetTimeLocal; add macros for LocalToUTC and - UTCToLocal. - <CS9> 6/5/97 msd Add MapLogicalToPhysical (internal routine), PBMapFilePosition - for external use. - <CS8> 6/4/97 djb More Unicode converter changes (support for non roman scripts). - <CS7> 6/2/97 msd Add prototype for AdjustEOF. - <CS6> 5/28/97 msd Add prototypes for attributes SPI, both internal routines and PB - calls. Add FindFileNameGlueRec and FindFileName routine. - Prototypes for FindFileControlBlock and AccessBTree disappeared, - so added again. - <CS5> 5/20/97 DSH Including LowMemPriv.a in DFA compiles - <CS4> 5/19/97 djb Add uppLockMappingTable to FSVars. - <CS3> 5/19/97 djb Add CreateVolumeCatalogCache and DisposeVolumeCatalogCache - prototypes. Remove private CatalogDataCache structure. - <CS2> 5/16/97 msd Use fixed-size integers for GetBlock_glue and RelBlock_glue so - it will build with compilers other than MPW C and SC. Add - prototype for FillHFSStack, UnMountVolume, and - MakeVCBsExtendedVCBs from VolumeRequests.c. Add prototypes for - CreateEmbeddedVolume and InitUnicodeConverter. - <CS1> 5/9/97 djb first checked in - <CS2> 5/7/97 djb Add summary trace data. Shrink FSVars.later to 4 longs. - <CS1> 4/28/97 djb first checked in + Copyright: © 1996-2001 by Apple Computer, Inc., all rights reserved. */ #ifndef __FILEMGRINTERNAL__ @@ -232,36 +103,7 @@ enum { /* internal flags*/ - enum { - /* File System busy flag:*/ - /* Bit zero of FSBusy (lomem $360) is true when the file system is running.*/ - /* The word at $360 is cleared when the file system is exited. The*/ - /* bits defined here are for additional flags in the FSBusy word that are*/ - /* valid only when the file system is running.*/ - fsBusyBit = 0, /* file system is running; other FSBusy bits are valid*/ - fsSCSIDefer = 1, /* file system is waiting for SCSI transaction to complete*/ - fsIntMaskDefer = 2, /* file system is waiting until the interrupt mask is lowered*/ - /* Flag bits in HFSFlags byte:*/ - hfsReq = 0, /* Set if request is specific to HFS*/ - dirCN = 1, /* Set if a CNode is a directory*/ - reportMissingParent = 4, /* tell Catalog to report missing parents (used by MakeFSSpec)*/ - skipPMSP = 5, /* Set to skip PMSP setup (one-shot)*/ - noPMSP = 6, /* Set to disable PMSP completely (status flag)*/ - hfsContd = 7, /* Set if Async trap is continued*/ - /* fsFlags values*/ - fsNoAllocate = 0, - fsNoAllocateMask = 0x01, /* true when allocating memory is a very bad idea*/ - fsNeedFCBs = 1, - fsNeedFCBsMask = 0x02, /* true when a local FCB couldn't be found */ - fsNoFCBExpansion = 2, - fsNoFCBExpansionMask = 0x04, /* true if no FCB expansion logic is desired*/ - /* ExtendFile option flags*/ - /* extendFileAllBit = 0, |* allocate all requested bytes or none *|*/ - /* extendFileAllMask = 0x0001,*/ - /* */ - /* extendFileContigBit = 1, |* force contiguous allocation *|*/ - /* extendFileContigMask = 0x0002*/ kEFContigBit = 1, /* force contiguous allocation*/ kEFContigMask = 0x02, kEFAllBit = 0, /* allocate all requested bytes or none*/ @@ -271,81 +113,9 @@ enum { }; enum { - kUndefinedStrLen = 0 /* Unknown string length */ -}; - -enum { - HFSStkLen = 1792, /* old stack size (pre HFS Plus)*/ - kFileSystemStackSlop = 16, /* additional temporary space*/ - kFileSystemStackSize = 16384, /* give us more breathing room*/ - kFileSystemVersion = FOUR_CHAR_CODE('2.0A'), /* current file system version*/ - /* 31744 = $7C00, a nice round number close to*/ - /* (32767*1000)/1024, which is about the largest */ - /* free space unsuspecting, decimal-K minded apps*/ - /* might be expected to handle.*/ - /* AlBlkLim*/ - kMaxHFSAllocationBlocks = 31744, - WDRfnMin = -32767, /* lowest assigned WD RefNum*/ - WDRfnMax = -4096, /* largest possible WDrefnum*/ - kFirstFileRefnum = 2, /* smallest FCB refnum*/ - kNoHint = 0 -}; - - -/* Internal LowMem pointers*/ - -/*€€ The following should really be in LowMemPriv.i*/ - -enum { - FSCallAsync = 0x0342, /* ONE BYTE FREE*/ - NoEject = 0x034B, /* used by Eject and Offline*/ - CacheFlag = 0x0377, - SysBMCPtr = 0x0378, /* System-wide bitmap cache pointer*/ - SysCtlCPtr = 0x0380, /* System-wide control cache pointer*/ - HFSDSErr = 0x0392, /* Final gasp - error that caused IOErr.*/ - LMParamBlock = 0x03A4, /* LMGetParams() just gives us a copy of it*/ - FSVarsPtr = 0x0BB8, /* lomem that points to file system variable block*/ - CacheVars = 0x0394, - HFSStkPtr = 0x036E, /* Temporary location of HFS Stack pointer*/ - FSIOErr = 0x03DE, /* last I/O error (NEXT WORD FREE)*/ - /* file manager vectors not found in LowMemPriv.i*/ - JUpdAltMDB = (0xED) * 4 + 0x0400, /* ($A0ED) $0400 is n/OSTable*/ - JCkExtFS = (0xEE) * 4 + 0x0400, /* ($A0EE) $0400 is n/OSTable*/ - JBMChk = (0xF0) * 4 + 0x0400, /* ($A0F0) $0400 is n/OSTable*/ - JTstMod = (0xF1) * 4 + 0x0400, /* ($A0F1) $0400 is n/OSTable*/ - JLocCRec = (0xF2) * 4 + 0x0400, /* ($A0F2) $0400 is n/OSTable*/ - JTreeSearch = (0xF3) * 4 + 0x0400, /* ($A0F3) $0400 is n/OSTable*/ - JMapFBlock = (0xF4) * 4 + 0x0400, /* ($A0F4) $0400 is n/OSTable*/ - JXFSearch = (0xF5) * 4 + 0x0400, /* ($A0F5) $0400 is n/OSTable*/ - JReadBM = (0xF6) * 4 + 0x0400 /* ($A0F6) $0400 is n/OSTable*/ -}; - - -/* Poor Man's Search Path*/ - -struct SearchPathHeader { - Ptr PMSPHook; /* Hook for PMSP modification*/ - short PMSPIndx; /* Index to PMSP index from start of PMSP*/ -}; -typedef struct SearchPathHeader SearchPathHeader; - -struct SearchPathEntry { - short spVRefNum; /* VRefNum in PMSP entry*/ - UInt32 spDirID; /* Directory ID in PMSP entry*/ -}; -typedef struct SearchPathEntry SearchPathEntry; - - -enum { - kPoorMansSearchIndex = -2, - MaxDVCnt = 8, /* Leave room for 8 default VRefNums*/ - PMSPSize = MaxDVCnt * sizeof(SearchPathEntry) + sizeof(SearchPathHeader) + 2 -}; - - + kUndefinedStrLen = 0, /* Unknown string length */ + kNoHint = 0, -enum { - fsWDCBExtendCount = 8, /* # of WDCB's to add when we run out*/ /* FileIDs variables*/ kNumExtentsToCache = 4 /* just guessing for ExchangeFiles*/ }; @@ -415,20 +185,6 @@ enum { }; -/* Catalog Node Data - universal data returned from the Catalog Manager*/ - - -enum { - xFFFilAttrLockMask = 0x70 -}; - -/* valence is overloaded for files and used as additional flags. 2201501*/ - -enum { - kLargeDataForkMask = 0x00000001, - kLargeRsrcForkMask = 0x00000002 -}; - /* Universal catalog name*/ union CatalogName { @@ -437,44 +193,6 @@ union CatalogName { }; typedef union CatalogName CatalogName; -/* Unicode Conversion*/ - - -enum { - kMacBaseEncodingCount = 50, - kTextEncodingUndefined = 0x00007FFF -}; - -struct ConversionContext { - TextToUnicodeInfo toUnicode; - UnicodeToTextInfo fromUnicode; -}; -typedef struct ConversionContext ConversionContext; - -struct CallProfile { - UInt16 refCount; - UInt16 errCount; - UInt32 callCount; - UInt32 minTime; - UInt32 maxTime; - UInt64 totalTime; - UInt64 startBase; /* in nanoseconds*/ -}; -typedef struct CallProfile CallProfile; - - -struct FSVarsRec { - UInt32 gDefaultBaseEncoding; - ItemCount gInstalledEncodings; - ConversionContext gConversionContext[50]; - Ptr gBootPToUTable; /* used by boot code to find Extensions folder*/ - StringPtr gTextEncodingFontName; /* points to font name (only used when no HFS Plus volumes have been mounted)*/ - Boolean gUseDynamicUnicodeConverters; - Boolean gIsUnicodeInstalled; -}; -typedef struct FSVarsRec FSVarsRec; - - /* * MacOS accessor routines @@ -483,9 +201,6 @@ typedef struct FSVarsRec FSVarsRec; #define GetFileRefNumFromFCB(filePtr) ((filePtr)->h_vp) -EXTERN_API_C( Boolean ) -BlockCameFromDisk (void); - /* The following macro marks a VCB as dirty by setting the upper 8 bits of the flags*/ EXTERN_API_C( void ) MarkVCBDirty (ExtendedVCB *vcb); @@ -522,11 +237,7 @@ EXTERN_API_C( void ) ExitOnError (OSErr result); #define ExitOnError( result ) if ( ( result ) != noErr ) goto ErrorExit; else ; -/* Return the low 16 bits of a 32 bit value, pinned if too large*/ -EXTERN_API_C( UInt16 ) -LongToShort (UInt32 l); -#define LongToShort( l ) l <= (UInt32)0x0000FFFF ? ((UInt16) l) : ((UInt16) 0xFFFF) /* Catalog Manager Routines (IPI)*/ @@ -537,7 +248,8 @@ CreateCatalogNode (ExtendedVCB * volume, ConstUTF8Param name, UInt32 nodeType, HFSCatalogNodeID * catalogNodeID, - UInt32 * catalogHint); + UInt32 * catalogHint, + UInt32 teHint); EXTERN_API_C( OSErr ) DeleteCatalogNode (ExtendedVCB * volume, @@ -569,7 +281,8 @@ MoveRenameCatalogNode (ExtendedVCB * volume, UInt32 srcHint, HFSCatalogNodeID dstParentID, ConstUTF8Param dstName, - UInt32 * newHint); + UInt32 * newHint, + UInt32 teHint); EXTERN_API_C( OSErr ) UpdateCatalogNode (ExtendedVCB * volume, @@ -675,44 +388,6 @@ ReplaceBTreeRecord (FileReference refNum, UInt16 dataSize, UInt32 * newHint); -/* From HFSVolumesInit.c*/ -EXTERN_API_C( void ) -InitBTreeHeader (UInt32 fileSize, - UInt32 clumpSize, - UInt16 nodeSize, - UInt16 recordCount, - UInt16 keySize, - UInt32 attributes, - UInt32 * mapNodes, - void * buffer); - -/* Prototypes for big block cache*/ - -EXTERN_API_C( OSErr ) -InitializeBlockCache (UInt32 blockSize, - UInt32 blockCount); - -EXTERN_API_C( OSErr ) -FlushBlockCache (void); - -EXTERN_API_C( OSErr ) -GetCacheBlock (FileReference fileRefNum, - UInt32 blockNumber, - UInt32 blockSize, - UInt16 options, - LogicalAddress * buffer, - Boolean * readFromDisk); - -EXTERN_API_C( OSErr ) -ReleaseCacheBlock (LogicalAddress buffer, - UInt16 options); - -EXTERN_API_C( OSErr ) -MarkCacheBlock (LogicalAddress buffer); - -EXTERN_API_C( OSErr ) -TrashCacheBlocks (FileReference fileRefNum); - /* Prototypes for C->Asm glue*/ EXTERN_API_C( OSErr ) GetBlock_glue (UInt16 flags, @@ -725,17 +400,6 @@ EXTERN_API_C( OSErr ) RelBlock_glue (Ptr nodeBuffer, UInt16 flags); -EXTERN_API_C( void ) -MarkBlock_glue (Ptr nodeBuffer); - -EXTERN_API_C( OSErr ) -C_FlushCache (ExtendedVCB * vcb, - UInt32 flags, - FileReference refNum); - - -EXTERN_API_C( void ) TrashVolumeDiskCache(ExtendedVCB * vcb); - /* Prototypes for exported routines in VolumeAllocation.c*/ EXTERN_API_C( OSErr ) BlockAllocate (ExtendedVCB * vcb, @@ -751,30 +415,10 @@ BlockDeallocate (ExtendedVCB * vcb, UInt32 firstBlock, UInt32 numBlocks); -EXTERN_API_C( OSErr ) -UpdateFreeCount (ExtendedVCB * vcb); - - -EXTERN_API_C( OSErr ) -AllocateFreeSpace (ExtendedVCB * vcb, - UInt32 * startBlock, - UInt32 * actualBlocks); - EXTERN_API_C( UInt32 ) FileBytesToBlocks (SInt64 numerator, UInt32 denominator); -EXTERN_API_C( OSErr ) -BlockAllocateAny (ExtendedVCB * vcb, - UInt32 startingBlock, - UInt32 endingBlock, - UInt32 maxBlocks, - UInt32 * actualStartBlock, - UInt32 * actualNumBlocks); - -EXTERN_API_C( void ) -UpdateVCBFreeBlks (ExtendedVCB * vcb); - /* File Extent Mapping routines*/ EXTERN_API_C( OSErr ) FlushExtentFile (ExtendedVCB * vcb); @@ -803,6 +447,7 @@ EXTERN_API_C( OSErr ) ExtendFileC (ExtendedVCB * vcb, FCB * fcb, SInt64 bytesToAdd, + UInt32 blockHint, UInt32 flags, SInt64 * actualBytesAdded); @@ -820,8 +465,6 @@ NodesAreContiguous (ExtendedVCB * vcb, FCB * fcb, UInt32 nodeSize); #endif -EXTERN_API_C( void ) -AdjustEOF (FCB * sourceFCB); /* Utility routines*/ @@ -829,14 +472,6 @@ EXTERN_API_C( void ) ClearMemory (void * start, UInt32 length); -EXTERN_API_C( Boolean ) -UnicodeBinaryCompare (ConstHFSUniStr255Param ustr1, - ConstHFSUniStr255Param ustr2); - -EXTERN_API_C( Boolean ) -PascalBinaryCompare (ConstStr31Param pstr1, - ConstStr31Param pstr2); - EXTERN_API_C( OSErr ) VolumeWritable (ExtendedVCB * vcb); @@ -860,36 +495,9 @@ UTCToLocal (UInt32 utcTime); EXTERN_API_C( OSErr ) FlushVolumeControlBlock (ExtendedVCB * vcb); -EXTERN_API_C( OSErr ) -CheckVolumeOffLine (ExtendedVCB * vcb); - EXTERN_API_C( OSErr ) ValidVolumeHeader (HFSPlusVolumeHeader * volumeHeader); -EXTERN_API_C( void ) -FillHFSStack (void); - - -EXTERN_API_C( OSErr ) -AccessBTree (ExtendedVCB * vcb, - FileReference refNum, - UInt32 fileID, - UInt32 fileClumpSize, - void * CompareRoutine); - -EXTERN_API_C( void ) -RemountWrappedVolumes (void); - -EXTERN_API_C( OSErr ) -CheckVolumeConsistency (ExtendedVCB * vcb); - -EXTERN_API_C( void ) -HFSBlocksFromTotalSectors (UInt32 totalSectors, - UInt32 * blockSize, - UInt16 * blockCount); - - - #if PRAGMA_STRUCT_ALIGN #pragma options align=reset diff --git a/bsd/hfs/rangelist.c b/bsd/hfs/rangelist.c new file mode 100644 index 000000000..cc062004f --- /dev/null +++ b/bsd/hfs/rangelist.c @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include <sys/param.h> +#include <mach/boolean.h> +#include <sys/time.h> +#include <sys/malloc.h> + +#include "rangelist.h" + +static enum rl_overlaptype rl_scan_from(struct rl_head *rangelist, off_t start, off_t end, struct rl_entry **overlap, struct rl_entry *range); +static void rl_collapse_forwards(struct rl_head *rangelist, struct rl_entry *range); +static void rl_collapse_backwards(struct rl_head *rangelist, struct rl_entry *range); +static void rl_collapse_neighbors(struct rl_head *rangelist, struct rl_entry *range); + + +#ifdef RL_DIAGNOSTIC +static void +rl_verify(struct rl_head *rangelist) { + struct rl_entry *entry; + off_t limit = 0; + + if (CIRCLEQ_EMPTY(rangelist)) return; + entry = CIRCLEQ_FIRST(rangelist); + while (1) { + if (CIRCLEQ_NEXT(entry, rl_link) == entry) panic("rl_verify: circular rangelist?!"); + if ((limit > 0) && (entry->rl_start <= limit)) panic("rl_verify: bad entry start?!"); + if (entry->rl_end < entry->rl_start) panic("rl_verify: bad entry end?!"); + limit = entry->rl_end; + if (entry == CIRCLEQ_LAST(rangelist)) return; + entry = CIRCLEQ_NEXT(entry, rl_link); + }; +} +#endif + + + +/* + * Initialize a range list head + */ +void +rl_init(struct rl_head *rangelist) +{ + CIRCLEQ_INIT(rangelist); +} + + + +/* + * Add a range to the list + */ +void +rl_add(off_t start, off_t end, struct rl_head *rangelist) +{ + struct rl_entry *range; + struct rl_entry *overlap; + enum rl_overlaptype ovcase; + +#ifdef RL_DIAGNOSTIC + if (end < start) panic("rl_add: end < start?!"); +#endif + + ovcase = rl_scan(rangelist, start, end, &overlap); + + /* + * Six cases: + * 0) no overlap + * 1) overlap == range + * 2) overlap contains range + * 3) range contains overlap + * 4) overlap starts before range + * 5) overlap ends after range + */ + switch (ovcase) { + case RL_NOOVERLAP: /* 0: no overlap */ + /* + * If the list was empty 'prev' is undisturbed and 'overlap' == NULL; + * if the search hit a non-overlapping entry PAST the start of the + * new range, 'prev' points to ITS predecessor, and 'overlap' points + * to that entry: + */ + MALLOC(range, struct rl_entry *, sizeof(*range), M_TEMP, M_WAITOK); + range->rl_start = start; + range->rl_end = end; + + /* Link in the new range: */ + if (overlap) { + CIRCLEQ_INSERT_AFTER(rangelist, overlap, range, rl_link); + } else { + CIRCLEQ_INSERT_HEAD(rangelist, range, rl_link); + } + + /* Check to see if any ranges can be combined (possibly including the immediately + preceding range entry) + */ + rl_collapse_neighbors(rangelist, range); + break; + + case RL_MATCHINGOVERLAP: /* 1: overlap == range */ + case RL_OVERLAPCONTAINSRANGE: /* 2: overlap contains range */ + range = overlap; /* for debug output below */ + break; + + case RL_OVERLAPISCONTAINED: /* 3: range contains overlap */ + /* + * Replace the overlap with the new, larger range: + */ + overlap->rl_start = start; + overlap->rl_end = end; + rl_collapse_neighbors(rangelist, overlap); + range = overlap; /* for debug output below */ + break; + + case RL_OVERLAPSTARTSBEFORE: /* 4: overlap starts before range */ + /* + * Expand the overlap area to cover the new range: + */ + overlap->rl_end = end; + rl_collapse_forwards(rangelist, overlap); + range = overlap; /* for debug output below */ + break; + + case RL_OVERLAPENDSAFTER: /* 5: overlap ends after range */ + /* + * Expand the overlap area to cover the new range: + */ + overlap->rl_start = start; + rl_collapse_backwards(rangelist, overlap); + range = overlap; /* for debug output below */ + break; + } + +#ifdef RL_DIAGNOSTIC + rl_verify(rangelist); +#endif +} + + + +/* + * Remove a range from a range list. + * + * Generally, find the range (or an overlap to that range) + * and remove it (or shrink it), then wakeup anyone we can. + */ +void +rl_remove(off_t start, off_t end, struct rl_head *rangelist) +{ + struct rl_entry *range, *next_range, *overlap, *splitrange; + int ovcase, moretotest; + +#ifdef RL_DIAGNOSTIC + if (end < start) panic("rl_remove: end < start?!"); +#endif + + if (CIRCLEQ_EMPTY(rangelist)) { + return; + }; + + range = CIRCLEQ_FIRST(rangelist); + while ((ovcase = rl_scan_from(rangelist, start, end, &overlap, range))) { + switch (ovcase) { + + case RL_MATCHINGOVERLAP: /* 1: overlap == range */ + CIRCLEQ_REMOVE(rangelist, overlap, rl_link); + FREE(overlap, M_TEMP); + break; + + case RL_OVERLAPCONTAINSRANGE: /* 2: overlap contains range: split it */ + if (overlap->rl_start == start) { + overlap->rl_start = end + 1; + break; + }; + + if (overlap->rl_end == end) { + overlap->rl_end = start - 1; + break; + }; + + /* + * Make a new range consisting of the last part of the encompassing range + */ + MALLOC(splitrange, struct rl_entry *, sizeof *splitrange, M_TEMP, M_WAITOK); + splitrange->rl_start = end + 1; + splitrange->rl_end = overlap->rl_end; + overlap->rl_end = start - 1; + + /* + * Now link the new entry into the range list after the range from which it was split: + */ + CIRCLEQ_INSERT_AFTER(rangelist, overlap, splitrange, rl_link); + break; + + case RL_OVERLAPISCONTAINED: /* 3: range contains overlap */ + moretotest = (overlap != CIRCLEQ_LAST(rangelist)); +#ifdef RL_DIAGNOSTIC + if (CIRCLEQ_NEXT(overlap, rl_link) == overlap) panic("rl_remove: circular range list?!"); +#endif + next_range = CIRCLEQ_NEXT(overlap, rl_link); /* Check before discarding overlap entry */ + CIRCLEQ_REMOVE(rangelist, overlap, rl_link); + FREE(overlap, M_TEMP); + if (moretotest) { + range = next_range; + continue; + }; + break; + + case RL_OVERLAPSTARTSBEFORE: /* 4: overlap starts before range */ + moretotest = (overlap != CIRCLEQ_LAST(rangelist)); + overlap->rl_end = start - 1; + if (moretotest) { +#ifdef RL_DIAGNOSTIC + if (CIRCLEQ_NEXT(overlap, rl_link) == overlap) panic("rl_remove: circular range list?!"); +#endif + range = CIRCLEQ_NEXT(overlap, rl_link); + continue; + }; + break; + + case RL_OVERLAPENDSAFTER: /* 5: overlap ends after range */ + overlap->rl_start = (end == RL_INFINITY ? RL_INFINITY : end + 1); + break; + } + break; + } + +#ifdef RL_DIAGNOSTIC + rl_verify(rangelist); +#endif +} + + + +/* + * Scan a range list for an entry in a specified range (if any): + * + * NOTE: this returns only the FIRST overlapping range. + * There may be more than one. + */ + +enum rl_overlaptype +rl_scan(struct rl_head *rangelist, + off_t start, + off_t end, + struct rl_entry **overlap) { + + if (CIRCLEQ_EMPTY(rangelist)) { + *overlap = NULL; + return RL_NOOVERLAP; + }; + + return rl_scan_from(rangelist, start, end, overlap, CIRCLEQ_FIRST(rangelist)); +} + + + +/* + * Walk the list of ranges for an entry to + * find an overlapping range (if any). + * + * NOTE: this returns only the FIRST overlapping range. + * There may be more than one. + */ +static enum rl_overlaptype +rl_scan_from(struct rl_head *rangelist, + off_t start, + off_t end, + struct rl_entry **overlap, + struct rl_entry *range) +{ + if (CIRCLEQ_EMPTY(rangelist)) { + *overlap = NULL; + return RL_NOOVERLAP; + }; + +#ifdef RL_DIAGNOSTIC + rl_verify(rangelist); +#endif + + *overlap = range; + + while (1) { + /* + * OK, check for overlap + * + * Six cases: + * 0) no overlap (RL_NOOVERLAP) + * 1) overlap == range (RL_MATCHINGOVERLAP) + * 2) overlap contains range (RL_OVERLAPCONTAINSRANGE) + * 3) range contains overlap (RL_OVERLAPISCONTAINED) + * 4) overlap starts before range (RL_OVERLAPSTARTSBEFORE) + * 5) overlap ends after range (RL_OVERLAPENDSAFTER) + */ + if (((range->rl_end != RL_INFINITY) && (start > range->rl_end)) || + ((end != RL_INFINITY) && (range->rl_start > end))) { + /* Case 0 (RL_NOOVERLAP), at least with the current entry: */ + if ((end != RL_INFINITY) && (range->rl_start > end)) { + return RL_NOOVERLAP; + }; + + /* Check the other entries in the list: */ + if (range == CIRCLEQ_LAST(rangelist)) { + return RL_NOOVERLAP; + }; +#ifdef RL_DIAGNOSTIC + if (CIRCLEQ_NEXT(range, rl_link) == range) panic("rl_scan_from: circular range list?!"); +#endif + *overlap = range = CIRCLEQ_NEXT(range, rl_link); + continue; + } + + if ((range->rl_start == start) && (range->rl_end == end)) { + /* Case 1 (RL_MATCHINGOVERLAP) */ + return RL_MATCHINGOVERLAP; + } + + if ((range->rl_start <= start) && + (end != RL_INFINITY) && + ((range->rl_end >= end) || (range->rl_end == RL_INFINITY))) { + /* Case 2 (RL_OVERLAPCONTAINSRANGE) */ + return RL_OVERLAPCONTAINSRANGE; + } + + if ((start <= range->rl_start) && + ((end == RL_INFINITY) || + ((range->rl_end != RL_INFINITY) && (end >= range->rl_end)))) { + /* Case 3 (RL_OVERLAPISCONTAINED) */ + return RL_OVERLAPISCONTAINED; + } + + if ((range->rl_start < start) && + ((range->rl_end >= start) || (range->rl_end == RL_INFINITY))) { + /* Case 4 (RL_OVERLAPSTARTSBEFORE) */ + return RL_OVERLAPSTARTSBEFORE; + } + + if ((range->rl_start > start) && + (end != RL_INFINITY) && + ((range->rl_end > end) || (range->rl_end == RL_INFINITY))) { + /* Case 5 (RL_OVERLAPENDSAFTER) */ + return RL_OVERLAPENDSAFTER; + } + + /* Control should never reach here... */ +#ifdef RL_DIAGNOSTIC + panic("rl_scan_from: unhandled overlap condition?!"); +#endif + } + + return RL_NOOVERLAP; +} + + +static void +rl_collapse_forwards(struct rl_head *rangelist, struct rl_entry *range) { + struct rl_entry *next_range; + + while (1) { + if (range == CIRCLEQ_LAST(rangelist)) return; + +#ifdef RL_DIAGNOSTIC + if (CIRCLEQ_NEXT(range, rl_link) == range) panic("rl_collapse_forwards: circular range list?!"); +#endif + next_range = CIRCLEQ_NEXT(range, rl_link); + if ((range->rl_end != RL_INFINITY) && (range->rl_end < next_range->rl_start - 1)) return; + + /* Expand this range to include the next range: */ + range->rl_end = next_range->rl_end; + + /* Remove the now covered range from the list: */ + CIRCLEQ_REMOVE(rangelist, next_range, rl_link); + FREE(next_range, M_TEMP); + +#ifdef RL_DIAGNOSTIC + rl_verify(rangelist); +#endif + }; +} + + + +static void +rl_collapse_backwards(struct rl_head *rangelist, struct rl_entry *range) { + struct rl_entry *prev_range; + + while (1) { + if (range == CIRCLEQ_FIRST(rangelist)) return; + +#ifdef RL_DIAGNOSTIC + if (CIRCLEQ_PREV(range, rl_link) == range) panic("rl_collapse_backwards: circular range list?!"); +#endif + prev_range = CIRCLEQ_PREV(range, rl_link); + if (prev_range->rl_end < range->rl_start - 1) { +#ifdef RL_DIAGNOSTIC + rl_verify(rangelist); +#endif + return; + }; + + /* Expand this range to include the previous range: */ + range->rl_start = prev_range->rl_start; + + /* Remove the now covered range from the list: */ + CIRCLEQ_REMOVE(rangelist, prev_range, rl_link); + FREE(prev_range, M_TEMP); + }; +} + + + +static void +rl_collapse_neighbors(struct rl_head *rangelist, struct rl_entry *range) +{ + rl_collapse_forwards(rangelist, range); + rl_collapse_backwards(rangelist, range); +} diff --git a/iokit/IOKit/graphics/IOAccelTypes.h b/bsd/hfs/rangelist.h similarity index 51% rename from iokit/IOKit/graphics/IOAccelTypes.h rename to bsd/hfs/rangelist.h index 19a20d408..f7c31ecf1 100644 --- a/iokit/IOKit/graphics/IOAccelTypes.h +++ b/bsd/hfs/rangelist.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,49 +20,34 @@ * @APPLE_LICENSE_HEADER_END@ */ -#ifndef _IOACCEL_TYPES_H -#define _IOACCEL_TYPES_H +#include <sys/types.h> +#include <sys/queue.h> -#include <IOKit/IOTypes.h> - -#define IOACCEL_TYPES_REV 3 - -/* Integer rectangle in device coordinates */ -typedef struct -{ - SInt16 x; - SInt16 y; - SInt16 w; - SInt16 h; -} IOAccelBounds; - -/* Surface information */ - -enum { - kIOAccelVolatileSurface = 0x00000001, - kIOAccelKeycolorSurface = 0x00000002 +enum rl_overlaptype { + RL_NOOVERLAP = 0, /* 0 */ + RL_MATCHINGOVERLAP, /* 1 */ + RL_OVERLAPCONTAINSRANGE, /* 2 */ + RL_OVERLAPISCONTAINED, /* 3 */ + RL_OVERLAPSTARTSBEFORE, /* 4 */ + RL_OVERLAPENDSAFTER /* 5 */ }; -typedef struct -{ - vm_address_t address[4]; - UInt32 rowBytes; - UInt32 width; - UInt32 height; - UInt32 pixelFormat; - IOOptionBits flags; - IOFixed colorTemperature[4]; - UInt32 typeDependent[4]; -} IOAccelSurfaceInformation; +#define RL_INFINITY ((off_t)-1) -typedef struct -{ - long x, y, w, h; - void *client_addr; - unsigned long client_row_bytes; -} IOAccelSurfaceReadData; +CIRCLEQ_HEAD(rl_head, rl_entry); +struct rl_entry { + CIRCLEQ_ENTRY(rl_entry) rl_link; + off_t rl_start; + off_t rl_end; +}; - -#endif /* _IOACCEL_TYPES_H */ - +__BEGIN_DECLS +void rl_init(struct rl_head *rangelist); +void rl_add(off_t start, off_t end, struct rl_head *rangelist); +void rl_remove(off_t start, off_t end, struct rl_head *rangelist); +enum rl_overlaptype rl_scan(struct rl_head *rangelist, + off_t start, + off_t end, + struct rl_entry **overlap); +__END_DECLS diff --git a/bsd/i386/param.h b/bsd/i386/param.h index 80626b0ff..32ead8a3e 100644 --- a/bsd/i386/param.h +++ b/bsd/i386/param.h @@ -95,7 +95,7 @@ * clusters (MAPPED_MBUFS), MCLBYTES must also be an integral multiple * of the hardware page size. */ -#define MSIZE 128 /* size of an mbuf */ +#define MSIZE 256 /* size of an mbuf */ #define MCLBYTES 2048 /* large enough for ether MTU */ #define MCLSHIFT 11 #define MCLOFSET (MCLBYTES - 1) diff --git a/bsd/i386/types.h b/bsd/i386/types.h index ff7bc23b4..10a5646ad 100644 --- a/bsd/i386/types.h +++ b/bsd/i386/types.h @@ -77,7 +77,7 @@ typedef unsigned long long u_int64_t; typedef int32_t register_t; -typedef int *intptr_t; -typedef unsigned long *uintptr_t; +typedef long int intptr_t; +typedef unsigned long int uintptr_t; #endif /* __ASSEMBLER__ */ #endif /* _MACHTYPES_H_ */ diff --git a/bsd/isofs/cd9660/cd9660_lookup.c b/bsd/isofs/cd9660/cd9660_lookup.c index 1cab9a13e..1c20c4b21 100644 --- a/bsd/isofs/cd9660/cd9660_lookup.c +++ b/bsd/isofs/cd9660/cd9660_lookup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -257,7 +257,7 @@ cd9660_lookup(ap) */ if ((imp->iso_ftype == ISO_FTYPE_JOLIET) && !((len == 1 && *name == '.') || (flags & ISDOTDOT))) { - int flags = 0; + int flags = UTF_PRECOMPOSED; if (BYTE_ORDER != BIG_ENDIAN) flags |= UTF_REVERSE_ENDIAN; diff --git a/bsd/isofs/cd9660/cd9660_util.c b/bsd/isofs/cd9660/cd9660_util.c index 689c091bc..ace849705 100644 --- a/bsd/isofs/cd9660/cd9660_util.c +++ b/bsd/isofs/cd9660/cd9660_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -293,7 +293,7 @@ ucsfntrans(infn, infnlen, outfn, outfnlen, dir) fnidx = infnlen/2; } - flags = UTF_NO_NULL_TERM; + flags = UTF_NO_NULL_TERM | UTF_DECOMPOSED; if (BYTE_ORDER != BIG_ENDIAN) flags |= UTF_REVERSE_ENDIAN; @@ -780,6 +780,8 @@ packcommonattr (struct attrlist *alist, struct finder_info finfo = {0}; finfo.fdFlags = ip->i_FinderFlags; + finfo.fdLocation.v = -1; + finfo.fdLocation.h = -1; if (ITOV(ip)->v_type == VREG) { finfo.fdType = ip->i_FileType; finfo.fdCreator = ip->i_Creator; diff --git a/bsd/isofs/cd9660/cd9660_vfsops.c b/bsd/isofs/cd9660/cd9660_vfsops.c index 68d602bcc..ea7221a15 100644 --- a/bsd/isofs/cd9660/cd9660_vfsops.c +++ b/bsd/isofs/cd9660/cd9660_vfsops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -77,6 +77,8 @@ #include <sys/malloc.h> #include <sys/stat.h> #include <sys/ubc.h> +#include <sys/utfconv.h> +#include <architecture/byte_order.h> #include <isofs/cd9660/iso.h> #include <isofs/cd9660/iso_rrip.h> @@ -147,6 +149,11 @@ cd9660_mountroot() MALLOC_ZONE(mp, struct mount *, sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + mp->mnt_op = &cd9660_vfsops; mp->mnt_flag = MNT_RDONLY; LIST_INIT(&mp->mnt_vnodelist); @@ -423,8 +430,11 @@ iso_mountfs(devvp, mp, p, argp) myPtr--; } } - /* YYY need to use secondary volume descriptor name for kanji disks */ - bcopy(pri->volume_id, isomp->volume_id, sizeof(isomp->volume_id)); + + if (pri->volume_id[0] == 0) + strcpy(isomp->volume_id, ISO_DFLT_VOLUME_ID); + else + bcopy(pri->volume_id, isomp->volume_id, sizeof(isomp->volume_id)); cd9660_tstamp_conv17(pri->creation_date, &isomp->creation_date); cd9660_tstamp_conv17(pri->modification_date, &isomp->modification_date); @@ -501,6 +511,33 @@ skipRRIP: /* Decide whether to use the Joliet descriptor */ if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level != 0) { + char vol_id[32]; + int i, convflags; + size_t convbytes; + u_int16_t *uchp; + + /* + * On Joliet CDs use the UCS-2 volume identifier. + * + * This name can have up to 15 UCS-2 chars and is + * terminated with 0x0000 or padded with 0x0020. + */ + convflags = UTF_DECOMPOSED; + if (BYTE_ORDER != BIG_ENDIAN) + convflags |= UTF_REVERSE_ENDIAN; + for (i = 0, uchp = (u_int16_t *)sup->volume_id; i < 15 && uchp[i]; ++i); + if ((utf8_encodestr((u_int16_t *)sup->volume_id, (i * 2), vol_id, + &convbytes, sizeof(vol_id), 0, convflags) == 0) + && convbytes && (vol_id[0] != ' ')) { + char * strp; + + /* Remove trailing spaces */ + strp = vol_id + convbytes - 1; + while (strp > vol_id && *strp == ' ') + *strp-- = '\0'; + bcopy(vol_id, isomp->volume_id, convbytes); + } + rootp = (struct iso_directory_record *) sup->root_directory_record; bcopy (rootp, isomp->root, sizeof isomp->root); @@ -1078,8 +1115,8 @@ DRGetTypeCreatorAndFlags( struct iso_mnt * theMountPointPtr, char *myPtr; foundStuff = 1; - myType = 0L; - myCreator = 0L; + myType = 0x3f3f3f3f; + myCreator = 0x3f3f3f3f; myFinderFlags = 0; *theFlagsPtr = 0x0000; diff --git a/bsd/isofs/cd9660/cd9660_vnops.c b/bsd/isofs/cd9660/cd9660_vnops.c index c6624b06f..3f199bacc 100644 --- a/bsd/isofs/cd9660/cd9660_vnops.c +++ b/bsd/isofs/cd9660/cd9660_vnops.c @@ -372,6 +372,7 @@ cd9660_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { diff --git a/bsd/isofs/cd9660/iso.h b/bsd/isofs/cd9660/iso.h index 7e6f702c9..55fca26c0 100644 --- a/bsd/isofs/cd9660/iso.h +++ b/bsd/isofs/cd9660/iso.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -92,6 +92,8 @@ struct iso_volume_descriptor { #define UCS_SEPARATOR1 0x002e #define UCS_SEPARATOR2 0x003b +#define ISO_DFLT_VOLUME_ID "ISO_9660_CD" + /* pathconf filename lengths */ #define ISO_NAMEMAX (31+1) #define ISO_JOLIET_NAMEMAX (64*3) @@ -119,7 +121,11 @@ struct finder_info { unsigned long fdType; unsigned long fdCreator; unsigned short fdFlags; - unsigned short fdReserved[3]; + struct { + short v; /* file's location */ + short h; + } fdLocation; + unsigned short fdReserved; }; struct iso_primary_descriptor { diff --git a/bsd/kern/bsd_init.c b/bsd/kern/bsd_init.c index e6e41c402..3042dfd67 100644 --- a/bsd/kern/bsd_init.c +++ b/bsd/kern/bsd_init.c @@ -386,9 +386,8 @@ bsd_init() } /* - * Initialize the calendar by - * reading the BBC, if not already set. - */ + * Initialize the calendar. + */ IOKitResetTime(); ubc_init(); diff --git a/bsd/kern/bsd_stubs.c b/bsd/kern/bsd_stubs.c index 1952e98cc..07966f77d 100644 --- a/bsd/kern/bsd_stubs.c +++ b/bsd/kern/bsd_stubs.c @@ -29,6 +29,7 @@ #include <sys/systm.h> #include <sys/conf.h> #include <sys/buf.h> /* for SET */ +#include <sys/user.h> /* Just to satisfy pstat command */ int dmmin, dmmax, dmtext; @@ -53,9 +54,25 @@ struct proc * current_proc(void) { /* Never returns a NULL */ - struct proc *p = (struct proc *)get_bsdtask_info(current_task()); + struct uthread * ut; + struct proc *p; + thread_act_t thr_act = current_act(); + + ut = (struct uthread *)get_bsdthread_info(thr_act); + if (ut && (ut->uu_flag & P_VFORK) && ut->uu_proc) { + p = ut->uu_proc; + if ((p->p_flag & P_INVFORK) == 0) + panic("returning child proc not under vfork"); + if (p->p_vforkact != (void *)thr_act) + panic("returning child proc which is not cur_act"); + return(p); + } + + p = (struct proc *)get_bsdtask_info(current_task()); + if (p == NULL) - p = kernproc; + return (kernproc); + return (p); } @@ -221,16 +238,6 @@ cdevsw_remove(int index, struct cdevsw * csw) return(index); } -int -memcmp(s1, s2, n) - register char *s1, *s2; - register n; -{ - while (--n >= 0) - if (*s1++ != *s2++) - return (*--s1 - *--s2); - return (0); -} int issingleuser(void) { diff --git a/bsd/kern/init_sysent.c b/bsd/kern/init_sysent.c index 58cfb48ec..efcdf87c8 100644 --- a/bsd/kern/init_sysent.c +++ b/bsd/kern/init_sysent.c @@ -333,6 +333,8 @@ int sem_post(); int sem_getvalue(); int sem_init(); int sem_destroy(); + +int issetugid(); /* * System call switch table. */ @@ -727,7 +729,7 @@ struct sysent sysent[] = { syss(mlockall,1), /* 324 */ syss(munlockall,1), /* 325 */ syss(nosys,0), /* 326 */ - syss(nosys,0), /* 327 */ + sysp(issetugid,0), /* 327 = issetugid */ syss(nosys,0), /* 328 */ syss(nosys,0), /* 329 */ syss(nosys,0), /* 330 */ diff --git a/bsd/kern/kdebug.c b/bsd/kern/kdebug.c index 89fff7000..c0b81b4b5 100644 --- a/bsd/kern/kdebug.c +++ b/bsd/kern/kdebug.c @@ -124,7 +124,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; return; } - simple_lock(&kd_trace_lock); + usimple_lock(&kd_trace_lock); if (kdebug_flags & KDBG_PIDCHECK) { /* If kdebug flag is not set for current proc, return */ @@ -132,7 +132,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((curproc && !(curproc->p_flag & P_KDEBUG)) && ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE))) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -144,7 +144,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((curproc && (curproc->p_flag & P_KDEBUG)) && ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE))) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -155,7 +155,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((debugid < kdlog_beg) || (debugid > kdlog_end) && (debugid >> 24 != DBG_TRACE)) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -168,7 +168,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; (debugid & DBG_FUNC_MASK) != kdlog_value4 && (debugid >> 24 != DBG_TRACE)) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -213,7 +213,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; kdebug_nolog = 1; kdebug_flags |= KDBG_WRAPPED; } - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); } @@ -235,7 +235,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; return; } - simple_lock(&kd_trace_lock); + usimple_lock(&kd_trace_lock); if (kdebug_flags & KDBG_PIDCHECK) { /* If kdebug flag is not set for current proc, return */ @@ -243,7 +243,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((curproc && !(curproc->p_flag & P_KDEBUG)) && ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE))) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -255,7 +255,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((curproc && (curproc->p_flag & P_KDEBUG)) && ((debugid&0xffff0000) != (MACHDBG_CODE(DBG_MACH_SCHED, 0) | DBG_FUNC_NONE))) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -266,7 +266,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; if ((debugid < kdlog_beg) || (debugid > kdlog_end) && (debugid >> 24 != DBG_TRACE)) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -279,7 +279,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; (debugid & DBG_FUNC_MASK) != kdlog_value4 && (debugid >> 24 != DBG_TRACE)) { - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); return; } @@ -321,7 +321,7 @@ unsigned int debugid, arg1, arg2, arg3, arg4, arg5; kdebug_nolog = 1; kdebug_flags |= KDBG_WRAPPED; } - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); } @@ -887,10 +887,10 @@ unsigned int my_kdebug_flags; kd_buf * my_kd_bufptr; s = ml_set_interrupts_enabled(FALSE); - simple_lock(&kd_trace_lock); + usimple_lock(&kd_trace_lock); my_kdebug_flags = kdebug_flags; my_kd_bufptr = kd_bufptr; - simple_unlock(&kd_trace_lock); + usimple_unlock(&kd_trace_lock); ml_set_interrupts_enabled(s); count = avail/sizeof(kd_buf); diff --git a/bsd/kern/kern_clock.c b/bsd/kern/kern_clock.c index 582f46377..649b0a6d4 100644 --- a/bsd/kern/kern_clock.c +++ b/bsd/kern/kern_clock.c @@ -135,7 +135,7 @@ bsd_hardclock(usermode, pc, numticks) * assuming that the current state has been around at least * one tick. */ - p = (struct proc *)get_bsdtask_info(current_task()); + p = (struct proc *)current_proc(); if (p && ((p->p_flag & P_WEXIT) == NULL)) { if (usermode) { if (p) { @@ -310,7 +310,7 @@ timeout( void *param, int interval) { - AbsoluteTime deadline; + uint64_t deadline; clock_interval_to_deadline(interval, NSEC_PER_SEC / hz, &deadline); thread_call_func_delayed((thread_call_func_t)fcn, param, deadline); diff --git a/bsd/kern/kern_core.c b/bsd/kern/kern_core.c index 7776eb45d..8637468fb 100644 --- a/bsd/kern/kern_core.c +++ b/bsd/kern/kern_core.c @@ -185,7 +185,8 @@ coredump(p) * into core file. */ #if defined (__ppc__) - fpu_save(); + fpu_save(current_act()); + vec_save(current_act()); #endif sprintf(core_name, "/cores/core.%d", p->p_pid); NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, core_name, p); diff --git a/bsd/kern/kern_descrip.c b/bsd/kern/kern_descrip.c index cf9ba2d06..7ede17b05 100644 --- a/bsd/kern/kern_descrip.c +++ b/bsd/kern/kern_descrip.c @@ -426,27 +426,34 @@ fcntl(p, uap, retval) case F_PEOFPOSMODE: - if ((alloc_struct.fst_offset != 0) || - (alloc_struct.fst_length < 0)) - return (EINVAL); + if (alloc_struct.fst_offset != 0) + return (EINVAL); alloc_flags |= ALLOCATEFROMPEOF; break; + case F_VOLPOSMODE: + + if (alloc_struct.fst_offset <= 0) + return (EINVAL); + + alloc_flags |= ALLOCATEFROMVOL; + break; + default: return(EINVAL); } - /* Now lock the vnode and call allocate to get the space */ vp = (struct vnode *)fp->f_data; VOP_LOCK(vp,LK_EXCLUSIVE,p); error = VOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags, - &alloc_struct.fst_bytesalloc,fp->f_cred,p); + &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset, + fp->f_cred, p); VOP_UNLOCK(vp,0,p); if (error2 = (copyout((caddr_t)&alloc_struct, (caddr_t)uap->arg, diff --git a/bsd/kern/kern_exec.c b/bsd/kern/kern_exec.c index 1db47973a..a2642b815 100644 --- a/bsd/kern/kern_exec.c +++ b/bsd/kern/kern_exec.c @@ -155,6 +155,8 @@ execve(p, uap, retval) load_return_t lret; load_result_t load_result; struct uthread *uthread; + vm_map_t old_map; + vm_map_t map; int i; union { /* #! and name of interpreter */ @@ -170,18 +172,28 @@ execve(p, uap, retval) int savedpathlen = 0; vm_offset_t *execargsp; char *cpnospace; - task_t tsk; + task_t task; + task_t new_task; + thread_act_t thr_act; int numthreads; + int vfexec=0; + unsigned long arch_offset =0; + unsigned long arch_size = 0; - tsk = current_task(); + task = current_task(); + thr_act = current_act(); + uthread = get_bsdthread_info(thr_act); - - if(tsk != kernel_task) { - numthreads = get_task_numacts(tsk); - if (numthreads <= 0 ) - return(EINVAL); - if (numthreads > 1) { - return(EOPNOTSUPP); + if (uthread->uu_flag & P_VFORK) { + vfexec = 1; /* Mark in exec */ + } else { + if (task != kernel_task) { + numthreads = get_task_numacts(task); + if (numthreads <= 0 ) + return(EINVAL); + if (numthreads > 1) { + return(EOPNOTSUPP); + } } } @@ -189,8 +201,6 @@ execve(p, uap, retval) if (ret != KERN_SUCCESS) return(ENOMEM); - uthread = get_bsdthread_info(current_act()); - savedpath = execargs; /* @@ -459,24 +469,45 @@ again: goto bad; } - /* - * Load the Mach-O file. - */ - VOP_UNLOCK(vp, 0, p); - lret = load_machfile(vp, mach_header, fat_arch.offset, - fat_arch.size, &load_result); + arch_offset = fat_arch.offset; + arch_size = fat_arch.size; } else { /* * Load the Mach-O file. */ - VOP_UNLOCK(vp, 0, p); - lret = load_machfile(vp, mach_header, 0, - (u_long)vattr.va_size, &load_result); + arch_offset = 0; + arch_size = (u_long)vattr.va_size; } + if (vfexec) { + kern_return_t result; + + result = task_create_local(task, FALSE, FALSE, &new_task); + if (result != KERN_SUCCESS) + printf("execve: task_create failed. Code: 0x%x\n", result); + p->task = new_task; + set_bsdtask_info(new_task, p); + task = new_task; + map = get_task_map(new_task); + result = thread_create(new_task, &thr_act); + if (result != KERN_SUCCESS) + printf("execve: thread_create failed. Code: 0x%x\n", result); + uthread = get_bsdthread_info(thr_act); + } else { + map = VM_MAP_NULL; + + } + + /* + * Load the Mach-O file. + */ + VOP_UNLOCK(vp, 0, p); + lret = load_machfile(vp, mach_header, arch_offset, + arch_size, &load_result, thr_act, map); + if (lret != LOAD_SUCCESS) { error = load_return_to_errno(lret); - goto bad; + goto badtoolate; } /* load_machfile() maps the vnode */ @@ -546,34 +577,38 @@ again: p->p_cred->p_svuid = p->p_ucred->cr_uid; p->p_cred->p_svgid = p->p_ucred->cr_gid; - if (p->p_flag & P_TRACED) { + if (!vfexec && (p->p_flag & P_TRACED)) { psignal(p, SIGTRAP); -#ifdef BSD_USE_APC - thread_apc_set(current_act(), bsd_ast); -#else ast_on(AST_BSD); -#endif } if (error) { - goto bad; + goto badtoolate; } VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY, p); vput(vp); vp = NULL; if (load_result.unixproc && - create_unix_stack(current_map(), - load_result.user_stack, p)) { + create_unix_stack(get_task_map(task), + load_result.user_stack, load_result.customstack, p)) { error = load_return_to_errno(LOAD_NOSPACE); - goto bad; + goto badtoolate; + } + + if (vfexec) { + uthread->uu_ar0 = (void *)get_user_regs(thr_act); } /* * Copy back arglist if necessary. */ + ucp = p->user_stack; + if (vfexec) { + old_map = vm_map_switch(get_task_map(task)); + } if (load_result.unixproc) { int pathptr; @@ -584,13 +619,16 @@ again: * the "path" at the begining of the execargs buffer. * copy it just before the string area. */ - savedpathlen = (savedpathlen + NBPW-1) & ~(NBPW-1); + savedpathlen = (savedpathlen + NBPW-1) & ~(NBPW-1); len = 0; pathptr = ucp - savedpathlen; error = copyoutstr(savedpath, (caddr_t)pathptr, (unsigned)savedpathlen, &len); - if (error) - goto bad; + if (error) { + if (vfexec) + vm_map_switch(old_map); + goto badtoolate; + } /* Save a NULL pointer below it */ (void) suword((caddr_t)(pathptr - NBPW), 0); @@ -645,6 +683,9 @@ again: (void) suword((caddr_t)ap, load_result.mach_header); } + if (vfexec) { + vm_map_switch(old_map); + } #if defined(i386) || defined(ppc) uthread->uu_ar0[PC] = load_result.entry_point; #else @@ -684,8 +725,13 @@ again: /* Collect the pathname for tracing */ kdbg_trace_string(p, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4); - KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE, - dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0); + + if (vfexec) + KERNEL_DEBUG_CONSTANT1((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE, + dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, getshuttle_thread(thr_act)); + else + KERNEL_DEBUG_CONSTANT((TRACEDBG_CODE(DBG_TRACE_STRING, 2)) | DBG_FUNC_NONE, + dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0); } /* @@ -698,18 +744,29 @@ again: wakeup((caddr_t)p->p_pptr); } + if (vfexec && (p->p_flag & P_TRACED)) { + psignal_vfork(p, new_task, thr_act, SIGTRAP); + } + +badtoolate: + if (vfexec) { + (void) thread_resume(thr_act); + task_deallocate(new_task); + act_deallocate(thr_act); + if (error) + error = 0; + } bad: FREE_ZONE(nd.ni_cnd.cn_pnbuf, nd.ni_cnd.cn_pnlen, M_NAMEI); if (vp) vput(vp); bad1: -#if FIXME /* [ */ - if (execargs) - kmem_free_wakeup(bsd_pageable_map, execargs, NCARGS); -#else /* FIXME ][ */ if (execargs) kmem_free(bsd_pageable_map, execargs, NCARGS); -#endif /* FIXME ] */ + if (!error && vfexec) { + vfork_return(current_act(), p->p_pptr, p, retval); + return(0); + } return(error); } @@ -717,23 +774,22 @@ bad1: #define unix_stack_size(p) (p->p_rlimit[RLIMIT_STACK].rlim_cur) kern_return_t -create_unix_stack(map, user_stack, p) +create_unix_stack(map, user_stack, customstack, p) vm_map_t map; vm_offset_t user_stack; + int customstack; struct proc *p; { vm_size_t size; vm_offset_t addr; p->user_stack = user_stack; - size = round_page(unix_stack_size(p)); -#if STACK_GROWTH_UP - /* stack always points to first address for stacks */ - addr = user_stack; -#else STACK_GROWTH_UP - addr = trunc_page(user_stack - size); -#endif /* STACK_GROWTH_UP */ - return (vm_allocate(map,&addr, size, FALSE)); + if (!customstack) { + size = round_page(unix_stack_size(p)); + addr = trunc_page(user_stack - size); + return (vm_allocate(map,&addr, size, FALSE)); + } else + return(KERN_SUCCESS); } #include <sys/reboot.h> diff --git a/bsd/kern/kern_exit.c b/bsd/kern/kern_exit.c index 385c63711..ffb3efdcf 100644 --- a/bsd/kern/kern_exit.c +++ b/bsd/kern/kern_exit.c @@ -89,7 +89,7 @@ #include <kern/assert.h> extern char init_task_failure_data[]; -void exit1 __P((struct proc *, int)); +int exit1 __P((struct proc *, int, int *)); /* * exit -- @@ -104,7 +104,7 @@ exit(p, uap, retval) struct exit_args *uap; int *retval; { - exit1(p, W_EXITCODE(uap->rval, 0)); + exit1(p, W_EXITCODE(uap->rval, 0), retval); /* drop funnel befewo we return */ thread_funnel_set(kernel_flock, FALSE); @@ -120,10 +120,11 @@ exit(p, uap, retval) * to zombie, and unlink proc from allproc and parent's lists. Save exit * status and rusage for wait(). Check for child processes and orphan them. */ -void -exit1(p, rv) +int +exit1(p, rv, retval) register struct proc *p; int rv; + int * retval; { register struct proc *q, *nq; thread_t self = current_thread(); @@ -137,12 +138,20 @@ exit1(p, rv) * called exit(), then halt any others * right here. */ + + ut = get_bsdthread_info(th_act_self); + if (ut->uu_flag & P_VFORK) { + vfork_exit(p, rv); + vfork_return(th_act_self, p->p_pptr, p , retval); + unix_syscall_return(0); + /* NOT REACHED */ + } signal_lock(p); while (p->exit_thread != self) { if (sig_try_locked(p) <= 0) { if (get_threadtask(th_act_self) != task) { signal_unlock(p); - return; + return(0); } signal_unlock(p); thread_terminate(th_act_self); @@ -184,6 +193,7 @@ exit1(p, rv) /*NOTREACHED*/ } #endif + return(0); } void @@ -495,7 +505,7 @@ wait1continue(result) int *retval; struct proc *p; - p = get_bsdtask_info(current_task()); + p = current_proc(); p->p_flag &= ~P_WAITING; if (result != 0) { @@ -715,7 +725,272 @@ process_terminate_self(void) struct proc *p = current_proc(); if (p != NULL) { - exit1(p, W_EXITCODE(0, SIGKILL)); + exit1(p, W_EXITCODE(0, SIGKILL), (int *)NULL); /*NOTREACHED*/ } } +/* + * Exit: deallocate address space and other resources, change proc state + * to zombie, and unlink proc from allproc and parent's lists. Save exit + * status and rusage for wait(). Check for child processes and orphan them. + */ + +void +vfork_exit(p, rv) + register struct proc *p; + int rv; +{ + register struct proc *q, *nq; + thread_t self = current_thread(); + thread_act_t th_act_self = current_act(); + struct task *task = p->task; + register int i,s; + struct uthread *ut; + + /* + * If a thread in this task has already + * called exit(), then halt any others + * right here. + */ + + ut = get_bsdthread_info(th_act_self); +#ifdef FIXME + signal_lock(p); + while (p->exit_thread != self) { + if (sig_try_locked(p) <= 0) { + if (get_threadtask(th_act_self) != task) { + signal_unlock(p); + return; + } + signal_unlock(p); + thread_terminate(th_act_self); + thread_funnel_set(kernel_flock, FALSE); + thread_exception_return(); + /* NOTREACHED */ + } + sig_lock_to_exit(p); + } + signal_unlock(p); + if (p->p_pid == 1) { + printf("pid 1 exited (signal %d, exit %d)", + WTERMSIG(rv), WEXITSTATUS(rv)); +panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data); + } +#endif /* FIXME */ + + s = splsched(); + p->p_flag |= P_WEXIT; + splx(s); + /* + * Remove proc from allproc queue and from pidhash chain. + * Need to do this before we do anything that can block. + * Not doing causes things like mount() find this on allproc + * in partially cleaned state. + */ + LIST_REMOVE(p, p_list); + LIST_REMOVE(p, p_hash); + /* + * If parent is waiting for us to exit or exec, + * P_PPWAIT is set; we will wakeup the parent below. + */ + p->p_flag &= ~(P_TRACED | P_PPWAIT); + p->p_sigignore = ~0; + p->p_siglist = 0; + + ut->uu_sig = 0; + untimeout(realitexpire, (caddr_t)p); + + p->p_xstat = rv; + + vproc_exit(p); +} + + +void +vproc_exit(struct proc *p) +{ + register struct proc *q, *nq; + thread_t self = current_thread(); + thread_act_t th_act_self = current_act(); + struct task *task = p->task; + register int i,s; + struct uthread *ut; + boolean_t funnel_state; + + MALLOC_ZONE(p->p_ru, struct rusage *, + sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK); + + /* + * Close open files and release open-file table. + * This may block! + */ + fdfree(p); + + /* Close ref SYSV Shared memory*/ + if (p->vm_shm) + shmexit(p); + + if (SESS_LEADER(p)) { + register struct session *sp = p->p_session; + + if (sp->s_ttyvp) { + /* + * Controlling process. + * Signal foreground pgrp, + * drain controlling terminal + * and revoke access to controlling terminal. + */ + if (sp->s_ttyp->t_session == sp) { + if (sp->s_ttyp->t_pgrp) + pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); + (void) ttywait(sp->s_ttyp); + /* + * The tty could have been revoked + * if we blocked. + */ + if (sp->s_ttyvp) + VOP_REVOKE(sp->s_ttyvp, REVOKEALL); + } + if (sp->s_ttyvp) + vrele(sp->s_ttyvp); + sp->s_ttyvp = NULL; + /* + * s_ttyp is not zero'd; we use this to indicate + * that the session once had a controlling terminal. + * (for logging and informational purposes) + */ + } + sp->s_leader = NULL; + } + + fixjobc(p, p->p_pgrp, 0); + p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; +#if KTRACE + /* + * release trace file + */ + p->p_traceflag = 0; /* don't trace the vrele() */ + if (p->p_tracep) + vrele(p->p_tracep); +#endif + + + q = p->p_children.lh_first; + if (q) /* only need this if any child is S_ZOMB */ + wakeup((caddr_t) initproc); + for (; q != 0; q = nq) { + nq = q->p_sibling.le_next; + proc_reparent(q, initproc); + /* + * Traced processes are killed + * since their existence means someone is messing up. + */ + if (q->p_flag & P_TRACED) { + q->p_flag &= ~P_TRACED; + if (q->sigwait_thread) { + thread_t sig_shuttle = getshuttle_thread(q->sigwait_thread); + /* + * The sigwait_thread could be stopped at a + * breakpoint. Wake it up to kill. + * Need to do this as it could be a thread which is not + * the first thread in the task. So any attempts to kill + * the process would result into a deadlock on q->sigwait. + */ + thread_resume((struct thread *)q->sigwait_thread); + clear_wait(sig_shuttle, THREAD_INTERRUPTED); + threadsignal(q->sigwait_thread, SIGKILL, 0); + } + psignal(q, SIGKILL); + } + } + + + /* + * Save exit status and final rusage info, adding in child rusage + * info and self times. + */ + *p->p_ru = p->p_stats->p_ru; + + timerclear(&p->p_ru->ru_utime); + timerclear(&p->p_ru->ru_stime); + +#ifdef FIXME + if (task) { + task_basic_info_data_t tinfo; + task_thread_times_info_data_t ttimesinfo; + int task_info_stuff, task_ttimes_stuff; + struct timeval ut,st; + + task_info_stuff = TASK_BASIC_INFO_COUNT; + task_info(task, TASK_BASIC_INFO, + &tinfo, &task_info_stuff); + p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds; + p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds; + p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds; + p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds; + + task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT; + task_info(task, TASK_THREAD_TIMES_INFO, + &ttimesinfo, &task_ttimes_stuff); + + ut.tv_sec = ttimesinfo.user_time.seconds; + ut.tv_usec = ttimesinfo.user_time.microseconds; + st.tv_sec = ttimesinfo.system_time.seconds; + st.tv_usec = ttimesinfo.system_time.microseconds; + timeradd(&ut,&p->p_ru->ru_utime,&p->p_ru->ru_utime); + timeradd(&st,&p->p_ru->ru_stime,&p->p_ru->ru_stime); + } +#endif /* FIXME */ + + ruadd(p->p_ru, &p->p_stats->p_cru); + + /* + * Free up profiling buffers. + */ + { + struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn; + + p1 = p0->pr_next; + p0->pr_next = NULL; + p0->pr_scale = 0; + + for (; p1 != NULL; p1 = pn) { + pn = p1->pr_next; + kfree((vm_offset_t)p1, sizeof *p1); + } + } + + /* + * Other substructures are freed from wait(). + */ + FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC); + p->p_stats = NULL; + + FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC); + p->p_sigacts = NULL; + + if (--p->p_limit->p_refcnt == 0) + FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC); + p->p_limit = NULL; + + /* + * Finish up by terminating the task + * and halt this thread (only if a + * member of the task exiting). + */ + p->task = TASK_NULL; + + /* + * Notify parent that we're gone. + */ + psignal(p->p_pptr, SIGCHLD); + + /* Place onto zombproc. */ + LIST_INSERT_HEAD(&zombproc, p, p_list); + p->p_stat = SZOMB; + + /* and now wakeup the parent */ + wakeup((caddr_t)p->p_pptr); + +} + diff --git a/bsd/kern/kern_fork.c b/bsd/kern/kern_fork.c index a11175f7b..58aa6ecf4 100644 --- a/bsd/kern/kern_fork.c +++ b/bsd/kern/kern_fork.c @@ -79,6 +79,7 @@ #include <machine/spl.h> thread_t cloneproc(struct proc *, int); +struct proc * forkproc(struct proc *, int); thread_t procdup(); #define DOFORK 0x1 /* fork() system call */ @@ -106,9 +107,158 @@ vfork(p, uap, retval) void *uap; register_t *retval; { - return (fork1(p, (long)DOVFORK, retval)); + register struct proc * newproc; + register uid_t uid; + thread_act_t cur_act = (thread_act_t)current_act(); + int count; + task_t t; + uthread_t ut; + + /* + * Although process entries are dynamically created, we still keep + * a global limit on the maximum number we will create. Don't allow + * a nonprivileged user to use the last process; don't let root + * exceed the limit. The variable nprocs is the current number of + * processes, maxproc is the limit. + */ + uid = p->p_cred->p_ruid; + if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) { + tablefull("proc"); + retval[1] = 0; + return (EAGAIN); + } + + /* + * Increment the count of procs running with this uid. Don't allow + * a nonprivileged user to exceed their current limit. + */ + count = chgproccnt(uid, 1); + if (uid != 0 && count > p->p_rlimit[RLIMIT_NPROC].rlim_cur) { + (void)chgproccnt(uid, -1); + return (EAGAIN); + } + + ut = (struct uthread *)get_bsdthread_info(cur_act); + if (ut->uu_flag & P_VFORK) { + printf("vfork called recursively by %s\n", p->p_comm); + return (EINVAL); + } + p->p_flag |= P_VFORK; + p->p_vforkcnt++; + + /* The newly created process comes with signal lock held */ + newproc = (struct proc *)forkproc(p,1); + + LIST_INSERT_AFTER(p, newproc, p_pglist); + newproc->p_pptr = p; + newproc->task = p->task; + LIST_INSERT_HEAD(&p->p_children, newproc, p_sibling); + LIST_INIT(&newproc->p_children); + LIST_INSERT_HEAD(&allproc, newproc, p_list); + LIST_INSERT_HEAD(PIDHASH(newproc->p_pid), newproc, p_hash); + TAILQ_INIT(& newproc->p_evlist); + newproc->p_stat = SRUN; + newproc->p_flag |= P_INVFORK; + newproc->p_vforkact = cur_act; + + ut->uu_flag |= P_VFORK; + ut->uu_proc = newproc; + ut->uu_userstate = (void *)act_thread_csave(); + + thread_set_child(cur_act, newproc->p_pid); + + newproc->p_stats->p_start = time; + newproc->p_acflag = AFORK; + + /* + * Preserve synchronization semantics of vfork. If waiting for + * child to exec or exit, set P_PPWAIT on child, and sleep on our + * proc (in case of exit). + */ + newproc->p_flag |= P_PPWAIT; + + /* drop the signal lock on the child */ + signal_unlock(newproc); + + retval[0] = newproc->p_pid; + retval[1] = 1; /* mark child */ + + return (0); } +/* + * Return to parent vfork ehread() + */ +void +vfork_return(th_act, p, p2, retval) + thread_act_t th_act; + struct proc * p; + struct proc *p2; + register_t *retval; +{ + long flags; + register uid_t uid; + thread_t newth, self = current_thread(); + thread_act_t cur_act = (thread_act_t)current_act(); + int s, count; + task_t t; + uthread_t ut; + + ut = (struct uthread *)get_bsdthread_info(cur_act); + + act_thread_catt(ut->uu_userstate); + + /* Make sure only one at this time */ + p->p_vforkcnt--; + if (p->p_vforkcnt <0) + panic("vfork cnt is -ve"); + if (p->p_vforkcnt <=0) + p->p_flag &= ~P_VFORK; + ut->uu_userstate = 0; + ut->uu_flag &= ~P_VFORK; + ut->uu_proc = 0; + p2->p_flag &= ~P_INVFORK; + p2->p_vforkact = (void *)0; + + thread_set_parent(cur_act, p2->p_pid); + + if (retval) { + retval[0] = p2->p_pid; + retval[1] = 0; /* mark parent */ + } + + return; +} + +thread_t +procdup( + struct proc *child, + struct proc *parent) +{ + thread_t thread; + task_t task; + kern_return_t result; + extern task_t kernel_task; + + if (parent->task == kernel_task) + result = task_create_local(TASK_NULL, FALSE, FALSE, &task); + else + result = task_create_local(parent->task, TRUE, FALSE, &task); + if (result != KERN_SUCCESS) + printf("fork/procdup: task_create failed. Code: 0x%x\n", result); + child->task = task; + /* task->proc = child; */ + set_bsdtask_info(task, child); + if (child->p_nice != 0) + resetpriority(child); + result = thread_create(task, &thread); + if (result != KERN_SUCCESS) + printf("fork/procdup: thread_create failed. Code: 0x%x\n", result); + + return(thread); +} + + static int fork1(p1, flags, retval) struct proc *p1; @@ -171,7 +321,7 @@ fork1(p1, flags, retval) (void) thread_resume(newth); /* drop the extra references we got during the creation */ - if (t = get_threadtask(newth)) { + if (t = (task_t)get_threadtask(newth)) { task_deallocate(t); } act_deallocate(newth); @@ -198,6 +348,32 @@ thread_t cloneproc(p1, lock) register struct proc *p1; register int lock; +{ + register struct proc *p2; + thread_t th; + + p2 = (struct proc *)forkproc(p1,lock); + th = procdup(p2, p1); /* child, parent */ + + LIST_INSERT_AFTER(p1, p2, p_pglist); + p2->p_pptr = p1; + LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling); + LIST_INIT(&p2->p_children); + LIST_INSERT_HEAD(&allproc, p2, p_list); + LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); + TAILQ_INIT(&p2->p_evlist); + /* + * Make child runnable, set start time. + */ + p2->p_stat = SRUN; + + return(th); +} + +struct proc * +forkproc(p1, lock) + register struct proc *p1; + register int lock; { register struct proc *p2, *newproc; static int nextpid = 0, pidchecked = 0; @@ -339,6 +515,8 @@ again: p2->exit_thread = NULL; p2->user_stack = p1->user_stack; p2->p_sigpending = 0; + p2->p_vforkcnt = 0; + p2->p_vforkact = 0; #if KTRACE /* @@ -351,21 +529,8 @@ again: VREF(p2->p_tracep); } #endif + return(p2); - th = procdup(p2, p1); /* child, parent */ - LIST_INSERT_AFTER(p1, p2, p_pglist); - p2->p_pptr = p1; - LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling); - LIST_INIT(&p2->p_children); - LIST_INSERT_HEAD(&allproc, p2, p_list); - LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); - TAILQ_INIT(&p2->p_evlist); - /* - * Make child runnable, set start time. - */ - p2->p_stat = SRUN; - - return(th); } #include <kern/zalloc.h> @@ -398,11 +563,13 @@ uthread_alloc(void) return (ut); } + void uthread_free(void *uthread) { struct _select *sel; struct uthread *uth = (struct uthread *)uthread; + int size; sel = &uth->uu_state.ss_select; /* cleanup the select bit space */ @@ -411,6 +578,14 @@ uthread_free(void *uthread) FREE(sel->obits, M_TEMP); } + if (sel->allocsize && uth->uu_wqsub){ + kfree(uth->uu_wqsub, sel->allocsize); + sel->count = sel->nfcount = 0; + sel->allocsize = 0; + uth->uu_wqsub = 0; + sel->wql = 0; + } + /* and free the uthread itself */ zfree(uthread_zone, (vm_offset_t)uthread); } diff --git a/bsd/kern/kern_lock.c b/bsd/kern/kern_lock.c index 117407d6d..d8ba1e858 100644 --- a/bsd/kern/kern_lock.c +++ b/bsd/kern/kern_lock.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -384,9 +384,11 @@ lockmgr(lkp, flags, interlkp, p) if (lkp->lk_exclusivecount != 0) { if (pid != lkp->lk_lockholder || lkp->lk_lockthread != self) - panic("lockmgr: pid %d, not %s %d unlocking", - pid, "exclusive lock holder", - lkp->lk_lockholder); + panic("lockmgr: pid %d, thread 0x%8x," + " not exclusive lock holder pid %d" + " thread 0x%8x unlocking, exclusive count %d", + pid, self, lkp->lk_lockholder, + lkp->lk_lockthread, lkp->lk_exclusivecount); lkp->lk_exclusivecount--; COUNT(p, -1); if (lkp->lk_exclusivecount == 0) { diff --git a/bsd/kern/kern_mman.c b/bsd/kern/kern_mman.c index 3fd5b0650..25c48f396 100644 --- a/bsd/kern/kern_mman.c +++ b/bsd/kern/kern_mman.c @@ -1061,7 +1061,7 @@ kern_return_t map_fd_funneled( vm_map_copy_t tmp; int err=0; vm_map_t my_map; - struct proc *p =(struct proc *)(get_bsdtask_info(current_task())); + struct proc *p =(struct proc *)current_proc(); #if 0 extern int print_map_addr; #endif /* 0 */ diff --git a/bsd/kern/kern_newsysctl.c b/bsd/kern/kern_newsysctl.c index 0bba174a6..d24a34b51 100644 --- a/bsd/kern/kern_newsysctl.c +++ b/bsd/kern/kern_newsysctl.c @@ -828,7 +828,7 @@ found: * Switch to the NETWORK funnel for CTL_NET and KERN_IPC sysctls */ - if ((req->newptr) && ((name[0] == CTL_NET) || ((name[0] == CTL_KERN) && + if (((name[0] == CTL_NET) || ((name[0] == CTL_KERN) && (name[1] == KERN_IPC)))) thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); @@ -846,7 +846,7 @@ found: * Switch back to the KERNEL funnel, if necessary */ - if ((req->newptr) && ((name[0] == CTL_NET) || ((name[0] == CTL_KERN) && + if (((name[0] == CTL_NET) || ((name[0] == CTL_KERN) && (name[1] == KERN_IPC)))) thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); diff --git a/bsd/kern/kern_pcsamples.c b/bsd/kern/kern_pcsamples.c index 68ba7cc97..7d338236a 100644 --- a/bsd/kern/kern_pcsamples.c +++ b/bsd/kern/kern_pcsamples.c @@ -37,6 +37,9 @@ unsigned int pc_bufsize = 0; unsigned int pcsample_flags = 0; unsigned int pcsample_enable = 0; +pid_t pc_sample_pid = 0; +boolean_t pc_trace_frameworks = FALSE; + char pcsample_comm[MAXCOMLEN + 1]; /* Set the default framework boundaries */ @@ -48,6 +51,65 @@ static pid_t global_state_pid = -1; /* Used to control exclusive use of pc extern int pc_trace_buf[]; extern int pc_trace_cnt; +int +enable_branch_tracing() +{ +#ifndef i386 + struct proc *p; + if (-1 != pc_sample_pid) { + p = pfind(pc_sample_pid); + if (p) { + p->p_flag |= P_BTRACE; + } + } + else { + pc_trace_frameworks = TRUE; + } + + return 1; + +#else + return 0; +#endif +} + +int +disable_branch_tracing() +{ + struct proc *p; + switch (pc_sample_pid) { + case -1: + pc_trace_frameworks = FALSE; + break; + case 0: + break; + default: + p = pfind(pc_sample_pid); + if (p) { + p->p_flag &= ~P_BTRACE; + } + break; +} + clr_be_bit(); + return 1; +} + +/* + * this only works for the current proc as it + * is called from context_switch in the scheduler + */ +int +branch_tracing_enabled() +{ + struct proc *p = current_proc(); + if (TRUE == pc_trace_frameworks) return TRUE; + if (p) { + return (P_BTRACE == (p->p_flag & P_BTRACE)); + } + return 0; +} + + void add_pcbuffer() { @@ -59,15 +121,6 @@ add_pcbuffer() if (!pcsample_enable) return; - if (pcsample_comm[0] != '\0') - { - /* If command string does not match, then return */ - curproc = current_proc(); - if (curproc && - (strncmp(curproc->p_comm, pcsample_comm, sizeof(pcsample_comm)))) - return; - } - for (i=0; i < pc_trace_cnt; i++) { pc = pc_trace_buf[i]; @@ -90,7 +143,7 @@ add_pcbuffer() if ((pc_bufptr + pc_trace_cnt) >= pc_buflast) { pcsample_enable = 0; - (void)clr_be_bit(); + (void)disable_branch_tracing(); wakeup(&pcsample_enable); } return; @@ -98,7 +151,7 @@ add_pcbuffer() pcsamples_bootstrap() { - if (!clr_be_bit()) + if (!disable_branch_tracing()) return(ENOTSUP); pc_bufsize = npcbufs * sizeof(* pc_buffer); @@ -148,7 +201,10 @@ pcsamples_clear() pcsample_beg= 0; pcsample_end= 0; bzero((void *)pcsample_comm, sizeof(pcsample_comm)); - (void)clr_be_bit(); + (void)disable_branch_tracing(); + pc_sample_pid = 0; + pc_trace_frameworks = FALSE; + } pcsamples_control(name, namelen, where, sizep) @@ -161,6 +217,7 @@ int ret=0; int size=*sizep; unsigned int value = name[1]; pcinfo_t pc_bufinfo; +pid_t *pidcheck; pid_t curpid; struct proc *p, *curproc; @@ -234,7 +291,7 @@ struct proc *p, *curproc; { /* Do not wait on the buffer */ pcsample_enable = 0; - (void)clr_be_bit(); + (void)disable_branch_tracing(); ret = pcsamples_read(where, sizep); break; } @@ -246,9 +303,9 @@ struct proc *p, *curproc; } /* Turn on branch tracing */ - if (!set_be_bit()) + if (!enable_branch_tracing()) { - ret = ENOTSUP;; + ret = ENOTSUP; break; } @@ -257,7 +314,7 @@ struct proc *p, *curproc; ret = tsleep(&pcsample_enable, PRIBIO | PCATCH, "pcsample", 0); pcsample_enable = 0; - (void)clr_be_bit(); + (void)disable_branch_tracing(); if (ret) { @@ -298,10 +355,31 @@ struct proc *p, *curproc; break; } bzero((void *)pcsample_comm, sizeof(pcsample_comm)); - if (copyin(where, pcsample_comm, size)) - { - ret = EINVAL; - } + if (copyin(where, pcsample_comm, size)) + { + ret = EINVAL; + break; + } + + /* Check for command name or pid */ + if (pcsample_comm[0] != '\0') + { + ret= EOPNOTSUPP; + break; + } + else + { + if (size != (2 * sizeof(pid_t))) + { + ret = EINVAL; + break; + } + else + { + pidcheck = (pid_t *)pcsample_comm; + pc_sample_pid = pidcheck[1]; + } + } break; default: ret= EOPNOTSUPP; @@ -356,6 +434,3 @@ int copycount; } } - - - diff --git a/bsd/kern/kern_prot.c b/bsd/kern/kern_prot.c index 579c321f6..5882e93cf 100644 --- a/bsd/kern/kern_prot.c +++ b/bsd/kern/kern_prot.c @@ -279,6 +279,27 @@ setpgid(curp, uap, retval) return (enterpgrp(targp, uap->pgid, 0)); } +struct issetugid_args { + int dummy; +}; +issetugid(p, uap, retval) + struct proc *p; + struct issetugid_args *uap; + register_t *retval; +{ + /* + * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, + * we use P_SUGID because we consider changing the owners as + * "tainting" as well. + * This is significant for procs that start as root and "become" + * a user without an exec - programs cannot know *everything* + * that libc *might* have put in their data segment. + */ + + *retval = (p->p_flag & P_SUGID) ? 1 : 0; + return (0); +} + struct setuid_args { uid_t uid; }; diff --git a/bsd/kern/kern_shutdown.c b/bsd/kern/kern_shutdown.c index e9a2a2c52..fcd80032e 100644 --- a/bsd/kern/kern_shutdown.c +++ b/bsd/kern/kern_shutdown.c @@ -70,11 +70,12 @@ boot(paniced, howto, command) int hostboot_option=0; int funnel_state; - static void proc_shutdown(); + static void proc_shutdown(); + extern void md_prepare_for_shutdown(int paniced, int howto, char * command); funnel_state = thread_funnel_set(kernel_flock, TRUE); - /* md_prepare_for_shutdown(paniced, howto, command); */ + md_prepare_for_shutdown(paniced, howto, command); if ((howto&RB_NOSYNC)==0 && waittime < 0) { int iter, nbusy; @@ -161,7 +162,7 @@ proc_shutdown() /* * Kill as many procs as we can. (Except ourself...) */ - self = (struct proc *)(get_bsdtask_info(current_task())); + self = (struct proc *)current_proc(); /* * Suspend /etc/init @@ -255,7 +256,7 @@ proc_shutdown() else { p->exit_thread = current_thread(); printf("."); - exit1(p, 1); + exit1(p, 1, (int *)NULL); } p = allproc.lh_first; } diff --git a/bsd/kern/kern_sig.c b/bsd/kern/kern_sig.c index 92f02ba12..83b6d4b8e 100644 --- a/bsd/kern/kern_sig.c +++ b/bsd/kern/kern_sig.c @@ -95,7 +95,7 @@ int cansignal __P((struct proc *, struct pcred *, struct proc *, int)); int killpg1 __P((struct proc *, int, int, int)); void sigexit_locked __P((struct proc *, int)); void setsigvec __P((struct proc *, int, struct sigaction *)); -void exit1 __P((struct proc *, int)); +void exit1 __P((struct proc *, int, int *)); int signal_lock __P((struct proc *)); int signal_unlock __P((struct proc *)); void signal_setast __P((thread_act_t *)); @@ -828,13 +828,15 @@ threadsignal(sig_actthread, signum, code) if ((mask & threadmask) == 0) return; sig_task = get_threadtask(sig_actthread); - /* p = sig_task->proc; */ p = (struct proc *)(get_bsdtask_info(sig_task)); + uth = get_bsdthread_info(sig_actthread); + if (uth && (uth->uu_flag & P_VFORK)) + p = uth->uu_proc; + if (!(p->p_flag & P_TRACED) && (p->p_sigignore & mask)) return; - uth = get_bsdthread_info(sig_actthread); uth->uu_sig |= mask; uth->uu_code = code; /* mark on process as well */ @@ -884,6 +886,112 @@ psignal(p, signum) } +void +psignal_vfork(p, new_task, thr_act, signum) + register struct proc *p; + task_t new_task; + thread_act_t thr_act; + register int signum; +{ + int withlock = 1; + int pend = 0; + register int s, prop; + register sig_t action; + int mask; + kern_return_t kret; + + if ((u_int)signum >= NSIG || signum == 0) + panic("psignal signal number"); + mask = sigmask(signum); + prop = sigprop[signum]; + +#if SIGNAL_DEBUG + if(rdebug_proc && (p == rdebug_proc)) { + ram_printf(3); + } +#endif /* SIGNAL_DEBUG */ + + if ((new_task == TASK_NULL) || (thr_act == (thread_act_t)NULL) || is_kerneltask(new_task)) + return; + + + signal_lock(p); + + /* + * proc is traced, always give parent a chance. + */ + action = SIG_DFL; + + if (p->p_nice > NZERO && action == SIG_DFL && (prop & SA_KILL) && + (p->p_flag & P_TRACED) == 0) + p->p_nice = NZERO; + + if (prop & SA_CONT) + p->p_siglist &= ~stopsigmask; + + if (prop & SA_STOP) { + /* + * If sending a tty stop signal to a member of an orphaned + * process group, discard the signal here if the action + * is default; don't stop the process below if sleeping, + * and don't clear any pending SIGCONT. + */ + if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 && + action == SIG_DFL) + goto psigout; + p->p_siglist &= ~contsigmask; + } + p->p_siglist |= mask; + + /* Deliver signal to the activation passed in */ + thread_ast_set(thr_act, AST_BSD); + + /* + * SIGKILL priority twiddling moved here from above because + * it needs sig_thread. Could merge it into large switch + * below if we didn't care about priority for tracing + * as SIGKILL's action is always SIG_DFL. + */ + if ((signum == SIGKILL) && (p->p_nice > NZERO)) { + p->p_nice = NZERO; +#if XXX + /* + * we need to make changes here to get nice to work + * reset priority to BASEPRI_USER + */ +#endif + } + + /* + * This Process is traced - wake it up (if not already + * stopped) so that it can discover the signal in + * issig() and stop for the parent. + */ + if (p->p_flag & P_TRACED) { + if (p->p_stat != SSTOP) + goto run; + else + goto psigout; + } +run: + /* + * If we're being traced (possibly because someone attached us + * while we were stopped), check for a signal from the debugger. + */ + if (p->p_stat == SSTOP) { + if ((p->p_flag & P_TRACED) != 0 && p->p_xstat != 0) + p->p_siglist |= sigmask(p->p_xstat); + } + + /* + * setrunnable(p) in BSD + */ + p->p_stat = SRUN; + +psigout: + signal_unlock(p); +} + /* * Send the signal to the process. If the signal has an action, the action * is usually performed by the target process rather than the caller; we add @@ -1023,6 +1131,15 @@ psignal_lock(p, signum, withlock, pend) cur_thread = current_thread(); /* this is a shuttle */ cur_act = current_act(); + if ((p->p_flag & P_INVFORK) && p->p_vforkact) { + sig_thread_act = p->p_vforkact; + + kret = check_actforsig(sig_task, sig_thread_act, &sig_thread, 1); + if (kret == KERN_SUCCESS) { + goto psig_foundthread; + } + } + /* If successful return with ast set */ kret = (kern_return_t)get_signalact(sig_task, &sig_thread_act, &sig_thread, 1); @@ -1030,17 +1147,22 @@ psignal_lock(p, signum, withlock, pend) if ((kret != KERN_SUCCESS) || (sig_thread_act == THREAD_NULL)) { /* XXXX FIXME /* if it is sigkill, may be we should - * inject a thread to terminate - */ - printf("WARNING: no activation in psignal\n"); + * inject a thread to terminate + */ +#if DIAGNOSTIC + printf("WARNING: no activation in psignal\n"); +#endif #if SIGNAL_DEBUG - ram_printf(1); + ram_printf(1); #endif /* SIGNAL_DEBUG */ - goto psigout; - } + goto psigout; + } +psig_foundthread: if (sig_thread == THREAD_NULL) { +#if DIAGNOSTIC printf("WARNING: valid act; but no shutte in psignal\n"); +#endif #if 0 /* FIXME : NO VALID SHUTTLE */ goto psigout; @@ -1337,7 +1459,7 @@ issignal(p) * XXX middle of it. */ task = p->task; - task_hold(task); + task_hold(task); p->sigwait = TRUE; p->sigwait_thread = cur_act; p->p_stat = SSTOP; @@ -1373,7 +1495,7 @@ issignal(p) * calls closef() which can trash u_qsave.) */ signal_unlock(p); - exit1(p,signum); + exit1(p,signum, (int *)NULL); return(0); } @@ -1461,6 +1583,8 @@ issignal(p) */ break; /* == ignore */ } else { + p->p_siglist &= ~mask; /* take the signal! */ + p->p_sigpending &= ~mask; /* take the pending signal */ signal_unlock(p); return (signum); } @@ -1482,6 +1606,8 @@ issignal(p) * This signal has an action, let * postsig() process it. */ + p->p_siglist &= ~mask; /* take the signal! */ + p->p_sigpending &= ~mask; /* take the pending signal */ signal_unlock(p); return (signum); } @@ -1743,7 +1869,7 @@ sigexit_locked(p, signum) signum |= WCOREFLAG; } signal_unlock(p); - exit1(p, W_EXITCODE(0, signum)); + exit1(p, W_EXITCODE(0, signum), (int *)NULL); /* NOTREACHED */ } diff --git a/bsd/kern/kern_symfile.c b/bsd/kern/kern_symfile.c index d90edce20..f4607b9d3 100644 --- a/bsd/kern/kern_symfile.c +++ b/bsd/kern/kern_symfile.c @@ -64,230 +64,273 @@ #include <vm/vm_kern.h> extern unsigned char rootdevice[]; -extern vm_size_t page_size; +extern struct mach_header _mh_execute_header; +static int kernel_symfile_opened = 0; +static int error_code = 0; -int kernel_symfile_opened = 0; -int error_code = 0; - -extern int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize ); -extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); - -struct segment_command *findSegmentByName( struct mach_header *mh, const char *section_name ); +extern int IODTGetLoaderInfo(char *key, void **infoAddr, int *infoSize); +extern void IODTFreeLoaderInfo(char *key, void *infoAddr, int infoSize); /* * */ -int get_kernel_symfile( struct proc *p, char **symfile ) +static int output_kernel_symbols(struct proc *p) { - if ( kernel_symfile_opened == 0 ) - { - kernel_symfile_opened = 1; - error_code = output_kernel_symbols( p ); + struct vnode *vp; + struct pcred *pcred = p->p_cred; + struct ucred *cred = pcred->pc_ucred; + struct nameidata nd; + struct vattr vattr; + struct load_command *cmd; + struct mach_header *orig_mh, *mh; + struct segment_command *orig_ds, *orig_ts, *orig_le, *sg; + struct section *se, *const_text; + struct symtab_command *st, *orig_st; + struct nlist *sym; + vm_size_t orig_mhsize, orig_st_size; + vm_offset_t header; + vm_size_t header_size; + int error, error1; + int i, j; + caddr_t addr; + vm_offset_t offset; + int rc_mh, rc_sc; + + error = EFAULT; + + vp = NULL; + header = NULL; + orig_mh = NULL; + orig_st = NULL; + + // Dispose of unnecessary gumf, the booter doesn't need to load these + rc_mh = IODTGetLoaderInfo("Kernel-__HEADER", + (void **)&orig_mh, &orig_mhsize); + if (rc_mh && orig_mh) + IODTFreeLoaderInfo("Kernel-__HEADER", + (void *)orig_mh, round_page(orig_mhsize)); + + rc_sc = IODTGetLoaderInfo("Kernel-__SYMTAB", + (void **) &orig_st, &orig_st_size); + if (rc_sc && orig_st) + IODTFreeLoaderInfo("Kernel-__SYMTAB", + (void *)orig_st, round_page(orig_st_size)); + + if (pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid) + goto out; + + // Check to see if the root is 'e' or 'n', is this a test for network? + if (rootdevice[0] == 'e' && rootdevice[1] == 'n') + goto out; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p); + if((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH))) goto out; + + vp = nd.ni_vp; + + /* Don't dump to non-regular files or files with links. */ + error = EFAULT; + if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) + || vattr.va_nlink != 1) + goto out; + + VATTR_NULL(&vattr); + vattr.va_size = 0; + VOP_LEASE(vp, p, cred, LEASE_WRITE); + VOP_SETATTR(vp, &vattr, cred, p); + p->p_acflag |= ACORE; + + // If the file type is MH_EXECUTE then this must be a kernel + // as all Kernel extensions must be of type MH_OBJECT + orig_ds = orig_ts = orig_le = NULL; + orig_st = NULL; + orig_mh = &_mh_execute_header; + cmd = (struct load_command *) &orig_mh[1]; + for (i = 0; i < orig_mh->ncmds; i++) { + if (cmd->cmd == LC_SEGMENT) { + struct segment_command *sg = (struct segment_command *) cmd; + + if (!strcmp(SEG_TEXT, sg->segname)) + orig_ts = sg; + else if (!strcmp(SEG_DATA, sg->segname)) + orig_ds = sg; + else if (!strcmp(SEG_LINKEDIT, sg->segname)) + orig_le = sg; + } + else if (cmd->cmd == LC_SYMTAB) + orig_st = (struct symtab_command *) cmd; + + cmd = (struct load_command *) ((caddr_t) cmd + cmd->cmdsize); } - if ( error_code == 0 ) *symfile = "\\mach.sym"; - return error_code; -} + if (!orig_ts || !orig_ds || !orig_le || !orig_st) + goto out; -/* - * - */ -int output_kernel_symbols( register struct proc *p ) -{ - register struct vnode *vp; - register struct pcred *pcred = p->p_cred; - register struct ucred *cred = pcred->pc_ucred; - struct nameidata nd; - struct vattr vattr; - struct mach_header *orig_mh, *mh; - struct load_command *lc; - struct segment_command *orig_ds, *orig_ts, *sg; - struct section *se; - struct symtab_command *sc, *sc0; - struct nlist *nl; - vm_size_t orig_mhsize, sc0_size; - vm_offset_t header; - vm_size_t header_size; - int error, error1; - int i, j; - int symfoffset, symsize; - int rc_mh, rc_sc; - - error = EFAULT; - - vp = NULL; - header = NULL; - orig_mh = NULL; - sc0 = NULL; - - rc_mh = IODTGetLoaderInfo( "Kernel-__HEADER", (void **)&orig_mh, &orig_mhsize ); - rc_sc = IODTGetLoaderInfo( "Kernel-__SYMTAB", (void **)&sc0, &sc0_size ); - - if ( rc_mh != 0 || orig_mh == 0 || orig_mhsize < sizeof(struct mach_header) ) goto out; - if ( rc_sc != 0 || sc0 == 0 || sc0_size < sizeof(struct symtab_command) ) goto out; - - if ( pcred->p_svuid != pcred->p_ruid || pcred->p_svgid != pcred->p_rgid ) goto out; - - if ( rootdevice[0] == 'e' && rootdevice[1] == 'n' ) goto out; - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "mach.sym", p); - if( (error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IRGRP | S_IROTH )) != 0 ) goto out; - - vp = nd.ni_vp; - - /* Don't dump to non-regular files or files with links. */ - error = EFAULT; - if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) goto out; - - VATTR_NULL(&vattr); - vattr.va_size = 0; - VOP_LEASE(vp, p, cred, LEASE_WRITE); - VOP_SETATTR(vp, &vattr, cred, p); - p->p_acflag |= ACORE; - - orig_ts = findSegmentByName(orig_mh, "__TEXT"); - orig_ds = findSegmentByName(orig_mh, "__DATA"); - - if ( orig_ts == NULL || orig_ds == NULL ) goto out; - - header_size = sizeof(struct mach_header) - + orig_ts->cmdsize - + orig_ds->cmdsize - + sizeof(struct symtab_command); - - (void) kmem_alloc_wired( kernel_map, - (vm_offset_t *)&header, - (vm_size_t)header_size); - - if ( header == NULL ) goto out; - - bzero( (void *)header, header_size ); - - /* - * Set up Mach-O header. - */ - mh = (struct mach_header *) header; - mh->magic = orig_mh->magic; - mh->cputype = orig_mh->cputype; - mh->cpusubtype = orig_mh->cpusubtype; - mh->filetype = orig_mh->filetype; - mh->ncmds = 3; - mh->sizeofcmds = header_size - sizeof(struct mach_header); - - /* - * Copy __DATA and __TEXT segment commands from mach_kernel so loadable drivers - * get correct section alignment hints. - */ - sg = (struct segment_command *)(mh+1); - bcopy( orig_ts, sg, orig_ts->cmdsize ); - - sg = (struct segment_command *)((int)sg + sg->cmdsize); - bcopy( orig_ds, sg, orig_ds->cmdsize ); - - sg = (struct segment_command *)(mh+1); - - for ( i = 0; i < 2; i++ ) - { - sg->vmaddr = 0; - sg->vmsize = 0x1000; - sg->fileoff = 0; - sg->filesize = 0; - sg->maxprot = 0; - sg->initprot = 0; - sg->flags = 0; - - se = (struct section *)(sg+1); - for ( j = 0; j < sg->nsects; j++, se++ ) - { - se->addr = 0; - se->size = 0; - se->offset = 0; - se->nreloc = 0; - } - - sg = (struct segment_command *)((int)sg + sg->cmdsize); - } - - symfoffset = round_page(header_size); - - /* - * Set up LC_SYMTAB command - */ - sc = (struct symtab_command *)sg; - sc->cmd = LC_SYMTAB; - sc->cmdsize = sizeof(struct symtab_command); - sc->symoff = symfoffset; - sc->nsyms = sc0->nsyms; - sc->strsize = sc0->strsize; - sc->stroff = symfoffset + sc->nsyms * sizeof(struct nlist); - - symsize = sc->nsyms * sizeof(struct nlist) + sc->strsize; - - nl = (struct nlist *)(sc0+1); - for (i = 0; i < sc->nsyms; i++, nl++ ) - { - if ( (nl->n_type & N_TYPE) == N_SECT ) - { - nl->n_sect = NO_SECT; - nl->n_type = (nl->n_type & ~N_TYPE) | N_ABS; - } - } - - /* - * Write out the load commands at the beginning of the - * file. - */ - error = vn_rdwr(UIO_WRITE, vp, (caddr_t)mh, header_size, (off_t)0, - UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); - if ( error != 0 ) goto out; - - /* - * Write out kernel symbols - */ - error = vn_rdwr(UIO_WRITE, vp, (caddr_t)(sc0+1), symsize, symfoffset, - UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); - if ( error != 0 ) goto out; + const_text = NULL; + se = (struct section *) &orig_ts[1]; + for (i = 0; i < orig_ts->nsects; i++, se++) { + if (!strcmp("__const", se->sectname)) { + const_text = se; + break; + } + } + if (!const_text) + goto out; + + header_size = sizeof(struct mach_header) + + orig_ts->cmdsize + + orig_ds->cmdsize + + sizeof(struct symtab_command); + + (void) kmem_alloc_wired(kernel_map, + (vm_offset_t *) &header, + (vm_size_t) header_size); + if (header) + bzero((void *) header, header_size); + else + goto out; + + /* + * Set up Mach-O header. + */ + mh = (struct mach_header *) header; + mh->magic = orig_mh->magic; + mh->cputype = orig_mh->cputype; + mh->cpusubtype = orig_mh->cpusubtype; + mh->filetype = orig_mh->filetype; + mh->ncmds = 3; + mh->sizeofcmds = header_size - sizeof(struct mach_header); + mh->flags = orig_mh->flags; + + // Initialise the current file offset and addr + offset = round_page(header_size); + addr = (caddr_t) const_text->addr; // Load address of __TEXT,__const + + /* + * Construct a TEXT segment load command + * the only part of the TEXT segment we keep is the __TEXT,__const + * which contains the kernel vtables. + */ + sg = (struct segment_command *) &mh[1]; + bcopy(orig_ts, sg, orig_ts->cmdsize); + sg->vmaddr = (unsigned long) addr; + sg->vmsize = const_text->size; + sg->fileoff = 0; + sg->filesize = const_text->size + round_page(header_size); + sg->maxprot = 0; + sg->initprot = 0; + sg->flags = 0; + se = (struct section *)(sg+1); + for ( j = 0; j < sg->nsects; j++, se++ ) { + se->addr = (unsigned long) addr; + se->size = 0; + se->offset = offset; + se->nreloc = 0; + if (!strcmp("__const", se->sectname)) { + se->size = const_text->size; + addr += const_text->size; + offset += const_text->size; + const_text = se; + } + } + offset = round_page((vm_address_t) offset); + + // Now copy of the __DATA segment load command, the image need + // not be stored to disk nobody needs it, yet! + sg = (struct segment_command *)((int)sg + sg->cmdsize); + bcopy(orig_ds, sg, orig_ds->cmdsize); + + sg->vmaddr = (unsigned long) addr; + sg->vmsize = 0x1000; // One page for some reason? + sg->fileoff = offset; + sg->filesize = 0; + sg->maxprot = 0; + sg->initprot = 0; + sg->flags = 0; + se = (struct section *)(sg+1); + for ( j = 0; j < sg->nsects; j++, se++ ) { + se->addr = (unsigned long) addr; + se->size = 0; + se->offset = offset; + se->nreloc = 0; + } + offset = round_page(offset); + + + /* + * Set up LC_SYMTAB command + */ + st = (struct symtab_command *)((int)sg + sg->cmdsize); + st->cmd = LC_SYMTAB; + st->cmdsize = sizeof(struct symtab_command); + st->symoff = offset; + st->nsyms = orig_st->nsyms; + st->strsize = orig_st->strsize; + st->stroff = offset + st->nsyms * sizeof(struct nlist); + + /* + * Convert the symbol table in place from section references + * to absolute references. + */ + sym = (struct nlist *) orig_le->vmaddr; + for (i = 0; i < st->nsyms; i++, sym++ ) { + if ( (sym->n_type & N_TYPE) == N_SECT) { + sym->n_sect = NO_SECT; + sym->n_type = (sym->n_type & ~N_TYPE) | N_ABS; + } + } + + /* + * Write out the load commands at the beginning of the file. + */ + error = vn_rdwr(UIO_WRITE, vp, (caddr_t) mh, header_size, (off_t) 0, + UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); + if (error) + goto out; + + /* + * Write out the __TEXT,__const data segment. + */ + error = vn_rdwr(UIO_WRITE, vp, (caddr_t) const_text->addr, + const_text->size, const_text->offset, + UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); + if (error) + goto out; + + /* + * Write out kernel symbols + */ + offset = st->nsyms * sizeof(struct nlist) + st->strsize; // symtab size + error = vn_rdwr(UIO_WRITE, vp, + (caddr_t) orig_le->vmaddr, offset, st->symoff, + UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0, p); + if (error) + goto out; out: - if ( header != 0 ) kmem_free(kernel_map, header, header_size); - if ( orig_mh != 0 ) IODTFreeLoaderInfo( "Kernel-__HEADER", (void *)orig_mh, round_page(orig_mhsize) ); - if ( sc0 != 0 ) IODTFreeLoaderInfo( "Kernel-__SYMTAB", (void *)sc0, round_page(sc0_size) ); - - if ( vp != 0 ) - { - VOP_UNLOCK(vp, 0, p); - error1 = vn_close(vp, FWRITE, cred, p); - if (error == 0) error = error1; - } - - return(error); -} + if (header) + kmem_free(kernel_map, header, header_size); + + if (vp) { + VOP_UNLOCK(vp, 0, p); + error1 = vn_close(vp, FWRITE, cred, p); + if (!error) error = error1; + } + return(error); +} /* * */ -struct segment_command *findSegmentByName( struct mach_header *mh, const char *section_name ) +int get_kernel_symfile(struct proc *p, char **symfile) { - struct segment_command *sg; - int i; - - sg = (struct segment_command *)(mh+1); - - for ( i=0; i < mh->ncmds; i++ ) - { - if ( (sg->cmd == LC_SEGMENT) && (strcmp(sg->segname, section_name) == 0) ) - { - return sg; - } - - sg = (struct segment_command *)((int)sg + sg->cmdsize); + if (!kernel_symfile_opened) { + kernel_symfile_opened = 1; + error_code = output_kernel_symbols(p); } + if (!error_code) + *symfile = "\\mach.sym"; - return NULL; -} - - - - - + return error_code; +} diff --git a/bsd/kern/kern_synch.c b/bsd/kern/kern_synch.c index ef076878d..657657490 100644 --- a/bsd/kern/kern_synch.c +++ b/bsd/kern/kern_synch.c @@ -101,20 +101,12 @@ _sleep_continue() } if ((error == EINTR) || (error == ERESTART)) { -#ifdef BSD_USE_APC - thread_apc_set(th_act, bsd_ast); -#else - thread_ast_set(th_act, AST_BSD); - ast_on(AST_BSD); -#endif + thread_ast_set(th_act, AST_BSD); + ast_on(AST_BSD); } if (ut->uu_timo) thread_cancel_timer(); -#if 0 - /* We should never get here without funnel, so we should not grab again */ - thread_funnel_set(kernel_flock, TRUE); -#endif /* 0 */ unix_syscall_return((*ut->uu_continuation)(error)); } @@ -136,12 +128,13 @@ _sleep_continue() static __inline__ #endif int -_sleep(chan, pri, wmsg, timo, continuation) +_sleep(chan, pri, wmsg, timo, continuation, preassert) caddr_t chan; int pri; char *wmsg; int timo; int (*continuation)(); + int preassert; { register struct proc *p; register thread_t thread = current_thread(); @@ -164,11 +157,15 @@ _sleep(chan, pri, wmsg, timo, continuation) #endif p->p_priority = pri & PRIMASK; - if (chan) - assert_wait(chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT); + if (!preassert) { + /* it is already pre asserted */ + if (chan) + assert_wait(chan, (catch) ? THREAD_ABORTSAFE : THREAD_UNINT); + } if (timo) thread_set_timer(timo, NSEC_PER_SEC / hz); + /* * We start our timeout * before calling CURSIG, as we could stop there, and a wakeup @@ -272,12 +269,8 @@ _sleep(chan, pri, wmsg, timo, continuation) } out: if ((error == EINTR) || (error == ERESTART)) { -#ifdef BSD_USE_APC - thread_apc_set(th_act, bsd_ast); -#else - thread_ast_set(th_act, AST_BSD); - ast_on(AST_BSD); -#endif + thread_ast_set(th_act, AST_BSD); + ast_on(AST_BSD); } if (timo) thread_cancel_timer(); @@ -290,7 +283,7 @@ int sleep(chan, pri) int pri; { - return (_sleep((caddr_t)chan, pri, (char *)NULL, 0, (void (*)())0 )); + return (_sleep((caddr_t)chan, pri, (char *)NULL, 0, (void (*)())0, 0)); } @@ -300,7 +293,7 @@ int tsleep(chan, pri, wmsg, timo) char * wmsg; int timo; { - return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0 )); + return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0, 0)); } int tsleep0(chan, pri, wmsg, timo, continuation) @@ -311,9 +304,24 @@ int tsleep0(chan, pri, wmsg, timo, continuation) int (*continuation)(); { #if defined (__i386__) - return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0 )); + return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0, 0)); +#else + return(_sleep((caddr_t)chan, pri, wmsg, timo, continuation, 0)); +#endif +} + +/* tsleeps without assertwait or thread block */ +int tsleep1(chan, pri, wmsg, timo, continuation) + void *chan; + int pri; + char * wmsg; + int timo; + int (*continuation)(); +{ +#if defined (__i386__) + return(_sleep((caddr_t)chan, pri, wmsg, timo, (void (*)())0, 1)); #else - return(_sleep((caddr_t)chan, pri, wmsg, timo, continuation)); + return(_sleep((caddr_t)chan, pri, wmsg, timo, continuation, 1)); #endif } @@ -348,16 +356,5 @@ void resetpriority(p) register struct proc *p; { - int newpri; -#if FIXME - if (p->p_nice < 0) - newpri = BASEPRI_USER + - (p->p_nice * (MAXPRI_USER - BASEPRI_USER)) / PRIO_MIN; - else - newpri = BASEPRI_USER - - (p->p_nice * BASEPRI_USER) / PRIO_MAX; - - (void)task_priority(p->task, newpri, TRUE); -#endif /* FIXME */ + (void)task_importance(p->task, -p->p_nice); } - diff --git a/bsd/kern/kern_sysctl.c b/bsd/kern/kern_sysctl.c index 047eb70b1..41091784d 100644 --- a/bsd/kern/kern_sysctl.c +++ b/bsd/kern/kern_sysctl.c @@ -189,6 +189,7 @@ __sysctl(p, uap, retval) sysctlfn *fn; int name[CTL_MAXNAME]; int i; + int error1; /* * all top-level sysctl names are non-terminal @@ -210,7 +211,8 @@ __sysctl(p, uap, retval) switch (name[0]) { case CTL_KERN: fn = kern_sysctl; - if (name[1] != KERN_VNODE) /* XXX */ + if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE) + && (name[1] != KERN_PROC)) dolock = 0; break; case CTL_HW: @@ -255,8 +257,16 @@ __sysctl(p, uap, retval) memlock.sl_lock = 1; } - if (dolock) - vslock(uap->old, oldlen); + if (dolock && oldlen && (error = vslock(uap->old, oldlen))) { + if (name[1] != KERN_PCSAMPLES) { + memlock.sl_lock = 0; + if (memlock.sl_want) { + memlock.sl_want = 0; + wakeup((caddr_t)&memlock); + } + } + return(error); + } savelen = oldlen; } @@ -272,8 +282,11 @@ __sysctl(p, uap, retval) uap->new, uap->newlen, &oldlen); if (uap->old != NULL) { - if (dolock) - vsunlock(uap->old, savelen, B_WRITE); + if (dolock && savelen) { + error1 = vsunlock(uap->old, savelen, B_WRITE); + if (!error && error1) + error = error1; + } if (name[1] != KERN_PCSAMPLES) { memlock.sl_lock = 0; if (memlock.sl_want) { @@ -1096,6 +1109,7 @@ sysctl_procargs(name, namelen, where, sizep) */ pid = name[0]; + restart: p = pfind(pid); if (p == NULL) { return(EINVAL); @@ -1126,7 +1140,16 @@ sysctl_procargs(name, namelen, where, sizep) if (task == NULL) return(EINVAL); - task_reference(task); + /* + * A regular task_reference call can block, causing the funnel + * to be dropped and allowing the proc/task to get freed. + * Instead, we issue a non-blocking attempt at the task reference, + * and look up the proc/task all over again if that fails. + */ + if (!task_reference_try(task)) { + mutex_pause(); + goto restart; + } ret = kmem_alloc(kernel_map, ©_start, round_page(arg_size)); if (ret != KERN_SUCCESS) { diff --git a/bsd/kern/kern_time.c b/bsd/kern/kern_time.c index 0f225ed52..f7eeeb639 100644 --- a/bsd/kern/kern_time.c +++ b/bsd/kern/kern_time.c @@ -225,12 +225,10 @@ inittodr(base) time_t base; { /* - * Initialize the calendar by - * reading the BBC, if not already set. - */ - clock_initialize_calendar(); - - /* + * Assertion: + * The calendar has already been + * set up from the battery clock. + * * The value returned by microtime() * is gotten from the calendar. */ diff --git a/bsd/kern/mach_fat.c b/bsd/kern/mach_fat.c index 899c8c0b0..6c25ae9d4 100644 --- a/bsd/kern/mach_fat.c +++ b/bsd/kern/mach_fat.c @@ -73,7 +73,6 @@ fatfile_getarch( int best_grade; int nfat_arch; int end_of_archs; - struct proc *p = current_proc(); /* XXXX */ struct fat_header *header; off_t filesize; @@ -93,7 +92,7 @@ fatfile_getarch( + nfat_arch * sizeof(struct fat_arch); #if 0 filesize = ubc_getsize(vp); - if (end_of_archs > (int)filesize) + if (end_of_archs > (int)filesize) { return(LOAD_BADMACHO); } #endif diff --git a/bsd/kern/mach_loader.c b/bsd/kern/mach_loader.c index 7f30881e9..ea6eda046 100644 --- a/bsd/kern/mach_loader.c +++ b/bsd/kern/mach_loader.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -41,10 +41,6 @@ #include <sys/fcntl.h> #include <sys/ubc.h> -#include <ufs/ufs/lockf.h> -#include <ufs/ufs/quota.h> -#include <ufs/ufs/inode.h> - #include <mach/mach_types.h> #include <kern/mach_loader.h> @@ -68,65 +64,60 @@ static load_return_t parse_machfile( struct vnode *vp, - vm_map_t map, + vm_map_t map, + thread_act_t thr_act, struct mach_header *header, unsigned long file_offset, unsigned long macho_size, - int depth, - unsigned long *lib_version, + int depth, load_result_t *result ), load_segment( struct segment_command *scp, - void * pager, - unsigned long pager_offset, - unsigned long macho_size, - unsigned long end_of_file, - vm_map_t map, - load_result_t *result + void * pager, + unsigned long pager_offset, + unsigned long macho_size, + unsigned long end_of_file, + vm_map_t map, + load_result_t *result ), load_unixthread( struct thread_command *tcp, - load_result_t *result + thread_act_t thr_act, + load_result_t *result ), load_thread( struct thread_command *tcp, - load_result_t *result + thread_act_t thr_act, + load_result_t *result ), load_threadstate( - thread_t thread, + thread_t thread, unsigned long *ts, unsigned long total_size ), load_threadstack( - thread_t thread, + thread_t thread, unsigned long *ts, unsigned long total_size, - vm_offset_t *user_stack + vm_offset_t *user_stack, + int *customstack ), load_threadentry( - thread_t thread, + thread_t thread, unsigned long *ts, unsigned long total_size, - vm_offset_t *entry_point -), -load_fvmlib( - struct fvmlib_command *lcp, - vm_map_t map, - int depth -), -load_idfvmlib( - struct fvmlib_command *lcp, - unsigned long *version + vm_offset_t *entry_point ), load_dylinker( struct dylinker_command *lcp, - vm_map_t map, - int depth, - load_result_t *result + vm_map_t map, + thread_act_t thr_act, + int depth, + load_result_t *result ), get_macho_vnode( - char *path, + char *path, struct mach_header *mach_header, unsigned long *file_offset, unsigned long *macho_size, @@ -139,7 +130,9 @@ load_machfile( struct mach_header *header, unsigned long file_offset, unsigned long macho_size, - load_result_t *result + load_result_t *result, + thread_act_t thr_act, + vm_map_t new_map ) { pmap_t pmap; @@ -148,29 +141,38 @@ load_machfile( load_result_t myresult; kern_return_t kret; load_return_t lret; + boolean_t create_map = TRUE; + + if (new_map != VM_MAP_NULL) { + create_map = FALSE; + } - old_map = current_map(); + if (create_map) { + old_map = current_map(); #ifdef i386 - pmap = get_task_pmap(current_task()); - pmap_reference(pmap); + pmap = get_task_pmap(current_task()); + pmap_reference(pmap); #else - pmap = pmap_create((vm_size_t) 0); + pmap = pmap_create((vm_size_t) 0); #endif - map = vm_map_create(pmap, - get_map_min(old_map), - get_map_max(old_map), - TRUE); /**** FIXME ****/ + map = vm_map_create(pmap, + get_map_min(old_map), + get_map_max(old_map), + TRUE); /**** FIXME ****/ + } else + map = new_map; if (!result) result = &myresult; *result = (load_result_t) { 0 }; - lret = parse_machfile(vp, map, header, file_offset, macho_size, - 0, (unsigned long *)0, result); + lret = parse_machfile(vp, map, thr_act, header, file_offset, macho_size, + 0, result); if (lret != LOAD_SUCCESS) { - vm_map_deallocate(map); /* will lose pmap reference too */ + if (create_map) + vm_map_deallocate(map); /* will lose pmap reference too */ return(lret); } /* @@ -185,18 +187,19 @@ load_machfile( * That lets us get off the pmap associated with it, and * then we can release it. */ - task_halt(current_task()); + if (create_map) { + task_halt(current_task()); - old_map = swap_task_map(current_task(), map); - vm_map_deallocate(old_map); + old_map = swap_task_map(current_task(), map); + vm_map_deallocate(old_map); - old_map = swap_act_map(current_act(), map); + old_map = swap_act_map(current_act(), map); #ifndef i386 - pmap_switch(pmap); /* Make sure we are using the new pmap */ + pmap_switch(pmap); /* Make sure we are using the new pmap */ #endif - - vm_map_deallocate(old_map); + vm_map_deallocate(old_map); + } return(LOAD_SUCCESS); } @@ -208,11 +211,11 @@ load_return_t parse_machfile( struct vnode *vp, vm_map_t map, + thread_act_t thr_act, struct mach_header *header, unsigned long file_offset, unsigned long macho_size, int depth, - unsigned long *lib_version, load_result_t *result ) { @@ -229,12 +232,16 @@ parse_machfile( struct proc *p = current_proc(); /* XXXX */ int error; int resid=0; + task_t task; /* * Break infinite recursion */ if (depth > 6) return(LOAD_FAILURE); + + task = (task_t)get_threadtask(thr_act); + depth++; /* @@ -293,35 +300,20 @@ parse_machfile( * Map the load commands into kernel memory. */ addr = 0; -#if 0 /* [ -#if FIXME - ret = vm_allocate_with_pager(kernel_map, &addr, size, TRUE, pager, - file_offset); -#else - ret = vm_map(kernel_map,&addr,size,0,TRUE, pager, file_offset, FALSE, - VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT); -#endif /* FIXME */ - if (ret != KERN_SUCCESS) { - return(LOAD_NOSPACE); - } - ubc_map(vp); -#else /* 0 ][ */ kl_size = size; kl_addr = kalloc(size); addr = kl_addr; - if (addr == NULL) { - printf("No space to readin load commands\n"); + if (addr == NULL) return(LOAD_NOSPACE); - } + if(error = vn_rdwr(UIO_READ, vp, addr, size, file_offset, UIO_SYSSPACE, 0, p->p_ucred, &resid, p)) { - printf("Load command read over nfs failed\n"); - if (kl_addr ) kfree(kl_addr,kl_size); + if (kl_addr ) + kfree(kl_addr, kl_size); return(EIO); } /* ubc_map(vp); */ /* NOT HERE */ -#endif /* 0 ] */ /* * Scan through the commands, processing each one as necessary. */ @@ -341,10 +333,8 @@ parse_machfile( */ if (offset > header->sizeofcmds + sizeof(struct mach_header)) { -#if 0 - vm_map_remove(kernel_map, addr, addr + size); -#endif - if (kl_addr ) kfree(kl_addr,kl_size); + if (kl_addr ) + kfree(kl_addr, kl_size); return(LOAD_BADMACHO); } @@ -366,31 +356,16 @@ parse_machfile( case LC_THREAD: if (pass != 2) break; - ret = load_thread((struct thread_command *)lcp, + ret = load_thread((struct thread_command *)lcp, thr_act, result); break; case LC_UNIXTHREAD: if (pass != 2) break; ret = load_unixthread( - (struct thread_command *) lcp, + (struct thread_command *) lcp, thr_act, result); break; - case LC_LOADFVMLIB: - if (pass != 1) - break; - ret = load_fvmlib((struct fvmlib_command *)lcp, - map, depth); - break; - case LC_IDFVMLIB: - if (pass != 1) - break; - if (lib_version) { - ret = load_idfvmlib( - (struct fvmlib_command *)lcp, - lib_version); - } - break; case LC_LOAD_DYLINKER: if (pass != 2) break; @@ -415,7 +390,7 @@ parse_machfile( shared_region_mapping_t next; RedoLookup: - vm_get_shared_region(current_task(), &shared_region); + vm_get_shared_region(task, &shared_region); map_info.self = (vm_offset_t)shared_region; shared_region_mapping_info(shared_region, &(map_info.text_region), @@ -432,7 +407,7 @@ RedoLookup: (map_info.flags & SHARED_REGION_SYSTEM)) { if(map_info.self != (vm_offset_t)system_shared_region) { shared_region_mapping_ref(system_shared_region); - vm_set_shared_region(current_task(), + vm_set_shared_region(task, system_shared_region); shared_region_mapping_dealloc( (shared_region_mapping_t)map_info.self); @@ -454,13 +429,12 @@ RedoLookup: map_info.data_region, 0, TRUE, VM_PROT_READ, VM_PROT_READ, VM_INHERIT_SHARE); } - ret = load_dylinker(dlp, map, depth, result); + ret = load_dylinker(dlp, map, thr_act, depth, result); } - if (kl_addr ) kfree(kl_addr,kl_size); -#if 0 - vm_map_remove(kernel_map, addr, addr + size); -#endif + if (kl_addr ) + kfree(kl_addr, kl_size); + if ((ret == LOAD_SUCCESS) && (depth == 1) && (result->thread_count == 0)) ret = LOAD_FAILURE; @@ -591,23 +565,31 @@ static load_return_t load_unixthread( struct thread_command *tcp, + thread_act_t thr_act, load_result_t *result ) { thread_t thread = current_thread(); load_return_t ret; + int customstack =0; if (result->thread_count != 0) return (LOAD_FAILURE); + thread = getshuttle_thread(thr_act); ret = load_threadstack(thread, (unsigned long *)(((vm_offset_t)tcp) + sizeof(struct thread_command)), tcp->cmdsize - sizeof(struct thread_command), - &result->user_stack); + &result->user_stack, + &customstack); if (ret != LOAD_SUCCESS) return(ret); + if (customstack) + result->customstack = 1; + else + result->customstack = 0; ret = load_threadentry(thread, (unsigned long *)(((vm_offset_t)tcp) + sizeof(struct thread_command)), @@ -633,17 +615,22 @@ static load_return_t load_thread( struct thread_command *tcp, + thread_act_t thr_act, load_result_t *result ) { thread_t thread; kern_return_t kret; load_return_t lret; + task_t task; + int customstack=0; - if (result->thread_count == 0) - thread = current_thread(); - else { - kret = thread_create(current_task(), &thread); + task = get_threadtask(thr_act); + thread = getshuttle_thread(thr_act); + + /* if count is 0; same as thr_act */ + if (result->thread_count != 0) { + kret = thread_create(task, &thread); if (kret != KERN_SUCCESS) return(LOAD_RESOURCE); thread_deallocate(thread); @@ -657,15 +644,21 @@ load_thread( return (lret); if (result->thread_count == 0) { - lret = load_threadstack(current_thread(), + lret = load_threadstack(thread, (unsigned long *)(((vm_offset_t)tcp) + sizeof(struct thread_command)), tcp->cmdsize - sizeof(struct thread_command), - &result->user_stack); + &result->user_stack, + &customstack); + if (customstack) + result->customstack = 1; + else + result->customstack = 0; + if (lret != LOAD_SUCCESS) return(lret); - lret = load_threadentry(current_thread(), + lret = load_threadentry(thread, (unsigned long *)(((vm_offset_t)tcp) + sizeof(struct thread_command)), tcp->cmdsize - sizeof(struct thread_command), @@ -722,7 +715,8 @@ load_threadstack( thread_t thread, unsigned long *ts, unsigned long total_size, - vm_offset_t *user_stack + vm_offset_t *user_stack, + int *customstack ) { kern_return_t ret; @@ -739,7 +733,7 @@ load_threadstack( total_size -= (size+2)*sizeof(unsigned long); if (total_size < 0) return(LOAD_BADMACHO); - ret = thread_userstack(thread, flavor, ts, size, user_stack); + ret = thread_userstack(thread, flavor, ts, size, user_stack, customstack); if (ret != KERN_SUCCESS) return(LOAD_FAILURE); ts += size; /* ts is a (unsigned long *) */ @@ -778,71 +772,13 @@ load_threadentry( return(LOAD_SUCCESS); } -static -load_return_t -load_fvmlib( - struct fvmlib_command *lcp, - vm_map_t map, - int depth -) -{ - char *name; - char *p; - struct vnode *vp; - struct mach_header header; - unsigned long file_offset; - unsigned long macho_size; - unsigned long lib_version; - load_result_t myresult; - kern_return_t ret; - - name = (char *)lcp + lcp->fvmlib.name.offset; - /* - * Check for a proper null terminated string. - */ - p = name; - do { - if (p >= (char *)lcp + lcp->cmdsize) - return(LOAD_BADMACHO); - } while (*p++); - - ret = get_macho_vnode(name, &header, &file_offset, &macho_size, &vp); - if (ret) - return (ret); - - myresult = (load_result_t) { 0 }; - - /* - * Load the Mach-O. - */ - ret = parse_machfile(vp, map, &header, - file_offset, macho_size, - depth, &lib_version, &myresult); - - if ((ret == LOAD_SUCCESS) && - (lib_version < lcp->fvmlib.minor_version)) - ret = LOAD_SHLIB; - - vrele(vp); - return(ret); -} - -static -load_return_t -load_idfvmlib( - struct fvmlib_command *lcp, - unsigned long *version -) -{ - *version = lcp->fvmlib.minor_version; - return(LOAD_SUCCESS); -} static load_return_t load_dylinker( struct dylinker_command *lcp, vm_map_t map, + thread_act_t thr_act, int depth, load_result_t *result ) @@ -883,9 +819,9 @@ load_dylinker( copy_map = vm_map_create(pmap_create(macho_size), get_map_min(map), get_map_max( map), TRUE); - ret = parse_machfile(vp, copy_map, &header, + ret = parse_machfile(vp, copy_map, thr_act, &header, file_offset, macho_size, - depth, 0, &myresult); + depth, &myresult); if (ret) goto out; @@ -959,20 +895,21 @@ get_macho_vnode( struct proc *p = current_proc(); /* XXXX */ boolean_t is_fat; struct fat_arch fat_arch; - int error; + int error = KERN_SUCCESS; int resid; union { struct mach_header mach_header; struct fat_header fat_header; char pad[512]; } header; - error = KERN_SUCCESS; + off_t fsize = (off_t)0; + struct ucred *cred = p->p_ucred; ndp = &nid; atp = &attr; /* init the namei data to point the file user's program name */ - NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF | SAVENAME, UIO_SYSSPACE, path, p); + NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, p); if (error = namei(ndp)) return(error); @@ -986,7 +923,7 @@ get_macho_vnode( } /* get attributes */ - if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) + if (error = VOP_GETATTR(vp, &attr, cred, p)) goto bad1; /* Check mount point */ @@ -998,22 +935,29 @@ get_macho_vnode( if ((vp->v_mount->mnt_flag & MNT_NOSUID) || (p->p_flag & P_TRACED)) atp->va_mode &= ~(VSUID | VSGID); - /* check access. for root we have to see if any exec bit on */ - if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) + /* check access. for root we have to see if any exec bit on */ + if (error = VOP_ACCESS(vp, VEXEC, cred, p)) goto bad1; if ((atp->va_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) { error = EACCES; goto bad1; } + /* hold the vnode for the IO */ + if (UBCINFOEXISTS(vp) && !ubc_hold(vp)) { + error = ENOENT; + goto bad1; + } + /* try to open it */ - if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) + if (error = VOP_OPEN(vp, FREAD, cred, p)) { + ubc_rele(vp); goto bad1; + } + if(error = vn_rdwr(UIO_READ, vp, (caddr_t)&header, sizeof(header), 0, - UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p)) + UIO_SYSSPACE, IO_NODELOCKED, cred, &resid, p)) goto bad2; - -/* XXXX WMG - we should check for a short read of the header here */ if (header.mach_header.magic == MH_MAGIC) is_fat = FALSE; @@ -1026,73 +970,51 @@ get_macho_vnode( } if (is_fat) { - /* - * Look up our architecture in the fat file. - */ + /* Look up our architecture in the fat file. */ error = fatfile_getarch(vp, (vm_offset_t)(&header.fat_header), &fat_arch); - if (error != LOAD_SUCCESS) { + if (error != LOAD_SUCCESS) goto bad2; - } - /* - * Read the Mach-O header out of it - */ + + /* Read the Mach-O header out of it */ error = vn_rdwr(UIO_READ, vp, &header.mach_header, sizeof(header.mach_header), fat_arch.offset, - UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p); + UIO_SYSSPACE, IO_NODELOCKED, cred, &resid, p); if (error) { error = LOAD_FAILURE; goto bad2; } - /* - * Is this really a Mach-O? - */ + /* Is this really a Mach-O? */ if (header.mach_header.magic != MH_MAGIC) { error = LOAD_BADMACHO; goto bad2; } - - *mach_header = header.mach_header; + *file_offset = fat_arch.offset; - *macho_size = fat_arch.size; - *vpp = vp; - /* leaks otherwise - A.R */ - FREE_ZONE(ndp->ni_cnd.cn_pnbuf, ndp->ni_cnd.cn_pnlen, M_NAMEI); - - /* i_lock exclusive panics, otherwise during pageins */ - VOP_UNLOCK(vp, 0, p); - return (error); + *macho_size = fsize = fat_arch.size; } else { - - *mach_header = header.mach_header; + *file_offset = 0; - if (UBCISVALID(vp)) - ubc_setsize(vp, attr.va_size); /* XXX why? */ - *macho_size = attr.va_size; - *vpp = vp; - /* leaks otherwise - A.R */ - FREE_ZONE(ndp->ni_cnd.cn_pnbuf, ndp->ni_cnd.cn_pnlen, M_NAMEI); - - /* i_lock exclusive panics, otherwise during pageins */ - VOP_UNLOCK(vp, 0, p); - return (error); + *macho_size = fsize = attr.va_size; } + *mach_header = header.mach_header; + *vpp = vp; + if (UBCISVALID(vp)) + ubc_setsize(vp, fsize); /* XXX why? */ + + VOP_UNLOCK(vp, 0, p); + ubc_rele(vp); + return (error); + bad2: - /* - * unlock and close the vnode, restore the old one, free the - * pathname buf, and punt. - */ VOP_UNLOCK(vp, 0, p); - vn_close(vp, FREAD, p->p_ucred, p); - FREE_ZONE(ndp->ni_cnd.cn_pnbuf, ndp->ni_cnd.cn_pnlen, M_NAMEI); + error = VOP_CLOSE(vp, FREAD, cred, p); + ubc_rele(vp); + vrele(vp); return (error); + bad1: - /* - * free the namei pathname buffer, and put the vnode - * (which we don't yet have open). - */ - FREE_ZONE(ndp->ni_cnd.cn_pnbuf, ndp->ni_cnd.cn_pnlen, M_NAMEI); vput(vp); return(error); } diff --git a/bsd/kern/mach_loader.h b/bsd/kern/mach_loader.h index 8e9715bcc..26cb05e9a 100644 --- a/bsd/kern/mach_loader.h +++ b/bsd/kern/mach_loader.h @@ -48,6 +48,7 @@ typedef struct _load_result { unsigned int /* boolean_t */ unixproc :1, dynlinker :1, + customstack :1, :0; } load_result_t; @@ -56,7 +57,9 @@ load_return_t load_machfile( struct mach_header *header, unsigned long file_offset, unsigned long macho_size, - load_result_t *result); + load_result_t *result, + thread_act_t thr_act, + vm_map_t map); #define LOAD_SUCCESS 0 #define LOAD_BADARCH 1 /* CPU type/subtype not found */ diff --git a/bsd/kern/mach_process.c b/bsd/kern/mach_process.c index 284e21a88..db317e75a 100644 --- a/bsd/kern/mach_process.c +++ b/bsd/kern/mach_process.c @@ -77,6 +77,7 @@ #include <sys/uio.h> #include <sys/user.h> #include <sys/sysctl.h> +#include <sys/wait.h> #include <sys/mount.h> @@ -126,6 +127,19 @@ ptrace(p, uap, retval) unsigned long state_count; + if (uap->req == PT_DENY_ATTACH) { + if (ISSET(p->p_flag, P_TRACED)) { + exit1(p, W_EXITCODE(ENOTSUP, 0), retval); + /* drop funnel befewo we return */ + thread_funnel_set(kernel_flock, FALSE); + thread_exception_return(); + /* NOTREACHED */ + } + SET(p->p_flag, P_NOATTACH); + + return(0); + } + /* * Intercept and deal with "please trace me" request. */ @@ -174,6 +188,10 @@ ptrace(p, uap, retval) (error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); + if (ISSET(t->p_flag, P_NOATTACH)) { + psignal(p, SIGSEGV); + return (EBUSY); + } SET(t->p_flag, P_TRACED); t->p_oppid = t->p_pptr->p_pid; if (t->p_pptr != p) @@ -231,7 +249,7 @@ ptrace(p, uap, retval) * Tell child process to kill itself after it * is resumed by adding NSIG to p_cursig. [see issig] */ - psignal_lock(t, SIGKILL, 0, 1); + psignal_lock(t, SIGKILL, 0, 0); goto resume; case PT_STEP: /* single step the child */ diff --git a/bsd/kern/subr_log.c b/bsd/kern/subr_log.c index 792975a0f..6f78c5d10 100644 --- a/bsd/kern/subr_log.c +++ b/bsd/kern/subr_log.c @@ -201,9 +201,10 @@ logread(dev, uio, flag) /*ARGSUSED*/ int -logselect(dev, rw, p) +logselect(dev, rw, wql, p) dev_t dev; int rw; + void * wql; struct proc *p; { int s = splhigh(); @@ -215,7 +216,7 @@ logselect(dev, rw, p) splx(s); return (1); } - selrecord(p, &logsoftc.sc_selp); + selrecord(p, &logsoftc.sc_selp, wql); break; } splx(s); diff --git a/bsd/kern/sys_generic.c b/bsd/kern/sys_generic.c index cf5878004..ad99a98d0 100644 --- a/bsd/kern/sys_generic.c +++ b/bsd/kern/sys_generic.c @@ -105,6 +105,8 @@ #include <netinet/tcp_var.h> #include <netinet/tcpip.h> #include <netinet/tcp_debug.h> +/* for wait queue based select */ +#include <kern/wait_queue.h> /* * Read system call. @@ -431,6 +433,8 @@ ioctl(p, uap, retval) int selwait, nselcoll; +#define SEL_FIRSTPASS 1 +#define SEL_SECONDPASS 2 /* * Select system call. @@ -444,8 +448,11 @@ struct select_args { }; extern int selcontinue(int error); -static int selscan( struct proc *p, u_int32_t *ibits, u_int32_t *obits, - int nfd, register_t *retval); +extern int selprocess(int error, int sel_pass); +static int selscan( struct proc *p, struct _select * sel, + int nfd, register_t *retval, int sel_pass); +static int selcount(struct proc *p, u_int32_t *ibits, u_int32_t *obits, + int nfd, int * count, int * nfcount); select(p, uap, retval) register struct proc *p; @@ -453,11 +460,14 @@ select(p, uap, retval) register_t *retval; { int s, error = 0, timo; - u_int ni, nw; + u_int ni, nw, size; thread_act_t th_act; struct uthread *uth; struct _select *sel; int needzerofill = 1; + int kfcount =0; + int nfcount = 0; + int count = 0; th_act = current_act(); uth = get_bsdthread_info(th_act); @@ -465,8 +475,9 @@ select(p, uap, retval) retval = (int *)get_bsduthreadrval(th_act); *retval = 0; - if (uap->nd < 0) + if (uap->nd < 0) { return (EINVAL); + } if (uap->nd > p->p_fd->fd_nfiles) uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ @@ -531,19 +542,55 @@ select(p, uap, retval) error = EINVAL; goto continuation; } - s = splhigh(); + timeradd(&sel->atv, &time, &sel->atv); timo = hzto(&sel->atv); - splx(s); } else timo = 0; sel->poll = timo; + sel->nfcount = 0; + if (error = selcount(p, sel->ibits, sel->obits, uap->nd, &count, &nfcount)) { + goto continuation; + } + + sel->nfcount = nfcount; + sel->count = count; + size = SIZEOF_WAITQUEUE_SUB + (count * SIZEOF_WAITQUEUE_LINK); + if (sel->allocsize) { + if (uth->uu_wqsub == 0) + panic("select: wql memory smashed"); + /* needed for the select now */ + if (size > sel->allocsize) { + kfree(uth->uu_wqsub, sel->allocsize); + sel->allocsize = size; + uth->uu_wqsub = (wait_queue_sub_t)kalloc(sel->allocsize); + if (uth->uu_wqsub == (wait_queue_sub_t)NULL) + panic("failed to allocate memory for waitqueue\n"); + sel->wql = (char *)uth->uu_wqsub + SIZEOF_WAITQUEUE_SUB; + } + } else { + sel->count = count; + sel->allocsize = size; + uth->uu_wqsub = (wait_queue_sub_t)kalloc(sel->allocsize); + if (uth->uu_wqsub == (wait_queue_sub_t)NULL) + panic("failed to allocate memory for waitqueue\n"); + sel->wql = (char *)uth->uu_wqsub + SIZEOF_WAITQUEUE_SUB; + } + bzero(uth->uu_wqsub, size); + wait_queue_sub_init(uth->uu_wqsub, (SYNC_POLICY_FIFO | SYNC_POLICY_PREPOST)); + continuation: - selcontinue(error); + selprocess(error, SEL_FIRSTPASS); +} + +int +selcontinue(int error) +{ + selprocess(error, SEL_SECONDPASS); } int -selcontinue(error) +selprocess(error, sel_pass) { int s, ncoll, timo; u_int ni, nw; @@ -553,6 +600,10 @@ selcontinue(error) struct select_args *uap; int *retval; struct _select *sel; + int unwind = 1; + int prepost =0; + int somewakeup = 0; + int doretry = 0; p = current_proc(); th_act = current_act(); @@ -561,21 +612,53 @@ selcontinue(error) uth = get_bsdthread_info(th_act); sel = &uth->uu_state.ss_select; + /* if it is first pass wait queue is not setup yet */ + if ((error != 0) && (sel_pass == SEL_FIRSTPASS)) + unwind = 0; + if (sel->count == 0) + unwind = 0; retry: - if (error != 0) + if (error != 0) { goto done; + } + ncoll = nselcoll; p->p_flag |= P_SELECT; - error = selscan(p, sel->ibits, sel->obits, uap->nd, retval); - if (error || *retval) - goto done; - s = splhigh(); + /* skip scans if the select is just for timeouts */ + if (sel->count) { + if (sel_pass == SEL_FIRSTPASS) + wait_queue_sub_clearrefs(uth->uu_wqsub); + + error = selscan(p, sel, uap->nd, retval, sel_pass); + if (error || *retval) { + goto done; + } + if (prepost) { + /* if the select of log, then we canwakeup and discover some one + * else already read the data; go toselct again if time permits + */ + prepost = 0; + doretry = 1; + } + if (somewakeup) { + somewakeup = 0; + doretry = 1; + } + } + /* this should be timercmp(&time, &atv, >=) */ if (uap->tv && (time.tv_sec > sel->atv.tv_sec || time.tv_sec == sel->atv.tv_sec && time.tv_usec >= sel->atv.tv_usec)) { - splx(s); goto done; } + + if (doretry) { + /* cleanup obits and try again */ + doretry = 0; + sel_pass = SEL_FIRSTPASS; + goto retry; + } + /* * To effect a poll, the timeout argument should be * non-nil, pointing to a zero-valued timeval structure. @@ -583,32 +666,45 @@ retry: timo = sel->poll; if (uap->tv && (timo == 0)) { - splx(s); goto done; } - if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { - splx(s); + + /* No spurious wakeups due to colls,no need to check for them */ + if ((sel_pass == SEL_SECONDPASS) || ((p->p_flag & P_SELECT) == 0)) { + sel_pass = SEL_FIRSTPASS; goto retry; } + p->p_flag &= ~P_SELECT; -#if 1 /* Use Continuations */ - error = tsleep0((caddr_t)&selwait, PSOCK | PCATCH, "select", timo, selcontinue); - /* NOTREACHED */ -#else - error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); -#endif - splx(s); - if (error == 0) + /* if the select is just for timeout skip check */ + if (sel->count &&(sel_pass == SEL_SECONDPASS)) + panic("selprocess: 2nd pass assertwaiting"); + + /* Wait Queue Subordinate has waitqueue as first element */ + if (wait_queue_assert_wait(uth->uu_wqsub, &selwait, THREAD_ABORTSAFE)) { + /* If it is true then there are no preposted events */ + error = tsleep1((caddr_t)&selwait, PSOCK | PCATCH, "select", timo, selcontinue); + } else { + prepost = 1; + error = 0; + } + + sel_pass = SEL_SECONDPASS; + if (error == 0) { + if (!prepost) + somewakeup =1; goto retry; + } done: + if (unwind) + wait_subqueue_unlink_all(uth->uu_wqsub); p->p_flag &= ~P_SELECT; /* select is not restarted after signals... */ if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; - nw = howmany(uap->nd, NFDBITS); ni = nw * sizeof(fd_mask); @@ -636,20 +732,27 @@ done: } static int -selscan(p, ibits, obits, nfd, retval) +selscan(p, sel, nfd, retval, sel_pass) struct proc *p; - u_int32_t *ibits, *obits; + struct _select *sel; int nfd; register_t *retval; + int sel_pass; { register struct filedesc *fdp = p->p_fd; register int msk, i, j, fd; register u_int32_t bits; struct file *fp; int n = 0; + int nc = 0; static int flag[3] = { FREAD, FWRITE, 0 }; u_int32_t *iptr, *optr; u_int nw; + u_int32_t *ibits, *obits; + char * wql; + int nfunnel = 0; + int count, nfcount; + char * wql_ptr; /* * Problems when reboot; due to MacOSX signal probs @@ -660,26 +763,81 @@ selscan(p, ibits, obits, nfd, retval) return(EIO); } + ibits = sel->ibits; + obits = sel->obits; + wql = sel->wql; + + count = sel->count; + nfcount = sel->nfcount; + + if (nfcount > count) + panic("selcount count<nfcount"); + nw = howmany(nfd, NFDBITS); - for (msk = 0; msk < 3; msk++) { - iptr = (u_int32_t *)&ibits[msk * nw]; - optr = (u_int32_t *)&obits[msk * nw]; - for (i = 0; i < nfd; i += NFDBITS) { - bits = iptr[i/NFDBITS]; - while ((j = ffs(bits)) && (fd = i + --j) < nfd) { - bits &= ~(1 << j); - fp = fdp->fd_ofiles[fd]; - if (fp == NULL || - (fdp->fd_ofileflags[fd] & UF_RESERVED)) - return (EBADF); - if (fp->f_ops && (*fp->f_ops->fo_select)(fp, flag[msk], p)) { - optr[fd/NFDBITS] |= (1 << (fd % NFDBITS)); - n++; + nc = 0; + if ( nfcount < count) { + /* some or all in kernel funnel */ + for (msk = 0; msk < 3; msk++) { + iptr = (u_int32_t *)&ibits[msk * nw]; + optr = (u_int32_t *)&obits[msk * nw]; + for (i = 0; i < nfd; i += NFDBITS) { + bits = iptr[i/NFDBITS]; + while ((j = ffs(bits)) && (fd = i + --j) < nfd) { + bits &= ~(1 << j); + fp = fdp->fd_ofiles[fd]; + if (fp == NULL || + (fdp->fd_ofileflags[fd] & UF_RESERVED)) { + return(EBADF); + } + if (sel_pass == SEL_SECONDPASS) + wql_ptr = (char *)0; + else + wql_ptr = (wql+ nc * SIZEOF_WAITQUEUE_LINK); + if (fp->f_ops && (fp->f_type != DTYPE_SOCKET) + && (*fp->f_ops->fo_select)(fp, flag[msk], wql_ptr, p)) { + optr[fd/NFDBITS] |= (1 << (fd % NFDBITS)); + n++; + } + nc++; } } } } + + if (nfcount) { + /* socket file descriptors for scan */ + thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); + + nc = 0; + for (msk = 0; msk < 3; msk++) { + iptr = (u_int32_t *)&ibits[msk * nw]; + optr = (u_int32_t *)&obits[msk * nw]; + for (i = 0; i < nfd; i += NFDBITS) { + bits = iptr[i/NFDBITS]; + while ((j = ffs(bits)) && (fd = i + --j) < nfd) { + bits &= ~(1 << j); + fp = fdp->fd_ofiles[fd]; + if (fp == NULL || + (fdp->fd_ofileflags[fd] & UF_RESERVED)) { + return(EBADF); + } + if (sel_pass == SEL_SECONDPASS) + wql_ptr = (char *)0; + else + wql_ptr = (wql+ nc * SIZEOF_WAITQUEUE_LINK); + if (fp->f_ops && (fp->f_type == DTYPE_SOCKET) && + (*fp->f_ops->fo_select)(fp, flag[msk], wql_ptr, p)) { + optr[fd/NFDBITS] |= (1 << (fd % NFDBITS)); + n++; + } + nc++; + } + } + } + thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); + } + *retval = n; return (0); } @@ -694,38 +852,100 @@ seltrue(dev, flag, p) return (1); } +static int +selcount(p, ibits, obits, nfd, count, nfcount) + struct proc *p; + u_int32_t *ibits, *obits; + int nfd; + int *count; + int *nfcount; +{ + register struct filedesc *fdp = p->p_fd; + register int msk, i, j, fd; + register u_int32_t bits; + struct file *fp; + int n = 0; + int nc = 0; + int nfc = 0; + static int flag[3] = { FREAD, FWRITE, 0 }; + u_int32_t *iptr, *fptr, *fbits; + u_int nw; + + /* + * Problems when reboot; due to MacOSX signal probs + * in Beaker1C ; verify that the p->p_fd is valid + */ + if (fdp == NULL) { + *count=0; + *nfcount=0; + return(EIO); + } + + nw = howmany(nfd, NFDBITS); + + + for (msk = 0; msk < 3; msk++) { + iptr = (u_int32_t *)&ibits[msk * nw]; + for (i = 0; i < nfd; i += NFDBITS) { + bits = iptr[i/NFDBITS]; + while ((j = ffs(bits)) && (fd = i + --j) < nfd) { + bits &= ~(1 << j); + fp = fdp->fd_ofiles[fd]; + if (fp == NULL || + (fdp->fd_ofileflags[fd] & UF_RESERVED)) { + *count=0; + *nfcount=0; + return(EBADF); + } + if (fp->f_type == DTYPE_SOCKET) + nfc++; + n++; + } + } + } + *count = n; + *nfcount = nfc; + return (0); +} + /* * Record a select request. */ void -selrecord(selector, sip) +selrecord(selector, sip, p_wql) struct proc *selector; struct selinfo *sip; + void * p_wql; { - int oldpri = splhigh(); - thread_t my_thread = current_thread(); - thread_t selthread; + thread_act_t cur_act = current_act(); + struct uthread * ut = get_bsdthread_info(cur_act); - selthread = sip->si_thread; - - if (selthread == my_thread) { - splx(oldpri); + /* need to look at collisions */ + + if ((p_wql == (void *)0) && ((sip->si_flags & SI_INITED) == 0)) { return; } - - if (selthread && is_thread_active(selthread) && - get_thread_waitevent(selthread) == (caddr_t)&selwait) { - sip->si_flags |= SI_COLL; - splx(oldpri); - } else { - sip->si_thread = my_thread; - splx(oldpri); - act_reference(current_act()); - if (selthread) { - act_deallocate(getact_thread(selthread)); - } + + /*do not record if this is second pass of select */ + if((p_wql == (void *)0)) { + return; + } + + if ((sip->si_flags & SI_INITED) == 0) { + wait_queue_init(&sip->wait_queue, SYNC_POLICY_FIFO); + sip->si_flags |= SI_INITED; + sip->si_flags &= ~SI_CLEAR; } + if (sip->si_flags & SI_RECORDED) { + sip->si_flags |= SI_COLL; + } else + sip->si_flags &= ~SI_COLL; + + sip->si_flags |= SI_RECORDED; + if (!wait_queue_member(&sip->wait_queue, ut->uu_wqsub)) + wait_queue_link_noalloc(&sip->wait_queue, ut->uu_wqsub, (wait_queue_link_t)p_wql); + return; } @@ -733,50 +953,41 @@ void selwakeup(sip) register struct selinfo *sip; { - register thread_t the_thread = (thread_t)sip->si_thread; - int oldpri; - struct proc *p; - thread_act_t th_act; - if (the_thread == 0) + if ((sip->si_flags & SI_INITED) == 0) { return; + } if (sip->si_flags & SI_COLL) { nselcoll++; sip->si_flags &= ~SI_COLL; - wakeup((caddr_t)&selwait); +#if 0 + /* will not support */ + //wakeup((caddr_t)&selwait); +#endif } - - oldpri = splhigh(); - - th_act = (thread_act_t)getact_thread(the_thread); - if (is_thread_active(the_thread)) { - if (get_thread_waitevent(the_thread) == &selwait) - clear_wait(the_thread, THREAD_AWAKENED); - if (p = current_proc()) - p->p_flag &= ~P_SELECT; + if (sip->si_flags & SI_RECORDED) { + wait_queue_wakeup_all(&sip->wait_queue, &selwait, THREAD_AWAKENED); + sip->si_flags &= ~SI_RECORDED; } - - /* th_act = (thread_act_t)getact_thread(the_thread); */ - act_deallocate(th_act); - - sip->si_thread = 0; - - splx(oldpri); } void selthreadclear(sip) register struct selinfo *sip; { - thread_act_t th_act; - if (sip->si_thread) { - th_act = (thread_act_t)getact_thread(sip->si_thread); - act_deallocate(th_act); + if ((sip->si_flags & SI_INITED) == 0) { + return; + } + if (sip->si_flags & SI_RECORDED) { + selwakeup(sip); + sip->si_flags &= ~(SI_RECORDED | SI_COLL); } + sip->si_flags |= SI_CLEAR; + wait_queue_unlinkall_nofree(&sip->wait_queue); } diff --git a/bsd/kern/sys_socket.c b/bsd/kern/sys_socket.c index f4637871d..c6ae049cc 100644 --- a/bsd/kern/sys_socket.c +++ b/bsd/kern/sys_socket.c @@ -75,7 +75,7 @@ int soo_write __P((struct file *fp, struct uio *uio, struct ucred *cred)); int soo_close __P((struct file *fp, struct proc *p)); -int soo_select __P((struct file *fp, int which, struct proc *p)); +int soo_select __P((struct file *fp, int which, void * wql, struct proc *p)); struct fileops socketops = { soo_read, soo_write, soo_ioctl, soo_select, soo_close }; @@ -95,7 +95,9 @@ soo_read(fp, uio, cred) struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)); + thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); + fsoreceive = so->so_proto->pr_usrreqs->pru_soreceive; if (fsoreceive != soreceive) { kp = sotokextcb(so); @@ -303,55 +305,54 @@ soo_ioctl(fp, cmd, data, p) } int -soo_select(fp, which, p) +soo_select(fp, which, wql, p) struct file *fp; int which; + void * wql; struct proc *p; { register struct socket *so = (struct socket *)fp->f_data; register int s = splnet(); int retnum=0; -/* thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); */ switch (which) { case FREAD: - so->so_rcv.sb_sel.si_flags |= SI_SBSEL; + so->so_rcv.sb_flags |= SB_SEL; if (soreadable(so)) { splx(s); retnum = 1; - so->so_rcv.sb_sel.si_flags &= ~SI_SBSEL; + so->so_rcv.sb_flags &= ~SB_SEL; goto done; } - selrecord(p, &so->so_rcv.sb_sel); + selrecord(p, &so->so_rcv.sb_sel, wql); break; case FWRITE: - so->so_snd.sb_sel.si_flags |= SI_SBSEL; + so->so_snd.sb_flags |= SB_SEL; if (sowriteable(so)) { splx(s); retnum = 1; - so->so_snd.sb_sel.si_flags &= ~SI_SBSEL; + so->so_snd.sb_flags &= ~SB_SEL; goto done; } - selrecord(p, &so->so_snd.sb_sel); + selrecord(p, &so->so_snd.sb_sel, wql); break; case 0: - so->so_rcv.sb_sel.si_flags |= SI_SBSEL; + so->so_rcv.sb_flags |= SB_SEL; if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) { splx(s); retnum = 1; - so->so_rcv.sb_sel.si_flags &= ~SI_SBSEL; + so->so_rcv.sb_flags &= ~SB_SEL; goto done; } - selrecord(p, &so->so_rcv.sb_sel); + selrecord(p, &so->so_rcv.sb_sel, wql); break; } splx(s); done: -/* thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); */ return (retnum); } diff --git a/bsd/kern/syscalls.c b/bsd/kern/syscalls.c index 5bd80b32a..d5b0b8bd9 100644 --- a/bsd/kern/syscalls.c +++ b/bsd/kern/syscalls.c @@ -378,5 +378,7 @@ char *syscallnames[] = { "#322", /* 322 = thr_sleep */ "#323", /* 323 = thr_wakeup */ "mlockall", /* 324 = mlockall */ - "munlockall" /* 325 = munlockall */ + "munlockall", /* 325 = munlockall */ + "#326", /* 326 */ + "issetugid" /* 327 = issetugid */ }; diff --git a/bsd/kern/sysctl_init.c b/bsd/kern/sysctl_init.c index 5402e009f..18b840051 100644 --- a/bsd/kern/sysctl_init.c +++ b/bsd/kern/sysctl_init.c @@ -126,6 +126,8 @@ extern struct sysctl_oid sysctl__net_link_ether_inet_maxtries; extern struct sysctl_oid sysctl__net_link_ether_inet_proxyall; extern struct sysctl_oid sysctl__net_link_ether_inet_prune_intvl; extern struct sysctl_oid sysctl__net_link_ether_inet_useloopback; +extern struct sysctl_oid sysctl__net_link_ether_inet_apple_hwcksum_tx; +extern struct sysctl_oid sysctl__net_link_ether_inet_apple_hwcksum_rx; #if NETMIBS extern struct sysctl_oid sysctl__net_link_generic_system_ifcount; @@ -398,6 +400,8 @@ struct sysctl_oid *newsysctl_list[] = ,&sysctl__net_link_ether_inet_proxyall ,&sysctl__net_link_ether_inet_prune_intvl ,&sysctl__net_link_ether_inet_useloopback + ,&sysctl__net_link_ether_inet_apple_hwcksum_tx + ,&sysctl__net_link_ether_inet_apple_hwcksum_rx #if NETMIBS ,&sysctl__net_link_generic_system_ifcount ,&sysctl__net_link_generic diff --git a/bsd/kern/tty.c b/bsd/kern/tty.c index 922299b3d..fc84d6f5f 100644 --- a/bsd/kern/tty.c +++ b/bsd/kern/tty.c @@ -243,7 +243,9 @@ ttyopen(device, tp) register struct tty *tp; { int s; + boolean_t funnel_state; + funnel_state = thread_funnel_set(kernel_flock, TRUE); s = spltty(); tp->t_dev = device; if (!ISSET(tp->t_state, TS_ISOPEN)) { @@ -265,6 +267,7 @@ ttyopen(device, tp) #endif /* !NeXT */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -1143,9 +1146,10 @@ ttioctl(tp, cmd, data, flag, p) } int -ttyselect(tp, rw, p) +ttyselect(tp, rw, wql, p) struct tty *tp; int rw; + void * wql; struct proc *p; { int s; @@ -1158,7 +1162,7 @@ ttyselect(tp, rw, p) case FREAD: if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE)) goto win; - selrecord(p, &tp->t_rsel); + selrecord(p, &tp->t_rsel, wql); break; case FWRITE: if ((tp->t_outq.c_cc <= tp->t_lowat && @@ -1167,7 +1171,7 @@ ttyselect(tp, rw, p) win: splx(s); return (1); } - selrecord(p, &tp->t_wsel); + selrecord(p, &tp->t_wsel, wql); break; } splx(s); @@ -1179,15 +1183,16 @@ win: splx(s); * cdevsw. It relies on a proper xxxdevtotty routine. */ int -ttselect(dev, rw, p) +ttselect(dev, rw, wql, p) dev_t dev; int rw; + void * wql; struct proc *p; { #ifndef NeXT - return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, p); + return ttyselect((*cdevsw[major(dev)]->d_devtotty)(dev), rw, wql, p); #else - return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, p); + return ttyselect(cdevsw[major(dev)].d_ttys[minor(dev)], rw, wql, p); #endif } @@ -1430,9 +1435,13 @@ int ttstart(tp) struct tty *tp; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if (tp->t_oproc != NULL) /* XXX: Kludge for pty. */ (*tp->t_oproc)(tp); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -1444,8 +1453,12 @@ ttylclose(tp, flag) struct tty *tp; int flag; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if ( (flag & FNONBLOCK) || ttywflush(tp)) ttyflush(tp, FREAD | FWRITE); + thread_funnel_set(kernel_flock, funnel_state); return (0); } @@ -1459,6 +1472,9 @@ ttymodem(tp, flag) register struct tty *tp; int flag; { + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); if (ISSET(tp->t_state, TS_CARR_ON) && ISSET(tp->t_cflag, MDMBUF)) { /* @@ -1487,6 +1503,7 @@ ttymodem(tp, flag) if (tp->t_session && tp->t_session->s_leader) psignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); + thread_funnel_set(kernel_flock, funnel_state); return (0); } } else { @@ -1500,6 +1517,7 @@ ttymodem(tp, flag) ttwakeup(tp); ttwwakeup(tp); } + thread_funnel_set(kernel_flock, funnel_state); return (1); } @@ -1554,7 +1572,9 @@ ttread(tp, uio, flag) int s, first, error = 0; int has_etime = 0, last_cc = 0; long slp = 0; /* XXX this should be renamed `timo'. */ + boolean_t funnel_state; + funnel_state = thread_funnel_set(kernel_flock, TRUE); loop: s = spltty(); lflag = tp->t_lflag; @@ -1575,17 +1595,22 @@ loop: splx(s); if ((p->p_sigignore & sigmask(SIGTTIN)) || (p->p_sigmask & sigmask(SIGTTIN)) || - p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) + p->p_flag & P_PPWAIT || p->p_pgrp->pg_jobc == 0) { + thread_funnel_set(kernel_flock, funnel_state); return (EIO); + } pgsignal(p->p_pgrp, SIGTTIN, 1); error = ttysleep(tp, &lbolt, TTIPRI | PCATCH | PTTYBLOCK, "ttybg2", 0); - if (error) + if (error){ + thread_funnel_set(kernel_flock, funnel_state); return (error); + } goto loop; } if (ISSET(tp->t_state, TS_ZOMBIE)) { splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); /* EOF */ } @@ -1602,9 +1627,11 @@ loop: goto read; if (!ISSET(lflag, ICANON) && cc[VMIN] == 0) { splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (EWOULDBLOCK); } if (!ISSET(lflag, ICANON)) { @@ -1629,6 +1656,7 @@ loop: /* m, t and qp->c_cc are all 0. 0 is enough input. */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } t *= 100000; /* time in us */ @@ -1685,6 +1713,7 @@ loop: if (timercmp(&etime, &timecopy, <=)) { /* Timed out, but 0 is enough input. */ splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (0); } slp = diff(etime, timecopy); @@ -1714,8 +1743,10 @@ sleep: splx(s); if (error == EWOULDBLOCK) error = 0; - else if (error) + else if (error) { + thread_funnel_set(kernel_flock, funnel_state); return (error); + } /* * XXX what happens if another process eats some input * while we are asleep (not just here)? It would be @@ -1832,6 +1863,7 @@ out: ttyunblock(tp); splx(s); + thread_funnel_set(kernel_flock, funnel_state); return (error); } @@ -1882,6 +1914,9 @@ ttwrite(tp, uio, flag) register struct proc *p; int i, hiwat, cnt, error, s; char obuf[OBUFSIZ]; + boolean_t funnel_state; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); hiwat = tp->t_hiwat; cnt = uio->uio_resid; @@ -1935,6 +1970,7 @@ loop: while (uio->uio_resid > 0 || cc > 0) { if (ISSET(tp->t_lflag, FLUSHO)) { uio->uio_resid = 0; + thread_funnel_set(kernel_flock, funnel_state); return (0); } if (tp->t_outq.c_cc > hiwat) @@ -2049,6 +2085,7 @@ out: * (the call will either return short or restart with a new uio). */ uio->uio_resid += cc; + thread_funnel_set(kernel_flock, funnel_state); return (error); #ifdef NeXT @@ -2077,6 +2114,7 @@ ovhiwat: if (flag & IO_NDELAY) { splx(s); uio->uio_resid += cc; + thread_funnel_set(kernel_flock, funnel_state); return (uio->uio_resid == cnt ? EWOULDBLOCK : 0); } SET(tp->t_state, TS_SO_OLOWAT); diff --git a/bsd/kern/tty_pty.c b/bsd/kern/tty_pty.c index f4eb1b31b..616d9e827 100644 --- a/bsd/kern/tty_pty.c +++ b/bsd/kern/tty_pty.c @@ -558,9 +558,10 @@ ptsstop(tp, flush) } FREE_BSDSTATIC int -ptcselect(dev, rw, p) +ptcselect(dev, rw, wql, p) dev_t dev; int rw; + void * wql; struct proc *p; { register struct tty *tp = pt_tty[minor(dev)]; @@ -589,7 +590,7 @@ ptcselect(dev, rw, p) ((pti->pt_flags&PF_PKT && pti->pt_send) || (pti->pt_flags&PF_UCNTL && pti->pt_ucntl))) return (1); - selrecord(p, &pti->pt_selr); + selrecord(p, &pti->pt_selr, wql); break; @@ -605,7 +606,7 @@ ptcselect(dev, rw, p) return (1); } } - selrecord(p, &pti->pt_selw); + selrecord(p, &pti->pt_selw, wql); break; } diff --git a/bsd/kern/tty_subr.c b/bsd/kern/tty_subr.c index f35c1ba79..9bc116f30 100644 --- a/bsd/kern/tty_subr.c +++ b/bsd/kern/tty_subr.c @@ -104,15 +104,15 @@ clalloc(clp, size, quot) int quot; { - MALLOC(clp->c_cs, u_char *, size, M_TTYS, M_WAITOK); + MALLOC_ZONE(clp->c_cs, u_char *, size, M_TTYS, M_WAITOK); if (!clp->c_cs) return (-1); bzero(clp->c_cs, size); if(quot) { - MALLOC(clp->c_cq, u_char *, QMEM(size), M_TTYS, M_WAITOK); + MALLOC_ZONE(clp->c_cq, u_char *, QMEM(size), M_TTYS, M_WAITOK); if (!clp->c_cq) { - FREE(clp->c_cs, M_TTYS); + FREE_ZONE(clp->c_cs, size, M_TTYS); return (-1); } bzero(clp->c_cs, QMEM(size)); @@ -131,9 +131,9 @@ clfree(clp) struct clist *clp; { if(clp->c_cs) - FREE(clp->c_cs, M_TTYS); + FREE_ZONE(clp->c_cs, clp->c_cn, M_TTYS); if(clp->c_cq) - FREE(clp->c_cq, M_TTYS); + FREE_ZONE(clp->c_cq, QMEM(clp->c_cn), M_TTYS); clp->c_cs = clp->c_cq = (u_char *)0; } diff --git a/bsd/kern/tty_tty.c b/bsd/kern/tty_tty.c index 0e6415ed6..359d71096 100644 --- a/bsd/kern/tty_tty.c +++ b/bsd/kern/tty_tty.c @@ -205,16 +205,17 @@ cttyioctl(dev, cmd, addr, flag, p) /*ARGSUSED*/ int -cttyselect(dev, flag, p) +cttyselect(dev, flag, wql, p) dev_t dev; int flag; + void * wql; struct proc *p; { struct vnode *ttyvp = cttyvp(p); if (ttyvp == NULL) return (1); /* try operation to get EOF/failure */ - return (VOP_SELECT(ttyvp, flag, FREAD|FWRITE, NOCRED, p)); + return (VOP_SELECT(ttyvp, flag, FREAD|FWRITE, NOCRED, wql, p)); } #ifndef NeXT diff --git a/bsd/kern/ubc_subr.c b/bsd/kern/ubc_subr.c index c56fe8b2b..32a5924cb 100644 --- a/bsd/kern/ubc_subr.c +++ b/bsd/kern/ubc_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -26,8 +26,11 @@ * * Functions related to Unified Buffer cache. * + * Caller of UBC functions MUST have a valid reference on the vnode. + * */ +#undef DIAGNOSTIC #define DIAGNOSTIC 1 #include <sys/types.h> @@ -59,44 +62,26 @@ struct zone *ubc_info_zone; -#if DIAGNOSTIC -#define USHOULDNOT(fun) panic("%s: should not", (fun)); -#else -#define USHOULDNOT(fun) -#endif /* DIAGNOSTIC */ - - -static void *_ubc_getobject(struct vnode *, int); -static void ubc_lock(struct vnode *); -static void ubc_unlock(struct vnode *); - -static void -ubc_getobjref(struct vnode *vp) +/* lock for changes to struct UBC */ +static __inline__ void +ubc_lock(struct vnode *vp) { - register struct ubc_info *uip; - void *pager_cport; - void *object; - - uip = vp->v_ubcinfo; - - if (pager_cport = (void *)vnode_pager_lookup(vp, uip->ui_pager)) - object = (void *)vm_object_lookup(pager_cport); - - if (object != uip->ui_object) { -#if 0 - Debugger("ubc_getobjref: object changed"); -#endif /* 0 */ - uip->ui_object = object; - } + /* For now, just use the v_interlock */ + simple_lock(&vp->v_interlock); +} - if (uip->ui_object == NULL) - panic("ubc_getobjref: lost object"); +/* unlock */ +static __inline__ void +ubc_unlock(struct vnode *vp) +{ + /* For now, just use the v_interlock */ + simple_unlock(&vp->v_interlock); } /* * Initialization of the zone for Unified Buffer Cache. */ -void +__private_extern__ void ubc_init() { int i; @@ -119,10 +104,10 @@ ubc_info_init(struct vnode *vp) struct proc *p = current_proc(); int error = 0; kern_return_t kret; - void * pager_cport; + memory_object_control_t control; - assert(vp); - assert(UBCISVALID(vp)); + if (!UBCISVALID(vp)) + return (EINVAL); ubc_lock(vp); if (ISSET(vp->v_flag, VUINIT)) { @@ -146,12 +131,20 @@ ubc_info_init(struct vnode *vp) if ((uip == UBC_INFO_NULL) || (uip == UBC_NOINFO)) { ubc_unlock(vp); uip = (struct ubc_info *) zalloc(ubc_info_zone); - bzero(uip, sizeof(struct ubc_info)); - ubc_lock(vp); - SET(uip->ui_flags, UI_INITED); + uip->ui_pager = MEMORY_OBJECT_NULL; + uip->ui_control = MEMORY_OBJECT_CONTROL_NULL; + uip->ui_flags = UI_INITED; uip->ui_vnode = vp; uip->ui_ucred = NOCRED; + uip->ui_refcount = 1; + uip->ui_size = 0; + uip->ui_mapped = 0; + ubc_lock(vp); } +#if DIAGNOSTIC + else + Debugger("ubc_info_init: already"); +#endif /* DIAGNOSTIC */ assert(uip->ui_flags != UI_NONE); assert(uip->ui_vnode == vp); @@ -167,35 +160,37 @@ ubc_info_init(struct vnode *vp) ubc_unlock(vp); pager = (void *)vnode_pager_setup(vp, uip->ui_pager); assert(pager); + ubc_setpager(vp, pager); /* - * Can not use VOP_GETATTR() to get accurate value - * of ui_size. Thanks to NFS. + * Note: We can not use VOP_GETATTR() to get accurate + * value of ui_size. Thanks to NFS. * nfs_getattr() can call vinvalbuf() and in this case * ubc_info is not set up to deal with that. * So use bogus size. */ - /* create a vm_object association */ - kret = vm_object_create_nomap(pager, (vm_object_offset_t)uip->ui_size); - if (kret != KERN_SUCCESS) - panic("ubc_info_init: vm_object_create_nomap returned %d", kret); - - /* _ubc_getobject() gets a reference on the memory object */ - if (_ubc_getobject(vp, 0) == NULL) - panic("ubc_info_init: lost vmobject : uip = 0X%08x", uip); - /* - * vm_object_allocate() called from vm_object_create_nomap() - * created the object with a refcount of 1 - * need to drop the reference gained by vm_object_lookup() + * create a vnode - vm_object association + * memory_object_create_named() creates a "named" reference on the + * memory object we hold this reference as long as the vnode is + * "alive." Since memory_object_create_named() took its own reference + * on the vnode pager we passed it, we can drop the reference + * vnode_pager_setup() returned here. */ - vm_object_deallocate(uip->ui_object); + kret = memory_object_create_named(pager, + (memory_object_size_t)uip->ui_size, &control); + vnode_pager_deallocate(pager); + if (kret != KERN_SUCCESS) + panic("ubc_info_init: memory_object_create_named returned %d", kret); + assert(control); + uip->ui_control = control; /* cache the value of the mo control */ + SET(uip->ui_flags, UI_HASOBJREF); /* with a named reference */ /* create a pager reference on the vnode */ - error = vget(vp, LK_INTERLOCK, p); + error = vnode_pager_vget(vp); if (error) - panic("ubc_info_init: vget error = %d", error); + panic("ubc_info_init: vnode_pager_vget error = %d", error); /* initialize the size */ error = VOP_GETATTR(vp, &vattr, p->p_ucred, p); @@ -212,29 +207,37 @@ done: } else ubc_unlock(vp); - return(error); + return (error); } /* Free the ubc_info */ -void -ubc_info_free(struct vnode *vp) +static void +ubc_info_free(struct ubc_info *uip) { - register struct ubc_info *uip; struct ucred *credp; - assert(vp); - - uip = vp->v_ubcinfo; - vp->v_ubcinfo = UBC_INFO_NULL; credp = uip->ui_ucred; if (credp != NOCRED) { uip->ui_ucred = NOCRED; crfree(credp); } + + if (uip->ui_control != MEMORY_OBJECT_CONTROL_NULL) + memory_object_control_deallocate(uip->ui_control); + zfree(ubc_info_zone, (vm_offset_t)uip); return; } +void +ubc_info_deallocate(struct ubc_info *uip) +{ + assert(uip->ui_refcount > 0); + + if (uip->ui_refcount-- == 1) + ubc_info_free(uip); +} + /* * Communicate with VM the size change of the file * returns 1 on success, 0 on failure @@ -245,20 +248,16 @@ ubc_setsize(struct vnode *vp, off_t nsize) off_t osize; /* ui_size before change */ off_t lastpg, olastpgend, lastoff; struct ubc_info *uip; - void *object; + memory_object_control_t control; kern_return_t kret; - int didhold; -#if DIAGNOSTIC - assert(vp); assert(nsize >= (off_t)0); -#endif if (UBCINVALID(vp)) - return(0); + return (0); if (!UBCINFOEXISTS(vp)) - return(0); + return (0); uip = vp->v_ubcinfo; osize = uip->ui_size; /* call ubc_getsize() ??? */ @@ -266,7 +265,7 @@ ubc_setsize(struct vnode *vp, off_t nsize) uip->ui_size = nsize; if (nsize >= osize) /* Nothing more to do */ - return(0); + return (1); /* return success */ /* * When the file shrinks, invalidate the pages beyond the @@ -276,11 +275,10 @@ ubc_setsize(struct vnode *vp, off_t nsize) * end of the file. */ - didhold = ubc_hold(vp); lastpg = trunc_page_64(nsize); olastpgend = round_page_64(osize); - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); + control = uip->ui_control; + assert(control); lastoff = (nsize & PAGE_MASK_64); /* @@ -288,59 +286,37 @@ ubc_setsize(struct vnode *vp, off_t nsize) * invalidating is sufficient */ if (!lastoff) { - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); - /* invalidate last page and old contents beyond nsize */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)lastpg, + kret = memory_object_lock_request(control, + (memory_object_offset_t)lastpg, (memory_object_size_t)(olastpgend - lastpg), - MEMORY_OBJECT_RETURN_NONE,TRUE, - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH, + VM_PROT_NO_CHANGE); if (kret != KERN_SUCCESS) printf("ubc_setsize: invalidate failed (error = %d)\n", kret); - if (didhold) - ubc_rele(vp); return ((kret == KERN_SUCCESS) ? 1 : 0); } - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); - /* flush the last page */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)lastpg, + kret = memory_object_lock_request(control, + (memory_object_offset_t)lastpg, PAGE_SIZE_64, - MEMORY_OBJECT_RETURN_DIRTY,FALSE, - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + MEMORY_OBJECT_RETURN_DIRTY, FALSE, + VM_PROT_NO_CHANGE); if (kret == KERN_SUCCESS) { - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); - /* invalidate last page and old contents beyond nsize */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)lastpg, + kret = memory_object_lock_request(control, + (memory_object_offset_t)lastpg, (memory_object_size_t)(olastpgend - lastpg), - MEMORY_OBJECT_RETURN_NONE,TRUE, - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + MEMORY_OBJECT_RETURN_NONE, MEMORY_OBJECT_DATA_FLUSH, + VM_PROT_NO_CHANGE); if (kret != KERN_SUCCESS) printf("ubc_setsize: invalidate failed (error = %d)\n", kret); } else printf("ubc_setsize: flush failed (error = %d)\n", kret); - if (didhold) - ubc_rele(vp); return ((kret == KERN_SUCCESS) ? 1 : 0); } @@ -356,39 +332,18 @@ ubc_getsize(struct vnode *vp) return (vp->v_ubcinfo->ui_size); } -/* lock for changes to struct UBC */ -static void -ubc_lock(struct vnode *vp) -{ - /* For now, just use the v_interlock */ - simple_lock(&vp->v_interlock); -} - -/* unlock */ -static void -ubc_unlock(struct vnode *vp) -{ - /* For now, just use the v_interlock */ - simple_unlock(&vp->v_interlock); -} - /* * Caller indicate that the object corresponding to the vnode * can not be cached in object cache. Make it so. * returns 1 on success, 0 on failure - * - * Caller of ubc_uncache() MUST have a valid reference on the vnode. */ int ubc_uncache(struct vnode *vp) { - void *object; kern_return_t kret; struct ubc_info *uip; + memory_object_control_t control; memory_object_perf_info_data_t perf; - int didhold; - - assert(vp); if (!UBCINFOEXISTS(vp)) return (0); @@ -407,46 +362,33 @@ ubc_uncache(struct vnode *vp) /* set the "do not cache" bit */ SET(uip->ui_flags, UI_DONTCACHE); - didhold = ubc_hold(vp); - - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - - /* - * memory_object_change_attributes() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); + control = uip->ui_control; + assert(control); perf.cluster_size = PAGE_SIZE; /* XXX use real cluster_size. */ perf.may_cache = FALSE; - kret = memory_object_change_attributes(object, + kret = memory_object_change_attributes(control, MEMORY_OBJECT_PERFORMANCE_INFO, (memory_object_info_t) &perf, - MEMORY_OBJECT_PERF_INFO_COUNT, - MACH_PORT_NULL, 0); - - if (didhold) - ubc_rele(vp); + MEMORY_OBJECT_PERF_INFO_COUNT); if (kret != KERN_SUCCESS) { -#if DIAGNOSTIC - panic("ubc_uncache: memory_object_change_attributes " + printf("ubc_uncache: memory_object_change_attributes_named " "kret = %d", kret); -#endif /* DIAGNOSTIC */ return (0); } + ubc_release_named(vp); + return (1); } - /* * call ubc_clean() and ubc_uncache() on all the vnodes * for this mount point. * returns 1 on success, 0 on failure */ -int +__private_extern__ int ubc_umount(struct mount *mp) { struct proc *p = current_proc(); @@ -463,9 +405,19 @@ loop: nvp = vp->v_mntvnodes.le_next; simple_unlock(&mntvnode_slock); if (UBCINFOEXISTS(vp)) { + + /* + * Must get a valid reference on the vnode + * before callig UBC functions + */ + if (vget(vp, 0, p)) { + ret = 0; + simple_lock(&mntvnode_slock); + continue; /* move on to the next vnode */ + } ret &= ubc_clean(vp, 0); /* do not invalidate */ ret &= ubc_uncache(vp); - ubc_release(vp); + vrele(vp); } simple_lock(&mntvnode_slock); } @@ -478,7 +430,7 @@ loop: * The list is traversed in reverse order * of mounting to avoid dependencies. */ -void +__private_extern__ void ubc_unmountall() { struct mount *mp, *nmp; @@ -498,15 +450,10 @@ ubc_getcred(struct vnode *vp) { struct ubc_info *uip; - assert(vp); - uip = vp->v_ubcinfo; - assert(uip); - - if (UBCINVALID(vp)) { + if (UBCINVALID(vp)) return (NOCRED); - } return (uip->ui_ucred); } @@ -516,24 +463,16 @@ ubc_getcred(struct vnode *vp) * existing credentials are not changed * returns 1 on success and 0 on failure */ - int ubc_setcred(struct vnode *vp, struct proc *p) { struct ubc_info *uip; struct ucred *credp; - assert(vp); - assert(p); - uip = vp->v_ubcinfo; - assert(uip); - - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_setcred"); + if (UBCINVALID(vp)) return (0); - } credp = uip->ui_ucred; if (credp == NOCRED) { @@ -545,21 +484,15 @@ ubc_setcred(struct vnode *vp, struct proc *p) } /* Get the pager */ -void * +__private_extern__ memory_object_t ubc_getpager(struct vnode *vp) { struct ubc_info *uip; - assert(vp); - uip = vp->v_ubcinfo; - assert(uip); - - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_getpager"); + if (UBCINVALID(vp)) return (0); - } return (uip->ui_pager); } @@ -568,91 +501,59 @@ ubc_getpager(struct vnode *vp) * Get the memory object associated with this vnode * If the vnode was reactivated, memory object would not exist. * Unless "do not rectivate" was specified, look it up using the pager. - * The vm_object_lookup() would create a reference on the memory object. * If hold was requested create an object reference of one does not * exist already. */ -static void * -_ubc_getobject(struct vnode *vp, int flags) +memory_object_control_t +ubc_getobject(struct vnode *vp, int flags) { struct ubc_info *uip; - void *object; + memory_object_control_t control; uip = vp->v_ubcinfo; - object = uip->ui_object; - - if ((object == NULL) && ISSET(uip->ui_flags, UI_HASPAGER) - && !(flags & UBC_NOREACTIVATE)) { - void *pager_cport; - if (ISSET(uip->ui_flags, UI_HASOBJREF)) - panic("ubc_getobject: lost object"); + if (UBCINVALID(vp)) + return (0); - if (pager_cport = (void *)vnode_pager_lookup(vp, uip->ui_pager)) { - object = (void *)vm_object_lookup(pager_cport); -#if 0 - if ((uip->ui_object) && (uip->ui_object != object)) - Debugger("_ubc_getobject: object changed"); -#endif /* 0 */ + ubc_lock(vp); - uip->ui_object = object; - } + control = uip->ui_control; - if (object != NULL) - SET(uip->ui_flags, UI_HASOBJREF); - } + if ((flags & UBC_HOLDOBJECT) && (!ISSET(uip->ui_flags, UI_HASOBJREF))) { - if ((flags & UBC_HOLDOBJECT) - && (object != NULL)) { - if (!ISSET(uip->ui_flags, UI_HASOBJREF)) { - ubc_getobjref(vp); + /* + * Take a temporary reference on the ubc info so that it won't go + * away during our recovery attempt. + */ + uip->ui_refcount++; + ubc_unlock(vp); + if (memory_object_recover_named(control, TRUE) == KERN_SUCCESS) { + ubc_lock(vp); SET(uip->ui_flags, UI_HASOBJREF); + ubc_unlock(vp); + } else { + control = MEMORY_OBJECT_CONTROL_NULL; } - } - return (uip->ui_object); -} - -void * -ubc_getobject(struct vnode *vp, int flags) -{ - struct ubc_info *uip; - void *object; + ubc_info_deallocate(uip); - assert(vp); - uip = vp->v_ubcinfo; - assert(uip); - - if (UBCINVALID(vp)) { - return (0); + } else { + ubc_unlock(vp); } - object = _ubc_getobject(vp, flags); - assert(object); - - if (!ISSET(uip->ui_flags, (UI_HASOBJREF|UI_WASMAPPED)) - && !(uip->ui_holdcnt)) { - if (!(flags & UBC_PAGINGOP)) - panic("ubc_getobject: lost reference"); - } + return (control); } /* Set the pager */ int -ubc_setpager(struct vnode *vp, void *pager) +ubc_setpager(struct vnode *vp, memory_object_t pager) { struct ubc_info *uip; - assert(vp); - uip = vp->v_ubcinfo; - assert(uip); - - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_setpager"); + if (UBCINVALID(vp)) return (0); - } uip->ui_pager = pager; return (1); @@ -663,20 +564,14 @@ ubc_setflags(struct vnode * vp, int flags) { struct ubc_info *uip; - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_setflags"); - return (EINVAL); - } - - assert(vp); + if (UBCINVALID(vp)) + return (0); uip = vp->v_ubcinfo; - assert(uip); - SET(uip->ui_flags, flags); - return(0); + return (1); } int @@ -684,20 +579,14 @@ ubc_clearflags(struct vnode * vp, int flags) { struct ubc_info *uip; - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_clearflags"); - return (EINVAL); - } - - assert(vp); + if (UBCINVALID(vp)) + return (0); uip = vp->v_ubcinfo; - assert(uip); - CLR(uip->ui_flags, flags); - return(0); + return (1); } @@ -706,18 +595,12 @@ ubc_issetflags(struct vnode * vp, int flags) { struct ubc_info *uip; - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_issetflags"); - return (EINVAL); - } - - assert(vp); + if (UBCINVALID(vp)) + return (0); uip = vp->v_ubcinfo; - assert(uip); - - return(ISSET(uip->ui_flags, flags)); + return (ISSET(uip->ui_flags, flags)); } off_t @@ -726,11 +609,8 @@ ubc_blktooff(struct vnode *vp, daddr_t blkno) off_t file_offset; int error; - assert(vp); - if (UBCINVALID(vp)) { - USHOULDNOT("ubc_blktooff"); + if (UBCINVALID(vp)) return ((off_t)-1); - } error = VOP_BLKTOOFF(vp, blkno, &file_offset); if (error) @@ -738,13 +618,13 @@ ubc_blktooff(struct vnode *vp, daddr_t blkno) return (file_offset); } + daddr_t ubc_offtoblk(struct vnode *vp, off_t offset) { daddr_t blkno; - int error=0; + int error = 0; - assert(vp); if (UBCINVALID(vp)) { return ((daddr_t)-1); } @@ -766,20 +646,15 @@ ubc_clean(struct vnode *vp, int invalidate) { off_t size; struct ubc_info *uip; - void *object; + memory_object_control_t control; kern_return_t kret; int flags = 0; - int didhold; - -#if DIAGNOSTIC - assert(vp); -#endif if (UBCINVALID(vp)) - return(0); + return (0); if (!UBCINFOEXISTS(vp)) - return(0); + return (0); /* * if invalidate was requested, write dirty data and then discard @@ -788,35 +663,24 @@ ubc_clean(struct vnode *vp, int invalidate) if (invalidate) flags = (MEMORY_OBJECT_DATA_FLUSH | MEMORY_OBJECT_DATA_NO_CHANGE); - didhold = ubc_hold(vp); uip = vp->v_ubcinfo; size = uip->ui_size; /* call ubc_getsize() ??? */ - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); + control = uip->ui_control; + assert(control); vp->v_flag &= ~VHASDIRTY; vp->v_clen = 0; /* Write the dirty data in the file and discard cached pages */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)0, + kret = memory_object_lock_request(control, + (memory_object_offset_t)0, (memory_object_size_t)round_page_64(size), MEMORY_OBJECT_RETURN_ALL, flags, - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + VM_PROT_NO_CHANGE); - if (kret != KERN_SUCCESS) { + if (kret != KERN_SUCCESS) printf("ubc_clean: clean failed (error = %d)\n", kret); - } - - if (didhold) - ubc_rele(vp); return ((kret == KERN_SUCCESS) ? 1 : 0); } @@ -831,49 +695,69 @@ ubc_pushdirty(struct vnode *vp) { off_t size; struct ubc_info *uip; - void *object; + memory_object_control_t control; kern_return_t kret; - int didhold; - -#if DIAGNOSTIC - assert(vp); -#endif if (UBCINVALID(vp)) - return(0); + return (0); if (!UBCINFOEXISTS(vp)) - return(0); + return (0); - didhold = ubc_hold(vp); uip = vp->v_ubcinfo; size = uip->ui_size; /* call ubc_getsize() ??? */ - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); + control = uip->ui_control; + assert(control); vp->v_flag &= ~VHASDIRTY; vp->v_clen = 0; /* Write the dirty data in the file and discard cached pages */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)0, + kret = memory_object_lock_request(control, + (memory_object_offset_t)0, (memory_object_size_t)round_page_64(size), - MEMORY_OBJECT_RETURN_DIRTY,FALSE, - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + MEMORY_OBJECT_RETURN_DIRTY, FALSE, + VM_PROT_NO_CHANGE); - if (kret != KERN_SUCCESS) { + if (kret != KERN_SUCCESS) printf("ubc_pushdirty: flush failed (error = %d)\n", kret); - } - if (didhold) - ubc_rele(vp); + return ((kret == KERN_SUCCESS) ? 1 : 0); +} + +/* + * Cause the file data in VM to be pushed out to the storage + * currently valid pages are NOT invalidated + * returns 1 on success, 0 on failure + */ +int +ubc_pushdirty_range(struct vnode *vp, off_t offset, off_t size) +{ + struct ubc_info *uip; + memory_object_control_t control; + kern_return_t kret; + + if (UBCINVALID(vp)) + return (0); + + if (!UBCINFOEXISTS(vp)) + return (0); + + uip = vp->v_ubcinfo; + + control = uip->ui_control; + assert(control); + + /* Write any dirty pages in the requested range of the file: */ + kret = memory_object_lock_request(control, + (memory_object_offset_t)offset, + (memory_object_size_t)round_page_64(size), + MEMORY_OBJECT_RETURN_DIRTY, FALSE, + VM_PROT_NO_CHANGE); + + if (kret != KERN_SUCCESS) + printf("ubc_pushdirty_range: flush failed (error = %d)\n", kret); return ((kret == KERN_SUCCESS) ? 1 : 0); } @@ -889,36 +773,50 @@ int ubc_hold(struct vnode *vp) { struct ubc_info *uip; - void *object; + memory_object_control_t object; if (UBCINVALID(vp)) return (0); if (!UBCINFOEXISTS(vp)) { - /* nothing more to do for a dying vnode */ - if ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE)) - return (0); - vp->v_ubcinfo = UBC_INFO_NULL; - ubc_info_init(vp); + /* must be invalid or dying vnode */ + assert(UBCINVALID(vp) || + ((vp->v_flag & VXLOCK) || (vp->v_flag & VTERMINATE))); + return (0); } + uip = vp->v_ubcinfo; - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); + assert(uip->ui_control != MEMORY_OBJECT_CONTROL_NULL); - if (uip->ui_holdcnt++ == 0) - ubc_getobjref(vp); - if (uip->ui_holdcnt < 0) - panic("ubc_hold: ui_holdcnt"); + ubc_lock(vp); + uip->ui_refcount++; + if (!ISSET(uip->ui_flags, UI_HASOBJREF)) { + ubc_unlock(vp); + if (memory_object_recover_named(uip->ui_control, TRUE) != KERN_SUCCESS) { + ubc_info_deallocate(uip); + return (0); + } + ubc_lock(vp); + SET(uip->ui_flags, UI_HASOBJREF); + ubc_unlock(vp); + } else { + ubc_unlock(vp); + } + + assert(uip->ui_refcount > 0); return (1); } -/* relese the reference on the vm object */ +/* + * Drop the holdcount. + * release the reference on the vm object if the this is "uncached" + * ubc_info. + */ void ubc_rele(struct vnode *vp) { struct ubc_info *uip; - void *object; if (UBCINVALID(vp)) return; @@ -932,76 +830,40 @@ ubc_rele(struct vnode *vp) uip = vp->v_ubcinfo; - /* get the object before loosing to hold count */ - object = _ubc_getobject(vp, UBC_NOREACTIVATE); + if (uip->ui_refcount == 1) + panic("ubc_rele: ui_refcount"); - if (uip->ui_holdcnt == 0) - panic("ubc_rele: ui_holdcnt"); + --uip->ui_refcount; - if (--uip->ui_holdcnt == 0) { - /* If the object is already dead do nothing */ - if (object) - vm_object_deallocate(object); -#if DIAGNOSTIC - else - printf("ubc_rele: null object for %x", vp); -#endif /* DIAGNOSTIC */ - } + if ((uip->ui_refcount == 1) + && ISSET(uip->ui_flags, UI_DONTCACHE)) + (void) ubc_release_named(vp); return; } /* - * The vnode is mapped explicitly - * Mark it so, and release the vm object reference gained in - * ubc_info_init() + * The vnode is mapped explicitly, mark it so. */ -void +__private_extern__ void ubc_map(struct vnode *vp) { struct ubc_info *uip; - void *object; - - ubc_lock(vp); -#if DIAGNOSTIC - assert(vp); -#endif - if (UBCINVALID(vp)) { - ubc_unlock(vp); + if (UBCINVALID(vp)) return; - } if (!UBCINFOEXISTS(vp)) - panic("ubc_map: can not"); + return; + ubc_lock(vp); uip = vp->v_ubcinfo; SET(uip->ui_flags, UI_WASMAPPED); uip->ui_mapped = 1; ubc_unlock(vp); -#if 1 - /* - * Do not release the ubc reference on the - * memory object right away. Let vnreclaim - * deal with that - */ -#else - /* - * Release the ubc reference. memory object cahe - * is responsible for caching this object now. - */ - if (ISSET(uip->ui_flags, UI_HASOBJREF)) { - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - CLR(uip->ui_flags, UI_HASOBJREF); - vm_object_deallocate(object); - } -#endif - return; - } /* @@ -1010,36 +872,109 @@ ubc_map(struct vnode *vp) * Return 1 if the reference was released, 0 otherwise. */ int -ubc_release(struct vnode *vp) +ubc_release_named(struct vnode *vp) { struct ubc_info *uip; - void *object; -#if DIAGNOSTIC - assert(vp); -#endif + memory_object_control_t control; + kern_return_t kret; if (UBCINVALID(vp)) return (0); if (!UBCINFOEXISTS(vp)) - panic("ubc_release: can not"); + return (0); uip = vp->v_ubcinfo; - /* can not release held vnodes */ - if (uip->ui_holdcnt) + /* can not release held or mapped vnodes */ + if (ISSET(uip->ui_flags, UI_HASOBJREF) && + (uip->ui_refcount == 1) && !uip->ui_mapped) { + control = uip->ui_control; + assert(control); + CLR(uip->ui_flags, UI_HASOBJREF); + kret = memory_object_release_name(control, + MEMORY_OBJECT_RESPECT_CACHE); + return ((kret != KERN_SUCCESS) ? 0 : 1); + } else return (0); +} - if (ISSET(uip->ui_flags, UI_HASOBJREF)) { - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - CLR(uip->ui_flags, UI_HASOBJREF); - vm_object_deallocate(object); +/* + * This function used to called by extensions directly. Some may + * still exist with this behavior. In those cases, we will do the + * release as part of reclaiming or cleaning the vnode. We don't + * need anything explicit - so just stub this out until those callers + * get cleaned up. + */ +int +ubc_release( + struct vnode *vp) +{ + return 0; +} + +/* + * destroy the named reference for a given vnode + */ +__private_extern__ int +ubc_destroy_named( + struct vnode *vp) +{ + memory_object_control_t control; + struct proc *p; + struct ubc_info *uip; + kern_return_t kret; + + /* + * We may already have had the object terminated + * and the ubcinfo released as a side effect of + * some earlier processing. If so, pretend we did + * it, because it probably was a result of our + * efforts. + */ + if (!UBCINFOEXISTS(vp)) return (1); - } else + + uip = vp->v_ubcinfo; + + /* can not destroy held vnodes */ + if (uip->ui_refcount > 1) return (0); + + /* + * Terminate the memory object. + * memory_object_destroy() will result in + * vnode_pager_no_senders(). + * That will release the pager reference + * and the vnode will move to the free list. + */ + control = ubc_getobject(vp, UBC_HOLDOBJECT); + if (control != MEMORY_OBJECT_CONTROL_NULL) { + + if (ISSET(vp->v_flag, VTERMINATE)) + panic("ubc_destroy_named: already teminating"); + SET(vp->v_flag, VTERMINATE); + + kret = memory_object_destroy(control, 0); + if (kret != KERN_SUCCESS) + return (0); + + /* + * memory_object_destroy() is asynchronous + * with respect to vnode_pager_no_senders(). + * wait for vnode_pager_no_senders() to clear + * VTERMINATE + */ + while (ISSET(vp->v_flag, VTERMINATE)) { + SET(vp->v_flag, VTERMWANT); + (void)tsleep((caddr_t)&vp->v_ubcinfo, + PINOD, "ubc_destroy_named", 0); + } + } + return (1); } + /* * Invalidate a range in the memory object that backs this * vnode. The offset is truncated to the page boundary and the @@ -1049,48 +984,33 @@ int ubc_invalidate(struct vnode *vp, off_t offset, size_t size) { struct ubc_info *uip; - void *object; + memory_object_control_t control; kern_return_t kret; off_t toff; size_t tsize; - int didhold; - -#if DIAGNOSTIC - assert(vp); -#endif if (UBCINVALID(vp)) - return; + return (0); if (!UBCINFOEXISTS(vp)) - panic("ubc_invalidate: can not"); + return (0); - didhold = ubc_hold(vp); toff = trunc_page_64(offset); tsize = (size_t)(round_page_64(offset+size) - toff); uip = vp->v_ubcinfo; - object = _ubc_getobject(vp, UBC_NOREACTIVATE); - assert(object); - - /* - * memory_object_lock_request() drops an object - * reference. gain a reference before calling it - */ - ubc_getobjref(vp); + control = uip->ui_control; + assert(control); /* invalidate pages in the range requested */ - kret = memory_object_lock_request(object, - (vm_object_offset_t)toff, + kret = memory_object_lock_request(control, + (memory_object_offset_t)toff, (memory_object_size_t)tsize, MEMORY_OBJECT_RETURN_NONE, (MEMORY_OBJECT_DATA_NO_CHANGE| MEMORY_OBJECT_DATA_FLUSH), - VM_PROT_NO_CHANGE,MACH_PORT_NULL); + VM_PROT_NO_CHANGE); if (kret != KERN_SUCCESS) printf("ubc_invalidate: invalidate failed (error = %d)\n", kret); - if (didhold) - ubc_rele(vp); - return ((kret == KERN_SUCCESS) ? 1 : 0); } @@ -1104,52 +1024,196 @@ ubc_isinuse(struct vnode *vp, int tookref) int busycount = tookref ? 2 : 1; if (!UBCINFOEXISTS(vp)) - return(0); + return (0); if (vp->v_usecount > busycount) return (1); if ((vp->v_usecount == busycount) && (vp->v_ubcinfo->ui_mapped == 1)) - return(1); + return (1); else - return(0); + return (0); } - -/* -- UGLY HACK ALERT -- */ /* - * The backdoor routine to clear the UI_WASMAPPED bit. + * The backdoor routine to clear the ui_mapped. * MUST only be called by the VM * - * Note that this routine is not under funnel. There are numerous - * thing about the calling sequence that make this work on SMP. + * Note that this routine is not called under funnel. There are numerous + * things about the calling sequence that make this work on SMP. * Any code change in those paths can break this. * - * This will be replaced soon. */ -void +__private_extern__ void ubc_unmap(struct vnode *vp) { struct ubc_info *uip; + boolean_t funnel_state; -#if DIAGNOSTIC - assert(vp); -#endif - - if (UBCINVALID(vp)) { + if (UBCINVALID(vp)) return; - } if (!UBCINFOEXISTS(vp)) - panic("ubc_unmap: can not"); + return; ubc_lock(vp); uip = vp->v_ubcinfo; - uip->ui_mapped = 0; + if ((uip->ui_refcount > 1) || !ISSET(uip->ui_flags, UI_DONTCACHE)) { + ubc_unlock(vp); + return; + } ubc_unlock(vp); - return; + funnel_state = thread_funnel_set(kernel_flock, TRUE); + (void) ubc_release_named(vp); + (void) thread_funnel_set(kernel_flock, funnel_state); +} + +kern_return_t +ubc_page_op( + struct vnode *vp, + off_t f_offset, + int ops, + vm_offset_t *phys_entryp, + int *flagsp) +{ + memory_object_control_t control; + + control = ubc_getobject(vp, UBC_FLAGS_NONE); + if (control == MEMORY_OBJECT_CONTROL_NULL) + return KERN_INVALID_ARGUMENT; + + return (memory_object_page_op(control, + (memory_object_offset_t)f_offset, + ops, + phys_entryp, + flagsp)); +} + +kern_return_t +ubc_create_upl( + struct vnode *vp, + off_t f_offset, + long bufsize, + upl_t *uplp, + upl_page_info_t **plp, + int uplflags) +{ + memory_object_control_t control; + int count; + off_t file_offset; + kern_return_t kr; + + if (bufsize & 0xfff) + return KERN_INVALID_ARGUMENT; + + control = ubc_getobject(vp, UBC_FLAGS_NONE); + if (control == MEMORY_OBJECT_CONTROL_NULL) + return KERN_INVALID_ARGUMENT; + + uplflags |= (UPL_NO_SYNC|UPL_CLEAN_IN_PLACE|UPL_SET_INTERNAL); + count = 0; + kr = memory_object_upl_request(control, f_offset, bufsize, + uplp, NULL, &count, uplflags); + if (plp != NULL) + *plp = UPL_GET_INTERNAL_PAGE_LIST(*uplp); + return kr; +} + + +kern_return_t +ubc_upl_map( + upl_t upl, + vm_offset_t *dst_addr) +{ + return (vm_upl_map(kernel_map, upl, dst_addr)); +} + + +kern_return_t +ubc_upl_unmap( + upl_t upl) +{ + return(vm_upl_unmap(kernel_map, upl)); +} + +kern_return_t +ubc_upl_commit( + upl_t upl) +{ + upl_page_info_t *pl; + kern_return_t kr; + + pl = UPL_GET_INTERNAL_PAGE_LIST(upl); + kr = upl_commit(upl, pl, MAX_UPL_TRANSFER); + upl_deallocate(upl); + return kr; } + +kern_return_t +ubc_upl_commit_range( + upl_t upl, + vm_offset_t offset, + vm_size_t size, + int flags) +{ + upl_page_info_t *pl; + boolean_t empty; + kern_return_t kr; + + if (flags & UPL_COMMIT_FREE_ON_EMPTY) + flags |= UPL_COMMIT_NOTIFY_EMPTY; + + pl = UPL_GET_INTERNAL_PAGE_LIST(upl); + + kr = upl_commit_range(upl, offset, size, flags, + pl, MAX_UPL_TRANSFER, &empty); + + if((flags & UPL_COMMIT_FREE_ON_EMPTY) && empty) + upl_deallocate(upl); + + return kr; +} + +kern_return_t +ubc_upl_abort_range( + upl_t upl, + vm_offset_t offset, + vm_size_t size, + int abort_flags) +{ + kern_return_t kr; + boolean_t empty = FALSE; + + if (abort_flags & UPL_ABORT_FREE_ON_EMPTY) + abort_flags |= UPL_ABORT_NOTIFY_EMPTY; + + kr = upl_abort_range(upl, offset, size, abort_flags, &empty); + + if((abort_flags & UPL_ABORT_FREE_ON_EMPTY) && empty) + upl_deallocate(upl); + + return kr; +} + +kern_return_t +ubc_upl_abort( + upl_t upl, + int abort_type) +{ + kern_return_t kr; + + kr = upl_abort(upl, abort_type); + upl_deallocate(upl); + return kr; +} + +upl_page_info_t * +ubc_upl_pageinfo( + upl_t upl) +{ + return (UPL_GET_INTERNAL_PAGE_LIST(upl)); +} diff --git a/bsd/kern/uipc_mbuf.c b/bsd/kern/uipc_mbuf.c index a3ab82cc7..7f7250d3c 100644 --- a/bsd/kern/uipc_mbuf.c +++ b/bsd/kern/uipc_mbuf.c @@ -461,6 +461,8 @@ m_getpacket(void) m->m_data = m->m_ext.ext_buf; m->m_flags = M_PKTHDR | M_EXT; m->m_pkthdr.aux = (struct mbuf *)NULL; + m->m_pkthdr.csum_data = 0; + m->m_pkthdr.csum_flags = 0; m->m_ext.ext_size = MCLBYTES; m->m_ext.ext_refs.forward = m->m_ext.ext_refs.backward = &m->m_ext.ext_refs; @@ -955,11 +957,10 @@ m_split(m0, len0, wait) extpacket: if (m->m_flags & M_EXT) { n->m_flags |= M_EXT; - n->m_ext = m->m_ext; MBUF_LOCK(); - mclrefcnt[mtocl(m->m_ext.ext_buf)]++; + n->m_ext = m->m_ext; + insque((queue_t)&n->m_ext.ext_refs, (queue_t)&m->m_ext.ext_refs); MBUF_UNLOCK(); - m->m_ext.ext_size = 0; /* For Accounting XXXXXX danger */ n->m_data = m->m_data + len; } else { bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain); diff --git a/bsd/kern/uipc_mbuf2.c b/bsd/kern/uipc_mbuf2.c index f5056527e..e395fc546 100644 --- a/bsd/kern/uipc_mbuf2.c +++ b/bsd/kern/uipc_mbuf2.c @@ -385,7 +385,7 @@ m_aux_add(m, af, type) if (n) return n; - MGET(n, M_DONTWAIT, m->m_type); + MGET(n, M_WAIT, m->m_type); if (n == NULL) return NULL; diff --git a/bsd/kern/uipc_socket.c b/bsd/kern/uipc_socket.c index 56eb901ee..f8fbf313d 100644 --- a/bsd/kern/uipc_socket.c +++ b/bsd/kern/uipc_socket.c @@ -497,14 +497,20 @@ sofree(so) while (kp) { if (kp->e_soif && kp->e_soif->sf_sofree) { error = (*kp->e_soif->sf_sofree)(so, kp); - if (error) + if (error) { + selthreadclear(&so->so_snd.sb_sel); + selthreadclear(&so->so_rcv.sb_sel); return; /* void fn */ + } } kp = kp->e_next; } - if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) + if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) { + selthreadclear(&so->so_snd.sb_sel); + selthreadclear(&so->so_rcv.sb_sel); return; + } if (head != NULL) { if (so->so_state & SS_INCOMP) { TAILQ_REMOVE(&head->so_incomp, so, so_list); @@ -516,6 +522,8 @@ sofree(so) * accept(2) may hang after select(2) indicated * that the listening socket was ready. */ + selthreadclear(&so->so_snd.sb_sel); + selthreadclear(&so->so_rcv.sb_sel); return; } else { panic("sofree: not queued"); @@ -525,6 +533,7 @@ sofree(so) so->so_head = NULL; } + selthreadclear(&so->so_snd.sb_sel); sbrelease(&so->so_snd); sorflush(so); sfilter_term(so); @@ -1506,6 +1515,7 @@ sorflush(so) s = splimp(); socantrcvmore(so); sbunlock(sb); + selthreadclear(&sb->sb_sel); asb = *sb; bzero((caddr_t)sb, sizeof (*sb)); splx(s); @@ -1881,9 +1891,7 @@ sohasoutofband(so) gsignal(-so->so_pgid, SIGURG); else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) psignal(p, SIGURG); - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&so->so_rcv.sb_sel); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); } /* @@ -1947,7 +1955,7 @@ sfilter_term(struct socket *so) int -sopoll(struct socket *so, int events, struct ucred *cred) +sopoll(struct socket *so, int events, struct ucred *cred, void * wql) { struct proc *p = current_proc(); int revents = 0; @@ -1967,13 +1975,13 @@ sopoll(struct socket *so, int events, struct ucred *cred) if (revents == 0) { if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { - selrecord(p, &so->so_rcv.sb_sel); - so->so_rcv.sb_sel.si_flags |= SI_SBSEL; + so->so_rcv.sb_flags |= SB_SEL; + selrecord(p, &so->so_rcv.sb_sel, wql); } if (events & (POLLOUT | POLLWRNORM)) { - selrecord(p, &so->so_snd.sb_sel); - so->so_snd.sb_sel.si_flags |= SI_SBSEL; + so->so_snd.sb_flags |= SB_SEL; + selrecord(p, &so->so_snd.sb_sel, wql); } } diff --git a/bsd/kern/uipc_socket2.c b/bsd/kern/uipc_socket2.c index 2b61d07fd..4026fe677 100644 --- a/bsd/kern/uipc_socket2.c +++ b/bsd/kern/uipc_socket2.c @@ -258,7 +258,7 @@ sonewconn(head, connstatus) if (head->so_qlen > 3 * head->so_qlimit / 2) return ((struct socket *)0); - so = soalloc(0, head->so_proto->pr_domain->dom_family, head->so_type); + so = soalloc(1, head->so_proto->pr_domain->dom_family, head->so_type); if (so == NULL) return ((struct socket *)0); @@ -409,10 +409,9 @@ sowakeup(so, sb) - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); - sb->sb_sel.si_flags &= ~SI_SBSEL; + + sb->sb_flags &= ~SB_SEL; selwakeup(&sb->sb_sel); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); if (sb->sb_flags & SB_WAIT) { sb->sb_flags &= ~SB_WAIT; @@ -489,6 +488,7 @@ soreserve(so, sndcc, rcvcc) so->so_snd.sb_lowat = so->so_snd.sb_hiwat; return (0); bad2: + selthreadclear(&so->so_snd.sb_sel); sbrelease(&so->so_snd); bad: return (ENOBUFS); @@ -516,6 +516,7 @@ sbreserve(sb, cc) /* * Free mbufs held by a socket, and reserved mbuf space. */ + /* WARNING needs to do selthreadclear() before calling this */ void sbrelease(sb) struct sockbuf *sb; @@ -523,12 +524,14 @@ sbrelease(sb) sbflush(sb); sb->sb_hiwat = sb->sb_mbmax = 0; - +#if 0 + /* this is getting called with bzeroed sb in sorflush */ { int oldpri = splimp(); selthreadclear(&sb->sb_sel); splx(oldpri); } +#endif } /* @@ -1179,6 +1182,116 @@ int pru_sopoll_notsupp(struct socket *so, int events, +/* + * Do we need to notify the other side when I/O is possible? + */ + +int +sb_notify(struct sockbuf *sb) +{ + return ((sb->sb_flags & (SB_WAIT|SB_SEL|SB_ASYNC|SB_UPCALL)) != 0); +} + +/* + * How much space is there in a socket buffer (so->so_snd or so->so_rcv)? + * This is problematical if the fields are unsigned, as the space might + * still be negative (cc > hiwat or mbcnt > mbmax). Should detect + * overflow and return 0. Should use "lmin" but it doesn't exist now. + */ +long +sbspace(struct sockbuf *sb) +{ + return ((long) imin((int)(sb->sb_hiwat - sb->sb_cc), + (int)(sb->sb_mbmax - sb->sb_mbcnt))); +} + +/* do we have to send all at once on a socket? */ +int +sosendallatonce(struct socket *so) +{ + return (so->so_proto->pr_flags & PR_ATOMIC); +} + +/* can we read something from so? */ +int +soreadable(struct socket *so) +{ + return (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat || + (so->so_state & SS_CANTRCVMORE) || + so->so_comp.tqh_first || so->so_error); +} + +/* can we write something to so? */ + +int +sowriteable(struct socket *so) +{ + return ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && + ((so->so_state&SS_ISCONNECTED) || + (so->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || + (so->so_state & SS_CANTSENDMORE) || + so->so_error); +} + +/* adjust counters in sb reflecting allocation of m */ + +void +sballoc(struct sockbuf *sb, struct mbuf *m) +{ + sb->sb_cc += m->m_len; + sb->sb_mbcnt += MSIZE; + if (m->m_flags & M_EXT) + sb->sb_mbcnt += m->m_ext.ext_size; +} + +/* adjust counters in sb reflecting freeing of m */ +void +sbfree(struct sockbuf *sb, struct mbuf *m) +{ + sb->sb_cc -= m->m_len; + sb->sb_mbcnt -= MSIZE; + if (m->m_flags & M_EXT) + sb->sb_mbcnt -= m->m_ext.ext_size; +} + +/* + * Set lock on sockbuf sb; sleep if lock is already held. + * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. + * Returns error without lock if sleep is interrupted. + */ +int +sblock(struct sockbuf *sb, int wf) +{ + return(sb->sb_flags & SB_LOCK ? + ((wf == M_WAIT) ? sb_lock(sb) : EWOULDBLOCK) : + (sb->sb_flags |= SB_LOCK), 0); +} + +/* release lock on sockbuf sb */ +void +sbunlock(struct sockbuf *sb) +{ + sb->sb_flags &= ~SB_LOCK; + if (sb->sb_flags & SB_WANT) { + sb->sb_flags &= ~SB_WANT; + wakeup((caddr_t)&(sb)->sb_flags); + } +} + +void +sorwakeup(struct socket * so) +{ + if (sb_notify(&so->so_rcv)) + sowakeup(so, &so->so_rcv); +} + +void +sowwakeup(struct socket * so) +{ + if (sb_notify(&so->so_snd)) + sowakeup(so, &so->so_snd); +} + /* * Make a copy of a sockaddr in a malloced buffer of type M_SONAME. */ diff --git a/bsd/kern/uipc_usrreq.c b/bsd/kern/uipc_usrreq.c index 480bc28f8..35f27aa4f 100644 --- a/bsd/kern/uipc_usrreq.c +++ b/bsd/kern/uipc_usrreq.c @@ -694,6 +694,11 @@ unp_connect2(so, so2) if (so2->so_type != so->so_type) return (EPROTOTYPE); unp2 = sotounpcb(so2); + + /* Verify both sockets are still opened */ + if (unp == 0 || unp2 == 0) + return (EINVAL); + unp->unp_conn = unp2; switch (so->so_type) { @@ -787,6 +792,12 @@ unp_pcblist SYSCTL_HANDLER_ARGS if (error) return error; + /* + * We are done if there is no pcb + */ + if (n == 0) + return 0; + unp_list = _MALLOC(n * sizeof *unp_list, M_TEMP, M_WAITOK); if (unp_list == 0) return ENOMEM; @@ -924,6 +935,7 @@ unp_externalize(rights) panic("unp_externalize"); fp = *rp; p->p_fd->fd_ofiles[f] = fp; + *fdflags(p, f) &= ~UF_RESERVED; fp->f_msgcount--; unp_rights--; *(int *)rp++ = f; diff --git a/bsd/libkern/random.c b/bsd/libkern/random.c index aed1b355b..8a002af2c 100644 --- a/bsd/libkern/random.c +++ b/bsd/libkern/random.c @@ -54,15 +54,8 @@ * @(#)random.c 8.1 (Berkeley) 6/10/93 */ -/* - * Modification History - * - * Feb 22, 1999 Dieter Siegmund (dieter@apple.com) - * - the first time, set the random seed to the microsecond time value - * to make the random numbers less predictable - */ -#include <libkern/libkern.h> -#include <sys/time.h> +#include <sys/types.h> +#include <sys/random.h> /* * Pseudo-random number generator for randomizing the profiling clock, @@ -72,32 +65,6 @@ u_long random() { - static int first = 1; - static u_long randseed = 1; - - register long x, hi, lo, t; - - if (first) { - struct timeval tv; - microtime(&tv); - randseed = tv.tv_usec; - if(!randseed) - randseed=1; - first = 0; - } - - /* - * Compute x[n + 1] = (7^5 * x[n]) mod (2^31 - 1). - * From "Random number generators: good ones are hard to find", - * Park and Miller, Communications of the ACM, vol. 31, no. 10, - * October 1988, p. 1195. - */ - x = randseed; - hi = x / 127773; - lo = x % 127773; - t = 16807 * lo - 2836 * hi; - if (t <= 0) - t += 0x7fffffff; - randseed = t; - return (t); + return RandomULong(); } + diff --git a/bsd/miscfs/deadfs/dead_vnops.c b/bsd/miscfs/deadfs/dead_vnops.c index d6145e093..aaca316c9 100644 --- a/bsd/miscfs/deadfs/dead_vnops.c +++ b/bsd/miscfs/deadfs/dead_vnops.c @@ -276,6 +276,7 @@ dead_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { diff --git a/bsd/miscfs/devfs/devfs_tree.c b/bsd/miscfs/devfs/devfs_tree.c index 8a335534a..60e1c0978 100644 --- a/bsd/miscfs/devfs/devfs_tree.c +++ b/bsd/miscfs/devfs/devfs_tree.c @@ -126,6 +126,11 @@ devfs_sinit(void) MALLOC(devfs_hidden_mount, struct mount *, sizeof(struct mount), M_MOUNT, M_WAITOK); bzero(devfs_hidden_mount,sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + devfs_mount(devfs_hidden_mount,"dummy",NULL,NULL,NULL); dev_root->de_dnp->dn_dvm = (struct devfsmount *)devfs_hidden_mount->mnt_data; diff --git a/bsd/miscfs/devfs/devfs_vfsops.c b/bsd/miscfs/devfs/devfs_vfsops.c index 4b11822bf..cdc5ee8a5 100644 --- a/bsd/miscfs/devfs/devfs_vfsops.c +++ b/bsd/miscfs/devfs/devfs_vfsops.c @@ -376,6 +376,11 @@ devfs_kernel_mount(char * mntname) */ mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); (void)vfs_busy(mp, LK_NOWAIT, 0, procp); LIST_INIT(&mp->mnt_vnodelist); diff --git a/bsd/miscfs/devfs/devfsdefs.h b/bsd/miscfs/devfs/devfsdefs.h index 630795bb4..6f5ef57a9 100644 --- a/bsd/miscfs/devfs/devfsdefs.h +++ b/bsd/miscfs/devfs/devfsdefs.h @@ -107,8 +107,8 @@ struct devnode devfstype_t dn_type; int dn_flags; u_short dn_mode; - u_short dn_uid; - u_short dn_gid; + uid_t dn_uid; + gid_t dn_gid; struct timespec dn_atime;/* time of last access */ struct timespec dn_mtime;/* time of last modification */ struct timespec dn_ctime;/* time file changed */ diff --git a/bsd/miscfs/fdesc/fdesc_vnops.c b/bsd/miscfs/fdesc/fdesc_vnops.c index d45582763..f5a7d31c9 100644 --- a/bsd/miscfs/fdesc/fdesc_vnops.c +++ b/bsd/miscfs/fdesc/fdesc_vnops.c @@ -768,6 +768,7 @@ fdesc_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { @@ -775,7 +776,7 @@ fdesc_select(ap) switch (VTOFDESC(ap->a_vp)->fd_type) { case Fctty: - error = cttyselect(devctty, ap->a_fflags, ap->a_p); + error = cttyselect(devctty, ap->a_fflags, ap->a_wql, ap->a_p); break; default: diff --git a/bsd/miscfs/fifofs/fifo.h b/bsd/miscfs/fifofs/fifo.h index b5d55b2e9..23ffa9d1a 100644 --- a/bsd/miscfs/fifofs/fifo.h +++ b/bsd/miscfs/fifofs/fifo.h @@ -58,12 +58,11 @@ /* * Prototypes for fifo operations on vnodes. */ -int fifo_badop(), - fifo_ebadf(); +int fifo_ebadf(); int fifo_lookup __P((struct vop_lookup_args *)); -#define fifo_create ((int (*) __P((struct vop_create_args *)))fifo_badop) -#define fifo_mknod ((int (*) __P((struct vop_mknod_args *)))fifo_badop) +#define fifo_create ((int (*) __P((struct vop_create_args *)))err_create) +#define fifo_mknod ((int (*) __P((struct vop_mknod_args *)))err_mknod) int fifo_open __P((struct vop_open_args *)); int fifo_close __P((struct vop_close_args *)); #define fifo_access ((int (*) __P((struct vop_access_args *)))fifo_ebadf) @@ -75,35 +74,35 @@ int fifo_write __P((struct vop_write_args *)); int fifo_ioctl __P((struct vop_ioctl_args *)); int fifo_select __P((struct vop_select_args *)); #define fifo_revoke vop_revoke -#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))fifo_badop) +#define fifo_mmap ((int (*) __P((struct vop_mmap_args *)))err_mmap) #define fifo_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) -#define fifo_seek ((int (*) __P((struct vop_seek_args *)))fifo_badop) -#define fifo_remove ((int (*) __P((struct vop_remove_args *)))fifo_badop) -#define fifo_link ((int (*) __P((struct vop_link_args *)))fifo_badop) -#define fifo_rename ((int (*) __P((struct vop_rename_args *)))fifo_badop) -#define fifo_mkdir ((int (*) __P((struct vop_mkdir_args *)))fifo_badop) -#define fifo_rmdir ((int (*) __P((struct vop_rmdir_args *)))fifo_badop) -#define fifo_symlink ((int (*) __P((struct vop_symlink_args *)))fifo_badop) -#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))fifo_badop) -#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))fifo_badop) -#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))fifo_badop) +#define fifo_seek ((int (*) __P((struct vop_seek_args *)))err_seek) +#define fifo_remove ((int (*) __P((struct vop_remove_args *)))err_remove) +#define fifo_link ((int (*) __P((struct vop_link_args *)))err_link) +#define fifo_rename ((int (*) __P((struct vop_rename_args *)))err_rename) +#define fifo_mkdir ((int (*) __P((struct vop_mkdir_args *)))err_mkdir) +#define fifo_rmdir ((int (*) __P((struct vop_rmdir_args *)))err_rmdir) +#define fifo_symlink ((int (*) __P((struct vop_symlink_args *)))err_symlink) +#define fifo_readdir ((int (*) __P((struct vop_readdir_args *)))err_readdir) +#define fifo_readlink ((int (*) __P((struct vop_readlink_args *)))err_readlink) +#define fifo_abortop ((int (*) __P((struct vop_abortop_args *)))err_abortop) int fifo_inactive __P((struct vop_inactive_args *)); #define fifo_reclaim ((int (*) __P((struct vop_reclaim_args *)))nullop) #define fifo_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock) #define fifo_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock) int fifo_bmap __P((struct vop_bmap_args *)); -#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))fifo_badop) +#define fifo_strategy ((int (*) __P((struct vop_strategy_args *)))err_strategy) int fifo_print __P((struct vop_print_args *)); #define fifo_islocked ((int(*) __P((struct vop_islocked_args *)))vop_noislocked) int fifo_pathconf __P((struct vop_pathconf_args *)); int fifo_advlock __P((struct vop_advlock_args *)); -#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))fifo_badop) -#define fifo_valloc ((int (*) __P((struct vop_valloc_args *)))fifo_badop) +#define fifo_blkatoff ((int (*) __P((struct vop_blkatoff_args *)))err_blkatoff) +#define fifo_valloc ((int (*) __P((struct vop_valloc_args *)))err_valloc) #define fifo_reallocblks \ - ((int (*) __P((struct vop_reallocblks_args *)))fifo_badop) -#define fifo_vfree ((int (*) __P((struct vop_vfree_args *)))fifo_badop) + ((int (*) __P((struct vop_reallocblks_args *)))err_reallocblks) +#define fifo_vfree ((int (*) __P((struct vop_vfree_args *)))err_vfree) #define fifo_truncate ((int (*) __P((struct vop_truncate_args *)))nullop) #define fifo_update ((int (*) __P((struct vop_update_args *)))nullop) #define fifo_bwrite ((int (*) __P((struct vop_bwrite_args *)))nullop) -#define fifo_blktooff ((int (*) __P((struct vop_blktooff_args *)))fifo_badop) +#define fifo_blktooff ((int (*) __P((struct vop_blktooff_args *)))err_blktooff) diff --git a/bsd/miscfs/fifofs/fifo_vnops.c b/bsd/miscfs/fifofs/fifo_vnops.c index d4edca03e..7406534b5 100644 --- a/bsd/miscfs/fifofs/fifo_vnops.c +++ b/bsd/miscfs/fifofs/fifo_vnops.c @@ -88,8 +88,8 @@ int (**fifo_vnodeop_p)(void *); struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { { &vop_default_desc, (VOPFUNC)vn_default_error }, { &vop_lookup_desc, (VOPFUNC)fifo_lookup }, /* lookup */ - { &vop_create_desc, (VOPFUNC)fifo_create }, /* create */ - { &vop_mknod_desc, (VOPFUNC)fifo_mknod }, /* mknod */ + { &vop_create_desc, (VOPFUNC)err_create }, /* create */ + { &vop_mknod_desc, (VOPFUNC)err_mknod }, /* mknod */ { &vop_open_desc, (VOPFUNC)fifo_open }, /* open */ { &vop_close_desc, (VOPFUNC)fifo_close }, /* close */ { &vop_access_desc, (VOPFUNC)fifo_access }, /* access */ @@ -101,31 +101,31 @@ struct vnodeopv_entry_desc fifo_vnodeop_entries[] = { { &vop_ioctl_desc, (VOPFUNC)fifo_ioctl }, /* ioctl */ { &vop_select_desc, (VOPFUNC)fifo_select }, /* select */ { &vop_revoke_desc, (VOPFUNC)fifo_revoke }, /* revoke */ - { &vop_mmap_desc, (VOPFUNC)fifo_mmap }, /* mmap */ + { &vop_mmap_desc, (VOPFUNC)err_mmap }, /* mmap */ { &vop_fsync_desc, (VOPFUNC)fifo_fsync }, /* fsync */ - { &vop_seek_desc, (VOPFUNC)fifo_seek }, /* seek */ - { &vop_remove_desc, (VOPFUNC)fifo_remove }, /* remove */ - { &vop_link_desc, (VOPFUNC)fifo_link }, /* link */ - { &vop_rename_desc, (VOPFUNC)fifo_rename }, /* rename */ - { &vop_mkdir_desc, (VOPFUNC)fifo_mkdir }, /* mkdir */ - { &vop_rmdir_desc, (VOPFUNC)fifo_rmdir }, /* rmdir */ - { &vop_symlink_desc, (VOPFUNC)fifo_symlink }, /* symlink */ - { &vop_readdir_desc, (VOPFUNC)fifo_readdir }, /* readdir */ - { &vop_readlink_desc, (VOPFUNC)fifo_readlink }, /* readlink */ - { &vop_abortop_desc, (VOPFUNC)fifo_abortop }, /* abortop */ + { &vop_seek_desc, (VOPFUNC)err_seek }, /* seek */ + { &vop_remove_desc, (VOPFUNC)err_remove }, /* remove */ + { &vop_link_desc, (VOPFUNC)err_link }, /* link */ + { &vop_rename_desc, (VOPFUNC)err_rename }, /* rename */ + { &vop_mkdir_desc, (VOPFUNC)err_mkdir }, /* mkdir */ + { &vop_rmdir_desc, (VOPFUNC)err_rmdir }, /* rmdir */ + { &vop_symlink_desc, (VOPFUNC)err_symlink }, /* symlink */ + { &vop_readdir_desc, (VOPFUNC)err_readdir }, /* readdir */ + { &vop_readlink_desc, (VOPFUNC)err_readlink }, /* readlink */ + { &vop_abortop_desc, (VOPFUNC)err_abortop }, /* abortop */ { &vop_inactive_desc, (VOPFUNC)fifo_inactive }, /* inactive */ { &vop_reclaim_desc, (VOPFUNC)fifo_reclaim }, /* reclaim */ { &vop_lock_desc, (VOPFUNC)fifo_lock }, /* lock */ { &vop_unlock_desc, (VOPFUNC)fifo_unlock }, /* unlock */ { &vop_bmap_desc, (VOPFUNC)fifo_bmap }, /* bmap */ - { &vop_strategy_desc, (VOPFUNC)fifo_strategy }, /* strategy */ + { &vop_strategy_desc, (VOPFUNC)err_strategy }, /* strategy */ { &vop_print_desc, (VOPFUNC)fifo_print }, /* print */ { &vop_islocked_desc, (VOPFUNC)fifo_islocked }, /* islocked */ { &vop_pathconf_desc, (VOPFUNC)fifo_pathconf }, /* pathconf */ { &vop_advlock_desc, (VOPFUNC)fifo_advlock }, /* advlock */ - { &vop_blkatoff_desc, (VOPFUNC)fifo_blkatoff }, /* blkatoff */ - { &vop_valloc_desc, (VOPFUNC)fifo_valloc }, /* valloc */ - { &vop_vfree_desc, (VOPFUNC)fifo_vfree }, /* vfree */ + { &vop_blkatoff_desc, (VOPFUNC)err_blkatoff }, /* blkatoff */ + { &vop_valloc_desc, (VOPFUNC)err_valloc }, /* valloc */ + { &vop_vfree_desc, (VOPFUNC)err_vfree }, /* vfree */ { &vop_truncate_desc, (VOPFUNC)fifo_truncate }, /* truncate */ { &vop_update_desc, (VOPFUNC)fifo_update }, /* update */ { &vop_bwrite_desc, (VOPFUNC)fifo_bwrite }, /* bwrite */ @@ -382,6 +382,7 @@ fifo_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void * a_wql; struct proc *a_p; } */ *ap; { @@ -390,13 +391,13 @@ fifo_select(ap) if (ap->a_fflags & FREAD) { filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_readsock; - ready = soo_select(&filetmp, ap->a_which, ap->a_p); + ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_p); if (ready) return (ready); } if (ap->a_fflags & FWRITE) { filetmp.f_data = (caddr_t)ap->a_vp->v_fifoinfo->fi_writesock; - ready = soo_select(&filetmp, ap->a_which, ap->a_p); + ready = soo_select(&filetmp, ap->a_which, ap->a_wql, ap->a_p); if (ready) return (ready); } @@ -561,12 +562,3 @@ fifo_advlock(ap) return (EOPNOTSUPP); } -/* - * Fifo bad operation - */ -fifo_badop() -{ - - panic("fifo_badop called"); - /* NOTREACHED */ -} diff --git a/bsd/miscfs/specfs/spec_vnops.c b/bsd/miscfs/specfs/spec_vnops.c index 5391c20aa..86dba1588 100644 --- a/bsd/miscfs/specfs/spec_vnops.c +++ b/bsd/miscfs/specfs/spec_vnops.c @@ -511,6 +511,7 @@ spec_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void * a_wql; struct proc *a_p; } */ *ap; { @@ -523,7 +524,7 @@ spec_select(ap) case VCHR: dev = ap->a_vp->v_rdev; - return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_p); + return (*cdevsw[major(dev)].d_select)(dev, ap->a_which, ap->a_wql, ap->a_p); } } /* @@ -677,12 +678,16 @@ spec_close(ap) break; case VBLK: +#ifdef DEVFS_IMPLEMENTS_LOCKING /* * On last close of a block device (that isn't mounted) * we must invalidate any in core blocks, so that * we can, for instance, change floppy disks. */ - if (error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0)) + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p); + error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0); + VOP_UNLOCK(vp, 0, ap->a_p); + if (error) return (error); /* * We do not want to really close the device if it @@ -695,6 +700,28 @@ spec_close(ap) */ if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) return (0); +#else /* DEVFS_IMPLEMENTS_LOCKING */ + /* + * We do not want to really close the device if it + * is still in use unless we are trying to close it + * forcibly. Since every use (buffer, vnode, swap, cmap) + * holds a reference to the vnode, and because we mark + * any other vnodes that alias this device, when the + * sum of the reference counts on all the aliased + * vnodes descends to one, we are on last close. + */ + if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0) + return (0); + + /* + * On last close of a block device (that isn't mounted) + * we must invalidate any in core blocks, so that + * we can, for instance, change floppy disks. + */ + error = vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 0, 0); + if (error) + return (error); +#endif /* DEVFS_IMPLEMENTS_LOCKING */ devclose = bdevsw[major(dev)].d_close; mode = S_IFBLK; break; diff --git a/bsd/miscfs/synthfs/synthfs_vfsops.c b/bsd/miscfs/synthfs/synthfs_vfsops.c index 44a64a09f..35c00e8dc 100644 --- a/bsd/miscfs/synthfs/synthfs_vfsops.c +++ b/bsd/miscfs/synthfs/synthfs_vfsops.c @@ -453,15 +453,19 @@ synthfs_vget(mp, ino, vpp) } loop: + simple_lock(&mntvnode_slock); LIST_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) { if (VTOS(vp)->s_nodeid == *((unsigned long *)ino)) { if (vget(vp, LK_EXCLUSIVE, current_proc()) != 0) { + simple_unlock(&mntvnode_slock); goto loop; }; + simple_unlock(&mntvnode_slock); *vpp = vp; return 0; }; }; + simple_unlock(&mntvnode_slock); *vpp = NULL; return -1; } diff --git a/bsd/miscfs/synthfs/synthfs_vnops.c b/bsd/miscfs/synthfs/synthfs_vnops.c index da66e50bd..a009e147a 100644 --- a/bsd/miscfs/synthfs/synthfs_vnops.c +++ b/bsd/miscfs/synthfs/synthfs_vnops.c @@ -1084,6 +1084,7 @@ struct vop_select_args /* { int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { diff --git a/bsd/miscfs/umapfs/umap_subr.c b/bsd/miscfs/umapfs/umap_subr.c index 5afa9be51..3eba697d0 100644 --- a/bsd/miscfs/umapfs/umap_subr.c +++ b/bsd/miscfs/umapfs/umap_subr.c @@ -303,7 +303,7 @@ loop: /* XXX end of transmogrified checkalias() */ if (vp->v_type == VREG) - ubc_info_init(); + ubc_info_init(vp); *vpp = vp; VREF(lowervp); /* Extra VREF will be vrele'd in umap_node_create */ diff --git a/bsd/miscfs/union/union_vnops.c b/bsd/miscfs/union/union_vnops.c index e67eb52df..df60cb8a6 100644 --- a/bsd/miscfs/union/union_vnops.c +++ b/bsd/miscfs/union/union_vnops.c @@ -843,6 +843,7 @@ union_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void * a_wql; struct proc *a_p; } */ *ap; { diff --git a/bsd/miscfs/volfs/volfs_vnops.c b/bsd/miscfs/volfs/volfs_vnops.c index dd54bb59a..0f5c6ecb8 100644 --- a/bsd/miscfs/volfs/volfs_vnops.c +++ b/bsd/miscfs/volfs/volfs_vnops.c @@ -323,7 +323,7 @@ volfs_getattr(ap) int volfs_select(ap) struct vop_select_args /* { struct vnode *a_vp; int a_which; int - * a_fflags; struct ucred *a_cred; struct + * a_fflags; struct ucred *a_cred; void * a_wql; struct proc *a_p; } */ *ap; { DBG_VOP(("volfs_select called\n")); @@ -883,7 +883,7 @@ volfs_lookup(ap) char *check_ptr; u_long id; - id = strtol(cnp, &check_ptr, 10); + id = strtoul(cnp, &check_ptr, 10); /* * strtol will leave us at the first non-numeric character. diff --git a/bsd/net/bpf.c b/bsd/net/bpf.c index 6363b4fb9..8c95fcdb6 100644 --- a/bsd/net/bpf.c +++ b/bsd/net/bpf.c @@ -451,6 +451,7 @@ bpfclose(dev, flags, fmt, p) if (d->bd_bif) bpf_detachd(d); splx(s); + selthreadclear(&d->bd_sel); bpf_freed(d); thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); return (0); @@ -621,16 +622,10 @@ bpf_wakeup(d) pgsigio(d->bd_sigio, d->bd_sig, 0); #if BSD >= 199103 - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&d->bd_sel); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); - /* XXX */ - d->bd_sel.si_thread = 0; #else if (d->bd_selproc) { - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(d->bd_selproc, (int)d->bd_selcoll); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); d->bd_selcoll = 0; d->bd_selproc = 0; } @@ -1006,6 +1001,8 @@ bpf_setf(d, fp) size = flen * sizeof(*fp->bf_insns); fcode = (struct bpf_insn *) _MALLOC(size, M_DEVBUF, M_WAIT); + if (fcode == NULL) + return (ENOBUFS); if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && bpf_validate(fcode, (int)flen)) { s = splimp(); @@ -1109,9 +1106,10 @@ bpf_ifname(ifp, ifr) * Otherwise, return false but make a note that a selwakeup() must be done. */ int -bpfpoll(dev, events, p) +bpfpoll(dev, events, wql, p) register dev_t dev; int events; + void * wql; struct proc *p; { register struct bpf_d *d; @@ -1129,7 +1127,7 @@ bpfpoll(dev, events, p) if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) revents |= events & (POLLIN | POLLRDNORM); else - selrecord(p, &d->bd_sel); + selrecord(p, &d->bd_sel, wql); splx(s); thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); @@ -1356,7 +1354,7 @@ bpfattach(ifp, dlt, hdrlen) { struct bpf_if *bp; int i; - bp = (struct bpf_if *) _MALLOC(sizeof(*bp), M_DEVBUF, M_DONTWAIT); + bp = (struct bpf_if *) _MALLOC(sizeof(*bp), M_DEVBUF, M_WAIT); if (bp == 0) panic("bpfattach"); diff --git a/bsd/net/bridge.c b/bsd/net/bridge.c index 53cf96617..d562eb62d 100644 --- a/bsd/net/bridge.c +++ b/bsd/net/bridge.c @@ -331,9 +331,13 @@ bdginit(dummy) bdg_table = (struct hash_table *) _MALLOC(HASH_SIZE * sizeof(struct hash_table), M_IFADDR, M_WAITOK); + if (bdg_table == NULL) + return (ENOBUFS); flush_table(); ifp2sc = _MALLOC(if_index * sizeof(struct bdg_softc *), M_IFADDR, M_WAITOK ); + if (ifp2sc == NULL) + return (ENOBUFS); bzero(ifp2sc, if_index * sizeof(struct bdg_softc *) ); bzero(&bdg_stats, sizeof(bdg_stats) ); @@ -358,6 +362,8 @@ bdginit(dummy) ifp2sc[bdg_ports] = _MALLOC(sizeof(struct bdg_softc), M_IFADDR, M_WAITOK ); + if (ifp2sc[bdg_ports] == NULL) + return (ENOBUFS); ifp2sc[bdg_ports]->ifp = ifp ; ifp2sc[bdg_ports]->flags = 0 ; ifp2sc[bdg_ports]->group = 0 ; diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index fcc3f96a5..001492dfb 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -179,6 +179,20 @@ struct if_proto *dlttoproto(dl_tag) } +static int dlil_ifp_proto_count(struct ifnet * ifp) +{ + int count = 0; + struct if_proto * proto; + struct dlil_proto_head * tmp; + + tmp = (struct dlil_proto_head *) &ifp->proto_head; + + TAILQ_FOREACH(proto, tmp, next) + count++; + + return count; +} + u_long ifptodlt(struct ifnet *ifp, u_long proto_family) { struct if_proto *proto; @@ -186,9 +200,8 @@ u_long ifptodlt(struct ifnet *ifp, u_long proto_family) TAILQ_FOREACH(proto, tmp, next) - if (proto->ifp == ifp) - if (proto->protocol_family == proto_family) - return proto->dl_tag; + if (proto->protocol_family == proto_family) + return proto->dl_tag; return 0; } @@ -231,6 +244,40 @@ int dlil_get_next_dl_tag(u_long current_tag, struct dl_tag_attr_str *next) return ENOENT; } +void dlil_post_msg(struct ifnet *ifp, u_long event_subclass, u_long event_code, + struct net_event_data *event_data, u_long event_data_len) +{ + struct net_event_data ev_data; + struct kev_msg ev_msg; + + /* + * a net event always start with a net_event_data structure + * but the caller can generate a simple net event or + * provide a longer event structure to post + */ + + ev_msg.vendor_code = KEV_VENDOR_APPLE; + ev_msg.kev_class = KEV_NETWORK_CLASS; + ev_msg.kev_subclass = event_subclass; + ev_msg.event_code = event_code; + + if (event_data == 0) { + event_data = &ev_data; + event_data_len = sizeof(struct net_event_data); + } + + strncpy(&event_data->if_name[0], ifp->if_name, IFNAMSIZ); + event_data->if_family = ifp->if_family; + event_data->if_unit = (unsigned long) ifp->if_unit; + + ev_msg.dv[0].data_length = event_data_len; + ev_msg.dv[0].data_ptr = event_data; + ev_msg.dv[1].data_length = 0; + + kev_post_msg(&ev_msg); +} + + void dlil_init() @@ -283,6 +330,9 @@ int dlil_attach_interface_filter(struct ifnet *ifp, MALLOC(tmp_ptr, struct dlil_filterq_entry *, sizeof(*tmp_ptr), M_NKE, M_WAITOK); + if (tmp_ptr == NULL) + return (ENOBUFS); + bcopy((caddr_t) if_filter, (caddr_t) &tmp_ptr->variants.if_filter, sizeof(struct dlil_if_flt_str)); @@ -340,6 +390,9 @@ int dlil_attach_protocol_filter(u_long dl_tag, return ENOENT; MALLOC(tmp_ptr, struct dlil_filterq_entry *, sizeof(*tmp_ptr), M_NKE, M_WAITOK); + if (tmp_ptr == NULL) + return (ENOBUFS); + bcopy((caddr_t) pr_filter, (caddr_t) &tmp_ptr->variants.pr_filter, sizeof(struct dlil_pr_flt_str)); @@ -429,14 +482,14 @@ dlil_input_thread_continue(void) struct mbuf *m, *m_loop; int expand_mcl; - simple_lock(&dlil_input_lock); + usimple_lock(&dlil_input_lock); m = dlil_input_mbuf_head; dlil_input_mbuf_head = NULL; dlil_input_mbuf_tail = NULL; m_loop = dlil_input_loop_head; dlil_input_loop_head = NULL; dlil_input_loop_tail = NULL; - simple_unlock(&dlil_input_lock); + usimple_unlock(&dlil_input_lock); MBUF_LOCK(); expand_mcl = dlil_expand_mcl; @@ -445,7 +498,7 @@ dlil_input_thread_continue(void) if (expand_mcl) { caddr_t p; MCLALLOC(p, M_WAIT); - MCLFREE(p); + if (p) MCLFREE(p); } /* @@ -521,7 +574,7 @@ dlil_input(struct ifnet *ifp, struct mbuf *m_head, struct mbuf *m_tail) * input queue */ - simple_lock(&dlil_input_lock); + usimple_lock(&dlil_input_lock); if (ifp->if_type != IFT_LOOP) { if (dlil_input_mbuf_head == NULL) dlil_input_mbuf_head = m_head; @@ -535,7 +588,7 @@ dlil_input(struct ifnet *ifp, struct mbuf *m_head, struct mbuf *m_tail) dlil_input_loop_tail->m_nextpkt = m_head; dlil_input_loop_tail = m_tail ? m_tail : m_head; } - simple_unlock(&dlil_input_lock); + usimple_unlock(&dlil_input_lock); wakeup((caddr_t)&dlil_input_thread_wakeup); @@ -1080,6 +1133,7 @@ dlil_attach_protocol(struct dlil_proto_reg_str *proto, struct if_family_str *if_family; int error; struct dlil_proto_head *tmp; + struct kev_dl_proto_data ev_pr_data; int s; boolean_t funnel_state; @@ -1170,7 +1224,6 @@ dlil_attach_protocol(struct dlil_proto_reg_str *proto, thread_funnel_set(network_flock, funnel_state); return error; } - /* * Add to if_proto list for this interface @@ -1182,6 +1235,13 @@ dlil_attach_protocol(struct dlil_proto_reg_str *proto, if (ifproto->dl_offer) ifp->offercnt++; + /* the reserved field carries the number of protocol still attached (subject to change) */ + ev_pr_data.proto_family = proto->protocol_family; + ev_pr_data.proto_remaining_count = dlil_ifp_proto_count(ifp); + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_PROTO_ATTACHED, + (struct net_event_data *)&ev_pr_data, + sizeof(struct kev_dl_proto_data)); + splx(s); thread_funnel_set(network_flock, funnel_state); return 0; @@ -1200,8 +1260,7 @@ dlil_detach_protocol(u_long dl_tag) struct dlil_filterq_entry *filter; int s, retval; struct dlil_filterq_head *fhead; - struct kev_msg ev_msg; - struct net_event_data ev_data; + struct kev_dl_proto_data ev_pr_data; boolean_t funnel_state; @@ -1246,12 +1305,22 @@ dlil_detach_protocol(u_long dl_tag) if (proto->dl_offer) ifp->offercnt--; + if (ifp->if_data.default_proto == dl_tag) + ifp->if_data.default_proto = 0; dl_tag_array[dl_tag].ifp = 0; - + + /* the reserved field carries the number of protocol still attached (subject to change) */ + ev_pr_data.proto_family = proto->protocol_family; TAILQ_REMOVE(tmp, proto, next); FREE(proto, M_IFADDR); - if (--ifp->refcnt == 0) { + ifp->refcnt--; + ev_pr_data.proto_remaining_count = dlil_ifp_proto_count(ifp); + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_PROTO_DETACHED, + (struct net_event_data *)&ev_pr_data, + sizeof(struct kev_dl_proto_data)); + + if (ifp->refcnt == 0 && (ifp->if_eflags & IFEF_DETACH_DISABLED) == 0) { if (ifp->if_flags & IFF_UP) printf("WARNING - dlil_detach_protocol - ifp refcnt 0, but IF still up\n"); @@ -1285,22 +1354,9 @@ dlil_detach_protocol(u_long dl_tag) } } - (*ifp->if_free)(ifp); + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_IF_DETACHED, 0, 0); - ev_msg.vendor_code = KEV_VENDOR_APPLE; - ev_msg.kev_class = KEV_NETWORK_CLASS; - ev_msg.kev_subclass = KEV_DL_SUBCLASS; - - ev_msg.event_code = KEV_DL_IF_DETACHED; - strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); - ev_data.if_family = ifp->if_family; - ev_data.if_unit = (unsigned long) ifp->if_unit; - - ev_msg.dv[0].data_length = sizeof(struct net_event_data); - ev_msg.dv[0].data_ptr = &ev_data; - ev_msg.dv[1].data_length = 0; - - kev_post_msg(&ev_msg); + (*ifp->if_free)(ifp); } splx(s); @@ -1320,8 +1376,6 @@ dlil_if_attach(struct ifnet *ifp) struct dlil_proto_head *tmp; int stat; int s; - struct kev_msg ev_msg; - struct net_event_data ev_data; boolean_t funnel_state; funnel_state = thread_funnel_set(network_flock, TRUE); @@ -1369,21 +1423,7 @@ dlil_if_attach(struct ifnet *ifp) old_if_attach(ifp); if_family->refcnt++; - ev_msg.vendor_code = KEV_VENDOR_APPLE; - ev_msg.kev_class = KEV_NETWORK_CLASS; - ev_msg.kev_subclass = KEV_DL_SUBCLASS; - - ev_msg.event_code = KEV_DL_IF_ATTACHED; - strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); - ev_data.if_family = ifp->if_family; - ev_data.if_unit = (unsigned long) ifp->if_unit; - - ev_msg.dv[0].data_length = sizeof(struct net_event_data); - ev_msg.dv[0].data_ptr = &ev_data; - - ev_msg.dv[1].data_length = 0; - - kev_post_msg(&ev_msg); + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_IF_ATTACHED, 0, 0); splx(s); thread_funnel_set(network_flock, funnel_state); @@ -1400,7 +1440,6 @@ dlil_if_detach(struct ifnet *ifp) struct dlil_filterq_head *fhead = (struct dlil_filterq_head *) &ifp->if_flt_head; int s; struct kev_msg ev_msg; - struct net_event_data ev_data; boolean_t funnel_state; funnel_state = thread_funnel_set(network_flock, TRUE); @@ -1421,7 +1460,9 @@ dlil_if_detach(struct ifnet *ifp) while (if_filter = TAILQ_FIRST(fhead)) dlil_detach_filter(if_filter->filter_id); - if (--ifp->refcnt == 0) { + ifp->refcnt--; + + if (ifp->refcnt == 0 && (ifp->if_eflags & IFEF_DETACH_DISABLED) == 0) { TAILQ_REMOVE(&ifnet, ifp, if_link); (*if_family->del_if)(ifp); @@ -1434,40 +1475,14 @@ dlil_if_detach(struct ifnet *ifp) FREE(if_family, M_IFADDR); } - ev_msg.vendor_code = KEV_VENDOR_APPLE; - ev_msg.kev_class = KEV_NETWORK_CLASS; - ev_msg.kev_subclass = KEV_DL_SUBCLASS; - - ev_msg.event_code = KEV_DL_IF_DETACHED; - strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); - ev_data.if_family = ifp->if_family; - ev_data.if_unit = (unsigned long) ifp->if_unit; - - ev_msg.dv[0].data_length = sizeof(struct net_event_data); - ev_msg.dv[0].data_ptr = &ev_data; - - ev_msg.dv[1].data_length = 0; - kev_post_msg(&ev_msg); + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_IF_DETACHED, 0, 0); splx(s); thread_funnel_set(network_flock, funnel_state); return 0; } else { - ev_msg.vendor_code = KEV_VENDOR_APPLE; - ev_msg.kev_class = KEV_NETWORK_CLASS; - ev_msg.kev_subclass = KEV_DL_SUBCLASS; - - ev_msg.event_code = KEV_DL_IF_DETACHING; - strncpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); - ev_data.if_family = ifp->if_family; - ev_data.if_unit = (unsigned long) ifp->if_unit; - ev_msg.dv[0].data_length = sizeof(struct net_event_data); - ev_msg.dv[0].data_ptr = &ev_data; - ev_msg.dv[1].data_length = 0; - - kev_post_msg(&ev_msg); - + dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_IF_DETACHING, 0, 0); splx(s); thread_funnel_set(network_flock, funnel_state); return DLIL_WAIT_FOR_FREE; diff --git a/bsd/net/dlil.h b/bsd/net/dlil.h index 63479e676..6a8740a57 100644 --- a/bsd/net/dlil.h +++ b/bsd/net/dlil.h @@ -95,6 +95,7 @@ struct dlil_pr_flt_str { caddr_t ioctl_arg); int (*filter_detach)(caddr_t cookie); + u_long reserved[2]; }; struct dlil_if_flt_str { @@ -121,7 +122,8 @@ struct dlil_if_flt_str { int (*filter_if_free)(caddr_t cookie, struct ifnet *ifnet_ptr); - int (*filter_detach)(caddr_t cookie); + int (*filter_detach)(caddr_t cookie); + u_long reserved[2]; }; @@ -176,6 +178,7 @@ struct if_proto { dl_offer_func dl_offer; dl_ioctl_func dl_ioctl; u_long protocol_family; + u_long reserved[4]; }; @@ -236,6 +239,7 @@ struct dlil_proto_reg_str { dl_event_func event; dl_offer_func offer; dl_ioctl_func ioctl; + u_long reserved[4]; }; @@ -287,6 +291,7 @@ struct dlil_ifmod_reg_str { int (*del_proto)(struct if_proto *proto, u_long dl_tag); int (*ifmod_ioctl)(struct ifnet *ifp, u_long ioctl_cmd, caddr_t data); int (*shutdown)(); + u_long reserved[4]; }; diff --git a/bsd/net/dlil_ethersubr.c b/bsd/net/dlil_ethersubr.c index 3d85f62f1..ae32c57c5 100644 --- a/bsd/net/dlil_ethersubr.c +++ b/bsd/net/dlil_ethersubr.c @@ -276,7 +276,7 @@ restart: if (!desc_in_bounds(proto->ifp->family_cookie, current_ptr, total_length)) { tmp = _MALLOC((ETHER_DESC_BLK_SIZE * (block_count + 1)), - M_IFADDR, M_NOWAIT); + M_IFADDR, M_WAITOK); if (tmp == 0) { /* * Remove any previous descriptors set in the call. @@ -739,7 +739,7 @@ int ether_add_if(struct ifnet *ifp) if (i == MAX_INTERFACES) return EOVERFLOW; - ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_NOWAIT); + ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_WAITOK); if (ether_desc_blk[i].block_ptr == 0) return ENOMEM; diff --git a/bsd/net/ether_if_module.c b/bsd/net/ether_if_module.c index 2d1a9f52a..3964774c4 100644 --- a/bsd/net/ether_if_module.c +++ b/bsd/net/ether_if_module.c @@ -267,7 +267,7 @@ restart: if (!desc_in_bounds(proto->ifp->family_cookie, current_ptr, total_length)) { tmp = _MALLOC((ETHER_DESC_BLK_SIZE * (block_count + 1)), - M_IFADDR, M_NOWAIT); + M_IFADDR, M_WAITOK); if (tmp == 0) { /* * Remove any previous descriptors set in the call. @@ -506,7 +506,7 @@ int ether_add_if(struct ifnet *ifp) if (i == MAX_INTERFACES) return ENOMEM; - ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_NOWAIT); + ether_desc_blk[i].block_ptr = _MALLOC(ETHER_DESC_BLK_SIZE, M_IFADDR, M_WAITOK); if (ether_desc_blk[i].block_ptr == 0) return ENOMEM; diff --git a/bsd/net/ether_inet6_pr_module.c b/bsd/net/ether_inet6_pr_module.c index 66aea6d16..5855805bd 100644 --- a/bsd/net/ether_inet6_pr_module.c +++ b/bsd/net/ether_inet6_pr_module.c @@ -297,8 +297,6 @@ ether_inet6_prmod_ioctl(dl_tag, ifp, command, data) u_char *e_addr; - funnel_state = thread_funnel_set(TRUE); - switch (command) { case SIOCRSLVMULTI: { switch(rsreq->sa->sa_family) { @@ -373,8 +371,6 @@ ether_inet6_prmod_ioctl(dl_tag, ifp, command, data) return EOPNOTSUPP; } - (void) thread_funnel_set(funnel_state); - return (error); } @@ -410,7 +406,7 @@ u_long ether_attach_inet6(struct ifnet *ifp) reg.event = 0; reg.offer = 0; reg.ioctl = ether_inet6_prmod_ioctl; - reg.default_proto = 1; + reg.default_proto = 0; reg.protocol_family = PF_INET6; stat = dlil_attach_protocol(®, &ip_dl_tag); diff --git a/bsd/net/ether_inet_pr_module.c b/bsd/net/ether_inet_pr_module.c index dd029a0fa..47147cb1f 100644 --- a/bsd/net/ether_inet_pr_module.c +++ b/bsd/net/ether_inet_pr_module.c @@ -463,6 +463,23 @@ ether_attach_inet(struct ifnet *ifp) printf("WARNING: ether_attach_inet can't attach ip to interface\n"); return stat; } - + /* XXX avoid free'ing the interface */ + ifp->if_eflags |= IFEF_DETACH_DISABLED; return ip_dl_tag; } + +int ether_detach_inet(struct ifnet *ifp) +{ + u_long ip_dl_tag = 0; + int stat; + + stat = dlil_find_dltag(ifp->if_family, ifp->if_unit, PF_INET, &ip_dl_tag); + if (stat == 0) { + stat = dlil_detach_protocol(ip_dl_tag); + if (stat) { + printf("WARNING: ether_detach_inet can't detach ip from interface\n"); + } + } + return stat; +} + diff --git a/bsd/net/if.h b/bsd/net/if.h index e601dbf4d..50ccff96f 100644 --- a/bsd/net/if.h +++ b/bsd/net/if.h @@ -78,6 +78,8 @@ #define KEV_DL_IF_DETACHED 11 #define KEV_DL_LINK_OFF 12 #define KEV_DL_LINK_ON 13 +#define KEV_DL_PROTO_ATTACHED 14 +#define KEV_DL_PROTO_DETACHED 15 /* * <net/if.h> does not depend on <sys/time.h> on most other systems. This @@ -107,9 +109,12 @@ #define IFF_MULTICAST 0x8000 /* supports multicast */ #define IFF_SPLITTER IFF_LINK2 /* Y splitter in force */ - - +#ifdef KERNEL_PRIVATE +/* extended flags definitions: (all bits are reserved for internal/future use) */ +#define IFEF_AUTOCONFIGURING 0x1 #define IFEF_DVR_REENTRY_OK 0x20 /* When set, driver may be reentered from its own thread */ +#define IFEF_DETACH_DISABLED 0x80000000 +#endif KERNEL_PRIVATE /* flags set internally only: */ @@ -235,6 +240,16 @@ struct ifconf { #define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */ }; +/* + * DLIL KEV_DL_PROTO_ATTACHED/DETACHED structure + */ +struct kev_dl_proto_data { + struct net_event_data link_data; + u_long proto_family; + u_long proto_remaining_count; +}; + + /* * Structure for SIOC[AGD]LIFADDR */ diff --git a/bsd/net/if_gif.c b/bsd/net/if_gif.c index aa0d3df0a..e54b949e2 100644 --- a/bsd/net/if_gif.c +++ b/bsd/net/if_gif.c @@ -278,7 +278,7 @@ gifattach(dummy) gif_reg_if_mods(); /* DLIL modules */ - gif = sc = _MALLOC (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT); + gif = sc = _MALLOC (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAITOK); bzero(sc, ngif * sizeof(struct gif_softc)); for (i = 0; i < ngif; sc++, i++) { sc->gif_if.if_name = "gif"; diff --git a/bsd/net/if_loop.c b/bsd/net/if_loop.c index 422303b87..e8cef396f 100644 --- a/bsd/net/if_loop.c +++ b/bsd/net/if_loop.c @@ -285,6 +285,9 @@ lo_output(ifp, m) */ m->m_pkthdr.header = mtod(m, char *); m->m_pkthdr.aux = ifp; /* HACKERY */ + m->m_pkthdr.csum_data = 0xffff; /* loopback checksums are always OK */ + m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_PSEUDO_HDR | + CSUM_IP_CHECKED | CSUM_IP_VALID; return dlil_input(ifp, m, m); } @@ -605,6 +608,7 @@ loopattach(dummy) ifp->if_set_bpf_tap = lo_set_bpf_tap; ifp->if_output = lo_output; ifp->if_type = IFT_LOOP; + ifp->if_hwassist = 0; /* HW cksum on send side breaks Classic loopback */ dlil_if_attach(ifp); #if NBPFILTER > 0 bpfattach(ifp, DLT_NULL, sizeof(u_int)); diff --git a/bsd/net/if_media.c b/bsd/net/if_media.c index afbf3ef82..59778216b 100644 --- a/bsd/net/if_media.c +++ b/bsd/net/if_media.c @@ -133,7 +133,7 @@ ifmedia_add(ifm, mword, data, aux) } #endif - entry = _MALLOC(sizeof(*entry), M_IFADDR, M_NOWAIT); + entry = _MALLOC(sizeof(*entry), M_IFADDR, M_WAITOK); if (entry == NULL) panic("ifmedia_add: can't malloc entry"); diff --git a/bsd/net/if_spppsubr.c b/bsd/net/if_spppsubr.c index 01f2f3e67..6d621b2f6 100644 --- a/bsd/net/if_spppsubr.c +++ b/bsd/net/if_spppsubr.c @@ -1939,7 +1939,7 @@ sppp_lcp_RCR(struct sppp *sp, struct lcp_header *h, int len) len -= 4; origlen = len; - buf = r = _MALLOC(len, M_TEMP, M_NOWAIT); + buf = r = _MALLOC(len, M_TEMP, M_WAITOK); if (! buf) return (0); @@ -2152,7 +2152,7 @@ sppp_lcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) u_char *buf, *p; len -= 4; - buf = MALLOC (len, M_TEMP, M_NOWAIT); + buf = MALLOC (len, M_TEMP, M_WAITOK); if (!buf) return; @@ -2216,7 +2216,7 @@ sppp_lcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) u_long magic; len -= 4; - buf = MALLOC (len, M_TEMP, M_NOWAIT); + buf = MALLOC (len, M_TEMP, M_WAITOK); if (!buf) return; @@ -2589,7 +2589,7 @@ sppp_ipcp_RCR(struct sppp *sp, struct lcp_header *h, int len) * Make sure to allocate a buf that can at least hold a * conf-nak with an `address' option. We might need it below. */ - buf = r = MALLOC ((len < 6? 6: len), M_TEMP, M_NOWAIT); + buf = r = MALLOC ((len < 6? 6: len), M_TEMP, M_WAITOK); if (! buf) return (0); @@ -2751,7 +2751,7 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header *h, int len) int debug = ifp->if_flags & IFF_DEBUG; len -= 4; - buf = MALLOC (len, M_TEMP, M_NOWAIT); + buf = MALLOC (len, M_TEMP, M_WAITOK); if (!buf) return; @@ -2798,7 +2798,7 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header *h, int len) u_long wantaddr; len -= 4; - buf = MALLOC (len, M_TEMP, M_NOWAIT); + buf = MALLOC (len, M_TEMP, M_WAITOK); if (!buf) return; diff --git a/bsd/net/if_tun.c b/bsd/net/if_tun.c index 833251c07..81eafd18e 100644 --- a/bsd/net/if_tun.c +++ b/bsd/net/if_tun.c @@ -249,9 +249,8 @@ tunclose(dev, foo, bar, p) } ifp->if_flags &= ~IFF_RUNNING; funsetown(tp->tun_sigio); - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&tp->tun_rsel); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); + selthreadclear(&tp->tun_rsel); TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit); return (0); @@ -451,9 +450,7 @@ tunoutput(ifp, m0, dst, rt) } if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) pgsigio(tp->tun_sigio, SIGIO, 0); - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&tp->tun_rsel); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); return 0; } @@ -730,9 +727,10 @@ tunwrite(dev, uio, flag) * anyway, it either accepts the packet or drops it. */ static int -tunpoll(dev, events, p) +tunpoll(dev, events, wql, p) dev_t dev; int events; + void * wql; struct proc *p; { int unit = dev_val(minor(dev)), s; @@ -751,7 +749,7 @@ tunpoll(dev, events, p) } else { TUNDEBUG("%s%d: tunpoll waiting\n", ifp->if_name, ifp->if_unit); - selrecord(p, &tp->tun_rsel); + selrecord(p, &tp->tun_rsel, wql); } if (events & (POLLOUT | POLLWRNORM)) diff --git a/bsd/net/if_vlan.c b/bsd/net/if_vlan.c index e4a3585a5..2bc498376 100644 --- a/bsd/net/if_vlan.c +++ b/bsd/net/if_vlan.c @@ -159,7 +159,9 @@ static int vlan_setmulti(struct ifnet *ifp) ifma != NULL;ifma = ifma->ifma_link.le_next) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; - mc = _MALLOC(sizeof(struct vlan_mc_entry), M_DEVBUF, M_NOWAIT); + mc = _MALLOC(sizeof(struct vlan_mc_entry), M_DEVBUF, M_WAITOK); + if (mc == NULL) + return (ENOMEM); bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr), (char *)&mc->mc_addr, ETHER_ADDR_LEN); SLIST_INSERT_HEAD(&sc->vlan_mc_listhead, mc, mc_entries); diff --git a/bsd/net/kext_net.h b/bsd/net/kext_net.h index a048de3a7..d11f61b86 100644 --- a/bsd/net/kext_net.h +++ b/bsd/net/kext_net.h @@ -63,6 +63,7 @@ struct NFDescriptor */ struct sockif *nf_soif; /* Socket functions */ struct sockutil *nf_soutil; /* Sockbuf utility functions */ + u_long reserved[4]; /* for future use if needed */ }; #define NFD_GLOBAL 0x01 @@ -100,6 +101,7 @@ struct so_nke { unsigned int nke_handle; unsigned int nke_where; int nke_flags; /* NFF_BEFORE, NFF_AFTER: net/kext_net.h */ + unsigned long reserved[4]; /* for future use */ }; /* @@ -157,6 +159,7 @@ struct sockif int (*sf_soreserve)(struct socket *, u_long, u_long, struct kextcb *); int (*sf_sowakeup)(struct socket *, struct sockbuf *, struct kextcb *); + u_long reserved[4]; }; @@ -195,6 +198,7 @@ struct sockutil int (*su_sbreserve)(struct sockbuf *, u_long, struct kextcb *); /* Calls tsleep() */ int (*su_sbwait)(struct sockbuf *, struct kextcb *); + u_long reserved[4]; }; #endif diff --git a/bsd/net/ndrv.c b/bsd/net/ndrv.c index 820b8cc7b..b9de35027 100644 --- a/bsd/net/ndrv.c +++ b/bsd/net/ndrv.c @@ -233,6 +233,8 @@ ndrv_attach(struct socket *so, int proto, struct proc *p) kprintf("NDRV attach: %x, %x, %x\n", so, proto, np); #endif MALLOC(np, struct ndrv_cb *, sizeof(*np), M_PCB, M_WAITOK); + if (np == NULL) + return (ENOMEM); #if NDRV_DEBUG kprintf("NDRV attach: %x, %x, %x\n", so, proto, np); #endif @@ -647,6 +649,8 @@ ndrv_setspec(struct ndrv_cb *np, struct ndrv_descr *nd) bzero((caddr_t)&proto_spec, sizeof (proto_spec)); i = nd->nd_len / (sizeof (struct dlil_demux_desc)); /* # elts */ MALLOC(native_values,int *, i * sizeof (int), M_TEMP, M_WAITOK); + if (native_values == NULL) + return (ENOMEM); mp = (struct dlil_demux_desc *)nd->nd_buf; for (j = 0; j++ < i;) { MALLOC(mp1, struct dlil_demux_desc *, @@ -680,8 +684,10 @@ ndrv_setspec(struct ndrv_cb *np, struct ndrv_descr *nd) if (error) { struct dlil_demux_desc *mp2; - TAILQ_FOREACH(mp2, &np->nd_dlist, next) + while ((mp2 = TAILQ_FIRST(&np->nd_dlist))) { + TAILQ_REMOVE(&np->nd_dlist, mp2, next); FREE(mp2, M_PCB); + } } else error = ndrv_add_descr(np, &proto_spec); #ifdef NDRV_DEBUG diff --git a/bsd/net/radix.h b/bsd/net/radix.h index be6c18d35..eeef4221b 100644 --- a/bsd/net/radix.h +++ b/bsd/net/radix.h @@ -170,7 +170,7 @@ struct radix_node_head { #define Bcmp(a, b, n) bcmp(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) #define Bcopy(a, b, n) bcopy(((caddr_t)(a)), ((caddr_t)(b)), (unsigned)(n)) #define Bzero(p, n) bzero((caddr_t)(p), (unsigned)(n)); -#define R_Malloc(p, t, n) (p = (t) _MALLOC((unsigned long)(n), M_RTABLE, M_DONTWAIT)) +#define R_Malloc(p, t, n) (p = (t) _MALLOC((unsigned long)(n), M_RTABLE, M_WAITOK)) #define Free(p) FREE((caddr_t)p, M_RTABLE); #endif /*KERNEL*/ diff --git a/bsd/net/raw_cb.h b/bsd/net/raw_cb.h index 541ade793..3224741d2 100644 --- a/bsd/net/raw_cb.h +++ b/bsd/net/raw_cb.h @@ -69,6 +69,7 @@ struct rawcb { struct sockaddr *rcb_faddr; /* destination address */ struct sockaddr *rcb_laddr; /* socket's address */ struct sockproto rcb_proto; /* protocol family, protocol */ + u_long reserved[4]; /* for future use */ }; #define sotorawcb(so) ((struct rawcb *)(so)->so_pcb) diff --git a/bsd/net/route.h b/bsd/net/route.h index 0e2c09f91..e4c06e50a 100644 --- a/bsd/net/route.h +++ b/bsd/net/route.h @@ -72,6 +72,7 @@ struct route { struct rtentry *ro_rt; struct sockaddr ro_dst; + u_long reserved[2]; /* for future use if needed */ }; /* diff --git a/bsd/net/rtsock.c b/bsd/net/rtsock.c index 8ac37c98d..0ff722bd2 100644 --- a/bsd/net/rtsock.c +++ b/bsd/net/rtsock.c @@ -755,7 +755,7 @@ again: if (rw->w_tmem) FREE(rw->w_tmem, M_RTABLE); rw->w_tmem = (caddr_t) - _MALLOC(len, M_RTABLE, M_NOWAIT); + _MALLOC(len, M_RTABLE, M_WAITOK); /*###LD0412 was NOWAIT */ if (rw->w_tmem) rw->w_tmemsize = len; } diff --git a/bsd/netat/asp_proto.c b/bsd/netat/asp_proto.c index a93025454..fc1efd738 100644 --- a/bsd/netat/asp_proto.c +++ b/bsd/netat/asp_proto.c @@ -580,8 +580,9 @@ int asp_wput(gref, m) aw.param2 = 0; scb->ioc_wait = (unsigned char)(iocbp->ioc_cmd & 0xff); iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF; + /* bms: make sure this is an ALO request */ asp_send_req(gref, mioc, &status_cmd->SLSEntityIdentifier, - &status_cmd->Retry, &aw, 1, ASPSTATE_WaitingForGetStatusRsp, 0xff); + &status_cmd->Retry, &aw, 0, ASPSTATE_WaitingForGetStatusRsp, 0xff); gbuf_freeb(mdata); return 0; @@ -1357,6 +1358,9 @@ asp_ack_reply(gref, mioc) } else { scb->rem_addr.node = scb->rem_node; scb->rem_addr.socket = awp->func; + /* bms: need to set the reply_socket for client side too. + This makes ALO atten replies sent by the client work. */ + scb->reply_socket = scb->rem_addr.socket; scb->sess_id = awp->param1; gbuf_freeb(mx); atalk_putnext(gref, mioc); @@ -1894,265 +1898,294 @@ asp_putnext(gref, mproto) /* in ASPputmsg we expect: - ASPFUNC_CmdReply - ASPFUNC_Attention - ASPFUNC_Command - ASPFUNC_Write - ASPFUNC_WriteContinue + ASPFUNC_CmdReply + ASPFUNC_Attention + ASPFUNC_Command + ASPFUNC_Write + ASPFUNC_WriteContinue + + bms: Make this callable from the kernel. + If mreq != NULL, then must be called from kernel space and the following apply: + 1) *mreq is data to be sent already in mbuf chains. + 2) datptr->len = size of data */ -int ASPputmsg(gref, ctlptr, datptr, flags, errp) - gref_t *gref; - strbuf_t *ctlptr; - strbuf_t *datptr; - int flags; - int *errp; +int ASPputmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t *mreq, int flags, int *errp) { - int s, i, err, len; - gbuf_t *mioc, *mdata, *mx; - ioc_t *iocbp; - strbuf_t ctlbuf; - strbuf_t datbuf; - asp_scb_t *scb; - int nbds, result, msize, Primitive; - unsigned char *wptr; - struct atp_set_default *sd; - at_ddp_t *ddp; - at_atp_t *atp; - struct atpBDS *atpBDS; - asp_word_t *awp; - union asp_primitives *primitives; - unsigned short tid; - - if ((scb = (asp_scb_t *)gref->info) == 0) { + int s, i, err, len; + gbuf_t *mioc, *mdata, *mx; + ioc_t *iocbp; + strbuf_t ctlbuf; + strbuf_t datbuf; + asp_scb_t *scb; + int nbds, result, msize, Primitive; + unsigned char *wptr; + struct atp_set_default *sd; + at_ddp_t *ddp; + at_atp_t *atp; + struct atpBDS *atpBDS; + asp_word_t *awp; + union asp_primitives *primitives; + unsigned short tid; + + if ((scb = (asp_scb_t *)gref->info) == 0) { dPrintf(D_M_ASP, D_L_ERROR, ("ASPputmsg: stale handle=0x%x, pid=%d\n", (u_int) gref, gref->pid)); - *errp = EINVAL; - return -1; - } - - if (scb->state == ASPSTATE_Close) - return 0; - if (scb->snd_stop) { - *errp = EAGAIN; - return -1; - } - - /* - * copy in the control and data info - */ - if ((err = copyin((caddr_t)ctlptr, - (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) - goto l_err; - if ((err = copyin((caddr_t)datptr, - (caddr_t)&datbuf, sizeof(datbuf))) != 0) - goto l_err; - - /* - * allocate buffer and copy in the control content - */ - if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) { - /* error return should not be possible */ - err = ENOBUFS; - goto l_err; - } - gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */ - gbuf_wset(mioc, ctlbuf.len); - if ((err = copyin((caddr_t)ctlbuf.buf, - (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) { - gbuf_freem(mioc); - goto l_err; - } + *errp = EINVAL; + return -1; + } + + if (scb->state == ASPSTATE_Close) + return 0; + if (scb->snd_stop) { + *errp = EAGAIN; + return -1; + } + + /* + * copy in the control and data info + */ + if (mreq != NULL) { + /* being called from kernel space */ + bcopy (ctlptr, &ctlbuf, sizeof (strbuf_t)); + bcopy (datptr, &datbuf, sizeof (strbuf_t)); + } else { + /* being called from user space */ + if ((err = copyin((caddr_t)ctlptr, (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) + goto l_err; + if ((err = copyin((caddr_t)datptr, (caddr_t)&datbuf, sizeof(datbuf))) != 0) + goto l_err; + } + + /* + * allocate buffer and copy in the control content + */ + if (!(mioc = gbuf_alloc_wait(ctlbuf.len, TRUE))) { + /* error return should not be possible */ + err = ENOBUFS; + goto l_err; + } + gbuf_set_type(mioc, MSG_IOCTL); /* for later, in ATP */ + gbuf_wset(mioc, ctlbuf.len); + + if (mreq != NULL) { + /* being called from kernel space */ + bcopy (ctlbuf.buf, gbuf_rptr(mioc), ctlbuf.len); + } else { + /* being called from user space */ + if ((err = copyin((caddr_t)ctlbuf.buf, (caddr_t)gbuf_rptr(mioc), ctlbuf.len)) != 0) { + gbuf_freem(mioc); + goto l_err; + } + } - iocbp = (ioc_t *)gbuf_rptr(mioc); - primitives = (union asp_primitives *)gbuf_rptr(mioc); - Primitive = primitives->Primitive; + iocbp = (ioc_t *)gbuf_rptr(mioc); + primitives = (union asp_primitives *)gbuf_rptr(mioc); + Primitive = primitives->Primitive; dPrintf(D_M_ASP, D_L_INFO, ("ASPputmsg: %s\n", aspCmdStr(Primitive))); - /* - * allocate buffer and copy in the data content - */ - len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize; - if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) { - /* error return should not be possible */ - err = ENOBUFS; - gbuf_freem(mioc); - goto l_err; - } - gbuf_wset(mdata,(datbuf.len+len)); - gbuf_cont(mioc) = mdata; - if ((err = copyin((caddr_t)datbuf.buf, - (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) { - gbuf_freem(mioc); - goto l_err; - } - - switch (Primitive) { - - case ASPFUNC_Command: - case ASPFUNC_Write: - case ASPFUNC_WriteContinue: - case ASPFUNC_Attention: - /* - * build the command/write/write_continue request - */ - wptr = gbuf_rptr(mdata); - atpBDS = (struct atpBDS *)wptr; - wptr += atpBDSsize; - for (i=0; i < ATP_TRESP_MAX; i++) { - *(unsigned long *)atpBDS[i].bdsBuffAddr = 1; - *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE; - } - sd = (struct atp_set_default *)wptr; - wptr += sizeof(struct atp_set_default); - sd->def_retries = (scb->cmd_retry.retries == -1) ? - ATP_INFINITE_RETRIES : scb->cmd_retry.retries; - sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC; - sd->def_BDSlen = atpBDSsize; - ddp = (at_ddp_t *)wptr; - NET_ASSIGN(ddp->src_net, scb->loc_addr.net); - ddp->src_node = scb->loc_addr.node; - NET_ASSIGN(ddp->dst_net, scb->rem_addr.net); - ddp->dst_node = scb->rem_addr.node; - ddp->dst_socket = scb->rem_addr.socket; - UAS_ASSIGN(ddp->checksum, 0); - atp = ATP_ATP_HDR(wptr); - wptr += TOTAL_ATP_HDR_SIZE; - atp->xo = 1; - atp->xo_relt = 1; - atp->bitmap = 0xff; - awp = (asp_word_t *)atp->user_bytes; - awp->func = (unsigned char)Primitive; - awp->param1 = scb->sess_id; - awp->param2 = scb->snd_seq_num; - iocbp->ioc_private = (void *)scb; - iocbp->ioc_count = gbuf_len(mdata); - iocbp->ioc_rval = 0; - iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF; - - /* - * send the command/write/write_continue/attention request - */ - ATDISABLE(s, scb->lock); - switch (awp->func) { - case ASPFUNC_Command: - scb->state = ASPSTATE_WaitingForCommandRsp; - break; - case ASPFUNC_Write: - scb->state = ASPSTATE_WaitingForWriteRsp; - break; - case ASPFUNC_WriteContinue: - scb->state = ASPSTATE_WaitingForWriteContinueRsp; - awp->param2 = scb->wrt_seq_num; - break; - case ASPFUNC_Attention: - scb->state = ASPSTATE_WaitingForCommandRsp; - atp->xo = 0; - atp->xo_relt = 0; - atp->bitmap = 0x01; - gbuf_wdec(mdata,2); - awp->param2 = *(unsigned short *)gbuf_wptr(mdata); - break; - } - ATENABLE(s, scb->lock); - dPrintf(D_M_ASP,D_L_INFO, - ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n", - (awp->func == ASPFUNC_Command ? "CommandReq" : - awp->func == ASPFUNC_Write ? "WriteReq" : - awp->func == ASPFUNC_WriteContinue ? "WriteContinue" : - "AttentionReq"),scb->loc_addr.socket, - NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket)); - atp_send_req(gref, mioc); - return 0; - - case ASPFUNC_CmdReply: - - ATDISABLE(s, scb->lock); - if (scb->req_msgq) { - mx = scb->req_msgq; - scb->req_msgq = gbuf_next(mx); - gbuf_next(mx) = 0; - ATENABLE(s, scb->lock); - asp_putnext(scb->gref, mx); - } else { - scb->req_flag = 0; - ATENABLE(s, scb->lock); - } - result = primitives->CmdReplyReq.CmdResult; - tid = primitives->CmdReplyReq.ReqRefNum; - - /* Re-use the original mioc mbuf to send the response. */ - gbuf_rinc(mioc,sizeof(void *)); - gbuf_wset(mioc,0); - ddp = (at_ddp_t *)gbuf_wptr(mioc); - gbuf_winc(mioc,DDP_X_HDR_SIZE); - atp = (at_atp_t *)gbuf_wptr(mioc); - gbuf_winc(mioc,ATP_HDR_SIZE); - NET_ASSIGN(ddp->src_net, scb->loc_addr.net); - ddp->src_node = scb->loc_addr.node; - NET_ASSIGN(ddp->dst_net, scb->rem_addr.net); - ddp->dst_node = scb->rem_addr.node; - ddp->dst_socket = scb->reply_socket; - ddp->type = DDP_ATP; - UAS_ASSIGN(ddp->checksum, 0); - UAS_ASSIGN(atp->tid, tid); - if (scb->attn_flag && (tid == scb->attn_tid)) { - scb->attn_flag = 0; - atp->xo = 0; - atp->xo_relt = 0; - } else { - atp->xo = 1; - atp->xo_relt = 1; - } - atpBDS = (struct atpBDS *)gbuf_wptr(mioc); - msize = mdata ? gbuf_msgsize(mdata) : 0; - for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) { - len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE; - msize -= ATP_DATA_SIZE; - *(long *)atpBDS[nbds].bdsUserData = 0; - UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1); - UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len); - } - UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds); - *(long *)atpBDS[0].bdsUserData = (long)result; - *(long *)atp->user_bytes = (long)result; - gbuf_winc(mioc,atpBDSsize); + /* + * allocate buffer and copy in the data content + */ + len = (Primitive == ASPFUNC_CmdReply) ? 0 : aspCMDsize; + + if (!(mdata = gbuf_alloc_wait(datbuf.len+len, TRUE))) { + /* error return should not be possible */ + err = ENOBUFS; + gbuf_freem(mioc); + goto l_err; + } + gbuf_wset(mdata, (datbuf.len+len)); + gbuf_cont(mioc) = mdata; + + if (mreq != NULL) { + /* being called from kernel space */ + gbuf_t *tmp = mreq; + unsigned long offset = 0; + + /* copy afp cmd data from the passed in mbufs to mdata. I cant + chain mreq to mdata since the rest of this code assumes + just one big mbuf with space in front for the BDS */ + offset = len; + while (tmp != NULL) { + bcopy (gbuf_rptr(tmp), (gbuf_rptr(mdata) + offset), gbuf_len(tmp)); + offset += gbuf_len(tmp); + tmp = gbuf_cont(tmp); /* on to next mbuf in chain */ + } + + /* all data copied out of mreq so free it */ + gbuf_freem(mreq); + } else { + /* being called from user space */ + if ((err = copyin((caddr_t)datbuf.buf, + (caddr_t)(gbuf_rptr(mdata)+len), datbuf.len)) != 0) { + gbuf_freem(mioc); + goto l_err; + } + } + + switch (Primitive) { + + case ASPFUNC_Command: + case ASPFUNC_Write: + case ASPFUNC_WriteContinue: + case ASPFUNC_Attention: + /* + * build the command/write/write_continue request + */ + wptr = gbuf_rptr(mdata); + atpBDS = (struct atpBDS *)wptr; + wptr += atpBDSsize; + for (i=0; i < ATP_TRESP_MAX; i++) { + *(unsigned long *)atpBDS[i].bdsBuffAddr = 1; + *(unsigned short *)atpBDS[i].bdsBuffSz = ATP_DATA_SIZE; + } + sd = (struct atp_set_default *)wptr; + wptr += sizeof(struct atp_set_default); + sd->def_retries = (scb->cmd_retry.retries == -1) ? + ATP_INFINITE_RETRIES : scb->cmd_retry.retries; + sd->def_rate = scb->cmd_retry.interval*TICKS_PER_SEC; + sd->def_BDSlen = atpBDSsize; + ddp = (at_ddp_t *)wptr; + NET_ASSIGN(ddp->src_net, scb->loc_addr.net); + ddp->src_node = scb->loc_addr.node; + NET_ASSIGN(ddp->dst_net, scb->rem_addr.net); + ddp->dst_node = scb->rem_addr.node; + ddp->dst_socket = scb->rem_addr.socket; + UAS_ASSIGN(ddp->checksum, 0); + atp = ATP_ATP_HDR(wptr); + wptr += TOTAL_ATP_HDR_SIZE; + atp->xo = 1; + atp->xo_relt = 1; + atp->bitmap = 0xff; + awp = (asp_word_t *)atp->user_bytes; + awp->func = (unsigned char)Primitive; + awp->param1 = scb->sess_id; + awp->param2 = scb->snd_seq_num; + iocbp->ioc_private = (void *)scb; + iocbp->ioc_count = gbuf_len(mdata); + iocbp->ioc_rval = 0; + iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST_DEF; + + /* + * send the command/write/write_continue/attention request + */ + ATDISABLE(s, scb->lock); + switch (awp->func) { + case ASPFUNC_Command: + scb->state = ASPSTATE_WaitingForCommandRsp; + break; + case ASPFUNC_Write: + scb->state = ASPSTATE_WaitingForWriteRsp; + break; + case ASPFUNC_WriteContinue: + scb->state = ASPSTATE_WaitingForWriteContinueRsp; + awp->param2 = scb->wrt_seq_num; + break; + case ASPFUNC_Attention: + scb->state = ASPSTATE_WaitingForCommandRsp; + atp->xo = 0; + atp->xo_relt = 0; + atp->bitmap = 0x01; + gbuf_wdec(mdata,2); + awp->param2 = *(unsigned short *)gbuf_wptr(mdata); + break; + } + ATENABLE(s, scb->lock); + dPrintf(D_M_ASP,D_L_INFO, + ("ASPputmsg: %s, loc=%d, rem=%x.%x.%d\n", + (awp->func == ASPFUNC_Command ? "CommandReq" : + awp->func == ASPFUNC_Write ? "WriteReq" : + awp->func == ASPFUNC_WriteContinue ? "WriteContinue" : + "AttentionReq"),scb->loc_addr.socket, + NET_VALUE(ddp->dst_net),ddp->dst_node,ddp->dst_socket)); + atp_send_req(gref, mioc); + return 0; + + case ASPFUNC_CmdReply: + + ATDISABLE(s, scb->lock); + if (scb->req_msgq) { + mx = scb->req_msgq; + scb->req_msgq = gbuf_next(mx); + gbuf_next(mx) = 0; + ATENABLE(s, scb->lock); + asp_putnext(scb->gref, mx); + } else { + scb->req_flag = 0; + ATENABLE(s, scb->lock); + } + result = primitives->CmdReplyReq.CmdResult; + tid = primitives->CmdReplyReq.ReqRefNum; + + /* Re-use the original mioc mbuf to send the response. */ + gbuf_rinc(mioc,sizeof(void *)); + gbuf_wset(mioc,0); + ddp = (at_ddp_t *)gbuf_wptr(mioc); + gbuf_winc(mioc,DDP_X_HDR_SIZE); + atp = (at_atp_t *)gbuf_wptr(mioc); + gbuf_winc(mioc,ATP_HDR_SIZE); + NET_ASSIGN(ddp->src_net, scb->loc_addr.net); + ddp->src_node = scb->loc_addr.node; + NET_ASSIGN(ddp->dst_net, scb->rem_addr.net); + ddp->dst_node = scb->rem_addr.node; + ddp->dst_socket = scb->reply_socket; + ddp->type = DDP_ATP; + UAS_ASSIGN(ddp->checksum, 0); + UAS_ASSIGN(atp->tid, tid); + if (scb->attn_flag && (tid == scb->attn_tid)) { + scb->attn_flag = 0; + atp->xo = 0; + atp->xo_relt = 0; + } else { + atp->xo = 1; + atp->xo_relt = 1; + } + atpBDS = (struct atpBDS *)gbuf_wptr(mioc); + msize = mdata ? gbuf_msgsize(mdata) : 0; + for (nbds=0; (nbds < ATP_TRESP_MAX) && (msize > 0); nbds++) { + len = msize < ATP_DATA_SIZE ? msize : ATP_DATA_SIZE; + msize -= ATP_DATA_SIZE; + *(long *)atpBDS[nbds].bdsUserData = 0; + UAL_ASSIGN(atpBDS[nbds].bdsBuffAddr, 1); + UAS_ASSIGN(atpBDS[nbds].bdsBuffSz, len); + } + UAS_ASSIGN(atpBDS[0].bdsDataSz, nbds); + *(long *)atpBDS[0].bdsUserData = (long)result; + *(long *)atp->user_bytes = (long)result; + gbuf_winc(mioc,atpBDSsize); dPrintf(D_M_ASP, D_L_INFO, ("ASPputmsg: ATP CmdReplyReq, loc=%d, state=%s, msgsize = %d, result = %d, tid = %d\n", scb->loc_addr.socket, aspStateStr(scb->state), (mdata ? gbuf_msgsize(mdata) : 0), result, tid)); - atp_send_rsp(gref, mioc, TRUE); - return 0; - } + atp_send_rsp(gref, mioc, TRUE); + return 0; + } - /* Not an expected ASPFUNC */ - gbuf_freem(mioc); - err = EOPNOTSUPP; + /* Not an expected ASPFUNC */ + gbuf_freem(mioc); + err = EOPNOTSUPP; l_err: - *errp = err; - return -1; + *errp = err; + return -1; } /* ASPputmsg */ -int -ASPgetmsg(gref, ctlptr, datptr, flags, errp) - gref_t *gref; - strbuf_t *ctlptr; - strbuf_t *datptr; - int *flags; - int *errp; -{ - int err, s, len, sum, rval; - gbuf_t *mproto, *mdata; - strbuf_t ctlbuf; - strbuf_t datbuf; - asp_scb_t *scb; - unsigned char get_wait; - if ((scb = (asp_scb_t *)gref->info) == 0) { +/* bms: make this callable from kernel. reply date is passed back as a mbuf chain in *mreply */ +int ASPgetmsg(gref_t *gref, strbuf_t *ctlptr, strbuf_t *datptr, gbuf_t **mreply, int *flags, int *errp) +{ + int err, s, len, sum, rval; + gbuf_t *mproto, *mdata; + strbuf_t ctlbuf; + strbuf_t datbuf; + asp_scb_t *scb; + unsigned char get_wait; + + if ((scb = (asp_scb_t *)gref->info) == 0) { dPrintf(D_M_ASP, D_L_ERROR, ("ASPgetmsg: stale handle=0x%x, pid=%d\n", (u_int) gref, gref->pid)); @@ -2161,138 +2194,162 @@ ASPgetmsg(gref, ctlptr, datptr, flags, errp) return -1; } - ATDISABLE(s, scb->lock); - if (scb->state == ASPSTATE_Close) { - ATENABLE(s, scb->lock); - return 0; - } - - /* - * get receive data - */ - while ((mproto = scb->sess_ioc) == 0) { - scb->get_wait = 1; - err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0); - if (err != 0) { - scb->get_wait = 0; - ATENABLE(s, scb->lock); - *errp = err; - return -1; - } - if (scb->state == ASPSTATE_Close) { - scb->get_wait = 0; - ATENABLE(s, scb->lock); - return 0; - } - } - get_wait = scb->get_wait; - scb->get_wait = 0; - if ((ctlptr == 0) && (datptr == 0)) { - ATENABLE(s, scb->lock); - return 0; - } - scb->sess_ioc = gbuf_next(mproto); - mdata = gbuf_cont(mproto); - ATENABLE(s, scb->lock); - - /* last remaining use of MSG_ERROR */ - if (gbuf_type(mproto) == MSG_ERROR) { - err = (int)gbuf_rptr(mproto)[0]; - goto l_err; - } - - /* - * copy in the control and data info - */ - if ((err = copyin((caddr_t)ctlptr, - (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) - goto l_err; - if ((err = copyin((caddr_t)datptr, - (caddr_t)&datbuf, sizeof(datbuf))) != 0) - goto l_err; - if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) { - ATDISABLE(s, scb->lock); - gbuf_next(mproto) = scb->sess_ioc; - scb->sess_ioc = mproto; - ATENABLE(s, scb->lock); - return MOREDATA; - } - - if (get_wait == 0) { - /* - * this is a hack to support the select() call. - * we're not supposed to dequeue messages in the Streams - * head's read queue this way; but there is no better way. - */ - ATDISABLE(s, scb->lock); - if (scb->sess_ioc == 0) { - ATENABLE(s, scb->lock); - } else { - ATENABLE(s, scb->lock); - atalk_notify_sel(gref); - } - } - - /* - * copy out the control content and info - */ - ctlbuf.len = gbuf_len(mproto); - if ((err = copyout((caddr_t)gbuf_rptr(mproto), - (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0) - goto l_err; - if ((err = copyout((caddr_t)&ctlbuf, - (caddr_t)ctlptr, sizeof(ctlbuf))) != 0) - goto l_err; - - /* - * copy out the data content and info - */ - for (rval=0, sum=0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) { - len = gbuf_len(mdata); - if (len) { - if ((len + sum) > datbuf.maxlen) { - len = datbuf.maxlen - sum; - rval = MOREDATA; - } - if ((err = copyout((caddr_t)gbuf_rptr(mdata), - (caddr_t)&datbuf.buf[sum], len)) != 0) - goto l_err; - sum += len; - } - } - datbuf.len = sum; - if ((err = copyout((caddr_t)&datbuf, - (caddr_t)datptr, sizeof(datbuf))) != 0) - goto l_err; - -#ifdef APPLETALK_DEBUG - if (mproto == 0) - kprintf("ASPgetmsg: null mproto!!!\n"); -#endif - - gbuf_freem(mproto); - - ATDISABLE(s, scb->lock); - if (scb->sess_ioc) - scb->rcv_cnt--; - else { - scb->rcv_cnt = 0; - scb->snd_stop = 0; - } - ATENABLE(s, scb->lock); - return rval; + ATDISABLE(s, scb->lock); + if (scb->state == ASPSTATE_Close) { + ATENABLE(s, scb->lock); + return 0; + } + + /* + * get receive data + */ + while ((mproto = scb->sess_ioc) == 0) { + scb->get_wait = 1; + err = tsleep(&scb->event, PSOCK | PCATCH, "aspgetmsg", 0); + if (err != 0) { + scb->get_wait = 0; + ATENABLE(s, scb->lock); + *errp = err; + return -1; + } + if (scb->state == ASPSTATE_Close) { + scb->get_wait = 0; + ATENABLE(s, scb->lock); + return 0; + } + } + get_wait = scb->get_wait; + scb->get_wait = 0; + if ((ctlptr == 0) && (datptr == 0)) { + ATENABLE(s, scb->lock); + return 0; + } + scb->sess_ioc = gbuf_next(mproto); + mdata = gbuf_cont(mproto); + ATENABLE(s, scb->lock); + + /* last remaining use of MSG_ERROR */ + if (gbuf_type(mproto) == MSG_ERROR) { + err = (int)gbuf_rptr(mproto)[0]; + goto l_err; + } + + /* + * copy in the control and data info + */ + if (mreply != NULL) { + /* called from kernel space */ + bcopy (ctlptr, &ctlbuf, sizeof(ctlbuf)); + bcopy (datptr, &datbuf, sizeof(datbuf)); + } else { + /* called from user space */ + if ((err = copyin((caddr_t)ctlptr, + (caddr_t)&ctlbuf, sizeof(ctlbuf))) != 0) + goto l_err; + if ((err = copyin((caddr_t)datptr, + (caddr_t)&datbuf, sizeof(datbuf))) != 0) + goto l_err; + } + if ((datbuf.maxlen < 0) || (datbuf.maxlen < gbuf_msgsize(mdata))) { + ATDISABLE(s, scb->lock); + gbuf_next(mproto) = scb->sess_ioc; + scb->sess_ioc = mproto; + ATENABLE(s, scb->lock); + return MOREDATA; + } + + if (get_wait == 0) { + /* + * this is a hack to support the select() call. + * we're not supposed to dequeue messages in the Streams + * head's read queue this way; but there is no better way. + */ + ATDISABLE(s, scb->lock); + if (scb->sess_ioc == 0) { + ATENABLE(s, scb->lock); + } else { + ATENABLE(s, scb->lock); + atalk_notify_sel(gref); + } + } + + /* + * copy out the control content and info + */ + ctlbuf.len = gbuf_len(mproto); + + if (mreply != NULL) { + /* called from kernel space */ + bcopy (gbuf_rptr(mproto), ctlbuf.buf, ctlbuf.len); + bcopy (&ctlbuf, ctlptr, sizeof(ctlbuf)); + } else { + /* called from user space */ + if ((err = copyout((caddr_t)gbuf_rptr(mproto), + (caddr_t)ctlbuf.buf, ctlbuf.len)) != 0) + goto l_err; + if ((err = copyout((caddr_t)&ctlbuf, + (caddr_t)ctlptr, sizeof(ctlbuf))) != 0) + goto l_err; + } + + /* + * copy out the data content and info + */ + for (rval = 0, sum = 0; mdata && (rval == 0); mdata = gbuf_cont(mdata)) + { + len = gbuf_len(mdata); + if (len) { + if ((len + sum) > datbuf.maxlen) { + len = datbuf.maxlen - sum; + rval = MOREDATA; + } + + if (mreply == NULL) { + /* called from user space */ + if ((err = copyout((caddr_t)gbuf_rptr(mdata), (caddr_t)&datbuf.buf[sum], len)) != 0) + goto l_err; + } + sum += len; + } + } + datbuf.len = sum; + if (mreply != NULL) { + /* called from kernel space */ + bcopy (&datbuf, datptr, sizeof(datbuf)); + } else { + /* called from user space */ + if ((err = copyout((caddr_t)&datbuf, (caddr_t)datptr, sizeof(datbuf))) != 0) + goto l_err; + } + + if (mreply != NULL) { + /* called from kernel space */ + /* return the reply data in mbufs, so dont free them. + Just free the proto info */ + mdata = gbuf_cont(mproto); + *mreply = mdata; + gbuf_cont(mproto) = NULL; + gbuf_freem(mproto); + } else { + /* called from user space */ + gbuf_freem(mproto); + } + + ATDISABLE(s, scb->lock); + if (scb->sess_ioc) + scb->rcv_cnt--; + else { + scb->rcv_cnt = 0; + scb->snd_stop = 0; + } + ATENABLE(s, scb->lock); + return rval; l_err: - dPrintf(D_M_ASP, D_L_ERROR, - ("ASPgetmsg: err=%d, loc=%d, rem=%x.%x.%d, state=%s\n", - err, scb->loc_addr.socket, - scb->rem_addr.net, - scb->rem_addr.node, scb->rem_addr.socket, - aspStateStr(scb->state))); - ATDISABLE(s, scb->lock); - gbuf_next(mproto) = scb->sess_ioc; - scb->sess_ioc = mproto; - ATENABLE(s, scb->lock); - *errp = err; - return -1; + ATDISABLE(s, scb->lock); + gbuf_next(mproto) = scb->sess_ioc; + scb->sess_ioc = mproto; + ATENABLE(s, scb->lock); + *errp = err; + return -1; } diff --git a/bsd/netat/at.c b/bsd/netat/at.c index f1a750bbf..00feb623e 100644 --- a/bsd/netat/at.c +++ b/bsd/netat/at.c @@ -51,7 +51,7 @@ #include <netat/routing_tables.h> #include <netat/debug.h> -extern int at_ioctl(struct atpcb *, u_long, caddr_t); +extern int at_ioctl(struct atpcb *, u_long, caddr_t, int fromKernel); extern int routerStart(at_kern_err_t *); extern void elap_offline(at_ifaddr_t *); extern at_ifaddr_t *find_ifID(char *); @@ -142,10 +142,10 @@ int at_control(so, cmd, data, ifp) work with BSD-style sockets instead of the special purpose system calls, ATsocket() and ATioctl(). *** */ - if ((error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data))) { + if ((error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data, 0))) { if (((struct atpcb *)so->so_pcb)->proto != ATPROTO_LAP) { ((struct atpcb *)so->so_pcb)->proto = ATPROTO_LAP; - error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data); + error = at_ioctl((struct atpcb *)so->so_pcb, cmd, data, 0); } } return(error); diff --git a/bsd/netat/atp.h b/bsd/netat/atp.h index 72dd34ae0..476e926b7 100644 --- a/bsd/netat/atp.h +++ b/bsd/netat/atp.h @@ -319,8 +319,9 @@ struct atp_trans { #define TRANS_TIMEOUT 0 /* waiting for a reply */ #define TRANS_REQUEST 1 /* waiting to send a request */ #define TRANS_RELEASE 2 /* waiting to send a release */ -#define TRANS_DONE 3 /* done - waiting for poll to complete */ +#define TRANS_DONE 3 /* done - waiting for poll to complete */ #define TRANS_FAILED 4 /* done - waiting for poll to report failure */ +#define TRANS_ABORTING 5 /* waiting on atp_trans_abort list for thread to wakeup */ /* * reply control block (local context at repling end) @@ -401,17 +402,21 @@ struct atp_state { #ifdef ATP_DECLARE struct atp_trans *atp_trans_free_list = NULL; /* free transactions */ -struct atp_rcb *atp_rcb_free_list = NULL; /* free rcbs */ -static struct atp_state *atp_free_list = NULL; /* free atp states */ +struct atp_rcb *atp_rcb_free_list = NULL; /* free rcbs */ +static struct atp_state *atp_free_list = NULL; /* free atp states */ +struct atp_trans_qhead atp_trans_abort; /* aborted trans list */ static struct atp_rcb atp_rcb_data[NATP_RCB]; static struct atp_state atp_state_data[NATP_STATE]; + + #else extern struct atp_trans *atp_trans_free_list; /* free transactions */ -extern struct atp_rcb *atp_rcb_free_list; /* free rcbs */ -extern struct atp_state *atp_free_list; /* free atp states */ +extern struct atp_rcb *atp_rcb_free_list; /* free rcbs */ +extern struct atp_state *atp_free_list; /* free atp states */ extern struct atp_rcb atp_rcb_data[]; extern struct atp_state atp_state_data[]; +extern struct atp_trans_qhead atp_trans_abort; /* aborting trans list */ extern void atp_req_timeout(); extern void atp_rcb_timer(); diff --git a/bsd/netat/atp_alloc.c b/bsd/netat/atp_alloc.c index fc2d97724..98ebd3d46 100644 --- a/bsd/netat/atp_alloc.c +++ b/bsd/netat/atp_alloc.c @@ -52,6 +52,8 @@ gbuf_t *atp_resource_m = 0; extern atlock_t atpgen_lock; +extern caddr_t atp_free_cluster_list; +extern void atp_delete_free_clusters(); struct atp_trans *atp_trans_alloc(atp) struct atp_state *atp; @@ -178,6 +180,8 @@ register struct atp_rcb *rcbp; for (i=0; i < rcbp->rc_pktcnt; i++) rcbp->rc_snd[i] = 0; } + if (atp_free_cluster_list) + atp_delete_free_clusters(); if (rc_state != RCB_UNQUEUED) { if (rc_state == RCB_PENDING) { ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list); diff --git a/bsd/netat/atp_misc.c b/bsd/netat/atp_misc.c index b332e1ebf..0bc9447b3 100644 --- a/bsd/netat/atp_misc.c +++ b/bsd/netat/atp_misc.c @@ -145,38 +145,53 @@ l_notify: void atp_free(trp) register struct atp_trans *trp; -{ +{ register struct atp_state *atp; register int i; int s; dPrintf(D_M_ATP_LOW, D_L_TRACE, ("atp_free: freeing trp 0x%x\n", (u_int) trp)); - ATDISABLE(s, atpgen_lock); - if (trp->tr_tmo_func) - atp_untimout(atp_req_timeout, trp); - atp = trp->tr_queue; - ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list); + ATDISABLE(s, atpgen_lock); - if (trp->tr_xmt) { - gbuf_freem(trp->tr_xmt); - trp->tr_xmt = NULL; + if (trp->tr_state == TRANS_ABORTING) { + ATP_Q_REMOVE(atp_trans_abort, trp, tr_list); + trp->tr_state = TRANS_DONE; } - for (i = 0; i < 8; i++) { - if (trp->tr_rcv[i]) { - gbuf_freem(trp->tr_rcv[i]); - trp->tr_rcv[i] = NULL; + else { + if (trp->tr_tmo_func) + atp_untimout(atp_req_timeout, trp); + + atp = trp->tr_queue; + ATP_Q_REMOVE(atp->atp_trans_wait, trp, tr_list); + + if (trp->tr_xmt) { + gbuf_freem(trp->tr_xmt); + trp->tr_xmt = NULL; + } + for (i = 0; i < 8; i++) { + if (trp->tr_rcv[i]) { + gbuf_freem(trp->tr_rcv[i]); + trp->tr_rcv[i] = NULL; + } + } + if (trp->tr_bdsp) { + gbuf_freem(trp->tr_bdsp); + trp->tr_bdsp = NULL; + } + + if (trp->tr_rsp_wait) { + trp->tr_state = TRANS_ABORTING; + ATP_Q_APPEND(atp_trans_abort, trp, tr_list); + thread_wakeup(&trp->tr_event); + ATENABLE(s, atpgen_lock); + return; } } - if (trp->tr_bdsp) { - gbuf_freem(trp->tr_bdsp); - trp->tr_bdsp = NULL; - } - + ATENABLE(s, atpgen_lock); atp_trans_free(trp); - } /* atp_free */ diff --git a/bsd/netat/atp_open.c b/bsd/netat/atp_open.c index 9c8b95e9f..de927389c 100644 --- a/bsd/netat/atp_open.c +++ b/bsd/netat/atp_open.c @@ -107,6 +107,9 @@ void atp_init() if (!atp_inited) { atp_inited = 1; atp_used_list = 0; + atp_trans_abort.head = NULL; + atp_trans_abort.tail = NULL; + for (i = 0; i < NATP_RCB; i++) { atp_rcb_data[i].rc_list.next = atp_rcb_free_list; atp_rcb_free_list = &atp_rcb_data[i]; diff --git a/bsd/netat/atp_write.c b/bsd/netat/atp_write.c index e0d84e9e1..38d3954a7 100644 --- a/bsd/netat/atp_write.c +++ b/bsd/netat/atp_write.c @@ -456,7 +456,8 @@ void atp_send_replies(atp, rcbp) unsigned char *m0_rptr = NULL, *m0_wptr = NULL; register at_atp_t *athp; register struct atpBDS *bdsp; - register gbuf_t *m2, *m1, *m0; + register gbuf_t *m2, *m1, *m0, *m3; + caddr_t lastPage; gbuf_t *mprev, *mlist = 0; at_socket src_socket = (at_socket)atp->atp_socket_no; gbuf_t *rc_xmt[ATP_TRESP_MAX]; @@ -549,6 +550,24 @@ void atp_send_replies(atp, rcbp) } else gbuf_cont(m1) = 0; gbuf_cont(m2) = m1; + + /* temp fix for page boundary problem - bug# 2703163 */ + lastPage = (caddr_t)((int)(gbuf_wptr(m1) - 1) & ~PAGE_MASK); /* 4k page of last byte */ + if (lastPage != (caddr_t)((int)(gbuf_rptr(m1)) & ~PAGE_MASK)) { /* 1st byte and last on same page ? */ + if ((m3 = gbuf_dupb(m1)) == NULL) { + for (i = 0; i < cnt; i++) + if (rc_xmt[i]) + gbuf_freem(rc_xmt[i]); + (gbuf_rptr(m0)) = m0_rptr; + gbuf_wset(m0, (m0_wptr - m0_rptr)); + goto nothing_to_send; + } + (gbuf_rptr(m3)) = lastPage; /* new mbuf starts at beginning of page */ + gbuf_wset(m3, (gbuf_wptr(m1) - lastPage)); /* len = remaining data crossing over page boundary */ + gbuf_wset(m1, (lastPage - (gbuf_rptr(m1)))); /* adjust len of m1 */ + (gbuf_cont(m1)) = m3; + (gbuf_cont(m3)) = 0; + } } } @@ -689,10 +708,11 @@ atp_unpack_bdsp(atp, m, rcbp, cnt, wait) struct atp_state *atp; gbuf_t *m; /* ddp, atp and bdsp gbuf_t */ register struct atp_rcb *rcbp; - register int cnt, wait; + register int cnt, wait; { register struct atpBDS *bdsp; - register gbuf_t *m2, *m1, *m0; + register gbuf_t *m2, *m1, *m0, *m3; + caddr_t lastPage; register at_atp_t *athp; register int i, len, s_gen; at_socket src_socket; @@ -823,8 +843,26 @@ atp_unpack_bdsp(atp, m, rcbp, cnt, wait) } else gbuf_cont(m1) = 0; gbuf_cont(m2) = m1; + + /* temp fix for page boundary problem - bug# 2703163 */ + lastPage = (caddr_t)((int)(gbuf_wptr(m1) - 1) & ~PAGE_MASK); /* 4k page of last byte */ + if (lastPage != (caddr_t)((int)(gbuf_rptr(m1)) & ~PAGE_MASK)) { /* 1st byte and last on same page ? */ + if ((m3 = gbuf_dupb_wait(m1, wait)) == NULL) { + for (i = 0; i < cnt; i++) + if (rc_xmt[i]) + gbuf_freem(rc_xmt[i]); + (gbuf_rptr(m0)) = m0_rptr; + gbuf_wset(m0, (m0_wptr - m0_rptr)); + return 0; + } + (gbuf_rptr(m3)) = lastPage; /* new mbuf starts at beginning of page */ + gbuf_wset(m3, (gbuf_wptr(m1) - lastPage)); /* len = remaining data crossing over page boundary */ + gbuf_wset(m1, (lastPage - (gbuf_rptr(m1)))); /* adjust len of m1 */ + (gbuf_cont(m1)) = m3; + (gbuf_cont(m3)) = 0; } } + } AT_DDP_HDR(m2)->src_socket = src_socket; dPrintf(D_M_ATP_LOW,D_L_INFO, @@ -1603,7 +1641,8 @@ _ATPsndreq(fd, buf, len, nowait, err, proc) * wait for the transaction to complete */ ATDISABLE(s, trp->tr_lock); - while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED)) { + while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) && + (trp->tr_state != TRANS_ABORTING)) { trp->tr_rsp_wait = 1; rc = tsleep(&trp->tr_event, PSOCK | PCATCH, "atpsndreq", 0); if (rc != 0) { @@ -1616,7 +1655,8 @@ _ATPsndreq(fd, buf, len, nowait, err, proc) trp->tr_rsp_wait = 0; ATENABLE(s, trp->tr_lock); - if (trp->tr_state == TRANS_FAILED) { + + if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) { /* * transaction timed out, return error */ @@ -1674,14 +1714,9 @@ _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc) /* * allocate buffer and copy in the response info */ - while ((m = gbuf_alloc(resplen, PRI_MED)) == 0) { - ATDISABLE(s, atp->atp_delay_lock); - rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspinfo", 10); - ATENABLE(s, atp->atp_delay_lock); - if (rc != 0) { - *err = rc; - return -1; - } + if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) { + *err = ENOMEM; + return -1; } if ((*err = copyin((caddr_t)respbuff, (caddr_t)gbuf_rptr(m), resplen)) != 0) { gbuf_freeb(m); @@ -1698,15 +1733,10 @@ _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc) /* * allocate buffer and copy in the response data */ - while ((mdata = gbuf_alloc(datalen+len, PRI_MED)) == 0) { - ATDISABLE(s, atp->atp_delay_lock); - rc = tsleep(&atp->atp_delay_event, PSOCK | PCATCH, "atprspdata", 10); - ATENABLE(s, atp->atp_delay_lock); - if (rc != 0) { - gbuf_freem(m); - *err = rc; - return -1; - } + if ((mdata = gbuf_alloc_wait(datalen+len, TRUE)) == 0) { + gbuf_freem(m); + *err = ENOMEM; + return -1; } gbuf_cont(m) = mdata; for (size=0; bdsp < (struct atpBDS *)gbuf_wptr(m); bdsp++) { diff --git a/bsd/netat/aurp_aurpd.c b/bsd/netat/aurp_aurpd.c index 8cc764bda..eca9c3757 100644 --- a/bsd/netat/aurp_aurpd.c +++ b/bsd/netat/aurp_aurpd.c @@ -139,6 +139,7 @@ aurpd_start() sopt.sopt_level = SOL_SOCKET; sopt.sopt_name = SO_RCVBUF; sopt.sopt_dir = SOPT_SET; + sopt.sopt_p = NULL; if ((error = sosetopt(so, &sopt)) != 0) goto out; } @@ -158,6 +159,7 @@ aurpd_start() sopt.sopt_level = SOL_SOCKET; sopt.sopt_name = SO_SNDBUF; sopt.sopt_dir = SOPT_SET; + sopt.sopt_p = NULL; if ((error = sosetopt(so, &sopt)) != 0) goto out; } @@ -165,10 +167,8 @@ aurpd_start() so->so_upcall = aurp_wakeup; so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */ so->so_state |= SS_NBIO; - so->so_rcv.sb_flags |=SB_NOINTR; - so->so_rcv.sb_sel.si_flags |=SI_SBSEL; - so->so_snd.sb_flags |=SB_NOINTR; - so->so_snd.sb_sel.si_flags |=SI_SBSEL; + so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR); + so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR); out: sbunlock(&so->so_snd); diff --git a/bsd/netat/ddp.c b/bsd/netat/ddp.c index a05405e14..4be1a6484 100644 --- a/bsd/netat/ddp.c +++ b/bsd/netat/ddp.c @@ -448,17 +448,19 @@ void ddp_notify_nbp(socket, pid, ddptype) unsigned char ddptype; /* not used */ { extern int nve_lock; - nve_entry_t *nve_entry; + nve_entry_t *nve_entry, *nve_next; if (at_state.flags & AT_ST_STARTED) { /* *** NBP_CLOSE_NOTE processing (from ddp_nbp.c) *** */ ATDISABLE(nve_lock, NVE_LOCK); - TAILQ_FOREACH(nve_entry, &name_registry, nve_link) { + for ((nve_entry = TAILQ_FIRST(&name_registry)); nve_entry; nve_entry = nve_next) { + nve_next = TAILQ_NEXT(nve_entry, nve_link); if ((at_socket)socket == nve_entry->address.socket && /* *** check complete address and ddptype here *** */ pid == nve_entry->pid && ot_ddp_check_socket(nve_entry->address.socket, nve_entry->pid) < 2) { + /* NB: nbp_delete_entry calls TAILQ_REMOVE */ nbp_delete_entry(nve_entry); } } @@ -1041,9 +1043,10 @@ void ddp_input(mp, ifID) ATP / raw-DDP and ADSP / raw-DDP are possible */ for (gref = ddp_head.atpcb_next; gref != &ddp_head; gref = gref->atpcb_next) - if (gref->lport == socket) { - dPrintf(D_M_DDP, D_L_INPUT, - ("ddp_input: streamq, skt %d\n", socket)); + if (gref->lport == socket && + (gref->ddptype == 0 || gref->ddptype == ddp->type)) { + dPrintf(D_M_DDP, D_L_INPUT, + ("ddp_input: streamq, skt %d\n", socket)); if (gref->atpcb_socket) { struct sockaddr_at ddp_in; ddp_in.sat_len = sizeof(ddp_in); diff --git a/bsd/netat/ddp_aarp.c b/bsd/netat/ddp_aarp.c index 1fbb21e43..af578e3be 100644 --- a/bsd/netat/ddp_aarp.c +++ b/bsd/netat/ddp_aarp.c @@ -802,29 +802,41 @@ StaticProc void aarp_build_pkt(pkt, elapp) StaticProc int aarp_sched_req(amt_ptr) register aarp_amt_t *amt_ptr; { - int s; + int s, i; boolean_t funnel_state; funnel_state = thread_funnel_set(network_flock, TRUE); - ATDISABLE(s, arpinp_lock); - if (amt_ptr->tmo == 0) - { - ATENABLE(s, arpinp_lock); - (void) thread_funnel_set(network_flock, FALSE); - return(0); - } - if (amt_ptr->no_of_retries < AARP_MAX_REQ_RETRIES) { - ATENABLE(s, arpinp_lock); - if (aarp_send_req(amt_ptr) == 0) { - (void) thread_funnel_set(network_flock, FALSE); - return(0); - } - ATDISABLE(s, arpinp_lock); - } - ATENABLE(s, arpinp_lock); - aarp_delete_amt_info(amt_ptr); - + /* + * make sure pointer still valid in case interface removed + * while trying to acquire the funnel. make sure it points + * into one of the amt arrays. + */ + for (i = 0; i < IF_TOTAL_MAX; i++) { + if (aarp_table[i] == NULL || amt_ptr < aarp_table[i] || amt_ptr >= (aarp_table[i] + 1)) + continue; /* no match - try next entry */ + + /* + * found match - pointer is valid + */ + ATDISABLE(s, arpinp_lock); + if (amt_ptr->tmo == 0) { + ATENABLE(s, arpinp_lock); + (void) thread_funnel_set(network_flock, FALSE); + return(0); + } + if (amt_ptr->no_of_retries < AARP_MAX_REQ_RETRIES) { + ATENABLE(s, arpinp_lock); + if (aarp_send_req(amt_ptr) == 0) { + (void) thread_funnel_set(network_flock, FALSE); + return(0); + } + ATDISABLE(s, arpinp_lock); + } + ATENABLE(s, arpinp_lock); + aarp_delete_amt_info(amt_ptr); + break; + } (void) thread_funnel_set(network_flock, FALSE); return(0); diff --git a/bsd/netat/ddp_lap.c b/bsd/netat/ddp_lap.c index 626d22f09..80a700a67 100644 --- a/bsd/netat/ddp_lap.c +++ b/bsd/netat/ddp_lap.c @@ -1137,7 +1137,7 @@ int ddp_shutdown(count_only) } } } - + /* ADSP */ for (sp = ccb_used_list; sp ; ) { sp_next = sp->otccbLink; diff --git a/bsd/netat/ddp_nbp.c b/bsd/netat/ddp_nbp.c index dd77e5fd5..e8dc74b46 100644 --- a/bsd/netat/ddp_nbp.c +++ b/bsd/netat/ddp_nbp.c @@ -116,10 +116,13 @@ void sethzonehash(elapp) void nbp_shutdown() { /* delete all NVE's and release buffers */ - register nve_entry_t *nve_entry, *next_nve; + register nve_entry_t *nve_entry, *nve_next; ATDISABLE(nve_lock_pri,NVE_LOCK); - TAILQ_FOREACH(nve_entry, &name_registry, nve_link) { + for ((nve_entry = TAILQ_FIRST(&name_registry)); nve_entry; nve_entry = nve_next) { + nve_next = TAILQ_NEXT(nve_entry, nve_link); + + /* NB: nbp_delete_entry calls TAILQ_REMOVE */ nbp_delete_entry(nve_entry); } ATENABLE(nve_lock_pri,NVE_LOCK); diff --git a/bsd/netat/ddp_usrreq.c b/bsd/netat/ddp_usrreq.c index b46a541c7..c3db5fba4 100644 --- a/bsd/netat/ddp_usrreq.c +++ b/bsd/netat/ddp_usrreq.c @@ -259,6 +259,8 @@ int ddp_pru_sockaddr(struct socket *so, struct sockaddr_at *sat; MALLOC(sat, struct sockaddr_at *, sizeof *sat, M_SONAME, M_WAITOK); + if (sat == NULL) + return(ENOMEM); bzero((caddr_t)sat, sizeof(*sat)); s = splnet(); @@ -287,6 +289,8 @@ int ddp_pru_peeraddr(struct socket *so, struct sockaddr_at *sat; MALLOC(sat, struct sockaddr_at *, sizeof *sat, M_SONAME, M_WAITOK); + if (sat == NULL) + return (ENOMEM); bzero((caddr_t)sat, sizeof(*sat)); s = splnet(); diff --git a/bsd/netat/sys_glue.c b/bsd/netat/sys_glue.c index 9d0e95620..d5df3286b 100644 --- a/bsd/netat/sys_glue.c +++ b/bsd/netat/sys_glue.c @@ -65,9 +65,13 @@ extern void aurp_wput(gref_t *gref, gbuf_t *m), #endif adsp_wput(gref_t *gref, gbuf_t *m); + +int atp_free_cluster_timeout_set = 0; + void atalk_putnext(gref_t *gref, gbuf_t *m); -static int gref_close(gref_t *gref); +/* bms: make gref_close non static so its callable from kernel */ +int gref_close(gref_t *gref); SYSCTL_DECL(_net_appletalk); dbgBits_t dbgBits; @@ -82,7 +86,9 @@ SYSCTL_STRUCT(_net_appletalk, OID_AUTO, ddpstats, CTLFLAG_RD, atlock_t refall_lock; -static void gref_wput(gref, m) +caddr_t atp_free_cluster_list = 0; + +void gref_wput(gref, m) gref_t *gref; gbuf_t *m; { @@ -208,7 +214,7 @@ int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc) if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { switch (gref->proto) { case ATPROTO_ASP: - rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); + rc = ASPgetmsg(gref, ctlptr, datptr, NULL, flags, err); break; case ATPROTO_AURP: #ifdef AURP_SUPPORT @@ -239,7 +245,7 @@ int _ATputmsg(fd, ctlptr, datptr, flags, err, proc) if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) { switch (gref->proto) { case ATPROTO_ASP: - rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break; + rc = ASPputmsg(gref, ctlptr, datptr, NULL, flags, err); break; default: *err = EPROTONOSUPPORT; break; } @@ -256,8 +262,6 @@ int _ATclose(fp, proc) int err; gref_t *gref; - - if ((err = atalk_closeref(fp, &gref)) == 0) { thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); (void)gref_close(gref); @@ -419,69 +423,76 @@ int _ATwrite(fp, uio, cred) /* Most of the processing from _ATioctl, so that it can be called from the new ioctl code */ -int at_ioctl(gref, cmd, arg) - gref_t *gref; - register caddr_t arg; +/* bms: update to be callable from kernel */ +int at_ioctl(gref_t *gref, u_long cmd, caddr_t arg, int fromKernel) { - int s, err = 0, len; - gbuf_t *m, *mdata; - ioc_t *ioc; - ioccmd_t ioccmd; + int s, err = 0, len; + gbuf_t *m, *mdata; + ioc_t *ioc; + ioccmd_t ioccmd; - /* error if not for us */ - if ((cmd & 0xffff) != 0xff99) - return EOPNOTSUPP; + /* error if not for us */ + if ((cmd & 0xffff) != 0xff99) + return EOPNOTSUPP; - /* copy in ioc command info */ + /* copy in ioc command info */ /* - kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n", - ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, - gref->lock, gref->event); + kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n", + ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, + gref->lock, gref->event); */ - if ((err = copyin((caddr_t)arg, - (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { + if (fromKernel) + bcopy (arg, &ioccmd, sizeof (ioccmd_t)); + else { + if ((err = copyin((caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { #ifdef APPLETALK_DEBUG - kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err, - (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t)); + kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err, + (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t)); #endif - return err; - } - - /* allocate a buffer to create an ioc command */ - if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) - return ENOBUFS; - gbuf_wset(m,sizeof(ioc_t)); - gbuf_set_type(m, MSG_IOCTL); - - /* create the ioc command */ - if (ioccmd.ic_len) { - if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) { - gbuf_freem(m); + return err; + } + } + + /* allocate a buffer to create an ioc command + first mbuf contains ioc command */ + if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0) + return ENOBUFS; + gbuf_wset(m, sizeof(ioc_t)); /* mbuf->m_len */ + gbuf_set_type(m, MSG_IOCTL); /* mbuf->m_type */ + + /* create the ioc command + second mbuf contains the actual ASP command */ + if (ioccmd.ic_len) { + if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) { + gbuf_freem(m); #ifdef APPLETALK_DEBUG kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS); #endif - return ENOBUFS; - } - gbuf_wset(gbuf_cont(m),ioccmd.ic_len); - if ((err = copyin((caddr_t)ioccmd.ic_dp, - (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { - gbuf_freem(m); - return err; - } - } - ioc = (ioc_t *)gbuf_rptr(m); - ioc->ioc_cmd = ioccmd.ic_cmd; - ioc->ioc_count = ioccmd.ic_len; - ioc->ioc_error = 0; - ioc->ioc_rval = 0; - - /* send the ioc command to the appropriate recipient */ + return ENOBUFS; + } + gbuf_wset(gbuf_cont(m), ioccmd.ic_len); /* mbuf->m_len */ + if (fromKernel) + bcopy (ioccmd.ic_dp, gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len); + else { + if ((err = copyin((caddr_t)ioccmd.ic_dp, (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { + gbuf_freem(m); + return err; + } + } + } + ioc = (ioc_t *) gbuf_rptr(m); + ioc->ioc_cmd = ioccmd.ic_cmd; + ioc->ioc_count = ioccmd.ic_len; + ioc->ioc_error = 0; + ioc->ioc_rval = 0; + + /* send the ioc command to the appropriate recipient */ gref_wput(gref, m); - /* wait for the ioc ack */ - ATDISABLE(s, gref->lock); - while ((m = gref->ichead) == 0) { - gref->sevents |= POLLPRI; + /* wait for the ioc ack */ + ATDISABLE(s, gref->lock); + while ((m = gref->ichead) == 0) { + gref->sevents |= POLLPRI; #ifdef APPLETALK_DEBUG kprintf("sleep gref = 0x%x\n", (unsigned)gref); #endif @@ -508,36 +519,43 @@ int at_ioctl(gref, cmd, arg) kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n", (unsigned)gref); #endif - /* process the ioc response */ - ioc = (ioc_t *)gbuf_rptr(m); - if ((err = ioc->ioc_error) == 0) { - ioccmd.ic_timout = ioc->ioc_rval; - ioccmd.ic_len = 0; - mdata = gbuf_cont(m); - if (mdata && ioccmd.ic_dp) { - ioccmd.ic_len = gbuf_msgsize(mdata); - for (len=0; mdata; mdata=gbuf_cont(mdata)) { - if ((err = copyout((caddr_t)gbuf_rptr(mdata), - (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) { + + /* process the ioc response */ + ioc = (ioc_t *) gbuf_rptr(m); + if ((err = ioc->ioc_error) == 0) { + ioccmd.ic_timout = ioc->ioc_rval; + ioccmd.ic_len = 0; + mdata = gbuf_cont(m); + if (mdata && ioccmd.ic_dp) { + ioccmd.ic_len = gbuf_msgsize(mdata); + for (len = 0; mdata; mdata = gbuf_cont(mdata)) { + if (fromKernel) + bcopy (gbuf_rptr(mdata), &ioccmd.ic_dp[len], gbuf_len(mdata)); + else { + if ((err = copyout((caddr_t)gbuf_rptr(mdata), (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) { #ifdef APPLETALK_DEBUG - kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n", - len, err, (caddr_t)gbuf_rptr(mdata), - (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata)); + kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n", + len, err, (caddr_t)gbuf_rptr(mdata), (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata)); #endif - goto l_done; - } - len += gbuf_len(mdata); - } - } - if ((err = copyout((caddr_t)&ioccmd, - (caddr_t)arg, sizeof(ioccmd_t))) != 0) { + goto l_done; + } + } + len += gbuf_len(mdata); + } + } + + if (fromKernel) + bcopy (&ioccmd, arg, sizeof(ioccmd_t)); + else { + if ((err = copyout((caddr_t)&ioccmd, (caddr_t)arg, sizeof(ioccmd_t))) != 0) { #ifdef APPLETALK_DEBUG - kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n", - err, &ioccmd, arg, sizeof(ioccmd_t)); + kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n", + err, &ioccmd, arg, sizeof(ioccmd_t)); #endif - goto l_done; - } - } + goto l_done; + } + } + } l_done: gbuf_freem(m); @@ -561,16 +579,17 @@ int _ATioctl(fp, cmd, arg, proc) #endif } else - err = at_ioctl(gref, cmd, arg); + err = at_ioctl(gref, cmd, arg, 0); thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); return err; } -int _ATselect(fp, which, proc) +int _ATselect(fp, which, wql, proc) struct file *fp; int which; + void * wql; struct proc *proc; { int s, err, rc = 0; @@ -589,7 +608,7 @@ int _ATselect(fp, which, proc) rc = 1; else { gref->sevents |= POLLIN; - selrecord(proc, &gref->si); + selrecord(proc, &gref->si, wql); } } else if (which == POLLOUT) { @@ -598,7 +617,7 @@ int _ATselect(fp, which, proc) rc = 1; else { gref->sevents |= POLLOUT; - selrecord(proc, &gref->si); + selrecord(proc, &gref->si, wql); } } else rc = 1; @@ -654,9 +673,7 @@ void atalk_putnext(gref, m) } if (gref->sevents & POLLIN) { gref->sevents &= ~POLLIN; - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&gref->si); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); } gref->rdtail = m; } @@ -725,9 +742,7 @@ void atalk_notify(gref, errno) /* select */ if (gref->sevents & POLLIN) { gref->sevents &= ~POLLIN; - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&gref->si); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); } } } @@ -742,9 +757,7 @@ void atalk_notify_sel(gref) ATDISABLE(s, gref->lock); if (gref->sevents & POLLIN) { gref->sevents &= ~POLLIN; - thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL); selwakeup(&gref->si); - thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL); } ATENABLE(s, gref->lock); } @@ -848,8 +861,8 @@ int gref_alloc(grefp) return 0; } /* gref_alloc */ -static int gref_close(gref) - gref_t *gref; +/* bms: make gref_close callable from kernel */ +int gref_close(gref_t *gref) { int s, rc; @@ -927,16 +940,62 @@ struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait) return (m); } + + +/* + temp fix for bug 2731148 - until this code is re-written to use standard clusters + Deletes any free clusters on the free list. +*/ +void atp_delete_free_clusters() +{ + caddr_t cluster; + caddr_t cluster_list; + + + /* check for free clusters on the free_cluster_list to be deleted */ + MBUF_LOCK(); /* lock used by mbuf routines */ + + untimeout(&atp_delete_free_clusters, NULL); + atp_free_cluster_timeout_set = 0; + + cluster_list = atp_free_cluster_list; + atp_free_cluster_list = 0; + + MBUF_UNLOCK(); + + while (cluster = cluster_list) + { + cluster_list = *((caddr_t*)cluster); + FREE(cluster, M_MCLUST); + } + +} + + /* Used as the "free" routine for over-size clusters allocated using - m_lgbuf_alloc(). + m_lgbuf_alloc(). Called by m_free while under MBUF_LOCK. */ void m_lgbuf_free(buf, size, arg) void *buf; int size, arg; /* not needed, but they're in m_free() */ { - FREE(buf, M_MCLUST); + /* FREE(buf, M_MCLUST); - can't free here - called from m_free while under lock */ + + /* move to free_cluster_list to be deleted later */ + caddr_t cluster = (caddr_t)buf; + + /* don't need a lock because this is only called called from m_free which */ + /* is under MBUF_LOCK */ + *((caddr_t*)cluster) = atp_free_cluster_list; + atp_free_cluster_list = cluster; + + if (atp_free_cluster_timeout_set == 0) + { + atp_free_cluster_timeout_set = 1; + timeout(&atp_delete_free_clusters, NULL, (1 * HZ)); + } } /* @@ -949,6 +1008,9 @@ struct mbuf *m_lgbuf_alloc(size, wait) { struct mbuf *m; + if (atp_free_cluster_list) + atp_delete_free_clusters(); /* delete any free clusters on the free list */ + /* If size is too large, allocate a cluster, otherwise, use the standard mbuf allocation routines.*/ if (size > MCLBYTES) { diff --git a/bsd/netccitt/pk_subr.c b/bsd/netccitt/pk_subr.c index c45bdd7f4..cb6cec959 100644 --- a/bsd/netccitt/pk_subr.c +++ b/bsd/netccitt/pk_subr.c @@ -940,8 +940,7 @@ unsigned pr; lcp -> lcd_window_condition = FALSE; if (so && ((so -> so_snd.sb_flags & SB_WAIT) || - (so -> so_snd.sb_flags & SB_NOTIFY)) || - (so->so_snd.sb_sel.si_flags & SI_SBSEL)) + (so -> so_snd.sb_flags & SB_NOTIFY))) sowwakeup (so); return (PACKET_OK); diff --git a/bsd/netinet/Makefile b/bsd/netinet/Makefile index 15d797279..55b955b83 100644 --- a/bsd/netinet/Makefile +++ b/bsd/netinet/Makefile @@ -22,10 +22,10 @@ EXPINC_SUBDIRS_I386 = \ DATAFILES = \ bootp.h icmp6.h icmp_var.h if_atm.h if_ether.h if_fddi.h \ igmp.h igmp_var.h in.h in_gif.h in_hostcache.h in_pcb.h \ - in_systm.h in_var.h ip.h ip6.h ip_auth.h ip_compat.h \ - ip_dummynet.h ip_ecn.h ip_encap.h ip_fil.h ip_flow.h \ - ip_frag.h ip_fw.h ip_icmp.h ip_mroute.h ip_nat.h \ - ip_proxy.h ip_state.h ip_var.h ipl.h tcp.h \ + in_systm.h in_var.h ip.h ip6.h ip_compat.h \ + ip_dummynet.h ip_ecn.h ip_encap.h ip_flow.h \ + ip_fw.h ip_icmp.h ip_mroute.h \ + ip_var.h ipl.h tcp.h \ tcp_debug.h tcp_fsm.h tcp_seq.h tcp_timer.h tcp_var.h \ tcpip.h udp.h udp_var.h diff --git a/bsd/netinet/fil.c b/bsd/netinet/fil.c deleted file mode 100644 index 4cba950af..000000000 --- a/bsd/netinet/fil.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1993-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -/* static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed"; */ -#endif - -#include "opt_ipfilter.h" - -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if !defined(__FreeBSD__) -# include <sys/ioctl.h> -#endif - -# include <sys/systm.h> - -#include <sys/uio.h> -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -#endif -#if defined(__FreeBSD__) -# include <sys/malloc.h> -#endif -#ifndef linux -# include <sys/protosw.h> -# include <sys/socket.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef KERNEL -# include "ipf.h" -# include "ipt.h" -extern int opts; - -# define FR_IFVERBOSE(ex,second,verb_pr) if (ex) { verbose verb_pr; \ - second; } -# define FR_IFDEBUG(ex,second,verb_pr) if (ex) { debug verb_pr; \ - second; } -# define FR_VERBOSE(verb_pr) verbose verb_pr -# define FR_DEBUG(verb_pr) debug verb_pr -# define SEND_RESET(ip, qif, if, m) send_reset(ip, if) -# define IPLLOG(a, c, d, e) ipllog() -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) -# if SOLARIS -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(ip) -# else -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_error(b, ip, if) -# endif -#else /* #ifndef KERNEL */ -# define FR_IFVERBOSE(ex,second,verb_pr) ; -# define FR_IFDEBUG(ex,second,verb_pr) ; -# define FR_VERBOSE(verb_pr) -# define FR_DEBUG(verb_pr) -# define IPLLOG(a, c, d, e) ipflog(a, c, d, e) -# if SOLARIS || defined(__sgi) -extern kmutex_t ipf_mutex, ipf_auth; -# endif -# if SOLARIS -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, \ - ip, qif) -# define SEND_RESET(ip, qif, if) send_reset(ip, qif) -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(ip, t, c, if, src) -# else /* SOLARIS */ -# define FR_NEWAUTH(m, fi, ip, qif) fr_newauth((mb_t *)m, fi, ip) -# ifdef linux -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip,\ - ifp) -# else -# define SEND_RESET(ip, qif, if) send_reset((tcpiphdr_t *)ip) -# endif -# ifdef __sgi -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(b, t, c, if, src, if) -# else -# if BSD < 199103 -# ifdef linux -# define ICMP_ERROR(b, ip, t, c, if, src) icmp_send(b,t,c,0,if) -# else -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(mtod(b, ip_t *), t, c, if, src) -# endif /* linux */ -# else -# define ICMP_ERROR(b, ip, t, c, if, src) \ - icmp_error(b, t, c, (src).s_addr, if) -# endif /* BSD < 199103 */ -# endif /* __sgi */ -# endif /* SOLARIS || __sgi */ -#endif /* KERNEL */ - - -struct filterstats frstats[2] = {{0,0,0,0,0},{0,0,0,0,0}}; -struct frentry *ipfilter[2][2] = { { NULL, NULL }, { NULL, NULL } }, - *ipacct[2][2] = { { NULL, NULL }, { NULL, NULL } }; -struct frgroup *ipfgroups[3][2]; -int fr_flags = IPF_LOGGING, fr_active = 0; -#if defined(IPFILTER_DEFAULT_BLOCK) -int fr_pass = FR_NOMATCH|FR_BLOCK; -#else -int fr_pass = (IPF_DEFAULT_PASS|FR_NOMATCH); -#endif - -fr_info_t frcache[2]; - -static void fr_makefrip __P((int, ip_t *, fr_info_t *)); -static int fr_tcpudpchk __P((frentry_t *, fr_info_t *)); -static int frflushlist __P((int, int, int *, frentry_t *, frentry_t **)); - - -/* - * bit values for identifying presence of individual IP options - */ -static struct optlist ipopts[20] = { - { IPOPT_NOP, 0x000001 }, - { IPOPT_RR, 0x000002 }, - { IPOPT_ZSU, 0x000004 }, - { IPOPT_MTUP, 0x000008 }, - { IPOPT_MTUR, 0x000010 }, - { IPOPT_ENCODE, 0x000020 }, - { IPOPT_TS, 0x000040 }, - { IPOPT_TR, 0x000080 }, - { IPOPT_SECURITY, 0x000100 }, - { IPOPT_LSRR, 0x000200 }, - { IPOPT_E_SEC, 0x000400 }, - { IPOPT_CIPSO, 0x000800 }, - { IPOPT_SATID, 0x001000 }, - { IPOPT_SSRR, 0x002000 }, - { IPOPT_ADDEXT, 0x004000 }, - { IPOPT_VISA, 0x008000 }, - { IPOPT_IMITD, 0x010000 }, - { IPOPT_EIP, 0x020000 }, - { IPOPT_FINN, 0x040000 }, - { 0, 0x000000 } -}; - -/* - * bit values for identifying presence of individual IP security options - */ -static struct optlist secopt[8] = { - { IPSO_CLASS_RES4, 0x01 }, - { IPSO_CLASS_TOPS, 0x02 }, - { IPSO_CLASS_SECR, 0x04 }, - { IPSO_CLASS_RES3, 0x08 }, - { IPSO_CLASS_CONF, 0x10 }, - { IPSO_CLASS_UNCL, 0x20 }, - { IPSO_CLASS_RES2, 0x40 }, - { IPSO_CLASS_RES1, 0x80 } -}; - - -/* - * compact the IP header into a structure which contains just the info. - * which is useful for comparing IP headers with. - */ -static void fr_makefrip(hlen, ip, fin) -int hlen; -ip_t *ip; -fr_info_t *fin; -{ - struct optlist *op; - tcphdr_t *tcp; - icmphdr_t *icmp; - fr_ip_t *fi = &fin->fin_fi; - u_short optmsk = 0, secmsk = 0, auth = 0; - int i, mv, ol, off; - u_char *s, opt; - - fin->fin_fr = NULL; - fin->fin_tcpf = 0; - fin->fin_data[0] = 0; - fin->fin_data[1] = 0; - fin->fin_rule = -1; - fin->fin_group = -1; - fin->fin_id = ip->ip_id; -#ifdef KERNEL - fin->fin_icode = ipl_unreach; -#endif - fi->fi_v = ip->ip_v; - fi->fi_tos = ip->ip_tos; - fin->fin_hlen = hlen; - fin->fin_dlen = ip->ip_len - hlen; - tcp = (tcphdr_t *)((char *)ip + hlen); - icmp = (icmphdr_t *)tcp; - fin->fin_dp = (void *)tcp; - (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); - (*(((u_32_t *)fi) + 1)) = (*(((u_32_t *)ip) + 3)); - (*(((u_32_t *)fi) + 2)) = (*(((u_32_t *)ip) + 4)); - - fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; - off = (ip->ip_off & 0x1fff) << 3; - if (ip->ip_off & 0x3fff) - fi->fi_fl |= FI_FRAG; - switch (ip->ip_p) - { - case IPPROTO_ICMP : - { - int minicmpsz = sizeof(struct icmp); - - if (!off && ip->ip_len > ICMP_MINLEN + hlen && - (icmp->icmp_type == ICMP_ECHOREPLY || - icmp->icmp_type == ICMP_UNREACH)) - minicmpsz = ICMP_MINLEN; - if ((!(ip->ip_len >= hlen + minicmpsz) && !off) || - (off && off < sizeof(struct icmp))) - fi->fi_fl |= FI_SHORT; - if (fin->fin_dlen > 1) - fin->fin_data[0] = *(u_short *)tcp; - break; - } - case IPPROTO_TCP : - fi->fi_fl |= FI_TCPUDP; - if ((!IPMINLEN(ip, tcphdr) && !off) || - (off && off < sizeof(struct tcphdr))) - fi->fi_fl |= FI_SHORT; - if (!(fi->fi_fl & FI_SHORT) && !off) - fin->fin_tcpf = tcp->th_flags; - goto getports; - case IPPROTO_UDP : - fi->fi_fl |= FI_TCPUDP; - if ((!IPMINLEN(ip, udphdr) && !off) || - (off && off < sizeof(struct udphdr))) - fi->fi_fl |= FI_SHORT; -getports: - if (!off && (fin->fin_dlen > 3)) { - fin->fin_data[0] = ntohs(tcp->th_sport); - fin->fin_data[1] = ntohs(tcp->th_dport); - } - break; - default : - break; - } - - - for (s = (u_char *)(ip + 1), hlen -= sizeof(*ip); hlen; ) { - if (!(opt = *s)) - break; - ol = (opt == IPOPT_NOP) ? 1 : (int)*(s+1); - if (opt > 1 && (ol < 2 || ol > hlen)) - break; - for (i = 9, mv = 4; mv >= 0; ) { - op = ipopts + i; - if (opt == (u_char)op->ol_val) { - optmsk |= op->ol_bit; - if (opt == IPOPT_SECURITY) { - struct optlist *sp; - u_char sec; - int j, m; - - sec = *(s + 2); /* classification */ - for (j = 3, m = 2; m >= 0; ) { - sp = secopt + j; - if (sec == sp->ol_val) { - secmsk |= sp->ol_bit; - auth = *(s + 3); - auth *= 256; - auth += *(s + 4); - break; - } - if (sec < sp->ol_val) - j -= m--; - else - j += m--; - } - } - break; - } - if (opt < op->ol_val) - i -= mv--; - else - i += mv--; - } - hlen -= ol; - s += ol; - } - if (auth && !(auth & 0x0100)) - auth &= 0xff00; - fi->fi_optmsk = optmsk; - fi->fi_secmsk = secmsk; - fi->fi_auth = auth; -} - - -/* - * check an IP packet for TCP/UDP characteristics such as ports and flags. - */ -static int fr_tcpudpchk(fr, fin) -frentry_t *fr; -fr_info_t *fin; -{ - register u_short po, tup; - register char i; - register int err = 1; - - /* - * Both ports should *always* be in the first fragment. - * So far, I cannot find any cases where they can not be. - * - * compare destination ports - */ - if ((i = (int)fr->fr_dcmp)) { - po = fr->fr_dport; - tup = fin->fin_data[1]; - /* - * Do opposite test to that required and - * continue if that succeeds. - */ - if (!--i && tup != po) /* EQUAL */ - err = 0; - else if (!--i && tup == po) /* NOTEQUAL */ - err = 0; - else if (!--i && tup >= po) /* LESSTHAN */ - err = 0; - else if (!--i && tup <= po) /* GREATERTHAN */ - err = 0; - else if (!--i && tup > po) /* LT or EQ */ - err = 0; - else if (!--i && tup < po) /* GT or EQ */ - err = 0; - else if (!--i && /* Out of range */ - (tup >= po && tup <= fr->fr_dtop)) - err = 0; - else if (!--i && /* In range */ - (tup <= po || tup >= fr->fr_dtop)) - err = 0; - } - /* - * compare source ports - */ - if (err && (i = (int)fr->fr_scmp)) { - po = fr->fr_sport; - tup = fin->fin_data[0]; - if (!--i && tup != po) - err = 0; - else if (!--i && tup == po) - err = 0; - else if (!--i && tup >= po) - err = 0; - else if (!--i && tup <= po) - err = 0; - else if (!--i && tup > po) - err = 0; - else if (!--i && tup < po) - err = 0; - else if (!--i && /* Out of range */ - (tup >= po && tup <= fr->fr_stop)) - err = 0; - else if (!--i && /* In range */ - (tup <= po || tup >= fr->fr_stop)) - err = 0; - } - - /* - * If we don't have all the TCP/UDP header, then how can we - * expect to do any sort of match on it ? If we were looking for - * TCP flags, then NO match. If not, then match (which should - * satisfy the "short" class too). - */ - if (err && (fin->fin_fi.fi_p == IPPROTO_TCP)) { - if (fin->fin_fi.fi_fl & FI_SHORT) - return !(fr->fr_tcpf | fr->fr_tcpfm); - /* - * Match the flags ? If not, abort this match. - */ - if (fr->fr_tcpf && - fr->fr_tcpf != (fin->fin_tcpf & fr->fr_tcpfm)) { - FR_DEBUG(("f. %#x & %#x != %#x\n", fin->fin_tcpf, - fr->fr_tcpfm, fr->fr_tcpf)); - err = 0; - } - } - return err; -} - -/* - * Check the input/output list of rules for a match and result. - * Could be per interface, but this gets real nasty when you don't have - * kernel sauce. - */ -int fr_scanlist(pass, ip, fin, m) -int pass; -ip_t *ip; -register fr_info_t *fin; -void *m; -{ - register struct frentry *fr; - register fr_ip_t *fi = &fin->fin_fi; - int rulen, portcmp = 0, off, skip = 0; - - fr = fin->fin_fr; - fin->fin_fr = NULL; - fin->fin_rule = 0; - fin->fin_group = 0; - off = ip->ip_off & 0x1fff; - pass |= (fi->fi_fl << 24); - - if ((fi->fi_fl & FI_TCPUDP) && (fin->fin_dlen > 3) && !off) - portcmp = 1; - - for (rulen = 0; fr; fr = fr->fr_next, rulen++) { - if (skip) { - skip--; - continue; - } - /* - * In all checks below, a null (zero) value in the - * filter struture is taken to mean a wildcard. - * - * check that we are working for the right interface - */ -#ifdef KERNEL - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; -#else - if (opts & (OPT_VERBOSE|OPT_DEBUG)) - printf("\n"); - FR_VERBOSE(("%c", (pass & FR_PASS) ? 'p' : - (pass & FR_AUTH) ? 'a' : 'b')); - if (fr->fr_ifa && fr->fr_ifa != fin->fin_ifp) - continue; - FR_VERBOSE((":i")); -#endif - { - register u_32_t *ld, *lm, *lip; - register int i; - - lip = (u_32_t *)fi; - lm = (u_32_t *)&fr->fr_mip; - ld = (u_32_t *)&fr->fr_ip; - i = ((lip[0] & lm[0]) != ld[0]); - FR_IFDEBUG(i,continue,("0. %#08x & %#08x != %#08x\n", - lip[0], lm[0], ld[0])); - i |= ((lip[1] & lm[1]) != ld[1]) << 21; - FR_IFDEBUG(i,continue,("1. %#08x & %#08x != %#08x\n", - lip[1], lm[1], ld[1])); - i |= ((lip[2] & lm[2]) != ld[2]) << 22; - FR_IFDEBUG(i,continue,("2. %#08x & %#08x != %#08x\n", - lip[2], lm[2], ld[2])); - i |= ((lip[3] & lm[3]) != ld[3]); - FR_IFDEBUG(i,continue,("3. %#08x & %#08x != %#08x\n", - lip[3], lm[3], ld[3])); - i |= ((lip[4] & lm[4]) != ld[4]); - FR_IFDEBUG(i,continue,("4. %#08x & %#08x != %#08x\n", - lip[4], lm[4], ld[4])); - i ^= (fi->fi_fl & (FR_NOTSRCIP|FR_NOTDSTIP)); - if (i) - continue; - } - - /* - * If a fragment, then only the first has what we're looking - * for here... - */ - if (!portcmp && (fr->fr_dcmp || fr->fr_scmp || fr->fr_tcpf || - fr->fr_tcpfm)) - continue; - if (fi->fi_fl & FI_TCPUDP) { - if (!fr_tcpudpchk(fr, fin)) - continue; - } else if (fr->fr_icmpm || fr->fr_icmp) { - if ((fi->fi_p != IPPROTO_ICMP) || off || - (fin->fin_dlen < 2)) - continue; - if ((fin->fin_data[0] & fr->fr_icmpm) != fr->fr_icmp) { - FR_DEBUG(("i. %#x & %#x != %#x\n", - fin->fin_data[0], fr->fr_icmpm, - fr->fr_icmp)); - continue; - } - } - FR_VERBOSE(("*")); - /* - * Just log this packet... - */ - if (!(skip = fr->fr_skip)) - pass = fr->fr_flags; - if ((pass & FR_CALLNOW) && fr->fr_func) - pass = (*fr->fr_func)(pass, ip, fin); -#if IPFILTER_LOG - if ((pass & FR_LOGMASK) == FR_LOG) { - if (!IPLLOG(fr->fr_flags, ip, fin, m)) - frstats[fin->fin_out].fr_skip++; - frstats[fin->fin_out].fr_pkl++; - } -#endif /* IPFILTER_LOG */ - FR_DEBUG(("pass %#x\n", pass)); - fr->fr_hits++; - if (pass & FR_ACCOUNT) - fr->fr_bytes += (U_QUAD_T)ip->ip_len; - else - fin->fin_icode = fr->fr_icode; - fin->fin_rule = rulen; - fin->fin_group = fr->fr_group; - fin->fin_fr = fr; - if (fr->fr_grp) { - fin->fin_fr = fr->fr_grp; - pass = fr_scanlist(pass, ip, fin, m); - if (fin->fin_fr == NULL) { - fin->fin_rule = rulen; - fin->fin_group = fr->fr_group; - fin->fin_fr = fr; - } - } - if (pass & FR_QUICK) - break; - } - return pass; -} - - -/* - * frcheck - filter check - * check using source and destination addresses/pors in a packet whether - * or not to pass it on or not. - */ -int fr_check(ip, hlen, ifp, out -#if defined(KERNEL) && SOLARIS -, qif, mp) -qif_t *qif; -#else -, mp) -#endif -mb_t **mp; -ip_t *ip; -int hlen; -void *ifp; -int out; -{ - /* - * The above is really bad, but short of writing a diff - */ - fr_info_t frinfo, *fc; - register fr_info_t *fin = &frinfo; - frentry_t *fr = NULL; - int pass, changed, apass, error = EHOSTUNREACH; -#if !SOLARIS || !defined(KERNEL) - register mb_t *m = *mp; -#endif - -#if KERNEL - mb_t *mc = NULL; -# if !defined(__SVR4) && !defined(__svr4__) -# ifdef __sgi - char hbuf[(0xf << 2) + sizeof(struct icmp) + sizeof(ip_t) + 8]; -# endif - int up; - -#if M_CANFASTFWD - /* - * XXX For now, IP Filter and fast-forwarding of cached flows - * XXX are mutually exclusive. Eventually, IP Filter should - * XXX get a "can-fast-forward" filter rule. - */ - m->m_flags &= ~M_CANFASTFWD; -#endif /* M_CANFASTFWD */ - - if ((ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP || - ip->ip_p == IPPROTO_ICMP)) { - int plen = 0; - - switch(ip->ip_p) - { - case IPPROTO_TCP: - plen = sizeof(tcphdr_t); - break; - case IPPROTO_UDP: - plen = sizeof(udphdr_t); - break; - case IPPROTO_ICMP: - /* 96 - enough for complete ICMP error IP header */ - plen = sizeof(struct icmp) + sizeof(ip_t) + 8; - break; - } - up = MIN(hlen + plen, ip->ip_len); - - if (up > m->m_len) { -#ifdef __sgi /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ - if ((up > sizeof(hbuf)) || (m_length(m) < up)) { - frstats[out].fr_pull[1]++; - return -1; - } - m_copydata(m, 0, up, hbuf); - frstats[out].fr_pull[0]++; - ip = (ip_t *)hbuf; -#else -# ifndef linux - if ((*mp = m_pullup(m, up)) == 0) { - frstats[out].fr_pull[1]++; - return -1; - } else { - frstats[out].fr_pull[0]++; - m = *mp; - ip = mtod(m, ip_t *); - } -# endif -#endif - } else - up = 0; - } else - up = 0; -# endif -# if SOLARIS - mb_t *m = qif->qf_m; -# endif -#endif - fr_makefrip(hlen, ip, fin); - fin->fin_ifp = ifp; - fin->fin_out = out; - fin->fin_mp = mp; - - MUTEX_ENTER(&ipf_mutex); - - /* - * Check auth now. This, combined with the check below to see if apass - * is 0 is to ensure that we don't count the packet twice, which can - * otherwise occur when we reprocess it. As it is, we only count it - * after it has no auth. table matchup. This also stops NAT from - * occuring until after the packet has been auth'd. - */ - apass = fr_checkauth(ip, fin); - - if (!out) { - changed = ip_natin(ip, hlen, fin); - if (!apass && (fin->fin_fr = ipacct[0][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) - frstats[0].fr_acct++; - } - - if (apass || (!(pass = ipfr_knownfrag(ip, fin)) && - !(pass = fr_checkstate(ip, fin)))) { - /* - * If a packet is found in the auth table, then skip checking - * the access lists for permission but we do need to consider - * the result as if it were from the ACL's. - */ - if (!apass) { - fc = frcache + out; - if (!bcmp((char *)fin, (char *)fc, FI_CSIZE)) { - /* - * copy cached data so we can unlock the mutex - * earlier. - */ - bcopy((char *)fc, (char *)fin, FI_COPYSIZE); - frstats[out].fr_chit++; - if ((fr = fin->fin_fr)) { - fr->fr_hits++; - pass = fr->fr_flags; - } else - pass = fr_pass; - } else { - pass = fr_pass; - if ((fin->fin_fr = ipfilter[out][fr_active])) - pass = FR_SCANLIST(fr_pass, ip, fin, m); - bcopy((char *)fin, (char *)fc, FI_COPYSIZE); - if (pass & FR_NOMATCH) - frstats[out].fr_nom++; - } - fr = fin->fin_fr; - } else - pass = apass; - - /* - * If we fail to add a packet to the authorization queue, - * then we drop the packet later. However, if it was added - * then pretend we've dropped it already. - */ - if ((pass & FR_AUTH)) - if (FR_NEWAUTH(m, fin, ip, qif) != 0) -#ifdef KERNEL - m = *mp = NULL; -#else - ; -#endif - - if (pass & FR_PREAUTH) { - MUTEX_ENTER(&ipf_auth); - if ((fin->fin_fr = ipauth) && - (pass = FR_SCANLIST(0, ip, fin, m))) - fr_authstats.fas_hits++; - else - fr_authstats.fas_miss++; - MUTEX_EXIT(&ipf_auth); - } - - if (pass & FR_KEEPFRAG) { - if (fin->fin_fi.fi_fl & FI_FRAG) { - if (ipfr_newfrag(ip, fin, pass) == -1) - frstats[out].fr_bnfr++; - else - frstats[out].fr_nfr++; - } else - frstats[out].fr_cfr++; - } - if (pass & FR_KEEPSTATE) { - if (fr_addstate(ip, fin, pass) == -1) - frstats[out].fr_bads++; - else - frstats[out].fr_ads++; - } - } - - if (fr && fr->fr_func && !(pass & FR_CALLNOW)) - pass = (*fr->fr_func)(pass, ip, fin); - - /* - * Only count/translate packets which will be passed on, out the - * interface. - */ - if (out && (pass & FR_PASS)) { - if ((fin->fin_fr = ipacct[1][fr_active]) && - (FR_SCANLIST(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) - frstats[1].fr_acct++; - fin->fin_fr = NULL; - changed = ip_natout(ip, hlen, fin); - } - fin->fin_fr = fr; - MUTEX_EXIT(&ipf_mutex); - -#if IPFILTER_LOG - if ((fr_flags & FF_LOGGING) || (pass & FR_LOGMASK)) { - if ((fr_flags & FF_LOGNOMATCH) && (pass & FR_NOMATCH)) { - pass |= FF_LOGNOMATCH; - frstats[out].fr_npkl++; - goto logit; - } else if (((pass & FR_LOGMASK) == FR_LOGP) || - ((pass & FR_PASS) && (fr_flags & FF_LOGPASS))) { - if ((pass & FR_LOGMASK) != FR_LOGP) - pass |= FF_LOGPASS; - frstats[out].fr_ppkl++; - goto logit; - } else if (((pass & FR_LOGMASK) == FR_LOGB) || - ((pass & FR_BLOCK) && (fr_flags & FF_LOGBLOCK))) { - if ((pass & FR_LOGMASK) != FR_LOGB) - pass |= FF_LOGBLOCK; - frstats[out].fr_bpkl++; -logit: - if (!IPLLOG(pass, ip, fin, m)) { - frstats[out].fr_skip++; - if ((pass & (FR_PASS|FR_LOGORBLOCK)) == - (FR_PASS|FR_LOGORBLOCK)) - pass ^= FR_PASS|FR_BLOCK; - } - } - } -#endif /* IPFILTER_LOG */ -#ifdef KERNEL - /* - * Only allow FR_DUP to work if a rule matched - it makes no sense to - * set FR_DUP as a "default" as there are no instructions about where - * to send the packet. - */ - if (fr && (pass & FR_DUP)) -# if SOLARIS - mc = dupmsg(m); -# else -# ifndef linux - mc = m_copy(m, 0, M_COPYALL); -# else - ; -# endif -# endif -#endif - if (pass & FR_PASS) - frstats[out].fr_pass++; - else if (pass & FR_BLOCK) { - frstats[out].fr_block++; - /* - * Should we return an ICMP packet to indicate error - * status passing through the packet filter ? - * WARNING: ICMP error packets AND TCP RST packets should - * ONLY be sent in repsonse to incoming packets. Sending them - * in response to outbound packets can result in a panic on - * some operating systems. - */ - if (!out) { -#ifdef KERNEL - if (pass & FR_RETICMP) { -# if SOLARIS - ICMP_ERROR(q, ip, ICMP_UNREACH, fin->fin_icode, - qif, ip->ip_src); -# else - ICMP_ERROR(m, ip, ICMP_UNREACH, fin->fin_icode, - ifp, ip->ip_src); - m = *mp = NULL; /* freed by icmp_error() */ -# endif - - frstats[0].fr_ret++; - } else if ((pass & FR_RETRST) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (SEND_RESET(ip, qif, ifp) == 0) - frstats[1].fr_ret++; - } -#else - if (pass & FR_RETICMP) { - verbose("- ICMP unreachable sent\n"); - frstats[0].fr_ret++; - } else if ((pass & FR_RETRST) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - verbose("- TCP RST sent\n"); - frstats[1].fr_ret++; - } -#endif - } else { - if (pass & FR_RETRST) - error = ECONNRESET; - } - } - - /* - * If we didn't drop off the bottom of the list of rules (and thus - * the 'current' rule fr is not NULL), then we may have some extra - * instructions about what to do with a packet. - * Once we're finished return to our caller, freeing the packet if - * we are dropping it (* BSD ONLY *). - */ -#if defined(KERNEL) -# if !SOLARIS -# if !defined(linux) - if (fr) { - frdest_t *fdp = &fr->fr_tif; - - if ((pass & FR_FASTROUTE) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(m, fin, fdp); - m = *mp = NULL; - } - if (mc) - ipfr_fastroute(mc, fin, &fr->fr_dif); - } - if (!(pass & FR_PASS) && m) - m_freem(m); -# ifdef __sgi - else if (changed && up && m) - m_copyback(m, 0, up, hbuf); -# endif -# endif /* !linux */ - return (pass & FR_PASS) ? 0 : error; -# else /* !SOLARIS */ - if (fr) { - frdest_t *fdp = &fr->fr_tif; - - if ((pass & FR_FASTROUTE) || - (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) { - ipfr_fastroute(qif, ip, m, mp, fin, fdp); - m = *mp = NULL; - } - if (mc) - ipfr_fastroute(qif, ip, mc, mp, fin, &fr->fr_dif); - } - return (pass & FR_PASS) ? changed : error; -# endif /* !SOLARIS */ -#else /* KERNEL */ - if (pass & FR_NOMATCH) - return 1; - if (pass & FR_PASS) - return 0; - if (pass & FR_AUTH) - return -2; - return -1; -#endif /* KERNEL */ -} - - -/* - * ipf_cksum - * addr should be 16bit aligned and len is in bytes. - * length is in bytes - */ -u_short ipf_cksum(addr, len) -register u_short *addr; -register int len; -{ - register u_32_t sum = 0; - - for (sum = 0; len > 1; len -= 2) - sum += *addr++; - - /* mop up an odd byte, if necessary */ - if (len == 1) - sum += *(u_char *)addr; - - /* - * add back carry outs from top 16 bits to low 16 bits - */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - return (u_short)(~sum); -} - - -/* - * NB: This function assumes we've pullup'd enough for all of the IP header - * and the TCP header. We also assume that data blocks aren't allocated in - * odd sizes. - */ -u_short fr_tcpsum(m, ip, tcp, len) -mb_t *m; -ip_t *ip; -tcphdr_t *tcp; -int len; -{ - union { - u_char c[2]; - u_short s; - } bytes; - u_32_t sum; - u_short *sp; -# if SOLARIS || defined(__sgi) - int add, hlen; -# endif - -# if SOLARIS - /* skip any leading M_PROTOs */ - while(m && (MTYPE(m) != M_DATA)) - m = m->b_cont; - PANIC((!m),("fr_tcpsum: no M_DATA")); -# endif - - /* - * Add up IP Header portion - */ - bytes.c[0] = 0; - bytes.c[1] = IPPROTO_TCP; - len -= (ip->ip_hl << 2); - sum = bytes.s; - sum += htons((u_short)len); - sp = (u_short *)&ip->ip_src; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - if (sp != (u_short *)tcp) - sp = (u_short *)tcp; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp++; - sum += *sp; - sp += 2; /* Skip over checksum */ - sum += *sp++; - -#if SOLARIS - /* - * In case we had to copy the IP & TCP header out of mblks, - * skip over the mblk bits which are the header - */ - if ((caddr_t)ip != (caddr_t)m->b_rptr) { - hlen = (caddr_t)sp - (caddr_t)ip; - while (hlen) { - add = MIN(hlen, m->b_wptr - m->b_rptr); - sp = (u_short *)((caddr_t)m->b_rptr + add); - hlen -= add; - if ((caddr_t)sp >= (caddr_t)m->b_wptr) { - m = m->b_cont; - PANIC((!m),("fr_tcpsum: not enough data")); - if (!hlen) - sp = (u_short *)m->b_rptr; - } - } - } -#endif -#ifdef __sgi - /* - * In case we had to copy the IP & TCP header out of mbufs, - * skip over the mbuf bits which are the header - */ - if ((caddr_t)ip != mtod(m, caddr_t)) { - hlen = (caddr_t)sp - (caddr_t)ip; - while (hlen) { - add = MIN(hlen, m->m_len); - sp = (u_short *)(mtod(m, caddr_t) + add); - hlen -= add; - if (add >= m->m_len) { - m = m->m_next; - PANIC((!m),("fr_tcpsum: not enough data")); - if (!hlen) - sp = mtod(m, u_short *); - } - } - } -#endif - - if (!(len -= sizeof(*tcp))) - goto nodata; - while (len > 0) { -#if SOLARIS - while ((caddr_t)sp >= (caddr_t)m->b_wptr) { - m = m->b_cont; - PANIC((!m),("fr_tcpsum: not enough data")); - sp = (u_short *)m->b_rptr; - } -#else - while (((caddr_t)sp - mtod(m, caddr_t)) >= m->m_len) - { - m = m->m_next; - PANIC((!m),("fr_tcpsum: not enough data")); - sp = mtod(m, u_short *); - } -#endif /* SOLARIS */ - if (len < 2) - break; - if((u_32_t)sp & 1) { - bcopy((char *)sp++, (char *)&bytes.s, sizeof(bytes.s)); - sum += bytes.s; - } else - sum += *sp++; - len -= 2; - } - if (len) { - bytes.c[1] = 0; - bytes.c[0] = *(u_char *)sp; - sum += bytes.s; - } -nodata: - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - sum = (u_short)((~sum) & 0xffff); - return sum; -} - - -#if defined(KERNEL) && ( ((BSD < 199306) && !SOLARIS) || defined(__sgi) ) -/* - * Copyright (c) 1982, 1986, 1988, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 - */ -/* - * Copy data from an mbuf chain starting "off" bytes from the beginning, - * continuing for "len" bytes, into the indicated buffer. - */ -void -m_copydata(m, off, len, cp) - register mb_t *m; - register int off; - register int len; - caddr_t cp; -{ - register unsigned count; - - if (off < 0 || len < 0) - panic("m_copydata"); - while (off > 0) { - if (m == 0) - panic("m_copydata"); - if (off < m->m_len) - break; - off -= m->m_len; - m = m->m_next; - } - while (len > 0) { - if (m == 0) - panic("m_copydata"); - count = MIN(m->m_len - off, len); - bcopy(mtod(m, caddr_t) + off, cp, count); - len -= count; - cp += count; - off = 0; - m = m->m_next; - } -} - - -# ifndef linux -/* - * Copy data from a buffer back into the indicated mbuf chain, - * starting "off" bytes from the beginning, extending the mbuf - * chain if necessary. - */ -void -m_copyback(m0, off, len, cp) - struct mbuf *m0; - register int off; - register int len; - caddr_t cp; -{ - register int mlen; - register struct mbuf *m = m0, *n; - int totlen = 0; - - if (m0 == 0) - return; - while (off > (mlen = m->m_len)) { - off -= mlen; - totlen += mlen; - if (m->m_next == 0) { - n = m_getclr(M_DONTWAIT, m->m_type); - if (n == 0) - goto out; - n->m_len = min(MLEN, len + off); - m->m_next = n; - } - m = m->m_next; - } - while (len > 0) { - mlen = min (m->m_len - off, len); - bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen); - cp += mlen; - len -= mlen; - mlen += off; - off = 0; - totlen += mlen; - if (len == 0) - break; - if (m->m_next == 0) { - n = m_get(M_DONTWAIT, m->m_type); - if (n == 0) - break; - n->m_len = min(MLEN, len); - m->m_next = n; - } - m = m->m_next; - } -out: -#if 0 - if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) - m->m_pkthdr.len = totlen; -#endif - return; -} -# endif /* linux */ -#endif /* (KERNEL) && ( ((BSD < 199306) && !SOLARIS) || __sgi) */ - - -frgroup_t *fr_findgroup(num, flags, which, set, fgpp) -u_short num; -u_32_t flags; -int which, set; -frgroup_t ***fgpp; -{ - frgroup_t *fg, **fgp; - - if (which == IPL_LOGAUTH) - fgp = &ipfgroups[2][set]; - else if (flags & FR_ACCOUNT) - fgp = &ipfgroups[1][set]; - else if (flags & (FR_OUTQUE|FR_INQUE)) - fgp = &ipfgroups[0][set]; - else - return NULL; - - while ((fg = *fgp)) - if (fg->fg_num == num) - break; - else - fgp = &fg->fg_next; - if (fgpp) - *fgpp = fgp; - return fg; -} - - -frgroup_t *fr_addgroup(num, fp, which, set) -u_short num; -frentry_t *fp; -int which, set; -{ - frgroup_t *fg, **fgp; - - if ((fg = fr_findgroup(num, fp->fr_flags, which, set, &fgp))) - return fg; - - KMALLOC(fg, frgroup_t *, sizeof(*fg)); - if (fg) { - fg->fg_num = num; - fg->fg_next = *fgp; - fg->fg_head = fp; - fg->fg_start = &fp->fr_grp; - *fgp = fg; - } - return fg; -} - - -void fr_delgroup(num, flags, which, set) -u_short num; -u_32_t flags; -int which, set; -{ - frgroup_t *fg, **fgp; - - if (!(fg = fr_findgroup(num, flags, which, set, &fgp))) - return; - - *fgp = fg->fg_next; - KFREE(fg); -} - - - -/* - * recursively flush rules from the list, descending groups as they are - * encountered. if a rule is the head of a group and it has lost all its - * group members, then also delete the group reference. - */ -static int frflushlist(set, unit, nfreedp, list, listp) -int set, unit, *nfreedp; -frentry_t *list, **listp; -{ - register frentry_t *fp = list, *fpn; - register int freed = 0; - - while (fp) { - fpn = fp->fr_next; - if (fp->fr_grp) { - fp->fr_ref -= frflushlist(set, unit, nfreedp, - fp->fr_grp, &fp->fr_grp); - } - - if (fp->fr_ref == 1) { - if (fp->fr_grhead) - fr_delgroup(fp->fr_grhead, fp->fr_flags, unit, - set); - KFREE(fp); - *listp = fpn; - freed++; - } - fp = fpn; - } - *nfreedp += freed; - return freed; -} - - -void frflush(unit, result) -int unit; -int *result; -{ - int flags = *result, flushed = 0, set = fr_active; - - bzero((char *)frcache, sizeof(frcache[0]) * 2); - - if (flags & FR_INACTIVE) - set = 1 - set; - - if (unit == IPL_LOGIPF) { - if (flags & FR_OUTQUE) { - (void) frflushlist(set, unit, &flushed, - ipfilter[1][set], - &ipfilter[1][set]); - (void) frflushlist(set, unit, &flushed, - ipacct[1][set], &ipacct[1][set]); - } - if (flags & FR_INQUE) { - (void) frflushlist(set, unit, &flushed, - ipfilter[0][set], - &ipfilter[0][set]); - (void) frflushlist(set, unit, &flushed, - ipacct[0][set], &ipacct[0][set]); - } - } - - *result = flushed; -} diff --git a/bsd/netinet/if_ether.c b/bsd/netinet/if_ether.c index 31932451d..3cd5fb6b1 100644 --- a/bsd/netinet/if_ether.c +++ b/bsd/netinet/if_ether.c @@ -96,12 +96,20 @@ static int arpt_prune = (5*60*1); /* walk list every 5 minutes */ static int arpt_keep = (20*60); /* once resolved, good for 20 more minutes */ static int arpt_down = 20; /* once declared down, don't send for 20 sec */ +/* Apple Hardware SUM16 checksuming */ +int apple_hwcksum_tx = 1; +int apple_hwcksum_rx = 1; + SYSCTL_INT(_net_link_ether_inet, OID_AUTO, prune_intvl, CTLFLAG_RW, &arpt_prune, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, &arpt_keep, 0, ""); SYSCTL_INT(_net_link_ether_inet, OID_AUTO, host_down_time, CTLFLAG_RW, &arpt_down, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, apple_hwcksum_tx, CTLFLAG_RW, + &apple_hwcksum_tx, 0, ""); +SYSCTL_INT(_net_link_ether_inet, OID_AUTO, apple_hwcksum_rx, CTLFLAG_RW, + &apple_hwcksum_rx, 0, ""); #define rt_expire rt_rmx.rmx_expire @@ -523,6 +531,13 @@ in_arpinput(m) op = ntohs(ea->arp_op); (void)memcpy(&isaddr, ea->arp_spa, sizeof (isaddr)); (void)memcpy(&itaddr, ea->arp_tpa, sizeof (itaddr)); + + /* Don't respond to requests for 0.0.0.0 */ + if (itaddr.s_addr == 0 && op == ARPOP_REQUEST) { + m_freem(m); + return; + } + for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) #if BRIDGE /* @@ -544,18 +559,7 @@ in_arpinput(m) return; } myaddr = ia ? ia->ia_addr.sin_addr : maybe_ia->ia_addr.sin_addr; - -#if 0 - /* - * In order to support BlueBox networking, we need to allow - * "self-addressed" stamped envelopes - */ - if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr, - sizeof (ea->arp_sha))) { - m_freem(m); /* it's from me, ignore it. */ - return; - } -#endif + if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr, sizeof (ea->arp_sha))) { log(LOG_ERR, @@ -668,7 +672,10 @@ reply: ea->arp_op = htons(ARPOP_REPLY); ea->arp_pro = htons(ETHERTYPE_IP); /* let's be sure! */ eh = (struct ether_header *)sa.sa_data; - (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); + if (IN_LINKLOCAL(ntohl(*((u_int32_t*)ea->arp_spa)))) + (void)memcpy(eh->ether_dhost, etherbroadcastaddr, sizeof(eh->ether_dhost)); + else + (void)memcpy(eh->ether_dhost, ea->arp_tha, sizeof(eh->ether_dhost)); eh->ether_type = htons(ETHERTYPE_ARP); sa.sa_family = AF_UNSPEC; sa.sa_len = sizeof(sa); diff --git a/bsd/netinet/igmp.c b/bsd/netinet/igmp.c index 0a1d51ef1..380540120 100644 --- a/bsd/netinet/igmp.c +++ b/bsd/netinet/igmp.c @@ -157,7 +157,7 @@ find_rti(ifp) #if ISFB31 MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, M_NOWAIT); #else - MALLOC(rti, struct router_info *, sizeof *rti, M_TEMP, M_NOWAIT); + MALLOC(rti, struct router_info *, sizeof *rti, M_TEMP, M_WAITOK); #endif rti->rti_ifp = ifp; rti->rti_type = IGMP_V2_ROUTER; @@ -473,6 +473,8 @@ igmp_sendpkt(inm, type, addr) MH_ALIGN(m, IGMP_MINLEN + sizeof(struct ip)); m->m_data += sizeof(struct ip); m->m_len = IGMP_MINLEN; + m->m_pkthdr.csum_flags = 0; + m->m_pkthdr.csum_data = 0; igmp = mtod(m, struct igmp *); igmp->igmp_type = type; igmp->igmp_code = 0; diff --git a/bsd/netinet/in.c b/bsd/netinet/in.c index 1389cf3a2..e8e82accd 100644 --- a/bsd/netinet/in.c +++ b/bsd/netinet/in.c @@ -105,6 +105,7 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, struct in_multihead in_multihead; /* XXX BSS initialization */ extern void arp_rtrequest(); +extern int ether_detach_inet(struct ifnet *ifp); /* @@ -252,9 +253,11 @@ in_control(so, cmd, data, ifp, p) #endif case SIOCGIFPSRCADDR: case SIOCGIFPDSTADDR: +#if NGIF > 0 if (strcmp(ifp->if_name, "gif") == 0) dl_tag = gif_attach_inet(ifp); return gif_ioctl(ifp, cmd, data); +#endif } } #endif @@ -302,6 +305,15 @@ in_control(so, cmd, data, ifp, p) } switch (cmd) { + case SIOCAUTOADDR: +#if 1 + if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) + return error; +#else + if ((so->so_state & SS_PRIV) == 0) + return (EPERM); +#endif + break; case SIOCAIFADDR: case SIOCDIFADDR: @@ -321,6 +333,8 @@ in_control(so, cmd, data, ifp, p) return EDESTADDRREQ; } } + else if (cmd == SIOCAIFADDR) + return (EINVAL); if (cmd == SIOCDIFADDR && ia == 0) return (EADDRNOTAVAIL); /* FALLTHROUGH */ @@ -338,6 +352,8 @@ in_control(so, cmd, data, ifp, p) if (ifp == 0) return (EADDRNOTAVAIL); + if (ifra->ifra_addr.sin_family != AF_INET && cmd == SIOCSIFADDR) + return (EINVAL); if (ia == (struct in_ifaddr *)0) { ia = (struct in_ifaddr *) _MALLOC(sizeof *ia, M_IFADDR, M_WAITOK); @@ -381,6 +397,16 @@ in_control(so, cmd, data, ifp, p) } break; + case SIOCPROTOATTACH: + case SIOCPROTODETACH: + if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) + return error; + if (ifp == 0) + return (EADDRNOTAVAIL); + if (strcmp(ifp->if_name, "en")) + return ENODEV; + break; + case SIOCSIFBRDADDR: #if ISFB31 if (p && (error = suser(p->p_ucred, &p->p_acflag)) != 0) @@ -400,6 +426,14 @@ in_control(so, cmd, data, ifp, p) break; } switch (cmd) { + case SIOCAUTOADDR: + if (ifp == 0) + return (EADDRNOTAVAIL); + if (ifr->ifr_data) + ifp->if_eflags |= IFEF_AUTOCONFIGURING; + else + ifp->if_eflags &= ~IFEF_AUTOCONFIGURING; + break; case SIOCGIFADDR: *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr; @@ -512,6 +546,17 @@ in_control(so, cmd, data, ifp, p) return (in_ifinit(ifp, ia, (struct sockaddr_in *) &ifr->ifr_addr, 1)); + case SIOCPROTOATTACH: + ether_attach_inet(ifp); + break; + + case SIOCPROTODETACH: + // if an ip address is still present, refuse to detach + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + if (ifa->ifa_addr->sa_family == AF_INET) + return EBUSY; + return ether_detach_inet(ifp); + case SIOCSIFNETMASK: i = ifra->ifra_addr.sin_addr.s_addr; ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i); @@ -658,6 +703,26 @@ in_control(so, cmd, data, ifp, p) oia = ia; TAILQ_REMOVE(&in_ifaddrhead, oia, ia_link); IFAFREE(&oia->ia_ifa); + + /* + * If the interface supports multicast, and no address is left, + * remove the "all hosts" multicast group from that interface. + */ + if (ifp->if_flags & IFF_MULTICAST) { + struct in_addr addr; + struct in_multi *inm; + + TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) + if (ifa->ifa_addr->sa_family == AF_INET) + break; + + if (ifa == 0) { + addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); + IN_LOOKUP_MULTI(addr, ifp, inm); + if (inm) + in_delmulti(inm); + } + } splx(s); break; @@ -1033,10 +1098,13 @@ in_ifinit(ifp, ia, sin, scrub) * multicast group on that interface. */ if (ifp->if_flags & IFF_MULTICAST) { + struct in_multi *inm; struct in_addr addr; addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP); - in_addmulti(&addr, ifp); + IN_LOOKUP_MULTI(addr, ifp, inm); + if (inm == 0) + in_addmulti(&addr, ifp); } return (error); } @@ -1065,7 +1133,9 @@ in_broadcast(in, ifp) */ #define ia ((struct in_ifaddr *)ifa) for (ifa = ifp->if_addrhead.tqh_first; ifa; - ifa = ifa->ifa_link.tqe_next) + ifa = ifa->ifa_link.tqe_next) { + if (ifa->ifa_addr == NULL) + return (0); if (ifa->ifa_addr->sa_family == AF_INET && (in.s_addr == ia->ia_broadaddr.sin_addr.s_addr || in.s_addr == ia->ia_netbroadcast.s_addr || @@ -1080,6 +1150,7 @@ in_broadcast(in, ifp) */ ia->ia_subnetmask != (u_long)0xffffffff) return 1; + } return (0); #undef ia } @@ -1119,9 +1190,7 @@ in_addmulti(ap, ifp) if (ifma->ifma_protospec != 0) return ifma->ifma_protospec; - /* XXX - if_addmulti uses M_WAITOK. Can this really be called - at interrupt time? If so, need to fix if_addmulti. XXX */ - inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_NOWAIT); + inm = (struct in_multi *) _MALLOC(sizeof(*inm), M_IPMADDR, M_WAITOK); if (inm == NULL) { splx(s); return (NULL); diff --git a/bsd/netinet/in.h b/bsd/netinet/in.h index e62cdc73f..12bc02389 100644 --- a/bsd/netinet/in.h +++ b/bsd/netinet/in.h @@ -299,6 +299,9 @@ struct in_addr { #define INADDR_ALLRTRS_GROUP (u_int32_t)0xe0000002 /* 224.0.0.2 */ #define INADDR_MAX_LOCAL_GROUP (u_int32_t)0xe00000ff /* 224.0.0.255 */ +#define IN_LINKLOCALNETNUM (u_int32_t)0xA9FE0000 /* 169.254.0.0 */ +#define IN_LINKLOCAL(i) (((u_int32_t)(i) & IN_CLASSB_NET) == IN_LINKLOCALNETNUM) + #define IN_LOOPBACKNET 127 /* official! */ /* @@ -508,6 +511,9 @@ struct ifnet; struct mbuf; /* forward declarations for Standard C */ int in_broadcast __P((struct in_addr, struct ifnet *)); int in_canforward __P((struct in_addr)); int in_cksum __P((struct mbuf *, int)); +int in_cksum_skip __P((struct mbuf *, u_short, u_short)); +u_short in_addword __P((u_short, u_short)); +u_short in_pseudo __P((u_int, u_int, u_int)); int in_localaddr __P((struct in_addr)); char *inet_ntoa __P((struct in_addr)); /* in libkern */ u_long in_netof __P((struct in_addr)); diff --git a/bsd/netinet/in_bootp.c b/bsd/netinet/in_bootp.c index 025a1c379..623197668 100644 --- a/bsd/netinet/in_bootp.c +++ b/bsd/netinet/in_bootp.c @@ -600,7 +600,11 @@ int bootp(struct ifnet * ifp, struct in_addr * iaddr_p, int max_try, { /* bind the socket */ struct sockaddr_in * sin; - sin = _MALLOC(sizeof(struct sockaddr_in), M_IFADDR, M_NOWAIT); + sin = _MALLOC(sizeof(struct sockaddr_in), M_IFADDR, M_WAIT); + if (sin == NULL) { + error = ENOMEM; + goto cleanup; + } sin->sin_len = sizeof(struct sockaddr_in); sin->sin_family = AF_INET; sin->sin_port = htons(IPPORT_BOOTPC); @@ -627,14 +631,3 @@ int bootp(struct ifnet * ifp, struct in_addr * iaddr_p, int max_try, return (error); } -/* - * Function: in_bootp - * Purpose: - * This is deprecated API. Once SIOCAUTOADDR is eliminated from - * the system (IOEthernet class as well), this routine can be removed. - */ -int -in_bootp(struct ifnet * ifp, struct sockaddr_in * sin, u_char my_enaddr[6]) -{ - return (EOPNOTSUPP); -} diff --git a/bsd/netinet/in_cksum.c b/bsd/netinet/in_cksum.c index 4262277c9..c8a2d462f 100644 --- a/bsd/netinet/in_cksum.c +++ b/bsd/netinet/in_cksum.c @@ -67,10 +67,64 @@ * code and should be modified for each CPU to be as fast as possible. */ +union s_util { + char c[2]; + u_short s; +}; +union l_util { + u_int16_t s[2]; + u_int32_t l; +}; +union q_util { + u_int16_t s[4]; + u_int32_t l[2]; + u_int64_t q; +}; + +#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) + +#define REDUCE32 \ + { \ + q_util.q = sum; \ + sum = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + } +#define REDUCE16 \ + { \ + q_util.q = sum; \ + l_util.l = q_util.s[0] + q_util.s[1] + q_util.s[2] + q_util.s[3]; \ + sum = l_util.s[0] + l_util.s[1]; \ + ADDCARRY(sum); \ + } + +#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} + + #if defined(ppc) +__inline unsigned short +in_addword(u_short a, u_short b) +{ + union l_util l_util; + u_int32_t sum = a + b; + REDUCE; + return (sum); +} + +__inline unsigned short +in_pseudo(u_int a, u_int b, u_int c) +{ + u_int64_t sum; + union q_util q_util; + union l_util l_util; + + sum = (u_int64_t) a + b + c; + REDUCE16; + return (sum); + +} + int in_cksum(m, len) register struct mbuf *m; @@ -108,12 +162,71 @@ in_cksum(m, len) return (~sum & 0xffff); } +u_short +in_cksum_skip(m, len, skip) + register struct mbuf *m; + register int len; + register int skip; +{ + register u_short *w; + register int sum = 0; + register int mlen = 0; + int starting_on_odd = 0; + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + w = (u_short *)(m->m_data+skip); + goto skip_start; + } else { + skip -= m->m_len; + } + } + for (;m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + mlen = m->m_len; + w = mtod(m, u_short *); + + if (len < mlen) + mlen = len; +skip_start: + sum = xsum_assym(w, mlen, sum, starting_on_odd); + len -= mlen; + if (mlen & 0x1) + { + if (starting_on_odd) + starting_on_odd = 0; + else + starting_on_odd = 1; + } + } + + return (~sum & 0xffff); +} #else +u_short +in_addword(u_short a, u_short b) +{ + union l_util l_util; + u_int32_t sum = a + b; + REDUCE(sum); + return (sum); +} -#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} +u_short +in_pseudo(u_int a, u_int b, u_int c) +{ + u_int64_t sum; + union q_util q_util; + union l_util l_util; + sum = (u_int64_t) a + b + c; + REDUCE16; + return (sum); +} int @@ -125,15 +238,8 @@ in_cksum(m, len) register int sum = 0; register int mlen = 0; int byte_swapped = 0; - - union { - char c[2]; - u_short s; - } s_util; - union { - u_short s[2]; - long l; - } l_util; + union s_util s_util; + union l_util l_util; KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0); @@ -221,4 +327,117 @@ in_cksum(m, len) return (~sum & 0xffff); } +int +in_cksum_skip(m, len, skip) + register struct mbuf *m; + register u_short len; + register u_short skip; +{ + register u_short *w; + register int sum = 0; + register int mlen = 0; + int byte_swapped = 0; + union s_util s_util; + union l_util l_util; + + KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_START, len,0,0,0,0); + + len -= skip; + for (; skip && m; m = m->m_next) { + if (m->m_len > skip) { + mlen = m->m_len - skip; + w = (u_short *)(m->m_data+skip); + goto skip_start; + } else { + skip -= m->m_len; + } + } + for (;m && len; m = m->m_next) { + if (m->m_len == 0) + continue; + w = mtod(m, u_short *); + + if (mlen == -1) { + /* + * The first byte of this mbuf is the continuation + * of a word spanning between this mbuf and the + * last mbuf. + * + * s_util.c[0] is already saved when scanning previous + * mbuf. + */ + s_util.c[1] = *(char *)w; + sum += s_util.s; + w = (u_short *)((char *)w + 1); + mlen = m->m_len - 1; + len--; + } else { + mlen = m->m_len; + } + if (len < mlen) + mlen = len; +skip_start: + + len -= mlen; + /* + * Force to even boundary. + */ + if ((1 & (int) w) && (mlen > 0)) { + REDUCE; + sum <<= 8; + s_util.c[0] = *(u_char *)w; + w = (u_short *)((char *)w + 1); + mlen--; + byte_swapped = 1; + } + /* + * Unroll the loop to make overhead from + * branches &c small. + */ + while ((mlen -= 32) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; + sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; + sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; + w += 16; + } + mlen += 32; + while ((mlen -= 8) >= 0) { + sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; + w += 4; + } + mlen += 8; + if (mlen == 0 && byte_swapped == 0) + continue; + REDUCE; + while ((mlen -= 2) >= 0) { + sum += *w++; + } + if (byte_swapped) { + REDUCE; + sum <<= 8; + byte_swapped = 0; + if (mlen == -1) { + s_util.c[1] = *(char *)w; + sum += s_util.s; + mlen = 0; + } else + mlen = -1; + } else if (mlen == -1) + s_util.c[0] = *(char *)w; + } + if (len) + printf("cksum: out of data\n"); + if (mlen == -1) { + /* The last mbuf has odd # of bytes. Follow the + standard (the odd byte may be shifted left by 8 bits + or not as determined by endian-ness of the machine) */ + s_util.c[1] = 0; + sum += s_util.s; + } + REDUCE; + KERNEL_DEBUG(DBG_FNC_IN_CKSUM | DBG_FUNC_END, 0,0,0,0,0); + return (~sum & 0xffff); +} + #endif diff --git a/bsd/netinet/in_gif.c b/bsd/netinet/in_gif.c index f57a3ea28..d76365f87 100644 --- a/bsd/netinet/in_gif.c +++ b/bsd/netinet/in_gif.c @@ -484,10 +484,14 @@ in_gif_ioctl(ifp, cmd, data) sc->gif_oflags = ifp->if_flags; sa = (struct sockaddr *)_MALLOC(size, M_IFADDR, M_WAITOK); + if (sa == NULL) + return (ENOMEM); bcopy((caddr_t)src, (caddr_t)sa, size); sc->gif_psrc = sa; sa = (struct sockaddr *)_MALLOC(size, M_IFADDR, M_WAITOK); + if (sa == NULL) + return (ENOMEM); bcopy((caddr_t)dst, (caddr_t)sa, size); sc->gif_pdst = sa; diff --git a/bsd/netinet/in_hostcache.c b/bsd/netinet/in_hostcache.c index e791f1598..0ff6a4070 100644 --- a/bsd/netinet/in_hostcache.c +++ b/bsd/netinet/in_hostcache.c @@ -99,6 +99,8 @@ inhc_alloc(struct sockaddr_in *sin) return 0; MALLOC(inhc, struct in_hcentry *, sizeof *inhc, M_HOSTCACHE, M_WAITOK); + if (inhc == NULL) + retturn (ENOMEM); bzero(inhc, sizeof *inhc); inhc->inhc_hc.hc_host = dup_sockaddr((struct sockaddr *)sin, 1); if (in_broadcast(sin->sin_addr, rt->rt_ifp)) diff --git a/bsd/netinet/in_pcb.c b/bsd/netinet/in_pcb.c index ab4f2fc3d..d12ef72b2 100644 --- a/bsd/netinet/in_pcb.c +++ b/bsd/netinet/in_pcb.c @@ -613,6 +613,8 @@ in_setsockaddr(so, nam) * Do the malloc first in case it blocks. */ MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); + if (sin == NULL) + return ENOBUFS; bzero(sin, sizeof *sin); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); @@ -645,6 +647,8 @@ in_setpeeraddr(so, nam) * Do the malloc first in case it blocks. */ MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK); + if (sin == NULL) + return ENOBUFS; bzero((caddr_t)sin, sizeof (*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); @@ -1004,7 +1008,7 @@ in_pcbinshash(inp) * If none exists, malloc one and tack it on. */ if (phd == NULL) { - MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_NOWAIT); + MALLOC(phd, struct inpcbport *, sizeof(struct inpcbport), M_PCB, M_WAITOK); if (phd == NULL) { return (ENOBUFS); /* XXX */ } diff --git a/bsd/netinet/in_pcb.h b/bsd/netinet/in_pcb.h index 13bc26209..0dc2ab78a 100644 --- a/bsd/netinet/in_pcb.h +++ b/bsd/netinet/in_pcb.h @@ -188,6 +188,7 @@ struct inpcb { #endif int hash_element; /* Array index of pcb's hash list */ caddr_t inp_saved_ppcb; /* place to save pointer while cached */ + u_long reserved[4]; }; /* * The range of the generation count, as used in this implementation, diff --git a/bsd/netinet/ip_auth.c b/bsd/netinet/ip_auth.c deleted file mode 100644 index 051008eea..000000000 --- a/bsd/netinet/ip_auth.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1997 by Darren Reed & Guido van Rooij. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ - -#define __FreeBSD_version 300000 /* just a hack - no <sys/osreldate.h> */ - -#if !defined(KERNEL) -# include <stdlib.h> -# include <string.h> -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if defined(KERNEL) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(KERNEL) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if defined(KERNEL) && (__FreeBSD_version >= 300000) -# include <sys/malloc.h> -#endif -#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(bsdi) -# include <kern/cpu_number.h> -#endif -#include <net/if.h> -#ifdef sun -#include <net/af.h> -#endif -#if !defined(KERNEL) && (__FreeBSD_version >= 300000) -# include <net/if_var.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef KERNEL -#define KERNEL -#define NOT_KERNEL -#endif -#ifndef linux -# include <netinet/ip_var.h> -#endif -#ifdef NOT_KERNEL -#undef KERNEL -#endif -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -# endif -#endif -#include <netinet/tcp.h> -#if defined(__sgi) && !defined(IFF_DRVRLOCK) /* IRIX < 6 */ -extern struct ifqueue ipintrq; /* ip packet input queue */ -#else -# ifndef linux -# include <netinet/in_var.h> -# include <netinet/tcp_fsm.h> -# endif -#endif -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_auth.h" -#if !SOLARIS && !defined(linux) -# include <net/netisr.h> -# ifdef __FreeBSD__ -# include <machine/cpufunc.h> -# endif -#endif - - -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_auth; -# if SOLARIS -extern kcondvar_t ipfauthwait; -# endif -#endif -#ifdef linux -static struct wait_queue *ipfauthwait = NULL; -#endif - -int fr_authsize = FR_NUMAUTH; -int fr_authused = 0; -int fr_defaultauthage = 600; -fr_authstat_t fr_authstats; -static frauth_t fr_auth[FR_NUMAUTH]; -mb_t *fr_authpkts[FR_NUMAUTH]; -static int fr_authstart = 0, fr_authend = 0, fr_authnext = 0; -static frauthent_t *fae_list = NULL; -frentry_t *ipauth = NULL; - - -/* - * Check if a packet has authorization. If the packet is found to match an - * authorization result and that would result in a feedback loop (i.e. it - * will end up returning FR_AUTH) then return FR_BLOCK instead. - */ -int fr_checkauth(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - u_short id = ip->ip_id; - u_32_t pass; - int i; - - MUTEX_ENTER(&ipf_auth); - for (i = fr_authstart; i != fr_authend; ) { - /* - * index becomes -2 only after an SIOCAUTHW. Check this in - * case the same packet gets sent again and it hasn't yet been - * auth'd. - */ - if ((fr_auth[i].fra_index == -2) && - (id == fr_auth[i].fra_info.fin_id) && - !bcmp((char *)fin,(char *)&fr_auth[i].fra_info,FI_CSIZE)) { - /* - * Avoid feedback loop. - */ - if (!(pass = fr_auth[i].fra_pass) || (pass & FR_AUTH)) - pass = FR_BLOCK; - fr_authstats.fas_hits++; - fr_auth[i].fra_index = -1; - fr_authused--; - if (i == fr_authstart) { - while (fr_auth[i].fra_index == -1) { - i++; - if (i == FR_NUMAUTH) - i = 0; - fr_authstart = i; - if (i == fr_authend) - break; - } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; - } - } - MUTEX_EXIT(&ipf_auth); - return pass; - } - i++; - if (i == FR_NUMAUTH) - i = 0; - } - fr_authstats.fas_miss++; - MUTEX_EXIT(&ipf_auth); - return 0; -} - - -/* - * Check if we have room in the auth array to hold details for another packet. - * If we do, store it and wake up any user programs which are waiting to - * hear about these events. - */ -int fr_newauth(m, fin, ip -#if defined(_KERNEL) && SOLARIS -, qif) -qif_t *qif; -#else -) -#endif -mb_t *m; -fr_info_t *fin; -ip_t *ip; -{ - int i; - - MUTEX_ENTER(&ipf_auth); - if ((fr_authstart > fr_authend) && (fr_authstart - fr_authend == -1)) { - fr_authstats.fas_nospace++; - MUTEX_EXIT(&ipf_auth); - return 0; - } - if (fr_authend - fr_authstart == FR_NUMAUTH - 1) { - fr_authstats.fas_nospace++; - MUTEX_EXIT(&ipf_auth); - return 0; - } - - fr_authstats.fas_added++; - fr_authused++; - i = fr_authend++; - if (fr_authend == FR_NUMAUTH) - fr_authend = 0; - MUTEX_EXIT(&ipf_auth); - fr_auth[i].fra_index = i; - fr_auth[i].fra_pass = 0; - fr_auth[i].fra_age = fr_defaultauthage; - bcopy((char *)fin, (char *)&fr_auth[i].fra_info, sizeof(*fin)); -#if !defined(sparc) && !defined(m68k) - /* - * No need to copyback here as we want to undo the changes, not keep - * them. - */ -# if SOLARIS && defined(KERNEL) - if (ip == (ip_t *)m->b_rptr) -# endif - { - register u_short bo; - - bo = ip->ip_len; - ip->ip_len = htons(bo); -# if !SOLARIS /* 4.4BSD converts this ip_input.c, but I don't in solaris.c */ - bo = ip->ip_id; - ip->ip_id = htons(bo); -# endif - bo = ip->ip_off; - ip->ip_off = htons(bo); - } -#endif -#if SOLARIS && defined(KERNEL) - m->b_rptr -= qif->qf_off; - fr_authpkts[i] = *(mblk_t **)fin->fin_mp; - fr_auth[i].fra_q = qif->qf_q; - cv_signal(&ipfauthwait); -#else - fr_authpkts[i] = m; -# if defined(linux) && defined(KERNEL) - wake_up_interruptible(&ipfauthwait); -# else - WAKEUP(&fr_authnext); -# endif -#endif - return 1; -} - - -int fr_auth_ioctl(data, cmd, fr, frptr) -caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif -frentry_t *fr, **frptr; -{ - mb_t *m; -#if defined(KERNEL) -# if !SOLARIS - struct ifqueue *ifq; - int s; -# endif -#endif - frauth_t auth, *au = &auth; - frauthent_t *fae, **faep; - int i, error = 0; - - switch (cmd) - { - case SIOCINIFR : - case SIOCRMIFR : - case SIOCADIFR : - error = EINVAL; - break; - case SIOCINAFR : - case SIOCRMAFR : - case SIOCADAFR : - for (faep = &fae_list; (fae = *faep); ) - if (&fae->fae_fr == fr) - break; - else - faep = &fae->fae_next; - if (cmd == SIOCRMAFR) { - if (!fae) - error = ESRCH; - else { - *faep = fae->fae_next; - *frptr = fr->fr_next; - KFREE(fae); - } - } else { - KMALLOC(fae, frauthent_t *, sizeof(*fae)); - if (fae != NULL) { - IRCOPY((char *)data, (char *)&fae->fae_fr, - sizeof(fae->fae_fr)); - if (!fae->fae_age) - fae->fae_age = fr_defaultauthage; - fae->fae_fr.fr_hits = 0; - fae->fae_fr.fr_next = *frptr; - *frptr = &fae->fae_fr; - fae->fae_next = *faep; - *faep = fae; - } else - error = ENOMEM; - } - break; - case SIOCATHST: - IWCOPY((char *)&fr_authstats, data, sizeof(fr_authstats)); - break; - case SIOCAUTHW: -fr_authioctlloop: - MUTEX_ENTER(&ipf_auth); - if ((fr_authnext != fr_authend) && fr_authpkts[fr_authnext]) { - IWCOPY((char *)&fr_auth[fr_authnext++], data, - sizeof(fr_info_t)); - if (fr_authnext == FR_NUMAUTH) - fr_authnext = 0; - MUTEX_EXIT(&ipf_auth); - return 0; - } -#ifdef KERNEL -# if SOLARIS - if (!cv_wait_sig(&ipfauthwait, &ipf_auth)) { - mutex_exit(&ipf_auth); - return EINTR; - } -# else -# ifdef linux - interruptible_sleep_on(&ipfauthwait); - if (current->signal & ~current->blocked) - error = -EINTR; -# else - error = SLEEP(&fr_authnext, "fr_authnext"); -# endif -# endif -#endif - MUTEX_EXIT(&ipf_auth); - if (!error) - goto fr_authioctlloop; - break; - case SIOCAUTHR: - IRCOPY(data, (caddr_t)&auth, sizeof(auth)); - MUTEX_ENTER(&ipf_auth); - i = au->fra_index; - if ((i < 0) || (i > FR_NUMAUTH) || - (fr_auth[i].fra_info.fin_id != au->fra_info.fin_id)) { - MUTEX_EXIT(&ipf_auth); - return EINVAL; - } - m = fr_authpkts[i]; - fr_auth[i].fra_index = -2; - fr_auth[i].fra_pass = au->fra_pass; - fr_authpkts[i] = NULL; -#ifdef KERNEL - MUTEX_EXIT(&ipf_auth); - SPL_NET(s); -# ifndef linux - if (m && au->fra_info.fin_out) { -# if SOLARIS - error = fr_qout(fr_auth[i].fra_q, m); -# else /* SOLARIS */ -#if IPSEC - m->m_pkthdr.rcvif = NULL; -#endif /*IPSEC*/ - - error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL); -# endif /* SOLARIS */ - if (error) - fr_authstats.fas_sendfail++; - else - fr_authstats.fas_sendok++; - } else if (m) { -# if SOLARIS - error = fr_qin(fr_auth[i].fra_q, m); -# else /* SOLARIS */ - ifq = &ipintrq; - if (IF_QFULL(ifq)) { - IF_DROP(ifq); - m_freem(m); - error = ENOBUFS; - } else { - IF_ENQUEUE(ifq, m); - schednetisr(NETISR_IP); - } -# endif /* SOLARIS */ - if (error) - fr_authstats.fas_quefail++; - else - fr_authstats.fas_queok++; - } else - error = EINVAL; -# endif -# if SOLARIS - if (error) - error = EINVAL; -# else - /* - * If we experience an error which will result in the packet - * not being processed, make sure we advance to the next one. - */ - if (error == ENOBUFS) { - fr_authused--; - fr_auth[i].fra_index = -1; - fr_auth[i].fra_pass = 0; - if (i == fr_authstart) { - while (fr_auth[i].fra_index == -1) { - i++; - if (i == FR_NUMAUTH) - i = 0; - fr_authstart = i; - if (i == fr_authend) - break; - } - if (fr_authstart == fr_authend) { - fr_authnext = 0; - fr_authstart = fr_authend = 0; - } - } - } -# endif - SPL_X(s); -#endif /* KERNEL */ - break; - default : - error = EINVAL; - break; - } - return error; -} - - -#ifdef KERNEL -/* - * Free all network buffer memory used to keep saved packets. - */ -void fr_authunload() -{ - register int i; - register frauthent_t *fae, **faep; - mb_t *m; - - MUTEX_ENTER(&ipf_auth); - for (i = 0; i < FR_NUMAUTH; i++) { - if ((m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - } - } - - - for (faep = &fae_list; (fae = *faep); ) { - *faep = fae->fae_next; - KFREE(fae); - } - MUTEX_EXIT(&ipf_auth); -} - - -/* - * Slowly expire held auth records. Timeouts are set - * in expectation of this being called twice per second. - */ -void fr_authexpire() -{ - register int i; - register frauth_t *fra; - register frauthent_t *fae, **faep; - mb_t *m; -#if !SOLARIS - int s; -#endif - - SPL_NET(s); - MUTEX_ENTER(&ipf_auth); - for (i = 0, fra = fr_auth; i < FR_NUMAUTH; i++, fra++) { - if ((!--fra->fra_age) && (m = fr_authpkts[i])) { - FREE_MB_T(m); - fr_authpkts[i] = NULL; - fr_auth[i].fra_index = -1; - fr_authstats.fas_expire++; - fr_authused--; - } - } - - for (faep = &fae_list; (fae = *faep); ) { - if (!--fra->fra_age) { - *faep = fae->fae_next; - KFREE(fae); - fr_authstats.fas_expire++; - } else - faep = &fae->fae_next; - } - MUTEX_EXIT(&ipf_auth); - SPL_X(s); -} -#endif diff --git a/bsd/netinet/ip_auth.h b/bsd/netinet/ip_auth.h deleted file mode 100644 index 0ea1e5c51..000000000 --- a/bsd/netinet/ip_auth.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1997 by Darren Reed & Guido Van Rooij. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - */ -#ifndef __IP_AUTH_H__ -#define __IP_AUTH_H__ - -#define FR_NUMAUTH 32 - -typedef struct fr_authstat { - U_QUAD_T fas_hits; - U_QUAD_T fas_miss; - u_long fas_nospace; - u_long fas_added; - u_long fas_sendfail; - u_long fas_sendok; - u_long fas_queok; - u_long fas_quefail; - u_long fas_expire; -} fr_authstat_t; - -typedef struct frauth { - int fra_age; - int fra_index; - u_32_t fra_pass; - fr_info_t fra_info; -#if SOLARIS - queue_t *fra_q; -#endif -} frauth_t; - -typedef struct frauthent { - struct frentry fae_fr; - struct frauthent *fae_next; - u_long fae_age; -} frauthent_t; - - -extern frentry_t *ipauth; -extern struct fr_authstat fr_authstats; -extern int fr_defaultauthage; -extern int fr_authstart; -extern int fr_authend; -extern int fr_authsize; -extern int fr_authused; -extern int fr_checkauth __P((ip_t *, fr_info_t *)); -extern void fr_authexpire __P((void)); -extern void fr_authunload __P((void)); -extern mb_t *fr_authpkts[]; -#if defined(_KERNEL) && SOLARIS -extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *, qif_t *)); -#else -extern int fr_newauth __P((mb_t *, fr_info_t *, ip_t *)); -#endif -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -extern int fr_auth_ioctl __P((caddr_t, u_long, frentry_t *, frentry_t **)); -#else -extern int fr_auth_ioctl __P((caddr_t, int, frentry_t *, frentry_t **)); -#endif -#endif /* __IP_AUTH_H__ */ diff --git a/bsd/netinet/ip_compat.h b/bsd/netinet/ip_compat.h index 115773c62..b6549bfc7 100644 --- a/bsd/netinet/ip_compat.h +++ b/bsd/netinet/ip_compat.h @@ -70,21 +70,6 @@ struct ether_addr { u_char ether_addr_octet[6]; }; - -#if defined(__sgi) && !defined(IPFILTER_LKM) -# ifdef __STDC__ -# define IPL_EXTERN(ep) ipfilter##ep -# else -# define IPL_EXTERN(ep) ipfilter/**/ep -# endif -#else -# ifdef __STDC__ -# define IPL_EXTERN(ep) ipl##ep -# else -# define IPL_EXTERN(ep) ipl/**/ep -# endif -#endif - #ifdef linux # include <sys/sysmacros.h> #endif @@ -211,9 +196,6 @@ typedef unsigned long u_32_t; # if __FreeBSD__ < 3 # include <machine/spl.h> # endif -# if defined(IPFILTER_LKM) && !defined(ACTUALLY_LKM_NOT_KERNEL) -# define ACTUALLY_LKM_NOT_KERNEL -# endif #endif /* __FreeBSD__ && KERNEL */ /* diff --git a/bsd/netinet/ip_dummynet.c b/bsd/netinet/ip_dummynet.c index 4788dc56a..61cc6f414 100644 --- a/bsd/netinet/ip_dummynet.c +++ b/bsd/netinet/ip_dummynet.c @@ -336,7 +336,7 @@ dummynet_io(int pipe_nr, int dir, (pipe->queue_size_bytes && ip->ip_len + pipe->r_len_bytes > pipe->queue_size_bytes) || (pkt = (struct dn_pkt *) _MALLOC(sizeof (*pkt), - M_IPFW, M_NOWAIT) ) == NULL ) { + M_IPFW, M_WAITOK) ) == NULL ) { splx(s); if (dn_debug) printf("-- dummynet: drop from pipe %d, have %d pks, %d bytes\n", @@ -552,7 +552,7 @@ ip_dn_ctl(struct sockopt *sopt) b->plr = p->plr ; } else { int s ; - x = _MALLOC(sizeof(struct dn_pipe), M_IPFW, M_DONTWAIT) ; + x = _MALLOC(sizeof(struct dn_pipe), M_IPFW, M_NOWAIT) ; if (x == NULL) { printf("ip_dummynet.c: sorry no memory\n"); error = ENOSPC ; diff --git a/bsd/netinet/ip_fil.h b/bsd/netinet/ip_fil.h deleted file mode 100644 index e847d070e..000000000 --- a/bsd/netinet/ip_fil.h +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1993-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_fil.h 1.35 6/5/96 - * $Id: ip_fil.h,v 1.3 2000/11/22 01:12:12 zarzycki Exp $ - */ - -#ifndef __IP_FIL_H__ -#define __IP_FIL_H__ - -/* - * Pathnames for various IP Filter control devices. Used by LKM - * and userland, so defined here. - */ -#define IPNAT_NAME "/dev/ipnat" -#define IPSTATE_NAME "/dev/ipstate" -#define IPAUTH_NAME "/dev/ipauth" - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#if defined(KERNEL) && !defined(_KERNEL) -#define _KERNEL -#endif - -#ifndef __P -# if __STDC__ -# define __P(x) x -# else -# define __P(x) () -# endif -#endif - -#if defined(__STDC__) || defined(__GNUC__) -#define SIOCADAFR _IOW('r', 60, struct frentry) -#define SIOCRMAFR _IOW('r', 61, struct frentry) -#define SIOCSETFF _IOW('r', 62, u_int) -#define SIOCGETFF _IOR('r', 63, u_int) -#define SIOCGETFS _IOR('r', 64, struct friostat) -#define SIOCIPFFL _IOWR('r', 65, int) -#define SIOCIPFFB _IOR('r', 66, int) -#define SIOCADIFR _IOW('r', 67, struct frentry) -#define SIOCRMIFR _IOW('r', 68, struct frentry) -#define SIOCSWAPA _IOR('r', 69, u_int) -#define SIOCINAFR _IOW('r', 70, struct frentry) -#define SIOCINIFR _IOW('r', 71, struct frentry) -#define SIOCFRENB _IOW('r', 72, u_int) -#define SIOCFRSYN _IOW('r', 73, u_int) -#define SIOCFRZST _IOWR('r', 74, struct friostat) -#define SIOCZRLST _IOWR('r', 75, struct frentry) -#define SIOCAUTHW _IOWR('r', 76, struct fr_info) -#define SIOCAUTHR _IOWR('r', 77, struct fr_info) -#define SIOCATHST _IOWR('r', 78, struct fr_authstat) -#else -#define SIOCADAFR _IOW(r, 60, struct frentry) -#define SIOCRMAFR _IOW(r, 61, struct frentry) -#define SIOCSETFF _IOW(r, 62, u_int) -#define SIOCGETFF _IOR(r, 63, u_int) -#define SIOCGETFS _IOR(r, 64, struct friostat) -#define SIOCIPFFL _IOWR(r, 65, int) -#define SIOCIPFFB _IOR(r, 66, int) -#define SIOCADIFR _IOW(r, 67, struct frentry) -#define SIOCRMIFR _IOW(r, 68, struct frentry) -#define SIOCSWAPA _IOR(r, 69, u_int) -#define SIOCINAFR _IOW(r, 70, struct frentry) -#define SIOCINIFR _IOW(r, 71, struct frentry) -#define SIOCFRENB _IOW(r, 72, u_int) -#define SIOCFRSYN _IOW(r, 73, u_int) -#define SIOCFRZST _IOWR(r, 74, struct friostat) -#define SIOCZRLST _IOWR(r, 75, struct frentry) -#define SIOCAUTHW _IOWR(r, 76, struct fr_info) -#define SIOCAUTHR _IOWR(r, 77, struct fr_info) -#define SIOCATHST _IOWR(r, 78, struct fr_authstat) -#endif -#define SIOCADDFR SIOCADAFR -#define SIOCDELFR SIOCRMAFR -#define SIOCINSFR SIOCINAFR - -typedef struct fr_ip { - u_int fi_v:4; /* IP version */ - u_int fi_fl:4; /* packet flags */ - u_char fi_tos; - u_char fi_ttl; - u_char fi_p; - struct in_addr fi_src; - struct in_addr fi_dst; - u_32_t fi_optmsk; /* bitmask composed from IP options */ - u_short fi_secmsk; /* bitmask composed from IP security options */ - u_short fi_auth; -} fr_ip_t; - -#define FI_OPTIONS (FF_OPTIONS >> 24) -#define FI_TCPUDP (FF_TCPUDP >> 24) /* TCP/UCP implied comparison*/ -#define FI_FRAG (FF_FRAG >> 24) -#define FI_SHORT (FF_SHORT >> 24) - -typedef struct fr_info { - struct fr_ip fin_fi; - u_short fin_data[2]; - u_short fin_out; - u_short fin_hlen; - u_char fin_tcpf; - u_char fin_icode; /* From here on is packet specific */ - u_short fin_rule; - u_short fin_group; - u_short fin_dlen; - u_short fin_id; - void *fin_ifp; - struct frentry *fin_fr; - char *fin_dp; /* start of data past IP header */ - void *fin_mp; -} fr_info_t; - -/* - * Size for compares on fr_info structures - */ -#define FI_CSIZE (sizeof(struct fr_ip) + sizeof(u_short) * 4 + \ - sizeof(u_char)) -/* - * Size for copying cache fr_info structure - */ -#define FI_COPYSIZE (sizeof(fr_info_t) - sizeof(void *) * 2) - -typedef struct frdest { - void *fd_ifp; - struct in_addr fd_ip; - char fd_ifname[IFNAMSIZ]; -} frdest_t; - -typedef struct frentry { - struct frentry *fr_next; - u_short fr_group; /* group to which this rule belongs */ - u_short fr_grhead; /* group # which this rule starts */ - struct frentry *fr_grp; - int fr_ref; /* reference count - for grouping */ - void *fr_ifa; - /* - * These are only incremented when a packet matches this rule and - * it is the last match - */ - U_QUAD_T fr_hits; - U_QUAD_T fr_bytes; - /* - * Fields after this may not change whilst in the kernel. - */ - struct fr_ip fr_ip; - struct fr_ip fr_mip; /* mask structure */ - - u_char fr_tcpfm; /* tcp flags mask */ - u_char fr_tcpf; /* tcp flags */ - - u_short fr_icmpm; /* data for ICMP packets (mask) */ - u_short fr_icmp; - - u_char fr_scmp; /* data for port comparisons */ - u_char fr_dcmp; - u_short fr_dport; - u_short fr_sport; - u_short fr_stop; /* top port for <> and >< */ - u_short fr_dtop; /* top port for <> and >< */ - u_32_t fr_flags; /* per-rule flags && options (see below) */ - int fr_skip; /* # of rules to skip */ - int (*fr_func) __P((int, ip_t *, fr_info_t *)); /* call this function */ - char fr_icode; /* return ICMP code */ - char fr_ifname[IFNAMSIZ]; - struct frdest fr_tif; /* "to" interface */ - struct frdest fr_dif; /* duplicate packet interfaces */ -} frentry_t; - -#define fr_proto fr_ip.fi_p -#define fr_ttl fr_ip.fi_ttl -#define fr_tos fr_ip.fi_tos -#define fr_dst fr_ip.fi_dst -#define fr_src fr_ip.fi_src -#define fr_dmsk fr_mip.fi_dst -#define fr_smsk fr_mip.fi_src - -#ifndef offsetof -#define offsetof(t,m) (int)((&((t *)0L)->m)) -#endif -#define FR_CMPSIZ (sizeof(struct frentry) - offsetof(frentry_t, fr_ip)) - -/* - * fr_flags - */ -#define FR_BLOCK 0x00001 /* do not allow packet to pass */ -#define FR_PASS 0x00002 /* allow packet to pass */ -#define FR_OUTQUE 0x00004 /* outgoing packets */ -#define FR_INQUE 0x00008 /* ingoing packets */ -#define FR_LOG 0x00010 /* Log */ -#define FR_LOGB 0x00011 /* Log-fail */ -#define FR_LOGP 0x00012 /* Log-pass */ -#define FR_LOGBODY 0x00020 /* Log the body */ -#define FR_LOGFIRST 0x00040 /* Log the first byte if state held */ -#define FR_RETRST 0x00080 /* Return TCP RST packet - reset connection */ -#define FR_RETICMP 0x00100 /* Return ICMP unreachable packet */ -#define FR_NOMATCH 0x00200 /* no match occured */ -#define FR_ACCOUNT 0x00400 /* count packet bytes */ -#define FR_KEEPFRAG 0x00800 /* keep fragment information */ -#define FR_KEEPSTATE 0x01000 /* keep `connection' state information */ -#define FR_INACTIVE 0x02000 -#define FR_QUICK 0x04000 /* match & stop processing list */ -#define FR_FASTROUTE 0x08000 /* bypass normal routing */ -#define FR_CALLNOW 0x10000 /* call another function (fr_func) if matches */ -#define FR_DUP 0x20000 /* duplicate packet */ -#define FR_LOGORBLOCK 0x40000 /* block the packet if it can't be logged */ -#define FR_NOTSRCIP 0x80000 /* not the src IP# */ -#define FR_NOTDSTIP 0x100000 /* not the dst IP# */ -#define FR_AUTH 0x200000 /* use authentication */ -#define FR_PREAUTH 0x400000 /* require preauthentication */ - -#define FR_LOGMASK (FR_LOG|FR_LOGP|FR_LOGB) - -/* - * These correspond to #define's for FI_* and are stored in fr_flags - */ -#define FF_OPTIONS 0x01000000 -#define FF_TCPUDP 0x02000000 -#define FF_FRAG 0x04000000 -#define FF_SHORT 0x08000000 -/* - * recognized flags for SIOCGETFF and SIOCSETFF, and get put in fr_flags - */ -#define FF_LOGPASS 0x10000000 -#define FF_LOGBLOCK 0x20000000 -#define FF_LOGNOMATCH 0x40000000 -#define FF_LOGGING (FF_LOGPASS|FF_LOGBLOCK|FF_LOGNOMATCH) -#define FF_BLOCKNONIP 0x80000000 /* Solaris2 Only */ - -#define FR_NONE 0 -#define FR_EQUAL 1 -#define FR_NEQUAL 2 -#define FR_LESST 3 -#define FR_GREATERT 4 -#define FR_LESSTE 5 -#define FR_GREATERTE 6 -#define FR_OUTRANGE 7 -#define FR_INRANGE 8 - -typedef struct filterstats { - u_long fr_pass; /* packets allowed */ - u_long fr_block; /* packets denied */ - u_long fr_nom; /* packets which don't match any rule */ - u_long fr_ppkl; /* packets allowed and logged */ - u_long fr_bpkl; /* packets denied and logged */ - u_long fr_npkl; /* packets unmatched and logged */ - u_long fr_pkl; /* packets logged */ - u_long fr_skip; /* packets to be logged but buffer full */ - u_long fr_ret; /* packets for which a return is sent */ - u_long fr_acct; /* packets for which counting was performed */ - u_long fr_bnfr; /* bad attempts to allocate fragment state */ - u_long fr_nfr; /* new fragment state kept */ - u_long fr_cfr; /* add new fragment state but complete pkt */ - u_long fr_bads; /* bad attempts to allocate packet state */ - u_long fr_ads; /* new packet state kept */ - u_long fr_chit; /* cached hit */ - u_long fr_tcpbad; /* TCP checksum check failures */ - u_long fr_pull[2]; /* good and bad pullup attempts */ -#if SOLARIS - u_long fr_bad; /* bad IP packets to the filter */ - u_long fr_notip; /* packets passed through no on ip queue */ - u_long fr_drop; /* packets dropped - no info for them! */ -#endif -} filterstats_t; - -/* - * For SIOCGETFS - */ -typedef struct friostat { - struct filterstats f_st[2]; - struct frentry *f_fin[2]; - struct frentry *f_fout[2]; - struct frentry *f_acctin[2]; - struct frentry *f_acctout[2]; - struct frentry *f_auth; - u_long f_froute[2]; - int f_active; -} friostat_t; - -typedef struct optlist { - u_short ol_val; - int ol_bit; -} optlist_t; - - -/* - * Group list structure. - */ -typedef struct frgroup { - u_short fg_num; - struct frgroup *fg_next; - struct frentry *fg_head; - struct frentry **fg_start; -} frgroup_t; - - -/* - * Log structure. Each packet header logged is prepended by one of these. - * Following this in the log records read from the device will be an ipflog - * structure which is then followed by any packet data. - */ -typedef struct iplog { - u_long ipl_magic; - u_long ipl_sec; - u_long ipl_usec; - u_int ipl_len; - u_int ipl_count; - size_t ipl_dsize; - struct iplog *ipl_next; -} iplog_t; - -#define IPL_MAGIC 0x49504c4d /* 'IPLM' */ - -typedef struct ipflog { -#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - u_char fl_ifname[IFNAMSIZ]; -#else - u_int fl_unit; - u_char fl_ifname[4]; -#endif - u_char fl_plen; /* extra data after hlen */ - u_char fl_hlen; /* length of IP headers saved */ - u_short fl_rule; /* assume never more than 64k rules, total */ - u_short fl_group; - u_32_t fl_flags; -} ipflog_t; - - -#ifndef ICMP_UNREACH_FILTER -#define ICMP_UNREACH_FILTER 13 -#endif - -#ifndef IPF_LOGGING -#define IPF_LOGGING 0 -#endif -#ifndef IPF_DEFAULT_PASS -#define IPF_DEFAULT_PASS FR_PASS -#endif - -#define IPMINLEN(i, h) ((i)->ip_len >= ((i)->ip_hl * 4 + sizeof(struct h))) -#define IPLLOGSIZE 8192 - -/* - * Device filenames for reading log information. Use ipf on Solaris2 because - * ipl is already a name used by something else. - */ -#ifndef IPL_NAME -# if SOLARIS -# define IPL_NAME "/dev/ipf" -# else -# define IPL_NAME "/dev/ipl" -# endif -#endif -#define IPL_NAT IPNAT_NAME -#define IPL_STATE IPSTATE_NAME -#define IPL_AUTH IPAUTH_NAME - -#define IPL_LOGIPF 0 /* Minor device #'s for accessing logs */ -#define IPL_LOGNAT 1 -#define IPL_LOGSTATE 2 -#define IPL_LOGAUTH 3 -#define IPL_LOGMAX 3 - -#if !defined(CDEV_MAJOR) && defined (__FreeBSD_version) && \ - (__FreeBSD_version >= 220000) -# define CDEV_MAJOR 79 -#endif - -#ifndef _KERNEL -struct ifnet; -extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -extern int send_reset __P((ip_t *, struct ifnet *)); -extern int icmp_error __P((ip_t *, struct ifnet *)); -extern int ipf_log __P((void)); -extern void ipfr_fastroute __P((ip_t *, fr_info_t *, frdest_t *)); -extern struct ifnet *get_unit __P((char *)); -# define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m) -# if defined(__NetBSD__) || defined(__OpenBSD__) || \ - (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300003) -extern int iplioctl __P((dev_t, u_long, caddr_t, int)); -# else -extern int iplioctl __P((dev_t, int, caddr_t, int)); -# endif -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); -#else /* #ifndef _KERNEL */ -# if defined(__NetBSD__) && defined(PFIL_HOOKS) -extern int ipfilterattach __P((int)); -# endif -extern int iplattach __P((void)); -extern int ipl_enable __P((void)); -extern int ipl_disable __P((void)); -extern void ipflog_init __P((void)); -extern int ipflog_clear __P((int)); -extern int ipflog_read __P((int, struct uio *)); -extern int ipflog __P((u_int, ip_t *, fr_info_t *, mb_t *)); -extern int ipllog __P((int, u_long, void **, size_t *, int *, int)); -# if SOLARIS -extern int fr_check __P((ip_t *, int, void *, int, qif_t *, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, - int, qif_t *, mb_t **)); -extern int icmp_error __P((ip_t *, int, int, qif_t *, - struct in_addr)); -extern int iplioctl __P((dev_t, int, int, int, cred_t *, int *)); -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int ipfsync __P((void)); -extern int send_reset __P((ip_t *, qif_t *)); -extern int ipfr_fastroute __P((qif_t *, ip_t *, mblk_t *, mblk_t **, - fr_info_t *, frdest_t *)); -extern void copyin_mblk __P((mblk_t *, int, int, char *)); -extern void copyout_mblk __P((mblk_t *, int, int, char *)); -extern int fr_qin __P((queue_t *, mblk_t *)); -extern int fr_qout __P((queue_t *, mblk_t *)); -# if IPFILTER_LOG -extern int iplread __P((dev_t, struct uio *, cred_t *)); -# endif -# else /* SOLARIS */ -extern int fr_check __P((ip_t *, int, void *, int, mb_t **)); -extern int (*fr_checkp) __P((ip_t *, int, void *, int, mb_t **)); -# if linux -extern int send_reset __P((tcpiphdr_t *, struct ifnet *)); -# else -extern int send_reset __P((tcpiphdr_t *)); -# endif -extern void ipfr_fastroute __P((mb_t *, fr_info_t *, frdest_t *)); -extern size_t mbufchainlen __P((mb_t *)); -# if __sgi -# include <sys/cred.h> -extern int iplioctl __P((dev_t, int, caddr_t, int, cred_t *, int *)); -extern int iplopen __P((dev_t *, int, int, cred_t *)); -extern int iplclose __P((dev_t, int, int, cred_t *)); -extern int iplread __P((dev_t, struct uio *, cred_t *)); -extern int ipfsync __P((void)); -extern int ipfilter_sgi_attach __P((void)); -extern void ipfilter_sgi_detach __P((void)); -extern void ipfilter_sgi_intfsync __P((void)); -# else -# if IPFILTER_LKM -extern int iplidentify __P((char *)); -# endif -# if (_BSDI_VERSION >= 199510) || (__FreeBSD_version >= 220000) || \ - (NetBSD >= 199511) -# if defined(__NetBSD__) || (_BSDI_VERSION >= 199701) || \ - (__FreeBSD_version >= 300003) -extern int iplioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); -# else -extern int iplioctl __P((dev_t, int, caddr_t, int, struct proc *)); -# endif -extern int iplopen __P((dev_t, int, int, struct proc *)); -extern int iplclose __P((dev_t, int, int, struct proc *)); -# else -# if defined(__OpenBSD__) -extern int iplioctl __P((dev_t, u_long, caddr_t, int)); -# else /* __OpenBSD__ */ -# ifndef linux -extern int iplioctl __P((dev_t, int, caddr_t, int)); -# else -extern int iplioctl(struct inode *, struct file *, u_int, u_long); -# endif -# endif /* __OpenBSD__ */ -# ifndef linux -extern int iplopen __P((dev_t, int)); -extern int iplclose __P((dev_t, int)); -# else -extern int iplopen __P((struct inode *, struct file *)); -extern void iplclose __P((struct inode *, struct file *)); -# endif /* !linux */ -# endif /* (_BSDI_VERSION >= 199510) */ -# if BSD >= 199306 -extern int iplread __P((dev_t, struct uio *, int)); -# else -# ifndef linux -extern int iplread __P((dev_t, struct uio *)); -# else -extern int iplread(struct inode *, struct file *, char *, int); -# endif /* !linux */ -# endif /* BSD >= 199306 */ -# endif /* __ sgi */ -# endif /* SOLARIS */ -#endif /* #ifndef _KERNEL */ - -/* - * Post NetBSD 1.2 has the PFIL interface for packet filters. This turns - * on those hooks. We don't need any special mods in non-IP Filter code - * with this! - */ -#if (defined(NetBSD) && (NetBSD > 199609) && (NetBSD <= 1991011)) || \ - (defined(NetBSD1_2) && NetBSD1_2 > 1) -# define NETBSD_PF -#endif - -extern int ipldetach __P((void)); -extern u_short fr_tcpsum __P((mb_t *, ip_t *, tcphdr_t *, int)); -#define FR_SCANLIST(p, ip, fi, m) fr_scanlist(p, ip, fi, m) -extern int fr_scanlist __P((int, ip_t *, fr_info_t *, void *)); -extern u_short ipf_cksum __P((u_short *, int)); -extern int fr_copytolog __P((int, char *, int)); -extern void frflush __P((int, int *)); -extern frgroup_t *fr_addgroup __P((u_short, frentry_t *, int, int)); -extern frgroup_t *fr_findgroup __P((u_short, u_32_t, int, int, frgroup_t ***)); -extern void fr_delgroup __P((u_short, u_32_t, int, int)); -extern int ipl_unreach; -extern int ipl_inited; -extern u_long ipl_frouteok[2]; -extern int fr_pass; -extern int fr_flags; -extern int fr_active; -extern fr_info_t frcache[2]; -#if IPFILTER_LOG -extern iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -extern int iplused[IPL_LOGMAX + 1]; -#endif -extern struct frentry *ipfilter[2][2], *ipacct[2][2]; -extern struct frgroup *ipfgroups[3][2]; -extern struct filterstats frstats[]; - -#endif /* __IP_FIL_H__ */ diff --git a/bsd/netinet/ip_frag.c b/bsd/netinet/ip_frag.c deleted file mode 100644 index ddb4f1ab4..000000000 --- a/bsd/netinet/ip_frag.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1993-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -/* static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed"; */ -#endif - - -#if !defined(KERNEL) -# include <string.h> -# include <stdlib.h> -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if defined(KERNEL) -#include <sys/filio.h> -#include <sys/fcntl.h> -#include <sys/malloc.h> -#else -#include <sys/ioctl.h> -#endif -#include <sys/uio.h> -#ifndef linux -#include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(KERNEL) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if defined(KERNEL) -#include <sys/malloc.h> -#endif - -#include <net/if.h> -#ifdef sun -#include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -#include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#include "netinet/ip_auth.h" - -static ipfr_t *ipfr_heads[IPFT_SIZE]; -static ipfr_t *ipfr_nattab[IPFT_SIZE]; -static ipfrstat_t ipfr_stats; -static int ipfr_inuse = 0; - int fr_ipfrttl = 120; /* 60 seconds */ -#ifdef KERNEL -extern int ipfr_timer_id; -#endif -#if (SOLARIS || defined(__sgi)) && defined(KERNEL) -extern kmutex_t ipf_frag; -extern kmutex_t ipf_natfrag; -extern kmutex_t ipf_nat; -#endif - - -static ipfr_t *ipfr_new __P((ip_t *, fr_info_t *, int, ipfr_t **)); -static ipfr_t *ipfr_lookup __P((ip_t *, fr_info_t *, ipfr_t **)); - - -ipfrstat_t *ipfr_fragstats() -{ - ipfr_stats.ifs_table = ipfr_heads; - ipfr_stats.ifs_nattab = ipfr_nattab; - ipfr_stats.ifs_inuse = ipfr_inuse; - return &ipfr_stats; -} - - -/* - * add a new entry to the fragment cache, registering it as having come - * through this box, with the result of the filter operation. - */ -static ipfr_t *ipfr_new(ip, fin, pass, table) -ip_t *ip; -fr_info_t *fin; -int pass; -ipfr_t *table[]; -{ - ipfr_t **fp, *fr, frag; - u_int idx; - - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; - idx *= 127; - idx %= IPFT_SIZE; - - /* - * first, make sure it isn't already there... - */ - for (fp = &table[idx]; (fr = *fp); fp = &fr->ipfr_next) - if (!bcmp((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, - IPFR_CMPSZ)) { - ipfr_stats.ifs_exists++; - return NULL; - } - - /* - * allocate some memory, if possible, if not, just record that we - * failed to do so. - */ - KMALLOC(fr, ipfr_t *, sizeof(*fr)); - if (fr == NULL) { - ipfr_stats.ifs_nomem++; - return NULL; - } - - /* - * Instert the fragment into the fragment table, copy the struct used - * in the search using bcopy rather than reassign each field. - * Set the ttl to the default and mask out logging from "pass" - */ - if ((fr->ipfr_next = table[idx])) - table[idx]->ipfr_prev = fr; - fr->ipfr_prev = NULL; - fr->ipfr_data = NULL; - table[idx] = fr; - bcopy((char *)&frag.ipfr_src, (char *)&fr->ipfr_src, IPFR_CMPSZ); - fr->ipfr_ttl = fr_ipfrttl; - fr->ipfr_pass = pass & ~(FR_LOGFIRST|FR_LOG); - /* - * Compute the offset of the expected start of the next packet. - */ - fr->ipfr_off = (ip->ip_off & 0x1fff) + (fin->fin_dlen >> 3); - ipfr_stats.ifs_new++; - ipfr_inuse++; - return fr; -} - - -int ipfr_newfrag(ip, fin, pass) -ip_t *ip; -fr_info_t *fin; -int pass; -{ - ipfr_t *ipf; - - MUTEX_ENTER(&ipf_frag); - ipf = ipfr_new(ip, fin, pass, ipfr_heads); - MUTEX_EXIT(&ipf_frag); - return ipf ? 0 : -1; -} - - -int ipfr_nat_newfrag(ip, fin, pass, nat) -ip_t *ip; -fr_info_t *fin; -int pass; -nat_t *nat; -{ - ipfr_t *ipf; - - MUTEX_ENTER(&ipf_natfrag); - if ((ipf = ipfr_new(ip, fin, pass, ipfr_nattab))) { - ipf->ipfr_data = nat; - nat->nat_data = ipf; - } - MUTEX_EXIT(&ipf_natfrag); - return ipf ? 0 : -1; -} - - -/* - * check the fragment cache to see if there is already a record of this packet - * with its filter result known. - */ -static ipfr_t *ipfr_lookup(ip, fin, table) -ip_t *ip; -fr_info_t *fin; -ipfr_t *table[]; -{ - ipfr_t *f, frag; - u_int idx; - - /* - * For fragments, we record protocol, packet id, TOS and both IP#'s - * (these should all be the same for all fragments of a packet). - * - * build up a hash value to index the table with. - */ - frag.ipfr_p = ip->ip_p; - idx = ip->ip_p; - frag.ipfr_id = ip->ip_id; - idx += ip->ip_id; - frag.ipfr_tos = ip->ip_tos; - frag.ipfr_src.s_addr = ip->ip_src.s_addr; - idx += ip->ip_src.s_addr; - frag.ipfr_dst.s_addr = ip->ip_dst.s_addr; - idx += ip->ip_dst.s_addr; - idx *= 127; - idx %= IPFT_SIZE; - - /* - * check the table, careful to only compare the right amount of data - */ - for (f = table[idx]; f; f = f->ipfr_next) - if (!bcmp((char *)&frag.ipfr_src, (char *)&f->ipfr_src, - IPFR_CMPSZ)) { - u_short atoff, off; - - if (f != table[idx]) { - /* - * move fragment info. to the top of the list - * to speed up searches. - */ - if ((f->ipfr_prev->ipfr_next = f->ipfr_next)) - f->ipfr_next->ipfr_prev = f->ipfr_prev; - f->ipfr_next = table[idx]; - table[idx]->ipfr_prev = f; - f->ipfr_prev = NULL; - table[idx] = f; - } - off = ip->ip_off; - atoff = off + (fin->fin_dlen >> 3); - /* - * If we've follwed the fragments, and this is the - * last (in order), shrink expiration time. - */ - if ((off & 0x1fff) == f->ipfr_off) { - if (!(off & IP_MF)) - f->ipfr_ttl = 1; - else - f->ipfr_off = atoff; - } - ipfr_stats.ifs_hits++; - return f; - } - return NULL; -} - - -/* - * functional interface for NAT lookups of the NAT fragment cache - */ -nat_t *ipfr_nat_knownfrag(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - nat_t *nat; - ipfr_t *ipf; - - MUTEX_ENTER(&ipf_natfrag); - ipf = ipfr_lookup(ip, fin, ipfr_nattab); - if (ipf) { - nat = ipf->ipfr_data; - /* - * This is the last fragment for this packet. - */ - if (ipf->ipfr_ttl == 1) { - nat->nat_data = NULL; - ipf->ipfr_data = NULL; - } - } else - nat = NULL; - MUTEX_EXIT(&ipf_natfrag); - return nat; -} - - -/* - * functional interface for normal lookups of the fragment cache - */ -int ipfr_knownfrag(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - int ret; - ipfr_t *ipf; - - MUTEX_ENTER(&ipf_frag); - ipf = ipfr_lookup(ip, fin, ipfr_heads); - ret = ipf ? ipf->ipfr_pass : 0; - MUTEX_EXIT(&ipf_frag); - return ret; -} - - -/* - * forget any references to this external object. - */ -void ipfr_forget(nat) -void *nat; -{ - ipfr_t *fr; - int idx; - - MUTEX_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fr = ipfr_heads[idx]; fr; fr = fr->ipfr_next) - if (fr->ipfr_data == nat) - fr->ipfr_data = NULL; - - MUTEX_EXIT(&ipf_natfrag); -} - - -/* - * Free memory in use by fragment state info. kept. - */ -void ipfr_unload() -{ - ipfr_t **fp, *fr; - nat_t *nat; - int idx; - - MUTEX_ENTER(&ipf_frag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fr = *fp); ) { - *fp = fr->ipfr_next; - KFREE(fr); - } - MUTEX_EXIT(&ipf_frag); - - MUTEX_ENTER(&ipf_nat); - MUTEX_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fr = *fp); ) { - *fp = fr->ipfr_next; - if ((nat = (nat_t *)fr->ipfr_data)) { - if (nat->nat_data == fr) - nat->nat_data = NULL; - } - KFREE(fr); - } - MUTEX_EXIT(&ipf_natfrag); - MUTEX_EXIT(&ipf_nat); -} - - -#ifdef KERNEL -/* - * Slowly expire held state for fragments. Timeouts are set * in expectation - * of this being called twice per second. - */ -# if (BSD >= 199306) || SOLARIS || defined(__sgi) -void ipfr_slowtimer() -# else -int ipfr_slowtimer() -# endif -{ - ipfr_t **fp, *fr; - nat_t *nat; - int s, idx; - boolean_t funnel_state; - - funnel_state = thread_funnel_set(network_flock, TRUE); -#ifdef __sgi - ipfilter_sgi_intfsync(); -#endif - - SPL_NET(s); - MUTEX_ENTER(&ipf_frag); - - /* - * Go through the entire table, looking for entries to expire, - * decreasing the ttl by one for each entry. If it reaches 0, - * remove it from the chain and free it. - */ - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_heads[idx]; (fr = *fp); ) { - --fr->ipfr_ttl; - if (fr->ipfr_ttl == 0) { - if (fr->ipfr_prev) - fr->ipfr_prev->ipfr_next = - fr->ipfr_next; - if (fr->ipfr_next) - fr->ipfr_next->ipfr_prev = - fr->ipfr_prev; - *fp = fr->ipfr_next; - ipfr_stats.ifs_expire++; - ipfr_inuse--; - KFREE(fr); - } else - fp = &fr->ipfr_next; - } - MUTEX_EXIT(&ipf_frag); - - /* - * Same again for the NAT table, except that if the structure also - * still points to a NAT structure, and the NAT structure points back - * at the one to be free'd, NULL the reference from the NAT struct. - * NOTE: We need to grab both mutex's early, and in this order so as - * to prevent a deadlock if both try to expire at the same time. - */ - MUTEX_ENTER(&ipf_nat); - MUTEX_ENTER(&ipf_natfrag); - for (idx = IPFT_SIZE - 1; idx >= 0; idx--) - for (fp = &ipfr_nattab[idx]; (fr = *fp); ) { - --fr->ipfr_ttl; - if (fr->ipfr_ttl == 0) { - if (fr->ipfr_prev) - fr->ipfr_prev->ipfr_next = - fr->ipfr_next; - if (fr->ipfr_next) - fr->ipfr_next->ipfr_prev = - fr->ipfr_prev; - *fp = fr->ipfr_next; - ipfr_stats.ifs_expire++; - ipfr_inuse--; - if ((nat = (nat_t *)fr->ipfr_data)) { - if (nat->nat_data == fr) - nat->nat_data = NULL; - } - KFREE(fr); - } else - fp = &fr->ipfr_next; - } - MUTEX_EXIT(&ipf_natfrag); - MUTEX_EXIT(&ipf_nat); - SPL_X(s); - fr_timeoutstate(); - ip_natexpire(); - fr_authexpire(); -# if SOLARIS - ipfr_timer_id = timeout(ipfr_slowtimer, NULL, drv_usectohz(500000)); -# else -# ifndef linux - ip_slowtimo(); -# endif -# if (BSD < 199306) && !defined(__sgi) - (void) thread_funnel_set(network_flock, FALSE); - return 0; -# endif -# endif - (void) thread_funnel_set(network_flock, FALSE); -} -#endif /* defined(KERNEL) */ diff --git a/bsd/netinet/ip_frag.h b/bsd/netinet/ip_frag.h deleted file mode 100644 index faff6d5d1..000000000 --- a/bsd/netinet/ip_frag.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1993-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_frag.h 1.5 3/24/96 - */ - -#ifndef __IP_FRAG_H__ -#define __IP_FRAG_H__ - -#define IPFT_SIZE 257 - -typedef struct ipfr { - struct ipfr *ipfr_next, *ipfr_prev; - void *ipfr_data; - struct in_addr ipfr_src; - struct in_addr ipfr_dst; - u_short ipfr_id; - u_char ipfr_p; - u_char ipfr_tos; - u_short ipfr_off; - u_short ipfr_ttl; - u_char ipfr_pass; -} ipfr_t; - - -typedef struct ipfrstat { - u_long ifs_exists; /* add & already exists */ - u_long ifs_nomem; - u_long ifs_new; - u_long ifs_hits; - u_long ifs_expire; - u_long ifs_inuse; - struct ipfr **ifs_table; - struct ipfr **ifs_nattab; -} ipfrstat_t; - -#define IPFR_CMPSZ (4 + 4 + 2 + 1 + 1) - -extern int fr_ipfrttl; -extern ipfrstat_t *ipfr_fragstats __P((void)); -extern int ipfr_newfrag __P((ip_t *, fr_info_t *, int)); -extern int ipfr_nat_newfrag __P((ip_t *, fr_info_t *, int, struct nat *)); -extern nat_t *ipfr_nat_knownfrag __P((ip_t *, fr_info_t *)); -extern int ipfr_knownfrag __P((ip_t *, fr_info_t *)); -extern void ipfr_forget __P((void *)); -extern void ipfr_unload __P((void)); - -#if (BSD >= 199306) || SOLARIS || defined(__sgi) -extern void ipfr_slowtimer __P((void)); -#else -extern int ipfr_slowtimer __P((void)); -#endif - -#endif /* __IP_FIL_H__ */ diff --git a/bsd/netinet/ip_fw.c b/bsd/netinet/ip_fw.c index 8705c5bab..e652e90d9 100644 --- a/bsd/netinet/ip_fw.c +++ b/bsd/netinet/ip_fw.c @@ -898,8 +898,8 @@ add_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl) u_short nbr = 0; int s; - fwc = _MALLOC(sizeof *fwc, M_IPFW, M_DONTWAIT); - ftmp = _MALLOC(sizeof *ftmp, M_IPFW, M_DONTWAIT); + fwc = _MALLOC(sizeof *fwc, M_IPFW, M_NOWAIT); + ftmp = _MALLOC(sizeof *ftmp, M_IPFW, M_NOWAIT); if (!fwc || !ftmp) { dprintf(("%s MALLOC said no\n", err_prefix)); if (fwc) FREE(fwc, M_IPFW); diff --git a/bsd/netinet/ip_icmp.c b/bsd/netinet/ip_icmp.c index e29e6a08a..8ecf5d4a2 100644 --- a/bsd/netinet/ip_icmp.c +++ b/bsd/netinet/ip_icmp.c @@ -733,6 +733,8 @@ icmp_send(m, opts) m->m_len += hlen; m->m_pkthdr.rcvif = (struct ifnet *)0; m->m_pkthdr.aux = NULL; + m->m_pkthdr.csum_data = 0; + m->m_pkthdr.csum_flags = 0; #if ICMPPRINTFS if (icmpprintfs) { char buf[4 * sizeof "123"]; diff --git a/bsd/netinet/ip_input.c b/bsd/netinet/ip_input.c index fd3530236..4ca8fece7 100644 --- a/bsd/netinet/ip_input.c +++ b/bsd/netinet/ip_input.c @@ -206,12 +206,6 @@ ip_nat_t *ip_nat_ptr; ip_nat_ctl_t *ip_nat_ctl_ptr; #endif -#if defined(IPFILTER_LKM) || defined(IPFILTER) -int iplattach __P((void)); -int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL; -#endif - - /* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here @@ -303,9 +297,6 @@ ip_init() #endif #if IPNAT ip_nat_init(); -#endif -#if IPFILTER - iplattach(); #endif ip_initialized = 1; } @@ -415,7 +406,13 @@ ip_input(struct mbuf *m) ip = mtod(m, struct ip *); } - sum = in_cksum(m, hlen); + if (m->m_pkthdr.rcvif->if_hwassist == 0) + m->m_pkthdr.csum_flags = 0; + + if (m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) { + sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID); + } else + sum = in_cksum(m, hlen); if (sum) { ipstat.ips_badsum++; @@ -466,19 +463,6 @@ tooshort: #if defined(IPFIREWALL) && defined(DUMMYNET) iphack: #endif -#if defined(IPFILTER) || defined(IPFILTER_LKM) - /* - * Check if we want to allow this packet to be processed. - * Consider it to be bad if not. - */ - if (fr_checkp) { - struct mbuf *m1 = m; - - if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) - return; - ip = mtod(m = m1, struct ip *); - } -#endif #if COMPAT_IPFW if (ip_fw_chk_ptr) { #if IPFIREWALL_FORWARD @@ -677,6 +661,12 @@ pass: if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; + if (m->m_pkthdr.rcvif + && (m->m_pkthdr.rcvif->if_eflags & IFEF_AUTOCONFIGURING) + && ip->ip_p == IPPROTO_UDP) { + goto ours; + } + #if defined(NFAITH) && NFAITH > 0 /* * FAITH(Firewall Aided Internet Translator) @@ -915,6 +905,8 @@ ip_reass(m, fp, where) m->m_data += hlen; m->m_len -= hlen; + if (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16) + m->m_pkthdr.csum_flags = 0; /* * If first fragment to arrive, create a reassembly queue. */ @@ -959,6 +951,7 @@ ip_reass(m, fp, where) if (i >= ip->ip_len) goto dropfrag; m_adj(dtom(ip), i); + m->m_pkthdr.csum_flags = 0; ip->ip_off += i; ip->ip_len -= i; } @@ -981,6 +974,7 @@ ip_reass(m, fp, where) GETIP(q)->ip_len -= i; GETIP(q)->ip_off += i; m_adj(q, i); + q->m_pkthdr.csum_flags = 0; break; } nq = q->m_nextpkt; @@ -1038,6 +1032,12 @@ inserted: for (q = nq; q != NULL; q = nq) { nq = q->m_nextpkt; q->m_nextpkt = NULL; + if (q->m_pkthdr.csum_flags & CSUM_TCP_SUM16) + m->m_pkthdr.csum_flags = 0; + else { + m->m_pkthdr.csum_data += q->m_pkthdr.csum_data ; + m->m_pkthdr.csum_flags &= q->m_pkthdr.csum_flags; + } m_cat(m, q); } diff --git a/bsd/netinet/ip_log.c b/bsd/netinet/ip_log.c deleted file mode 100644 index 8a588a370..000000000 --- a/bsd/netinet/ip_log.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - */ -#include "opt_ipfilter.h" - -#if IPFILTER_LOG -# ifndef SOLARIS -# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -# endif - -# if defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -# endif -# ifdef __FreeBSD__ -# if defined(_KERNEL) && !defined(IPFILTER_LKM) -# define __FreeBSD_version 300000 /* this will do as a hack */ -# else -# include <osreldate.h> -# endif -# endif -# ifndef _KERNEL -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -# include <ctype.h> -# endif -# include <sys/errno.h> -# include <sys/types.h> -# include <sys/param.h> -# include <sys/file.h> -# if __FreeBSD_version >= 220000 && defined(_KERNEL) -# include <sys/fcntl.h> -# include <sys/filio.h> -# else -# include <sys/ioctl.h> -# endif -# include <sys/time.h> -# if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -# endif -# include <sys/uio.h> -# if !SOLARIS -# if (NetBSD > 199609) || (OpenBSD > 199603) || defined(__FreeBSD__) -# include <sys/dirent.h> -# else -# include <sys/dir.h> -# endif -# ifndef linux -# include <sys/mbuf.h> -# endif -# else -# include <sys/filio.h> -# include <sys/cred.h> -# include <sys/ddi.h> -# include <sys/sunddi.h> -# include <sys/ksynch.h> -# include <sys/kmem.h> -# include <sys/mkdev.h> -# include <sys/dditypes.h> -# include <sys/cmn_err.h> -# endif -# ifndef linux -# include <sys/protosw.h> -# endif -# include <sys/socket.h> - -# include <net/if.h> -# ifdef sun -# include <net/af.h> -# endif -# if __FreeBSD_version >= 300000 -# include <sys/malloc.h> -# include <machine/random.h> -# endif -# include <net/route.h> -# include <netinet/in.h> -# ifdef __sgi -# include <sys/ddi.h> -# ifdef IFF_DRVRLOCK /* IRIX6 */ -# include <sys/hashing.h> -# endif -# endif -# if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ -# include <netinet/in_var.h> -# endif -# include <netinet/in_systm.h> -# include <netinet/ip.h> -# include <netinet/tcp.h> -# include <netinet/udp.h> -# include <netinet/ip_icmp.h> -# ifndef linux -# include <netinet/ip_var.h> -# endif -# ifndef _KERNEL -# include <syslog.h> -# endif -# include "netinet/ip_compat.h" -# include <netinet/tcpip.h> -# include "netinet/ip_fil.h" -# include "netinet/ip_proxy.h" -# include "netinet/ip_nat.h" -# include "netinet/ip_frag.h" -# include "netinet/ip_state.h" -# include "netinet/ip_auth.h" -# ifndef MIN -# define MIN(a,b) (((a)<(b))?(a):(b)) -# endif - - -# if SOLARIS || defined(__sgi) -extern kmutex_t ipl_mutex; -# if SOLARIS -extern kcondvar_t iplwait; -# endif -# endif - -iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1]; -int iplused[IPL_LOGMAX+1]; -static u_long iplcrc[IPL_LOGMAX+1]; -static u_long iplcrcinit; -#ifdef linux -static struct wait_queue *iplwait[IPL_LOGMAX+1]; -#endif - - -/* - * Initialise log buffers & pointers. Also iniialised the CRC to a local - * secret for use in calculating the "last log checksum". - */ -void ipflog_init() -{ - int i; - - for (i = IPL_LOGMAX; i >= 0; i--) { - iplt[i] = NULL; - iplh[i] = &iplt[i]; - iplused[i] = 0; - } -# if defined(__FreeBSD__) && __FreeBSD_version >= 300000 - read_random(&iplcrcinit, sizeof iplcrcinit); -# else - { - struct timeval tv; - -#if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) - microtime(&tv); -# else - uniqtime(&tv); -# endif - iplcrcinit = tv.tv_sec ^ (tv.tv_usec << 8) ^ tv.tv_usec; - } -# endif -} - - -/* - * ipflog - * Create a log record for a packet given that it has been triggered by a - * rule (or the default setting). Calculate the transport protocol header - * size using predetermined size of a couple of popular protocols and thus - * how much data to copy into the log, including part of the data body if - * requested. - */ -int ipflog(flags, ip, fin, m) -u_int flags; -ip_t *ip; -fr_info_t *fin; -mb_t *m; -{ - ipflog_t ipfl; - register int mlen, hlen; - u_long crc; - size_t sizes[2]; - void *ptrs[2]; - int types[2]; -# if SOLARIS - ill_t *ifp = fin->fin_ifp; -# else - struct ifnet *ifp = fin->fin_ifp; -# endif - - /* - * calculate header size. - */ - hlen = fin->fin_hlen; - if (ip->ip_p == IPPROTO_TCP) - hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); - else if (ip->ip_p == IPPROTO_UDP) - hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); - else if (ip->ip_p == IPPROTO_ICMP) { - struct icmp *icmp = (struct icmp *)((char *)ip + hlen); - - /* - * For ICMP, if the packet is an error packet, also include - * the information about the packet which caused the error. - */ - switch (icmp->icmp_type) - { - case ICMP_UNREACH : - case ICMP_SOURCEQUENCH : - case ICMP_REDIRECT : - case ICMP_TIMXCEED : - case ICMP_PARAMPROB : - hlen += MIN(sizeof(struct icmp) + 8, fin->fin_dlen); - break; - default : - hlen += MIN(sizeof(struct icmp), fin->fin_dlen); - break; - } - } - /* - * Get the interface number and name to which this packet is - * currently associated. - */ -# if SOLARIS - ipfl.fl_unit = (u_char)ifp->ill_ppa; - bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); - mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; -# else -# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ - (defined(OpenBSD) && (OpenBSD >= 199603)) - strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); -# else -# ifndef linux - ipfl.fl_unit = (u_char)ifp->if_unit; -# endif - if ((ipfl.fl_ifname[0] = ifp->if_name[0])) - if ((ipfl.fl_ifname[1] = ifp->if_name[1])) - if ((ipfl.fl_ifname[2] = ifp->if_name[2])) - ipfl.fl_ifname[3] = ifp->if_name[3]; -# endif - mlen = (flags & FR_LOGBODY) ? MIN(ip->ip_len - hlen, 128) : 0; -# endif - ipfl.fl_plen = (u_char)mlen; - ipfl.fl_hlen = (u_char)hlen; - ipfl.fl_rule = fin->fin_rule; - ipfl.fl_group = fin->fin_group; - ipfl.fl_flags = flags; - ptrs[0] = (void *)&ipfl; - sizes[0] = sizeof(ipfl); - types[0] = 0; -#if SOLARIS - /* - * Are we copied from the mblk or an aligned array ? - */ - if (ip == (ip_t *)m->b_rptr) { - ptrs[1] = m; - sizes[1] = hlen + mlen; - types[1] = 1; - } else { - ptrs[1] = ip; - sizes[1] = hlen + mlen; - types[1] = 0; - } -#else - ptrs[1] = m; - sizes[1] = hlen + mlen; - types[1] = 1; -#endif - crc = (ipf_cksum((u_short *)fin, FI_CSIZE) << 8) + iplcrcinit; - return ipllog(IPL_LOGIPF, crc, ptrs, sizes, types, 2); -} - - -/* - * ipllog - */ -int ipllog(dev, crc, items, itemsz, types, cnt) -int dev; -u_long crc; -void **items; -size_t *itemsz; -int *types, cnt; -{ - iplog_t *ipl; - caddr_t buf, s; - int len, i; - - /* - * Check to see if this log record has a CRC which matches the last - * record logged. If it does, just up the count on the previous one - * rather than create a new one. - */ - if (crc) { - MUTEX_ENTER(&ipl_mutex); - if ((iplcrc[dev] == crc) && *iplh[dev]) { - (*iplh[dev])->ipl_count++; - MUTEX_EXIT(&ipl_mutex); - return 1; - } - iplcrc[dev] = crc; - MUTEX_EXIT(&ipl_mutex); - } - - /* - * Get the total amount of data to be logged. - */ - for (i = 0, len = sizeof(iplog_t); i < cnt; i++) - len += itemsz[i]; - - /* - * check that we have space to record this information and can - * allocate that much. - */ - KMALLOC(buf, caddr_t, len); - if (!buf) - return 0; - MUTEX_ENTER(&ipl_mutex); - if ((iplused[dev] + len) > IPLLOGSIZE) { - MUTEX_EXIT(&ipl_mutex); - KFREES(buf, len); - return 0; - } - iplused[dev] += len; - MUTEX_EXIT(&ipl_mutex); - - /* - * advance the log pointer to the next empty record and deduct the - * amount of space we're going to use. - */ - ipl = (iplog_t *)buf; - ipl->ipl_magic = IPL_MAGIC; - ipl->ipl_count = 1; - ipl->ipl_next = NULL; - ipl->ipl_dsize = len; -# if SOLARIS || defined(sun) || defined(linux) - uniqtime((struct timeval *)&ipl->ipl_sec); -# else -# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) - microtime((struct timeval *)&ipl->ipl_sec); -# endif -# endif - - /* - * Loop through all the items to be logged, copying each one to the - * buffer. Use bcopy for normal data or the mb_t copyout routine. - */ - for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { - if (types[i] == 0) - bcopy(items[i], s, itemsz[i]); - else if (types[i] == 1) { -# if SOLARIS - copyout_mblk(items[i], 0, itemsz[i], s); -# else - m_copydata(items[i], 0, itemsz[i], s); -# endif - } - s += itemsz[i]; - } - MUTEX_ENTER(&ipl_mutex); - *iplh[dev] = ipl; - iplh[dev] = &ipl->ipl_next; -# if SOLARIS - cv_signal(&iplwait); - mutex_exit(&ipl_mutex); -# else - MUTEX_EXIT(&ipl_mutex); -# ifdef linux - wake_up_interruptible(&iplwait[dev]); -# else - wakeup(&iplh[dev]); -# endif -# endif - return 1; -} - - -int ipflog_read(unit, uio) -int unit; -struct uio *uio; -{ - iplog_t *ipl; - int error = 0, dlen, copied; -# if defined(_KERNEL) && !SOLARIS - int s; -# endif - - /* - * Sanity checks. Make sure the minor # is valid and we're copying - * a valid chunk of data. - */ - if ((IPL_LOGMAX < unit) || (unit < 0)) - return ENXIO; - if (!uio->uio_resid) - return 0; - if ((uio->uio_resid < sizeof(iplog_t)) || - (uio->uio_resid > IPLLOGSIZE)) - return EINVAL; - - /* - * Lock the log so we can snapshot the variables. Wait for a signal - * if the log is empty. - */ - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - - while (!iplused[unit] || !iplt[unit]) { -# if SOLARIS && defined(_KERNEL) - if (!cv_wait_sig(&iplwait, &ipl_mutex)) { - MUTEX_EXIT(&ipl_mutex); - return EINTR; - } -# else -# ifdef linux - interruptible_sleep_on(&iplwait[unit]); - if (current->signal & ~current->blocked) - return -EINTR; -# else - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - error = SLEEP(&iplh[unit], "ipl sleep"); - if (error) - return error; - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); -# endif /* linux */ -# endif /* SOLARIS */ - } - -# if BSD >= 199306 || defined(__FreeBSD__) - uio->uio_rw = UIO_READ; -# endif - - for (copied = 0; (ipl = iplt[unit]); copied += dlen) { - dlen = ipl->ipl_dsize; - if (dlen + sizeof(iplog_t) > uio->uio_resid) - break; - /* - * Don't hold the mutex over the uiomove call. - */ - iplt[unit] = ipl->ipl_next; - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - error = UIOMOVE((caddr_t)ipl, ipl->ipl_dsize, UIO_READ, uio); - KFREES((caddr_t)ipl, ipl->ipl_dsize); - if (error) - break; - SPL_NET(s); - MUTEX_ENTER(&ipl_mutex); - iplused[unit] -= dlen; - } - if (!ipl) { - iplused[unit] = 0; - iplh[unit] = &iplt[unit]; - } - - if (!error) { - MUTEX_EXIT(&ipl_mutex); - SPL_X(s); - } -#ifdef linux - if (!error) - return copied; - return -error; -#else - return error; -#endif -} - - -int ipflog_clear(unit) -int unit; -{ - iplog_t *ipl; - int used; - - while ((ipl = iplt[unit])) { - iplt[unit] = ipl->ipl_next; - KFREES((caddr_t)ipl, ipl->ipl_dsize); - } - iplh[unit] = &iplt[unit]; - used = iplused[unit]; - iplused[unit] = 0; - iplcrc[unit] = 0; - return used; -} -#endif /* IPFILTER_LOG */ diff --git a/bsd/netinet/ip_nat.c b/bsd/netinet/ip_nat.c deleted file mode 100644 index d8a0f6219..000000000 --- a/bsd/netinet/ip_nat.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1995-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * Added redirect stuff and a LOT of bug fixes. (mcn@EnGarde.com) - */ -#if !defined(lint) -/* static const char sccsid[] = "@(#)ip_nat.c 1.11 6/5/96 (C) 1995 Darren Reed"; */ -#endif - -#include "opt_ipfilter.h" -#define __FreeBSD_version 300000 /* it's a hack, but close enough */ - -#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) -#define _KERNEL -#endif - -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if defined(KERNEL) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/fcntl.h> -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if __FreeBSD_version >= 300000 -# include <sys/queue.h> -# include <sys/malloc.h> -#endif -#include <net/if.h> -#if __FreeBSD_version >= 300000 -# include <net/if_var.h> -#endif -#ifdef sun -#include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> - -#ifdef __sgi -# ifdef IFF_DRVRLOCK /* IRIX6 */ -#include <sys/hashing.h> -#include <netinet/in_var.h> -# endif -#endif - -#if RFC1825 -#include <vpn/md5.h> -#include <vpn/ipsec.h> -extern struct ifnet vpnif; -#endif - -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_state.h" -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#undef SOCKADDR_IN -#define SOCKADDR_IN struct sockaddr_in - - nat_t *nat_table[2][NAT_SIZE], *nat_instances = NULL; -static ipnat_t *nat_list = NULL; -u_long fr_defnatage = 1200, /* 10 minutes (600 seconds) */ - fr_defnaticmpage = 6; /* 3 seconds */ -static natstat_t nat_stats; -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_nat; -#endif - -static int nat_flushtable __P((void)); -static int nat_clearlist __P((void)); -static void nat_delete __P((struct nat *)); -static int nat_ifpaddr __P((nat_t *, void *, struct in_addr *)); - - -#define LONG_SUM(in) (((in) & 0xffff) + ((in) >> 16)) - -#define CALC_SUMD(s1, s2, sd) { \ - /* Do it twice */ \ - (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ - (s1) = ((s1) & 0xffff) + ((s1) >> 16); \ - /* Do it twice */ \ - (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ - (s2) = ((s2) & 0xffff) + ((s2) >> 16); \ - /* Because ~1 == -2, We really need ~1 == -1 */ \ - if ((s1) > (s2)) (s2)--; \ - (sd) = (s2) - (s1); \ - (sd) = ((sd) & 0xffff) + ((sd) >> 16); } - -void fix_outcksum(sp, n) -u_short *sp; -u_32_t n; -{ - register u_short sumshort; - register u_32_t sum1; - - if (!n) - return; - sum1 = (~ntohs(*sp)) & 0xffff; - sum1 += (n); - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - /* Again */ - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - sumshort = ~(u_short)sum1; - *(sp) = htons(sumshort); -} - - -void fix_incksum(sp, n) -u_short *sp; -u_32_t n; -{ - register u_short sumshort; - register u_32_t sum1; - - if (!n) - return; -#if sparc - sum1 = (~(*sp)) & 0xffff; -#else - sum1 = (~ntohs(*sp)) & 0xffff; -#endif - sum1 += ~(n) & 0xffff; - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - /* Again */ - sum1 = (sum1 >> 16) + (sum1 & 0xffff); - sumshort = ~(u_short)sum1; - *(sp) = htons(sumshort); -} - - -/* - * How the NAT is organised and works. - * - * Inside (interface y) NAT Outside (interface x) - * -------------------- -+- ------------------------------------- - * Packet going | out, processsed by ip_natout() for x - * ------------> | ------------> - * src=10.1.1.1 | src=192.1.1.1 - * | - * | in, processed by ip_natin() for x - * <------------ | <------------ - * dst=10.1.1.1 | dst=192.1.1.1 - * -------------------- -+- ------------------------------------- - * ip_natout() - changes ip_src and if required, sport - * - creates a new mapping, if required. - * ip_natin() - changes ip_dst and if required, dport - * - * In the NAT table, internal source is recorded as "in" and externally - * seen as "out". - */ - -/* - * Handle ioctls which manipulate the NAT. - */ -int nat_ioctl(data, cmd, mode) -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -u_long cmd; -#else -int cmd; -#endif -caddr_t data; -int mode; -{ - register ipnat_t *nat, *n = NULL, **np = NULL; - ipnat_t natd; - int error = 0, ret; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - nat = NULL; /* XXX gcc -Wuninitialized */ - - /* - * For add/delete, look to see if the NAT entry is already present - */ - SPL_NET(s); - MUTEX_ENTER(&ipf_nat); - if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) { - IRCOPY(data, (char *)&natd, sizeof(natd)); - nat = &natd; - nat->in_inip &= nat->in_inmsk; - nat->in_outip &= nat->in_outmsk; - for (np = &nat_list; (n = *np); np = &n->in_next) - if (!bcmp((char *)&nat->in_flags, (char *)&n->in_flags, - IPN_CMPSIZ)) - break; - } - - switch (cmd) - { - case SIOCADNAT : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - if (n) { - error = EEXIST; - break; - } - KMALLOC(n, ipnat_t *, sizeof(*n)); - if (n == NULL) { - error = ENOMEM; - break; - } - bcopy((char *)nat, (char *)n, sizeof(*n)); - n->in_ifp = (void *)GETUNIT(n->in_ifname); - if (!n->in_ifp) - n->in_ifp = (void *)-1; - n->in_apr = ap_match(n->in_p, n->in_plabel); - n->in_next = *np; - n->in_use = 0; - n->in_space = ~(0xffffffff & ntohl(n->in_outmsk)); - if (n->in_space) /* lose 2: broadcast + network address */ - n->in_space -= 2; - else - n->in_space = 1; /* single IP# mapping */ - if ((n->in_outmsk != 0xffffffff) && n->in_outmsk) - n->in_nip = ntohl(n->in_outip) + 1; - else - n->in_nip = ntohl(n->in_outip); - if (n->in_redir & NAT_MAP) { - n->in_pnext = ntohs(n->in_pmin); - /* - * Multiply by the number of ports made available. - */ - if (ntohs(n->in_pmax) > ntohs(n->in_pmin)) - n->in_space *= (ntohs(n->in_pmax) - - ntohs(n->in_pmin)); - } - /* Otherwise, these fields are preset */ - *np = n; - nat_stats.ns_rules++; - break; - case SIOCRMNAT : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - if (!n) { - error = ESRCH; - break; - } - *np = n->in_next; - if (!n->in_use) { - if (n->in_apr) - ap_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } - break; - case SIOCGNATS : - nat_stats.ns_table[0] = nat_table[0]; - nat_stats.ns_table[1] = nat_table[1]; - nat_stats.ns_list = nat_list; - IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats)); - break; - case SIOCGNATL : - { - natlookup_t nl; - - IRCOPY((char *)data, (char *)&nl, sizeof(nl)); - - if (nat_lookupredir(&nl)) { - IWCOPY((char *)&nl, (char *)data, sizeof(nl)); - } else - error = ESRCH; - break; - } - case SIOCFLNAT : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - ret = nat_flushtable(); - (void) ap_unload(); - IWCOPY((caddr_t)&ret, data, sizeof(ret)); - break; - case SIOCCNATL : - if (!(mode & FWRITE)) { - error = EPERM; - break; - } - ret = nat_clearlist(); - IWCOPY((caddr_t)&ret, data, sizeof(ret)); - break; - case FIONREAD : -#if IPFILTER_LOG - IWCOPY((caddr_t)&iplused[IPL_LOGNAT], (caddr_t)data, - sizeof(iplused[IPL_LOGNAT])); -#endif - break; - } - MUTEX_EXIT(&ipf_nat); - SPL_X(s); - return error; -} - - -/* - * Delete a nat entry from the various lists and table. - */ -static void nat_delete(natd) -struct nat *natd; -{ - register struct nat **natp, *nat; - struct ipnat *ipn; - - for (natp = natd->nat_hstart[0]; (nat = *natp); - natp = &nat->nat_hnext[0]) - if (nat == natd) { - *natp = nat->nat_hnext[0]; - break; - } - - for (natp = natd->nat_hstart[1]; (nat = *natp); - natp = &nat->nat_hnext[1]) - if (nat == natd) { - *natp = nat->nat_hnext[1]; - break; - } - - /* - * If there is an active reference from the nat entry to its parent - * rule, decrement the rule's reference count and free it too if no - * longer being used. - */ - if ((ipn = natd->nat_ptr)) { - ipn->in_space++; - ipn->in_use--; - if (!ipn->in_use && (ipn->in_flags & IPN_DELETE)) { - if (ipn->in_apr) - ap_free(ipn->in_apr); - KFREE(ipn); - nat_stats.ns_rules--; - } - } - - /* - * If there's a fragment table entry too for this nat entry, then - * dereference that as well. - */ - ipfr_forget((void *)natd); - KFREE(natd); -} - - -/* - * nat_flushtable - clear the NAT table of all mapping entries. - */ -static int nat_flushtable() -{ - register nat_t *nat, **natp; - register int j = 0; - - /* - * Everything will be deleted, so lets just make it the deletions - * quicker. - */ - bzero((char *)nat_table[0], sizeof(nat_table[0])); - bzero((char *)nat_table[1], sizeof(nat_table[1])); - - for (natp = &nat_instances; (nat = *natp); ) { - *natp = nat->nat_next; - nat_delete(nat); - j++; - } - - return j; -} - - -/* - * nat_clearlist - delete all entries in the active NAT mapping list. - */ -static int nat_clearlist() -{ - register ipnat_t *n, **np = &nat_list; - int i = 0; - - while ((n = *np)) { - *np = n->in_next; - if (!n->in_use) { - if (n->in_apr) - ap_free(n->in_apr); - KFREE(n); - nat_stats.ns_rules--; - i++; - } else { - n->in_flags |= IPN_DELETE; - n->in_next = NULL; - } - } - nat_stats.ns_inuse = 0; - return i; -} - - -/* - * return the first IP Address associated with an interface - */ -static int nat_ifpaddr(nat, ifptr, inp) -nat_t *nat; -void *ifptr; -struct in_addr *inp; -{ -#if SOLARIS - ill_t *ill = ifptr; -#else - struct ifnet *ifp = ifptr; -#endif - struct in_addr in; - -#if SOLARIS - in.s_addr = ntohl(ill->ill_ipif->ipif_local_addr); -#else /* SOLARIS */ -# if linux - ; -# else /* linux */ - struct ifaddr *ifa; - struct sockaddr_in *sin; - -# if (__FreeBSD_version >= 300000) - ifa = TAILQ_FIRST(&ifp->if_addrhead); -# else -# if defined(__NetBSD__) || defined(__OpenBSD__) - ifa = ifp->if_addrlist.tqh_first; -# else -# if defined(__sgi) && defined(IFF_DRVRLOCK) /* IRIX 6 */ - ifa = &((struct in_ifaddr *)ifp->in_ifaddr)->ia_ifa; -# else - ifa = ifp->if_addrlist; -# endif -# endif /* __NetBSD__ || __OpenBSD__ */ -# endif /* __FreeBSD_version >= 300000 */ -# if (BSD < 199306) && !(/*IRIX6*/defined(__sgi) && defined(IFF_DRVRLOCK)) - sin = (SOCKADDR_IN *)&ifa->ifa_addr; -# else - sin = (SOCKADDR_IN *)ifa->ifa_addr; - while (sin && ifa && - sin->sin_family != AF_INET) { -# if (__FreeBSD_version >= 300000) - ifa = TAILQ_NEXT(ifa, ifa_link); -# else -# if defined(__NetBSD__) || defined(__OpenBSD__) - ifa = ifa->ifa_list.tqe_next; -# else - ifa = ifa->ifa_next; -# endif -# endif /* __FreeBSD_version >= 300000 */ - if (ifa) - sin = (SOCKADDR_IN *)ifa->ifa_addr; - } - if (!ifa) - sin = NULL; - if (!sin) { - KFREE(nat); - return -1; - } -# endif /* (BSD < 199306) && (!__sgi && IFF_DRVLOCK) */ - in = sin->sin_addr; - in.s_addr = ntohl(in.s_addr); -# endif /* linux */ -#endif /* SOLARIS */ - *inp = in; - return 0; -} - - -/* - * Create a new NAT table entry. - */ -nat_t *nat_new(np, ip, fin, flags, direction) -ipnat_t *np; -ip_t *ip; -fr_info_t *fin; -u_short flags; -int direction; -{ - register u_32_t sum1, sum2, sumd, l; - u_short port = 0, sport = 0, dport = 0, nport = 0; - struct in_addr in; - tcphdr_t *tcp = NULL; - nat_t *nat, **natp; - u_short nflags; - - nflags = flags & np->in_flags; - if (flags & IPN_TCPUDP) { - tcp = (tcphdr_t *)fin->fin_dp; - sport = tcp->th_sport; - dport = tcp->th_dport; - } - - /* Give me a new nat */ - KMALLOC(nat, nat_t *, sizeof(*nat)); - if (nat == NULL) - return NULL; - - bzero((char *)nat, sizeof(*nat)); - nat->nat_flags = flags; - - /* - * Search the current table for a match. - */ - if (direction == NAT_OUTBOUND) { - /* - * If it's an outbound packet which doesn't match any existing - * record, then create a new port - */ - l = 0; - do { - l++; - port = 0; - in.s_addr = np->in_nip; - if (!in.s_addr && (np->in_outmsk == 0xffffffff)) { - if ((l > 1) || - nat_ifpaddr(nat, fin->fin_ifp, &in) == -1) { - KFREE(nat); - return NULL; - } - } else if (!in.s_addr && !np->in_outmsk) { - if (l > 1) { - KFREE(nat); - return NULL; - } - in.s_addr = ntohl(ip->ip_src.s_addr); - if (nflags & IPN_TCPUDP) - port = sport; - } else if (nflags & IPN_TCPUDP) { - port = htons(np->in_pnext++); - if (np->in_pnext >= ntohs(np->in_pmax)) { - np->in_pnext = ntohs(np->in_pmin); - np->in_space--; - if (np->in_outmsk != 0xffffffff) - np->in_nip++; - } - } else if (np->in_outmsk != 0xffffffff) { - np->in_space--; - np->in_nip++; - } - - if (!port && (flags & IPN_TCPUDP)) - port = sport; - if ((np->in_nip & ntohl(np->in_outmsk)) > - ntohl(np->in_outip)) - np->in_nip = ntohl(np->in_outip) + 1; - } while (nat_inlookup(fin->fin_ifp, flags, ip->ip_dst, - dport, in, port)); - - /* Setup the NAT table */ - nat->nat_inip = ip->ip_src; - nat->nat_outip.s_addr = htonl(in.s_addr); - nat->nat_oip = ip->ip_dst; - - sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) + - (ntohl(ip->ip_src.s_addr) >> 16) + ntohs(sport); - - sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(port); - - if (flags & IPN_TCPUDP) { - nat->nat_inport = sport; - nat->nat_outport = port; - nat->nat_oport = dport; - } - } else { - - /* - * Otherwise, it's an inbound packet. Most likely, we don't - * want to rewrite source ports and source addresses. Instead, - * we want to rewrite to a fixed internal address and fixed - * internal port. - */ - in.s_addr = ntohl(np->in_inip); - if (!(nport = np->in_pnext)) - nport = dport; - - nat->nat_inip.s_addr = htonl(in.s_addr); - nat->nat_outip = ip->ip_dst; - nat->nat_oip = ip->ip_src; - - sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) + - (ntohl(ip->ip_dst.s_addr) >> 16) + ntohs(dport); - - sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16) + ntohs(nport); - - if (flags & IPN_TCPUDP) { - nat->nat_inport = nport; - nat->nat_outport = dport; - nat->nat_oport = sport; - } - } - - /* Do it twice */ - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - - /* Do it twice */ - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - - if (sum1 > sum2) - sum2--; /* Because ~1 == -2, We really need ~1 == -1 */ - sumd = sum2 - sum1; - sumd = (sumd & 0xffff) + (sumd >> 16); - nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16); - - if ((flags & IPN_TCPUDP) && ((sport != port) || (dport != nport))) { - if (direction == NAT_OUTBOUND) - sum1 = (ntohl(ip->ip_src.s_addr) & 0xffff) + - (ntohl(ip->ip_src.s_addr) >> 16); - else - sum1 = (ntohl(ip->ip_dst.s_addr) & 0xffff) + - (ntohl(ip->ip_dst.s_addr) >> 16); - - sum2 = (in.s_addr & 0xffff) + (in.s_addr >> 16); - - /* Do it twice */ - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - - /* Do it twice */ - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - - if (sum1 > sum2) - sum2--; /* Because ~1 == -2, We really need ~1 == -1 */ - sumd = sum2 - sum1; - sumd = (sumd & 0xffff) + (sumd >> 16); - nat->nat_ipsumd = (sumd & 0xffff) + (sumd >> 16); - } else - nat->nat_ipsumd = nat->nat_sumd; - - in.s_addr = htonl(in.s_addr); - nat->nat_next = nat_instances; - nat_instances = nat; - natp = &nat_table[0][nat->nat_inip.s_addr % NAT_SIZE]; - nat->nat_hstart[0] = natp; - nat->nat_hnext[0] = *natp; - *natp = nat; - natp = &nat_table[1][nat->nat_outip.s_addr % NAT_SIZE]; - nat->nat_hstart[1] = natp; - nat->nat_hnext[1] = *natp; - *natp = nat; - nat->nat_ptr = np; - nat->nat_bytes = 0; - nat->nat_pkts = 0; - nat->nat_ifp = fin->fin_ifp; - nat->nat_dir = direction; - if (direction == NAT_OUTBOUND) { - if (flags & IPN_TCPUDP) - tcp->th_sport = port; - } else { - if (flags & IPN_TCPUDP) - tcp->th_dport = nport; - } - nat_stats.ns_added++; - nat_stats.ns_inuse++; - np->in_use++; - return nat; -} - - -nat_t *nat_icmpinlookup(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - icmphdr_t *icmp; - tcphdr_t *tcp = NULL; - ip_t *oip; - int flags = 0, type; - - icmp = (icmphdr_t *)fin->fin_dp; - /* - * Does it at least have the return (basic) IP header ? - * Only a basic IP header (no options) should be with an ICMP error - * header. - */ - if ((ip->ip_hl != 5) || (ip->ip_len < sizeof(*icmp) + sizeof(ip_t))) - return NULL; - type = icmp->icmp_type; - /* - * If it's not an error type, then return. - */ - if ((type != ICMP_UNREACH) && (type != ICMP_SOURCEQUENCH) && - (type != ICMP_REDIRECT) && (type != ICMP_TIMXCEED) && - (type != ICMP_PARAMPROB)) - return NULL; - - oip = (ip_t *)((char *)fin->fin_dp + 8); - if (oip->ip_p == IPPROTO_TCP) - flags = IPN_TCP; - else if (oip->ip_p == IPPROTO_UDP) - flags = IPN_UDP; - if (flags & IPN_TCPUDP) { - tcp = (tcphdr_t *)((char *)oip + (oip->ip_hl << 2)); - return nat_inlookup(fin->fin_ifp, flags, oip->ip_dst, - tcp->th_dport, oip->ip_src, tcp->th_sport); - } - return nat_inlookup(fin->fin_ifp, 0, oip->ip_src, 0, oip->ip_dst, 0); -} - - -/* - * This should *ONLY* be used for incoming packets to make sure a NAT'd ICMP - * packet gets correctly recognised. - */ -nat_t *nat_icmpin(ip, fin, nflags) -ip_t *ip; -fr_info_t *fin; -int *nflags; -{ - icmphdr_t *icmp; - nat_t *nat; - ip_t *oip; - int flags = 0; - - if (!(nat = nat_icmpinlookup(ip, fin))) - return NULL; - - *nflags = IPN_ICMPERR; - icmp = (icmphdr_t *)fin->fin_dp; - oip = (ip_t *)((char *)icmp + 8); - if (oip->ip_p == IPPROTO_TCP) - flags = IPN_TCP; - else if (oip->ip_p == IPPROTO_UDP) - flags = IPN_UDP; - /* - * Need to adjust ICMP header to include the real IP#'s and - * port #'s. Only apply a checksum change relative to the - * IP address change is it will be modified again in ip_natout - * for both address and port. Two checksum changes are - * necessary for the two header address changes. Be careful - * to only modify the checksum once for the port # and twice - * for the IP#. - */ - if (flags & IPN_TCPUDP) { - tcphdr_t *tcp = (tcphdr_t *)(oip + 1); - u_32_t sum1, sum2, sumd; - struct in_addr in; - - if (nat->nat_dir == NAT_OUTBOUND) { - sum1 = LONG_SUM(ntohl(oip->ip_src.s_addr)); - in = nat->nat_outip; - oip->ip_src = in; - tcp->th_sport = nat->nat_outport; - } else { - sum1 = LONG_SUM(ntohl(oip->ip_dst.s_addr)); - in = nat->nat_inip; - oip->ip_dst = in; - tcp->th_dport = nat->nat_inport; - } - - sum2 = LONG_SUM(in.s_addr); - - CALC_SUMD(sum1, sum2, sumd); - sumd = (sumd & 0xffff) + (sumd >> 16); - - if (nat->nat_dir == NAT_OUTBOUND) { - fix_incksum(&oip->ip_sum, sumd); - fix_incksum(&icmp->icmp_cksum, sumd); - } else { - fix_outcksum(&oip->ip_sum, sumd); - fix_outcksum(&icmp->icmp_cksum, sumd); - } - - /* - * TCP checksum doesn't make it into the 1st eight - * bytes but UDP does. - */ - if (ip->ip_p == IPPROTO_UDP) { - udphdr_t *udp = (udphdr_t *)tcp; - - if (udp->uh_sum) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&udp->uh_sum, - nat->nat_sumd); - else - fix_outcksum(&udp->uh_sum, - nat->nat_sumd); - } - } - } else - ip->ip_dst = nat->nat_outip; - nat->nat_age = fr_defnaticmpage; - return nat; -} - - -/* - * NB: these lookups don't lock access to the list, it assume it has already - * been done! - */ -/* - * Lookup a nat entry based on the mapped destination ip address/port and - * real source address/port. We use this lookup when receiving a packet, - * we're looking for a table entry, based on the destination address. - * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. - */ -#ifdef __STDC__ -nat_t *nat_inlookup(void *ifp, int flags, struct in_addr src, u_short sport, struct in_addr mapdst, u_short mapdport) -#else -nat_t *nat_inlookup(ifp, flags, src, sport, mapdst, mapdport) -void *ifp; -register int flags; -struct in_addr src , mapdst; -u_short sport, mapdport; -#endif -{ - register nat_t *nat; - - flags &= IPN_TCPUDP; - - nat = nat_table[1][mapdst.s_addr % NAT_SIZE]; - for (; nat; nat = nat->nat_hnext[1]) - if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_oip.s_addr == src.s_addr && - nat->nat_outip.s_addr == mapdst.s_addr && - flags == nat->nat_flags && (!flags || - (nat->nat_oport == sport && - nat->nat_outport == mapdport))) - return nat; - return NULL; -} - - -/* - * Lookup a nat entry based on the source 'real' ip address/port and - * destination address/port. We use this lookup when sending a packet out, - * we're looking for a table entry, based on the source address. - * NOTE: THE PACKET BEING CHECKED (IF FOUND) HAS A MAPPING ALREADY. - */ -#ifdef __STDC__ -nat_t *nat_outlookup(void *ifp, int flags, struct in_addr src, u_short sport, struct in_addr dst, u_short dport) -#else -nat_t *nat_outlookup(ifp, flags, src, sport, dst, dport) -void *ifp; -register int flags; -struct in_addr src , dst; -u_short sport, dport; -#endif -{ - register nat_t *nat; - - flags &= IPN_TCPUDP; - - nat = nat_table[0][src.s_addr % NAT_SIZE]; - for (; nat; nat = nat->nat_hnext[0]) { - if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_inip.s_addr == src.s_addr && - nat->nat_oip.s_addr == dst.s_addr && - flags == nat->nat_flags && (!flags || - (nat->nat_inport == sport && nat->nat_oport == dport))) - return nat; - } - return NULL; -} - - -/* - * Lookup a nat entry based on the mapped source ip address/port and - * real destination address/port. We use this lookup when sending a packet - * out, we're looking for a table entry, based on the source address. - */ -#ifdef __STDC__ -nat_t *nat_lookupmapip(void *ifp, int flags, struct in_addr mapsrc, u_short mapsport, struct in_addr dst, u_short dport) -#else -nat_t *nat_lookupmapip(ifp, flags, mapsrc, mapsport, dst, dport) -void *ifp; -register int flags; -struct in_addr mapsrc , dst; -u_short mapsport, dport; -#endif -{ - register nat_t *nat; - - flags &= IPN_TCPUDP; - - nat = nat_table[1][mapsrc.s_addr % NAT_SIZE]; - for (; nat; nat = nat->nat_hnext[0]) - if ((!ifp || ifp == nat->nat_ifp) && - nat->nat_oip.s_addr == dst.s_addr && - nat->nat_outip.s_addr == mapsrc.s_addr && - flags == nat->nat_flags && (!flags || - (nat->nat_outport == mapsport && - nat->nat_oport == dport))) - return nat; - return NULL; -} - - -/* - * Lookup the NAT tables to search for a matching redirect - */ -nat_t *nat_lookupredir(np) -register natlookup_t *np; -{ - nat_t *nat; - - /* - * If nl_inip is non null, this is a lookup based on the real - * ip address. Else, we use the fake. - */ - if ((nat = nat_outlookup(NULL, np->nl_flags, np->nl_inip, - np->nl_inport, np->nl_outip, - np->nl_outport))) { - np->nl_realip = nat->nat_outip; - np->nl_realport = nat->nat_outport; - } - return nat; -} - - -/* - * Packets going out on the external interface go through this. - * Here, the source address requires alteration, if anything. - */ -int ip_natout(ip, hlen, fin) -ip_t *ip; -int hlen; -fr_info_t *fin; -{ - register ipnat_t *np; - register u_32_t ipa; - tcphdr_t *tcp = NULL; - u_short nflags = 0, sport = 0, dport = 0, *csump = NULL; - struct ifnet *ifp; - frentry_t *fr; - nat_t *nat; - int natadd = 1; - - if ((fr = fin->fin_fr) && !(fr->fr_flags & FR_DUP) && - fr->fr_tif.fd_ifp && fr->fr_tif.fd_ifp != (void *)-1) - ifp = fr->fr_tif.fd_ifp; - else - ifp = fin->fin_ifp; - - if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) - nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) - nflags = IPN_UDP; - if (nflags) { - tcp = (tcphdr_t *)fin->fin_dp; - sport = tcp->th_sport; - dport = tcp->th_dport; - } - } - - ipa = ip->ip_src.s_addr; - - MUTEX_ENTER(&ipf_nat); - if ((ip->ip_off & (IP_OFFMASK|IP_MF)) && - (nat = ipfr_nat_knownfrag(ip, fin))) - natadd = 0; - else if ((nat = nat_outlookup(ifp, nflags, ip->ip_src, sport, - ip->ip_dst, dport))) - ; - else - /* - * If there is no current entry in the nat table for this IP#, - * create one for it (if there is a matching rule). - */ - for (np = nat_list; np; np = np->in_next) - if ((np->in_ifp == ifp) && np->in_space && - (!np->in_flags || (np->in_flags & nflags)) && - ((ipa & np->in_inmsk) == np->in_inip) && - ((np->in_redir & NAT_MAP) || - (np->in_pnext == sport))) { - if (*np->in_plabel && !ap_ok(ip, tcp, np)) - continue; - /* - * If it's a redirection, then we don't want to - * create new outgoing port stuff. - * Redirections are only for incoming - * connections. - */ - if (!(np->in_redir & NAT_MAP)) - continue; - if ((nat = nat_new(np, ip, fin, nflags, - NAT_OUTBOUND))) -#if IPFILTER_LOG - nat_log(nat, (u_short)np->in_redir); -#else - ; -#endif - break; - } - - if (nat) { - if (natadd && fin->fin_fi.fi_fl & FI_FRAG) - ipfr_nat_newfrag(ip, fin, 0, nat); - nat->nat_age = fr_defnatage; - ip->ip_src = nat->nat_outip; - nat->nat_bytes += ip->ip_len; - nat->nat_pkts++; - - /* - * Fix up checksums, not by recalculating them, but - * simply computing adjustments. - */ -#if SOLARIS || defined(__sgi) - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); - else - fix_incksum(&ip->ip_sum, nat->nat_ipsumd); -#endif - - if (nflags && !(ip->ip_off & 0x1fff) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - - if (nat->nat_outport) - tcp->th_sport = nat->nat_outport; - - if (ip->ip_p == IPPROTO_TCP) { - csump = &tcp->th_sum; - fr_tcp_age(&nat->nat_age, - nat->nat_state, ip, fin,1); - /* - * Increase this because we may have - * "keep state" following this too and - * packet storms can occur if this is - * removed too quickly. - */ - if (nat->nat_age == fr_tcpclosed) - nat->nat_age = fr_tcplastack; - } else if (ip->ip_p == IPPROTO_UDP) { - udphdr_t *udp = (udphdr_t *)tcp; - - if (udp->uh_sum) - csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - icmphdr_t *ic = (icmphdr_t *)tcp; - - csump = &ic->icmp_cksum; - } - if (csump) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_outcksum(csump, - nat->nat_sumd); - else - fix_incksum(csump, - nat->nat_sumd); - } - } - (void) ap_check(ip, tcp, fin, nat); - nat_stats.ns_mapped[1]++; - MUTEX_EXIT(&ipf_nat); - return -2; - } - MUTEX_EXIT(&ipf_nat); - return 0; -} - - -/* - * Packets coming in from the external interface go through this. - * Here, the destination address requires alteration, if anything. - */ -int ip_natin(ip, hlen, fin) -ip_t *ip; -int hlen; -fr_info_t *fin; -{ - register ipnat_t *np; - register struct in_addr in; - struct ifnet *ifp = fin->fin_ifp; - tcphdr_t *tcp = NULL; - u_short sport = 0, dport = 0, *csump = NULL; - nat_t *nat; - int nflags = 0, natadd = 1; - - if (!(ip->ip_off & 0x1fff) && !(fin->fin_fi.fi_fl & FI_SHORT)) { - if (ip->ip_p == IPPROTO_TCP) - nflags = IPN_TCP; - else if (ip->ip_p == IPPROTO_UDP) - nflags = IPN_UDP; - if (nflags) { - tcp = (tcphdr_t *)((char *)ip + hlen); - dport = tcp->th_dport; - sport = tcp->th_sport; - } - } - - in = ip->ip_dst; - - MUTEX_ENTER(&ipf_nat); - - if ((ip->ip_p == IPPROTO_ICMP) && (nat = nat_icmpin(ip, fin, &nflags))) - ; - else if ((ip->ip_off & IP_OFFMASK) && - (nat = ipfr_nat_knownfrag(ip, fin))) - natadd = 0; - else if ((nat = nat_inlookup(fin->fin_ifp, nflags, ip->ip_src, sport, - ip->ip_dst, dport))) - ; - else - /* - * If there is no current entry in the nat table for this IP#, - * create one for it (if there is a matching rule). - */ - for (np = nat_list; np; np = np->in_next) - if ((np->in_ifp == ifp) && - (!np->in_flags || (nflags & np->in_flags)) && - ((in.s_addr & np->in_outmsk) == np->in_outip) && - (np->in_redir & NAT_REDIRECT) && - (!np->in_pmin || np->in_pmin == dport)) { - if ((nat = nat_new(np, ip, fin, nflags, - NAT_INBOUND))) -#if IPFILTER_LOG - nat_log(nat, (u_short)np->in_redir); -#else - ; -#endif - break; - } - if (nat) { - if (natadd && fin->fin_fi.fi_fl & FI_FRAG) - ipfr_nat_newfrag(ip, fin, 0, nat); - (void) ap_check(ip, tcp, fin, nat); - - if (nflags != IPN_ICMPERR) - nat->nat_age = fr_defnatage; - - ip->ip_dst = nat->nat_inip; - nat->nat_bytes += ip->ip_len; - nat->nat_pkts++; - - /* - * Fix up checksums, not by recalculating them, but - * simply computing adjustments. - */ -#if SOLARIS || defined(__sgi) - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(&ip->ip_sum, nat->nat_ipsumd); - else - fix_outcksum(&ip->ip_sum, nat->nat_ipsumd); -#endif - if ((nflags & IPN_TCPUDP) && !(ip->ip_off & 0x1fff) && - !(fin->fin_fi.fi_fl & FI_SHORT)) { - - if (nat->nat_inport) - tcp->th_dport = nat->nat_inport; - - if (ip->ip_p == IPPROTO_TCP) { - csump = &tcp->th_sum; - fr_tcp_age(&nat->nat_age, - nat->nat_state, ip, fin,0); - /* - * Increase this because we may have - * "keep state" following this too and - * packet storms can occur if this is - * removed too quickly. - */ - if (nat->nat_age == fr_tcpclosed) - nat->nat_age = fr_tcplastack; - } else if (ip->ip_p == IPPROTO_UDP) { - udphdr_t *udp = (udphdr_t *)tcp; - - if (udp->uh_sum) - csump = &udp->uh_sum; - } else if (ip->ip_p == IPPROTO_ICMP) { - icmphdr_t *ic = (icmphdr_t *)tcp; - - csump = &ic->icmp_cksum; - } - if (csump) { - if (nat->nat_dir == NAT_OUTBOUND) - fix_incksum(csump, - nat->nat_sumd); - else - fix_outcksum(csump, - nat->nat_sumd); - } - } - nat_stats.ns_mapped[0]++; - MUTEX_EXIT(&ipf_nat); - return -2; - } - MUTEX_EXIT(&ipf_nat); - return 0; -} - - -/* - * Free all memory used by NAT structures allocated at runtime. - */ -void ip_natunload() -{ - MUTEX_ENTER(&ipf_nat); - (void) nat_clearlist(); - (void) nat_flushtable(); - (void) ap_unload(); - MUTEX_EXIT(&ipf_nat); -} - - -/* - * Slowly expire held state for NAT entries. Timeouts are set in - * expectation of this being called twice per second. - */ -void ip_natexpire() -{ - register struct nat *nat, **natp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - SPL_NET(s); - MUTEX_ENTER(&ipf_nat); - for (natp = &nat_instances; (nat = *natp); ) { - if (--nat->nat_age) { - natp = &nat->nat_next; - continue; - } - *natp = nat->nat_next; -#if IPFILTER_LOG - nat_log(nat, NL_EXPIRE); -#endif - nat_delete(nat); - nat_stats.ns_expire++; - } - - ap_expire(); - - MUTEX_EXIT(&ipf_nat); - SPL_X(s); -} - - -/* - */ -#ifdef __STDC__ -void ip_natsync(void *ifp) -#else -void ip_natsync(ifp) -void *ifp; -#endif -{ - register nat_t *nat; - register u_32_t sum1, sum2, sumd; - struct in_addr in; - ipnat_t *np; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - SPL_NET(s); - MUTEX_ENTER(&ipf_nat); - for (nat = nat_instances; nat; nat = nat->nat_next) - if ((ifp == nat->nat_ifp) && (np = nat->nat_ptr)) - if ((np->in_outmsk == 0xffffffff) && !np->in_nip) { - /* - * Change the map-to address to be the same - * as the new one. - */ - sum1 = nat->nat_outip.s_addr; - if (nat_ifpaddr(nat, ifp, &in) == -1) - nat->nat_outip.s_addr = htonl(in.s_addr); - sum2 = nat->nat_outip.s_addr; - - /* - * Readjust the checksum adjustment to take - * into account the new IP#. - * - * Do it twice - */ - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - - /* Do it twice */ - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - - /* Because ~1 == -2, We really need ~1 == -1 */ - if (sum1 > sum2) - sum2--; - sumd = sum2 - sum1; - sumd = (sumd & 0xffff) + (sumd >> 16); - sumd += nat->nat_sumd; - nat->nat_sumd = (sumd & 0xffff) + (sumd >> 16); - } - MUTEX_EXIT(&ipf_nat); - SPL_X(s); -} - - -#if IPFILTER_LOG -# ifdef __STDC__ -void nat_log(struct nat *nat, u_short type) -# else -void nat_log(nat, type) -struct nat *nat; -u_short type; -# endif -{ - struct ipnat *np; - struct natlog natl; - void *items[1]; - size_t sizes[1]; - int rulen, types[1]; - - natl.nl_inip = nat->nat_inip; - natl.nl_outip = nat->nat_outip; - natl.nl_origip = nat->nat_oip; - natl.nl_bytes = nat->nat_bytes; - natl.nl_pkts = nat->nat_pkts; - natl.nl_origport = nat->nat_oport; - natl.nl_inport = nat->nat_inport; - natl.nl_outport = nat->nat_outport; - natl.nl_type = type; - natl.nl_rule = -1; - if (nat->nat_ptr) { - for (rulen = 0, np = nat_list; np; np = np->in_next, rulen++) - if (np == nat->nat_ptr) { - natl.nl_rule = rulen; - break; - } - } - items[0] = &natl; - sizes[0] = sizeof(natl); - types[0] = 0; - - (void) ipllog(IPL_LOGNAT, 0, items, sizes, types, 1); -} -#endif diff --git a/bsd/netinet/ip_nat.h b/bsd/netinet/ip_nat.h deleted file mode 100644 index 5df61b662..000000000 --- a/bsd/netinet/ip_nat.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1995-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_nat.h 1.5 2/4/96 - */ - -#ifndef __IP_NAT_H__ -#define __IP_NAT_H__ - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#if defined(__STDC__) || defined(__GNUC__) -#define SIOCADNAT _IOW('r', 80, struct ipnat) -#define SIOCRMNAT _IOW('r', 81, struct ipnat) -#define SIOCGNATS _IOR('r', 82, struct natstat) -#define SIOCGNATL _IOWR('r', 83, struct natlookup) -#define SIOCGFRST _IOR('r', 84, struct ipfrstat) -#define SIOCGIPST _IOR('r', 85, struct ips_stat) -#define SIOCFLNAT _IOWR('r', 86, int) -#define SIOCCNATL _IOWR('r', 87, int) -#else -#define SIOCADNAT _IOW(r, 80, struct ipnat) -#define SIOCRMNAT _IOW(r, 81, struct ipnat) -#define SIOCGNATS _IOR(r, 82, struct natstat) -#define SIOCGNATL _IOWR(r, 83, struct natlookup) -#define SIOCGFRST _IOR(r, 84, struct ipfrstat) -#define SIOCGIPST _IOR(r, 85, struct ips_stat) -#define SIOCFLNAT _IOWR(r, 86, int) -#define SIOCCNATL _IOWR(r, 87, int) -#endif - -#define NAT_SIZE 367 -#ifndef APR_LABELLEN -#define APR_LABELLEN 16 -#endif - -typedef struct nat { - u_long nat_age; - int nat_flags; - u_32_t nat_sumd; - u_32_t nat_ipsumd; - void *nat_data; - struct in_addr nat_inip; - struct in_addr nat_outip; - struct in_addr nat_oip; /* other ip */ - U_QUAD_T nat_pkts; - U_QUAD_T nat_bytes; - u_short nat_oport; /* other port */ - u_short nat_inport; - u_short nat_outport; - u_short nat_use; - u_char nat_state[2]; - struct ipnat *nat_ptr; - struct nat *nat_next; - struct nat *nat_hnext[2]; - struct nat **nat_hstart[2]; - void *nat_ifp; - int nat_dir; -} nat_t; - -typedef struct ipnat { - struct ipnat *in_next; - void *in_ifp; - void *in_apr; - u_int in_space; - u_int in_use; - struct in_addr in_nextip; - u_short in_pnext; - u_short in_flags; - u_short in_port[2]; - struct in_addr in_in[2]; - struct in_addr in_out[2]; - int in_redir; /* 0 if it's a mapping, 1 if it's a hard redir */ - char in_ifname[IFNAMSIZ]; - char in_plabel[APR_LABELLEN]; /* proxy label */ - char in_p; /* protocol */ - u_short in_dport; -} ipnat_t; - -#define in_pmin in_port[0] /* Also holds static redir port */ -#define in_pmax in_port[1] -#define in_nip in_nextip.s_addr -#define in_inip in_in[0].s_addr -#define in_inmsk in_in[1].s_addr -#define in_outip in_out[0].s_addr -#define in_outmsk in_out[1].s_addr - -#define NAT_OUTBOUND 0 -#define NAT_INBOUND 1 - -#define NAT_MAP 0x01 -#define NAT_REDIRECT 0x02 -#define NAT_BIMAP (NAT_MAP|NAT_REDIRECT) - -#define IPN_CMPSIZ (sizeof(struct in_addr) * 4 + sizeof(u_short) * 3 + \ - sizeof(int) + IFNAMSIZ + APR_LABELLEN + sizeof(char)) - -typedef struct natlookup { - struct in_addr nl_inip; - struct in_addr nl_outip; - struct in_addr nl_realip; - int nl_flags; - u_short nl_inport; - u_short nl_outport; - u_short nl_realport; -} natlookup_t; - -typedef struct natstat { - u_long ns_mapped[2]; - u_long ns_rules; - u_long ns_added; - u_long ns_expire; - u_long ns_inuse; - u_long ns_logged; - u_long ns_logfail; - nat_t **ns_table[2]; - ipnat_t *ns_list; -} natstat_t; - -#define IPN_ANY 0x00 -#define IPN_TCP 0x01 -#define IPN_UDP 0x02 -#define IPN_TCPUDP 0x03 -#define IPN_DELETE 0x04 -#define IPN_ICMPERR 0x08 - - -typedef struct natlog { - struct in_addr nl_origip; - struct in_addr nl_outip; - struct in_addr nl_inip; - u_short nl_origport; - u_short nl_outport; - u_short nl_inport; - u_short nl_type; - int nl_rule; - U_QUAD_T nl_pkts; - U_QUAD_T nl_bytes; -} natlog_t; - - -#define NL_NEWMAP NAT_MAP -#define NL_NEWRDR NAT_REDIRECT -#define NL_EXPIRE 0xffff - - -extern void ip_natsync __P((void *)); -extern u_long fr_defnatage; -extern u_long fr_defnaticmpage; -extern nat_t *nat_table[2][NAT_SIZE]; -#if defined(__NetBSD__) || defined(__OpenBSD__) || (__FreeBSD_version >= 300003) -extern int nat_ioctl __P((caddr_t, u_long, int)); -#else -extern int nat_ioctl __P((caddr_t, int, int)); -#endif -extern nat_t *nat_new __P((ipnat_t *, ip_t *, fr_info_t *, u_short, int)); -extern nat_t *nat_outlookup __P((void *, int, struct in_addr, u_short, - struct in_addr, u_short)); -extern nat_t *nat_inlookup __P((void *, int, struct in_addr, u_short, - struct in_addr, u_short)); -extern nat_t *nat_lookupredir __P((natlookup_t *)); -extern nat_t *nat_lookupmapip __P((void *, int, struct in_addr, u_short, - struct in_addr, u_short)); -extern nat_t *nat_icmpinlookup __P((ip_t *, fr_info_t *)); -extern nat_t *nat_icmpin __P((ip_t *, fr_info_t *, int *)); - -extern int ip_natout __P((ip_t *, int, fr_info_t *)); -extern int ip_natin __P((ip_t *, int, fr_info_t *)); -extern void ip_natunload __P((void)), ip_natexpire __P((void)); -extern void nat_log __P((struct nat *, u_short)); -extern void fix_incksum __P((u_short *, u_32_t)); -extern void fix_outcksum __P((u_short *, u_32_t)); - -#endif /* __IP_NAT_H__ */ diff --git a/bsd/netinet/ip_output.c b/bsd/netinet/ip_output.c index 7f74f5998..1018b8d21 100644 --- a/bsd/netinet/ip_output.c +++ b/bsd/netinet/ip_output.c @@ -146,14 +146,10 @@ static int ip_pcbopts __P((int, struct mbuf **, struct mbuf *)); static int ip_setmoptions __P((struct sockopt *, struct ip_moptions **)); static u_long lo_dl_tag = 0; - -#if IPFILTER_LKM || IPFILTER -int ip_optcopy __P((struct ip *, struct ip *)); -extern int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); -#else static int ip_optcopy __P((struct ip *, struct ip *)); -#endif +void in_delayed_cksum(struct mbuf *m); +extern int apple_hwcksum_tx; extern struct protosw inetsw[]; @@ -179,7 +175,7 @@ ip_output(m0, opt, ro, flags, imo) int len, off, error = 0; struct sockaddr_in *dst; struct in_ifaddr *ia; - int isbroadcast; + int isbroadcast, sw_csum; #if IPSEC struct route iproute; struct socket *so; @@ -500,16 +496,6 @@ sendit: * - Wrap: fake packet's addr/port <unimpl.> * - Encapsulate: put it in another IP and send out. <unimp.> */ -#if IPFILTER || IPFILTER_LKM - if (fr_checkp) { - struct mbuf *m1 = m; - - if ((error = (*fr_checkp)(ip, hlen, ifp, 1, &m1)) || !m1) - goto done; - ip = mtod(m = m1, struct ip *); - } -#endif - #if COMPAT_IPFW if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, ifp, IP_NAT_OUT)) { error = EACCES; @@ -560,6 +546,22 @@ sendit: #endif #if IPDIVERT if (off > 0 && off < 0x10000) { /* Divert packet */ + + /* + * delayed checksums are not currently compatible + * with divert sockets. + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + if (m == NULL) + return(ENOMEM); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } + + /* Restore packet header fields to original values */ + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)ip->ip_off); + ip_divert_port = off & 0xffff ; (*ip_protox[IPPROTO_DIVERT]->pr_input)(m, 0); goto done; @@ -616,11 +618,17 @@ sendit: ip_fw_fwd_addr = dst; if (m->m_pkthdr.rcvif == NULL) m->m_pkthdr.rcvif = ifunit("lo0"); + + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + m->m_pkthdr.csum_flags |= + CSUM_DATA_VALID | CSUM_PSEUDO_HDR; + m0->m_pkthdr.csum_data = 0xffff; + } + m->m_pkthdr.csum_flags |= + CSUM_IP_CHECKED | CSUM_IP_VALID; ip->ip_len = htons((u_short)ip->ip_len); ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = 0; - - ip->ip_sum = in_cksum(m, hlen); + ip_input(m); goto done; @@ -732,9 +740,6 @@ pass: printf("ip_output: Invalid policy found. %d\n", sp->policy); } - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = 0; { struct ipsec_output_state state; @@ -747,6 +752,21 @@ pass: state.ro = ro; state.dst = (struct sockaddr *)dst; + ip->ip_sum = 0; + + /* + * delayed checksums are not currently compatible with IPsec + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + in_delayed_cksum(m); + if (m == NULL) + return(ENOMEM); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } + + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)ip->ip_off); + error = ipsec4_output(&state, sp, flags); m = state.m; @@ -809,14 +829,52 @@ pass: skip_ipsec: #endif /*IPSEC*/ + + sw_csum = m->m_pkthdr.csum_flags | CSUM_IP; + + + /* frames that can be checksumed by GMACE SUM16 HW: frame >64, no fragments, no UDP odd length */ + + if (apple_hwcksum_tx && (sw_csum & CSUM_DELAY_DATA) && (ifp->if_hwassist & CSUM_TCP_SUM16) + && (ip->ip_len > 50) && (ip->ip_len <= ifp->if_mtu) + && !((ip->ip_len & 0x1) && (sw_csum & CSUM_UDP)) ) { + + /* Apple GMAC HW, expects STUFF_OFFSET << 16 | START_OFFSET */ + u_short offset = (IP_VHL_HL(ip->ip_vhl) << 2) +14 ; /* IP+Enet header length */ + u_short csumprev= m->m_pkthdr.csum_data & 0xFFFF; + m->m_pkthdr.csum_flags = CSUM_DATA_VALID | CSUM_TCP_SUM16; /* for GMAC */ + m->m_pkthdr.csum_data = (csumprev + offset) << 16 ; + m->m_pkthdr.csum_data += offset; + sw_csum = CSUM_DELAY_IP; /* do IP hdr chksum in software */ + } + else { + if (ifp->if_hwassist & CSUM_TCP_SUM16) /* force SW checksuming */ + m->m_pkthdr.csum_flags = 0; + else { /* not Apple enet */ + m->m_pkthdr.csum_flags = sw_csum & ifp->if_hwassist; + sw_csum &= ~ifp->if_hwassist; + } + + if (sw_csum & CSUM_DELAY_DATA) { /* perform TCP/UDP checksuming now */ + in_delayed_cksum(m); + if (m == NULL) + return(ENOMEM); + sw_csum &= ~CSUM_DELAY_DATA; + } + } + /* - * If small enough for interface, can just send directly. + * If small enough for interface, or the interface will take + * care of the fragmentation for us, can just send directly. */ - if ((u_short)ip->ip_len <= ifp->if_mtu) { + if ((u_short)ip->ip_len <= ifp->if_mtu || + ifp->if_hwassist & CSUM_FRAGMENT) { + ip->ip_len = htons((u_short)ip->ip_len); ip->ip_off = htons((u_short)ip->ip_off); ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, hlen); + if (sw_csum & CSUM_DELAY_IP) + ip->ip_sum = in_cksum(m, hlen); error = dlil_output(dl_tag, m, (void *) ro->ro_rt, (struct sockaddr *)dst, 0); goto done; @@ -848,9 +906,24 @@ skip_ipsec: goto bad; } + /* + * if the interface will not calculate checksums on + * fragmented packets, then do it here. + */ + if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA && + (ifp->if_hwassist & CSUM_IP_FRAGS) == 0) { + in_delayed_cksum(m); + if (m == NULL) + return(ENOMEM); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } + + { int mhlen, firstlen = len; struct mbuf **mnext = &m->m_nextpkt; + int nfrags = 1; + /* * Loop through length of segment after first fragment, @@ -865,7 +938,7 @@ skip_ipsec: ipstat.ips_odropped++; goto sendorfree; } - m->m_flags |= (m0->m_flags & M_MCAST); + m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG; m->m_data += max_linkhdr; mhip = mtod(m, struct ip *); *mhip = *ip; @@ -891,13 +964,21 @@ skip_ipsec: } m->m_pkthdr.len = mhlen + len; m->m_pkthdr.rcvif = (struct ifnet *)0; + m->m_pkthdr.csum_flags = m0->m_pkthdr.csum_flags; mhip->ip_off = htons((u_short)mhip->ip_off); mhip->ip_sum = 0; - mhip->ip_sum = in_cksum(m, mhlen); + if (sw_csum & CSUM_DELAY_IP) + mhip->ip_sum = in_cksum(m, mhlen); *mnext = m; mnext = &m->m_nextpkt; - ipstat.ips_ofragments++; + nfrags++; } + ipstat.ips_ofragments += nfrags; + + /* set first/last markers for fragment chain */ + m0->m_flags |= M_FRAG; + m0->m_pkthdr.csum_data = nfrags; + /* * Update first fragment by trimming what's been copied out * and updating header, then send each fragment (in order). @@ -908,7 +989,8 @@ skip_ipsec: ip->ip_len = htons((u_short)m->m_pkthdr.len); ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); ip->ip_sum = 0; - ip->ip_sum = in_cksum(m, hlen); + if (sw_csum & CSUM_DELAY_IP) + ip->ip_sum = in_cksum(m, hlen); sendorfree: @@ -948,6 +1030,43 @@ bad: goto done; } +extern u_short in_chksum_skip(struct mbuf *, int, int); + +void +in_delayed_cksum(struct mbuf *m) +{ + struct ip *ip; + u_short csum, csum2, offset; + + ip = mtod(m, struct ip *); + offset = IP_VHL_HL(ip->ip_vhl) << 2 ; + + csum = in_cksum_skip(m, ip->ip_len, offset); + + if (csum == 0) + csum = 0xffff; + + offset += m->m_pkthdr.csum_data & 0xFFFF; /* checksum offset */ + + if (offset > ip->ip_len) /* bogus offset */ + return; + + if (offset + sizeof(u_short) > m->m_len) { + printf("delayed m_pullup, m->len: %d off: %d p: %d\n", + m->m_len, offset, ip->ip_p); + /* + * XXX + * this shouldn't happen, but if it does, the + * correct behavior may be to insert the checksum + * in the existing chain instead of rearranging it. + */ + if (m = m_pullup(m, offset + sizeof(u_short)) == 0) + return; + } + + *(u_short *)(m->m_data + offset) = csum; +} + /* * Insert IP options into preformed packet. * Adjust IP destination as required for IP source routing, @@ -1001,9 +1120,6 @@ ip_insertoptions(m, opt, phlen) * Copy options from ip to jp, * omitting those not copied during fragmentation. */ -#if !IPFILTER && !IPFILTER_LKM -static -#endif int ip_optcopy(ip, jp) struct ip *ip, *jp; @@ -1844,6 +1960,27 @@ ip_mloopback(ifp, m, dst, hlen) } #endif + + /* + * Mark checksum as valid or calculate checksum for loopback. + * + * This is done this way because we have to embed the ifp of + * the interface we will send the original copy of the packet + * out on in the mbuf. ip_input will check if_hwassist of the + * embedded ifp and ignore all csum_flags if if_hwassist is 0. + * The UDP checksum has not been calculated yet. + */ + if (copym->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { + if (ifp->if_hwassist) { + copym->m_pkthdr.csum_flags |= + CSUM_DATA_VALID | CSUM_PSEUDO_HDR | + CSUM_IP_CHECKED | CSUM_IP_VALID; + copym->m_pkthdr.csum_data = 0xffff; + } else + in_delayed_cksum(copym); + } + + /* * TedW: * We need to send all loopback traffic down to dlil in case diff --git a/bsd/netinet/ip_proxy.c b/bsd/netinet/ip_proxy.c deleted file mode 100644 index 8d645eb40..000000000 --- a/bsd/netinet/ip_proxy.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -#endif - -#if defined(__FreeBSD__) && defined(KERNEL) && !defined(_KERNEL) -# define _KERNEL -#endif - -#if !defined(_KERNEL) && !defined(KERNEL) -# include <stdio.h> -# include <string.h> -# include <stdlib.h> -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#if !defined(__FreeBSD__) -# include <sys/ioctl.h> -#endif -#include <sys/fcntl.h> -#include <sys/uio.h> -#ifndef linux -# include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) -# if !defined(linux) -# include <sys/systm.h> -# else -# include <linux/string.h> -# endif -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -# include <sys/kmem.h> -#endif -#if __FreeBSD__ > 2 -# include <sys/queue.h> -# include <sys/malloc.h> -#endif -#include <net/if.h> -#ifdef sun -# include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#ifndef linux -# include <netinet/ip_var.h> -#endif -#include <netinet/tcp.h> -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_state.h" - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -static ap_session_t *ap_find __P((ip_t *, tcphdr_t *)); -static ap_session_t *ap_new_session __P((aproxy_t *, ip_t *, tcphdr_t *, - fr_info_t *, nat_t *)); - -static int ap_matchsrcdst __P((ap_session_t *aps, struct in_addr src, - struct in_addr dst, void *tcp, u_short sport, - u_short dport)); - -#define AP_SESS_SIZE 53 - -#if defined(_KERNEL) && !defined(linux) -#include "netinet/ip_ftp_pxy.c" -#endif - -ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -aproxy_t ap_proxies[] = { -#if IPF_FTP_PROXY - { "ftp", (char)IPPROTO_TCP, 0, 0, ippr_ftp_init, ippr_ftp_in, ippr_ftp_out }, -#endif - { "", '\0', 0, 0, NULL, NULL } -}; - - -int ap_ok(ip, tcp, nat) -ip_t *ip; -tcphdr_t *tcp; -ipnat_t *nat; -{ - aproxy_t *apr = nat->in_apr; - u_short dport = nat->in_dport; - - if (!apr || (apr && (apr->apr_flags & APR_DELETE)) || - (ip->ip_p != apr->apr_p)) - return 0; - if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) - return 0; - return 1; -} - - -static int -ap_matchsrcdst(aps, src, dst, tcp, sport, dport) -ap_session_t *aps; -struct in_addr src, dst; -void *tcp; -u_short sport, dport; -{ - if (aps->aps_dst.s_addr == dst.s_addr) { - if ((aps->aps_src.s_addr == src.s_addr) && - (!tcp || (sport == aps->aps_sport) && - (dport == aps->aps_dport))) - return 1; - } else if (aps->aps_dst.s_addr == src.s_addr) { - if ((aps->aps_src.s_addr == dst.s_addr) && - (!tcp || (sport == aps->aps_dport) && - (dport == aps->aps_sport))) - return 1; - } - return 0; -} - - -static ap_session_t *ap_find(ip, tcp) -ip_t *ip; -tcphdr_t *tcp; -{ - register u_char p = ip->ip_p; - register ap_session_t *aps; - register u_short sp, dp; - register u_long hv; - struct in_addr src, dst; - - src = ip->ip_src, dst = ip->ip_dst; - sp = dp = 0; /* XXX gcc -Wunitialized */ - - hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr; - hv *= 651733; - if (tcp) { - sp = tcp->th_sport; - dp = tcp->th_dport; - hv ^= (sp + dp); - hv *= 5; - } - hv %= AP_SESS_SIZE; - - for (aps = ap_sess_tab[hv]; aps; aps = aps->aps_next) - if ((aps->aps_p == p) && - ap_matchsrcdst(aps, src, dst, tcp, sp, dp)) - break; - return aps; -} - - -/* - * Allocate a new application proxy structure and fill it in with the - * relevant details. call the init function once complete, prior to - * returning. - */ -static ap_session_t *ap_new_session(apr, ip, tcp, fin, nat) -aproxy_t *apr; -ip_t *ip; -tcphdr_t *tcp; -fr_info_t *fin; -nat_t *nat; -{ - register ap_session_t *aps; - u_short dport; - u_long hv; - - if (!apr || (apr && (apr->apr_flags & APR_DELETE)) || - (ip->ip_p != apr->apr_p)) - return NULL; - dport = nat->nat_ptr->in_dport; - if ((tcp && (tcp->th_dport != dport)) || (!tcp && dport)) - return NULL; - - hv = ip->ip_src.s_addr ^ ip->ip_dst.s_addr; - hv *= 651733; - if (tcp) { - hv ^= (tcp->th_sport + tcp->th_dport); - hv *= 5; - } - hv %= AP_SESS_SIZE; - - KMALLOC(aps, ap_session_t *, sizeof(*aps)); - if (!aps) - return NULL; - bzero((char *)aps, sizeof(*aps)); - aps->aps_apr = apr; - aps->aps_src = ip->ip_src; - aps->aps_dst = ip->ip_dst; - aps->aps_p = ip->ip_p; - aps->aps_tout = 1200; /* XXX */ - if (tcp) { - aps->aps_sport = tcp->th_sport; - aps->aps_dport = tcp->th_dport; - } - aps->aps_data = NULL; - aps->aps_psiz = 0; - aps->aps_next = ap_sess_tab[hv]; - ap_sess_tab[hv] = aps; - (void) (*apr->apr_init)(fin, ip, tcp, aps, nat); - return aps; -} - - -/* - * check to see if a packet should be passed through an active proxy routine - * if one has been setup for it. - */ -int ap_check(ip, tcp, fin, nat) -ip_t *ip; -tcphdr_t *tcp; -fr_info_t *fin; -nat_t *nat; -{ - ap_session_t *aps; - aproxy_t *apr; - int err; - - if (!(fin->fin_fi.fi_fl & FI_TCPUDP)) - tcp = NULL; - - if ((aps = ap_find(ip, tcp)) || - (aps = ap_new_session(nat->nat_ptr->in_apr, ip, tcp, fin, nat))) { - if (ip->ip_p == IPPROTO_TCP) { - /* - * verify that the checksum is correct. If not, then - * don't do anything with this packet. - */ - if (tcp->th_sum != fr_tcpsum(*(mb_t **)fin->fin_mp, - ip, tcp, ip->ip_len)) { - frstats[fin->fin_out].fr_tcpbad++; - return -1; - } - fr_tcp_age(&aps->aps_tout, aps->aps_state, ip, fin, - tcp->th_sport == aps->aps_sport); - } - - apr = aps->aps_apr; - err = 0; - if (fin->fin_out) { - if (apr->apr_outpkt) - err = (*apr->apr_outpkt)(fin, ip, tcp, - aps, nat); - } else { - if (apr->apr_inpkt) - err = (*apr->apr_inpkt)(fin, ip, tcp, - aps, nat); - } - if (err == 2) { - tcp->th_sum = fr_tcpsum(*(mb_t **)fin->fin_mp, ip, - tcp, ip->ip_len); - err = 0; - } - return err; - } - return -1; -} - - -aproxy_t *ap_match(pr, name) -u_char pr; -char *name; -{ - aproxy_t *ap; - - for (ap = ap_proxies; ap->apr_p; ap++) - if ((ap->apr_p == pr) && - !strncmp(name, ap->apr_label, sizeof(ap->apr_label))) { - ap->apr_ref++; - return ap; - } - return NULL; -} - - -void ap_free(ap) -aproxy_t *ap; -{ - ap->apr_ref--; -} - - -void aps_free(aps) -ap_session_t *aps; -{ - if (aps->aps_data && aps->aps_psiz) - KFREES(aps->aps_data, aps->aps_psiz); - KFREE(aps); -} - - -void ap_unload() -{ - ap_session_t *aps; - int i; - - for (i = 0; i < AP_SESS_SIZE; i++) - while ((aps = ap_sess_tab[i])) { - ap_sess_tab[i] = aps->aps_next; - aps_free(aps); - } -} - - -void ap_expire() -{ - ap_session_t *aps, **apsp; - int i; - - for (i = 0; i < AP_SESS_SIZE; i++) - for (apsp = &ap_sess_tab[i]; (aps = *apsp); ) { - aps->aps_tout--; - if (!aps->aps_tout) { - ap_sess_tab[i] = aps->aps_next; - aps_free(aps); - *apsp = aps->aps_next; - } else - apsp = &aps->aps_next; - } -} diff --git a/bsd/netinet/ip_proxy.h b/bsd/netinet/ip_proxy.h deleted file mode 100644 index 1447027e0..000000000 --- a/bsd/netinet/ip_proxy.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - */ - -#ifndef __IP_PROXY_H__ -#define __IP_PROXY_H__ - -#ifndef SOLARIS -#define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) -#endif - -#ifndef APR_LABELLEN -#define APR_LABELLEN 16 -#endif -#define AP_SESS_SIZE 53 - -struct nat; -struct ipnat; - -typedef struct ap_tcp { - u_short apt_sport; /* source port */ - u_short apt_dport; /* destination port */ - short apt_sel; /* seqoff/after set selector */ - short apt_seqoff[2]; /* sequence # difference */ - tcp_seq apt_after[2]; /* don't change seq-off until after this */ - u_char apt_state[2]; /* connection state */ -} ap_tcp_t; - -typedef struct ap_udp { - u_short apu_sport; /* source port */ - u_short apu_dport; /* destination port */ -} ap_udp_t; - -typedef struct ap_session { - struct aproxy *aps_apr; - struct in_addr aps_src; /* source IP# */ - struct in_addr aps_dst; /* destination IP# */ - u_char aps_p; /* protocol */ - union { - struct ap_tcp apu_tcp; - struct ap_udp apu_udp; - } aps_un; - u_int aps_flags; - QUAD_T aps_bytes; /* bytes sent */ - QUAD_T aps_pkts; /* packets sent */ - u_long aps_tout; /* time left before expiring */ - void *aps_data; /* private data */ - int aps_psiz; /* size of private data */ - struct ap_session *aps_next; -} ap_session_t ; - -#define aps_sport aps_un.apu_tcp.apt_sport -#define aps_dport aps_un.apu_tcp.apt_dport -#define aps_sel aps_un.apu_tcp.apt_sel -#define aps_seqoff aps_un.apu_tcp.apt_seqoff -#define aps_after aps_un.apu_tcp.apt_after -#define aps_state aps_un.apu_tcp.apt_state - - -typedef struct aproxy { - char apr_label[APR_LABELLEN]; /* Proxy label # */ - u_char apr_p; /* protocol */ - int apr_ref; /* +1 per rule referencing it */ - int apr_flags; - int (* apr_init) __P((fr_info_t *, ip_t *, tcphdr_t *, - ap_session_t *, struct nat *)); - int (* apr_inpkt) __P((fr_info_t *, ip_t *, tcphdr_t *, - ap_session_t *, struct nat *)); - int (* apr_outpkt) __P((fr_info_t *, ip_t *, tcphdr_t *, - ap_session_t *, struct nat *)); -} aproxy_t; - -#define APR_DELETE 1 - - -extern ap_session_t *ap_sess_tab[AP_SESS_SIZE]; -extern aproxy_t ap_proxies[]; - -extern int ap_ok __P((ip_t *, tcphdr_t *, struct ipnat *)); -extern void ap_unload __P((void)); -extern void ap_free __P((aproxy_t *)); -extern void aps_free __P((ap_session_t *)); -extern int ap_check __P((ip_t *, tcphdr_t *, fr_info_t *, struct nat *)); -extern aproxy_t *ap_match __P((u_char, char *)); -extern void ap_expire __P((void)); - -#endif /* __IP_PROXY_H__ */ diff --git a/bsd/netinet/ip_state.c b/bsd/netinet/ip_state.c deleted file mode 100644 index b920df6c9..000000000 --- a/bsd/netinet/ip_state.c +++ /dev/null @@ -1,821 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1995-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - */ -#if !defined(lint) -/* static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-1995 Darren Reed"; */ -#endif - -#include "opt_ipfilter.h" -#if defined(KERNEL) && !defined(_KERNEL) -#define _KERNEL -#endif -#define __FreeBSD_version 300000 /* it's a hack, but close enough */ - -#if !defined(_KERNEL) && !defined(KERNEL) && !defined(__KERNEL__) -# include <stdlib.h> -# include <string.h> -#else -# ifdef linux -# include <linux/kernel.h> -# include <linux/module.h> -# endif -#endif -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#if defined(KERNEL) && (__FreeBSD_version >= 220000) -# include <sys/filio.h> -# include <sys/fcntl.h> -# include <sys/malloc.h> -#else -# include <sys/ioctl.h> -#endif -#include <sys/time.h> -#include <sys/uio.h> -#ifndef linux -#include <sys/protosw.h> -#endif -#include <sys/socket.h> -#if defined(_KERNEL) && !defined(linux) -# include <sys/systm.h> -#endif -#if !defined(__SVR4) && !defined(__svr4__) -# ifndef linux -# include <sys/mbuf.h> -# endif -#else -# include <sys/filio.h> -# include <sys/byteorder.h> -# include <sys/dditypes.h> -# include <sys/stream.h> -# include <sys/kmem.h> -#endif - -#include <net/if.h> -#if sun -#include <net/af.h> -#endif -#include <net/route.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> -#ifndef linux -# include <netinet/ip_var.h> -# include <netinet/tcp_fsm.h> -#endif -#include <netinet/udp.h> -#include <netinet/ip_icmp.h> -#include "netinet/ip_compat.h" -#include <netinet/tcpip.h> -#include "netinet/ip_fil.h" -#include "netinet/ip_nat.h" -#include "netinet/ip_frag.h" -#include "netinet/ip_proxy.h" -#include "netinet/ip_state.h" -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif - -#define TCP_CLOSE (TH_FIN|TH_RST) - -static ipstate_t *ips_table[IPSTATE_SIZE]; -static int ips_num = 0; -static ips_stat_t ips_stats; -#if (SOLARIS || defined(__sgi)) && defined(_KERNEL) -extern kmutex_t ipf_state; -#endif - -static int fr_matchsrcdst __P((ipstate_t *, struct in_addr, struct in_addr, - fr_info_t *, void *, u_short, u_short)); -static int fr_state_flush __P((int)); -static ips_stat_t *fr_statetstats __P((void)); - - -#define FIVE_DAYS (2 * 5 * 86400) /* 5 days: half closed session */ - -u_long fr_tcpidletimeout = FIVE_DAYS, - fr_tcpclosewait = 60, - fr_tcplastack = 20, - fr_tcptimeout = 120, - fr_tcpclosed = 1, - fr_udptimeout = 120, - fr_icmptimeout = 120; - - -static ips_stat_t *fr_statetstats() -{ - ips_stats.iss_active = ips_num; - ips_stats.iss_table = ips_table; - return &ips_stats; -} - - -/* - * flush state tables. two actions currently defined: - * which == 0 : flush all state table entries - * which == 1 : flush TCP connections which have started to close but are - * stuck for some reason. - */ -static int fr_state_flush(which) -int which; -{ - register int i; - register ipstate_t *is, **isp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - int delete, removed = 0; - - SPL_NET(s); - MUTEX_ENTER(&ipf_state); - for (i = 0; i < IPSTATE_SIZE; i++) - for (isp = &ips_table[i]; (is = *isp); ) { - delete = 0; - - switch (which) - { - case 0 : - delete = 1; - break; - case 1 : - if ((is->is_p == IPPROTO_TCP) && - (((is->is_state[0] <= TCPS_ESTABLISHED) && - (is->is_state[1] > TCPS_ESTABLISHED)) || - ((is->is_state[1] <= TCPS_ESTABLISHED) && - (is->is_state[0] > TCPS_ESTABLISHED)))) - delete = 1; - break; - } - - if (delete) { - *isp = is->is_next; - if (is->is_p == IPPROTO_TCP) - ips_stats.iss_fin++; - else - ips_stats.iss_expire++; -#if IPFILTER_LOG - ipstate_log(is, ISL_FLUSH); -#endif - KFREE(is); - ips_num--; - removed++; - } else - isp = &is->is_next; - } - MUTEX_EXIT(&ipf_state); - SPL_X(s); - return removed; -} - - -int fr_state_ioctl(data, cmd, mode) -caddr_t data; -#if defined(__NetBSD__) || defined(__OpenBSD__) -u_long cmd; -#else -int cmd; -#endif -int mode; -{ - int arg, ret, error = 0; - - switch (cmd) - { - case SIOCIPFFL : - IRCOPY(data, (caddr_t)&arg, sizeof(arg)); - if (arg == 0 || arg == 1) { - ret = fr_state_flush(arg); - IWCOPY((caddr_t)&ret, data, sizeof(ret)); - } else - error = EINVAL; - break; - case SIOCGIPST : - IWCOPY((caddr_t)fr_statetstats(), data, sizeof(ips_stat_t)); - break; - case FIONREAD : -#if IPFILTER_LOG - IWCOPY((caddr_t)&iplused[IPL_LOGSTATE], (caddr_t)data, - sizeof(iplused[IPL_LOGSTATE])); -#endif - break; - default : - return EINVAL; - } - return error; -} - - -/* - * Create a new ipstate structure and hang it off the hash table. - */ -int fr_addstate(ip, fin, pass) -ip_t *ip; -fr_info_t *fin; -u_int pass; -{ - ipstate_t ips; - register ipstate_t *is = &ips; - register u_int hv; - - if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT)) - return -1; - if (ips_num == IPSTATE_MAX) { - ips_stats.iss_max++; - return -1; - } - ips.is_age = 1; - ips.is_state[0] = 0; - ips.is_state[1] = 0; - /* - * Copy and calculate... - */ - hv = (is->is_p = ip->ip_p); - hv += (is->is_src.s_addr = ip->ip_src.s_addr); - hv += (is->is_dst.s_addr = ip->ip_dst.s_addr); - - switch (ip->ip_p) - { - case IPPROTO_ICMP : - { - struct icmp *ic = (struct icmp *)fin->fin_dp; - - switch (ic->icmp_type) - { - case ICMP_ECHO : - is->is_icmp.ics_type = ICMP_ECHOREPLY; /* XXX */ - hv += (is->is_icmp.ics_id = ic->icmp_id); - hv += (is->is_icmp.ics_seq = ic->icmp_seq); - break; - case ICMP_TSTAMP : - case ICMP_IREQ : - case ICMP_MASKREQ : - is->is_icmp.ics_type = ic->icmp_type + 1; - break; - default : - return -1; - } - ips_stats.iss_icmp++; - is->is_age = fr_icmptimeout; - break; - } - case IPPROTO_TCP : - { - register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - - /* - * The endian of the ports doesn't matter, but the ack and - * sequence numbers do as we do mathematics on them later. - */ - hv += (is->is_dport = tcp->th_dport); - hv += (is->is_sport = tcp->th_sport); - is->is_seq = ntohl(tcp->th_seq); - is->is_ack = ntohl(tcp->th_ack); - is->is_swin = ntohs(tcp->th_win); - is->is_dwin = is->is_swin; /* start them the same */ - ips_stats.iss_tcp++; - /* - * If we're creating state for a starting connection, start the - * timer on it as we'll never see an error if it fails to - * connect. - */ - if ((tcp->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) - is->is_ack = 0; /* Trumpet WinSock 'ism */ - fr_tcp_age(&is->is_age, is->is_state, ip, fin, - tcp->th_sport == is->is_sport); - break; - } - case IPPROTO_UDP : - { - register tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - - hv += (is->is_dport = tcp->th_dport); - hv += (is->is_sport = tcp->th_sport); - ips_stats.iss_udp++; - is->is_age = fr_udptimeout; - break; - } - default : - return -1; - } - - KMALLOC(is, ipstate_t *, sizeof(*is)); - if (is == NULL) { - ips_stats.iss_nomem++; - return -1; - } - bcopy((char *)&ips, (char *)is, sizeof(*is)); - hv %= IPSTATE_SIZE; - MUTEX_ENTER(&ipf_state); - - is->is_pass = pass; - is->is_pkts = 1; - is->is_bytes = ip->ip_len; - /* - * Copy these from the rule itself. - */ - is->is_opt = fin->fin_fr->fr_ip.fi_optmsk; - is->is_optmsk = fin->fin_fr->fr_mip.fi_optmsk; - is->is_sec = fin->fin_fr->fr_ip.fi_secmsk; - is->is_secmsk = fin->fin_fr->fr_mip.fi_secmsk; - is->is_auth = fin->fin_fr->fr_ip.fi_auth; - is->is_authmsk = fin->fin_fr->fr_mip.fi_auth; - is->is_flags = fin->fin_fr->fr_ip.fi_fl; - is->is_flags |= fin->fin_fr->fr_mip.fi_fl << 4; - /* - * add into table. - */ - is->is_next = ips_table[hv]; - ips_table[hv] = is; - if (fin->fin_out) { - is->is_ifpin = NULL; - is->is_ifpout = fin->fin_ifp; - } else { - is->is_ifpin = fin->fin_ifp; - is->is_ifpout = NULL; - } - if (pass & FR_LOGFIRST) - is->is_pass &= ~(FR_LOGFIRST|FR_LOG); - ips_num++; -#if IPFILTER_LOG - ipstate_log(is, ISL_NEW); -#endif - MUTEX_EXIT(&ipf_state); - if (fin->fin_fi.fi_fl & FI_FRAG) - ipfr_newfrag(ip, fin, pass ^ FR_KEEPSTATE); - return 0; -} - - -/* - * check to see if a packet with TCP headers fits within the TCP window. - * change timeout depending on whether new packet is a SYN-ACK returning for a - * SYN or a RST or FIN which indicate time to close up shop. - */ -int fr_tcpstate(is, fin, ip, tcp) -register ipstate_t *is; -fr_info_t *fin; -ip_t *ip; -tcphdr_t *tcp; -{ - register int seqskew, ackskew; - register u_short swin, dwin; - register tcp_seq seq, ack; - int source; - - /* - * Find difference between last checked packet and this packet. - */ - seq = ntohl(tcp->th_seq); - ack = ntohl(tcp->th_ack); - source = (ip->ip_src.s_addr == is->is_src.s_addr); - - if (!(tcp->th_flags & TH_ACK)) /* Pretend an ack was sent */ - ack = source ? is->is_ack : is->is_seq; - - if (source) { - if (!is->is_seq) - /* - * Must be an outgoing SYN-ACK in reply to a SYN. - */ - is->is_seq = seq; - seqskew = seq - is->is_seq; - ackskew = ack - is->is_ack; - } else { - if (!is->is_ack) - /* - * Must be a SYN-ACK in reply to a SYN. - */ - is->is_ack = seq; - ackskew = seq - is->is_ack; - seqskew = ack - is->is_seq; - } - - /* - * Make skew values absolute - */ - if (seqskew < 0) - seqskew = -seqskew; - if (ackskew < 0) - ackskew = -ackskew; - - /* - * If the difference in sequence and ack numbers is within the - * window size of the connection, store these values and match - * the packet. - */ - if (source) { - swin = is->is_swin; - dwin = is->is_dwin; - } else { - dwin = is->is_swin; - swin = is->is_dwin; - } - - if ((seqskew <= dwin) && (ackskew <= swin)) { - if (source) { - is->is_seq = seq; - is->is_ack = ack; - is->is_swin = ntohs(tcp->th_win); - } else { - is->is_seq = ack; - is->is_ack = seq; - is->is_dwin = ntohs(tcp->th_win); - } - ips_stats.iss_hits++; - is->is_pkts++; - is->is_bytes += ip->ip_len; - /* - * Nearing end of connection, start timeout. - */ - fr_tcp_age(&is->is_age, is->is_state, ip, fin, source); - return 1; - } - return 0; -} - - -static int fr_matchsrcdst(is, src, dst, fin, tcp, sp, dp) -ipstate_t *is; -struct in_addr src, dst; -fr_info_t *fin; -void *tcp; -u_short sp, dp; -{ - int ret = 0, rev, out; - void *ifp; - - rev = (is->is_dst.s_addr != dst.s_addr); - ifp = fin->fin_ifp; - out = fin->fin_out; - - if (!rev) { - if (out) { - if (!is->is_ifpout) - is->is_ifpout = ifp; - } else { - if (!is->is_ifpin) - is->is_ifpin = ifp; - } - } else { - if (out) { - if (!is->is_ifpin) - is->is_ifpin = ifp; - } else { - if (!is->is_ifpout) - is->is_ifpout = ifp; - } - } - - if (!rev) { - if (((out && is->is_ifpout == ifp) || - (!out && is->is_ifpin == ifp)) && - (is->is_dst.s_addr == dst.s_addr) && - (is->is_src.s_addr == src.s_addr) && - (!tcp || (sp == is->is_sport) && - (dp == is->is_dport))) { - ret = 1; - } - } else { - if (((out && is->is_ifpin == ifp) || - (!out && is->is_ifpout == ifp)) && - (is->is_dst.s_addr == src.s_addr) && - (is->is_src.s_addr == dst.s_addr) && - (!tcp || (sp == is->is_dport) && - (dp == is->is_sport))) { - ret = 1; - } - } - - /* - * Whether or not this should be here, is questionable, but the aim - * is to get this out of the main line. - */ - if (ret) { - if (((fin->fin_fi.fi_optmsk & is->is_optmsk) != is->is_opt) || - ((fin->fin_fi.fi_secmsk & is->is_secmsk) != is->is_sec) || - ((fin->fin_fi.fi_auth & is->is_authmsk) != is->is_auth) || - ((fin->fin_fi.fi_fl & (is->is_flags >> 4)) != - (is->is_flags & 0xf))) - ret = 0; - } - return ret; -} - - -/* - * Check if a packet has a registered state. - */ -int fr_checkstate(ip, fin) -ip_t *ip; -fr_info_t *fin; -{ - register struct in_addr dst, src; - register ipstate_t *is, **isp; - register u_char pr; - struct icmp *ic; - tcphdr_t *tcp; - u_int hv, hlen, pass; - - if ((ip->ip_off & 0x1fff) || (fin->fin_fi.fi_fl & FI_SHORT)) - return 0; - - hlen = fin->fin_hlen; - tcp = (tcphdr_t *)((char *)ip + hlen); - ic = (struct icmp *)tcp; - hv = (pr = ip->ip_p); - hv += (src.s_addr = ip->ip_src.s_addr); - hv += (dst.s_addr = ip->ip_dst.s_addr); - - /* - * Search the hash table for matching packet header info. - */ - switch (ip->ip_p) - { - case IPPROTO_ICMP : - hv += ic->icmp_id; - hv += ic->icmp_seq; - hv %= IPSTATE_SIZE; - MUTEX_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) - if ((is->is_p == pr) && - (ic->icmp_id == is->is_icmp.ics_id) && - (ic->icmp_seq == is->is_icmp.ics_seq) && - fr_matchsrcdst(is, src, dst, fin, NULL, 0, 0)) { - if (is->is_icmp.ics_type != ic->icmp_type) - continue; - is->is_age = fr_icmptimeout; - is->is_pkts++; - is->is_bytes += ip->ip_len; - ips_stats.iss_hits++; - pass = is->is_pass; - MUTEX_EXIT(&ipf_state); - return pass; - } - MUTEX_EXIT(&ipf_state); - break; - case IPPROTO_TCP : - { - register u_short dport = tcp->th_dport, sport = tcp->th_sport; - - hv += dport; - hv += sport; - hv %= IPSTATE_SIZE; - MUTEX_ENTER(&ipf_state); - for (isp = &ips_table[hv]; (is = *isp); isp = &is->is_next) - if ((is->is_p == pr) && - fr_matchsrcdst(is, src, dst, fin, tcp, - sport, dport)) { - if (fr_tcpstate(is, fin, ip, tcp)) { - pass = is->is_pass; -#ifdef _KERNEL - MUTEX_EXIT(&ipf_state); -#else - - if (tcp->th_flags & TCP_CLOSE) { - *isp = is->is_next; - isp = &ips_table[hv]; - KFREE(is); - } -#endif - return pass; - } - } - MUTEX_EXIT(&ipf_state); - break; - } - case IPPROTO_UDP : - { - register u_short dport = tcp->th_dport, sport = tcp->th_sport; - - hv += dport; - hv += sport; - hv %= IPSTATE_SIZE; - /* - * Nothing else to match on but ports. and IP#'s - */ - MUTEX_ENTER(&ipf_state); - for (is = ips_table[hv]; is; is = is->is_next) - if ((is->is_p == pr) && - fr_matchsrcdst(is, src, dst, fin, - tcp, sport, dport)) { - ips_stats.iss_hits++; - is->is_pkts++; - is->is_bytes += ip->ip_len; - is->is_age = fr_udptimeout; - pass = is->is_pass; - MUTEX_EXIT(&ipf_state); - return pass; - } - MUTEX_EXIT(&ipf_state); - break; - } - default : - break; - } - ips_stats.iss_miss++; - return 0; -} - - -/* - * Free memory in use by all state info. kept. - */ -void fr_stateunload() -{ - register int i; - register ipstate_t *is, **isp; - - MUTEX_ENTER(&ipf_state); - for (i = 0; i < IPSTATE_SIZE; i++) - for (isp = &ips_table[i]; (is = *isp); ) { - *isp = is->is_next; - KFREE(is); - } - MUTEX_EXIT(&ipf_state); -} - - -/* - * Slowly expire held state for thingslike UDP and ICMP. Timeouts are set - * in expectation of this being called twice per second. - */ -void fr_timeoutstate() -{ - register int i; - register ipstate_t *is, **isp; -#if defined(_KERNEL) && !SOLARIS - int s; -#endif - - SPL_NET(s); - MUTEX_ENTER(&ipf_state); - for (i = 0; i < IPSTATE_SIZE; i++) - for (isp = &ips_table[i]; (is = *isp); ) - if (is->is_age && !--is->is_age) { - *isp = is->is_next; - if (is->is_p == IPPROTO_TCP) - ips_stats.iss_fin++; - else - ips_stats.iss_expire++; -#if IPFILTER_LOG - ipstate_log(is, ISL_EXPIRE); -#endif - KFREE(is); - ips_num--; - } else - isp = &is->is_next; - MUTEX_EXIT(&ipf_state); - SPL_X(s); -} - - -/* - * Original idea freom Pradeep Krishnan for use primarily with NAT code. - * (pkrishna@netcom.com) - */ -void fr_tcp_age(age, state, ip, fin, dir) -u_long *age; -u_char *state; -ip_t *ip; -fr_info_t *fin; -int dir; -{ - tcphdr_t *tcp = (tcphdr_t *)fin->fin_dp; - u_char flags = tcp->th_flags; - int dlen, ostate; - - ostate = state[1 - dir]; - - dlen = ip->ip_len - fin->fin_hlen - (tcp->th_off << 2); - - if (flags & TH_RST) { - if (!(tcp->th_flags & TH_PUSH) && !dlen) { - *age = fr_tcpclosed; - state[dir] = TCPS_CLOSED; - } else { - *age = fr_tcpclosewait; - state[dir] = TCPS_CLOSE_WAIT; - } - return; - } - - *age = fr_tcptimeout; /* 1 min */ - - switch(state[dir]) - { - case TCPS_FIN_WAIT_2: - case TCPS_CLOSED: - if ((flags & TH_OPENING) == TH_OPENING) - state[dir] = TCPS_SYN_RECEIVED; - else if (flags & TH_SYN) - state[dir] = TCPS_SYN_SENT; - break; - case TCPS_SYN_RECEIVED: - if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) { - state[dir] = TCPS_ESTABLISHED; - current_active_connections++; - *age = fr_tcpidletimeout; - } - break; - case TCPS_SYN_SENT: - if ((flags & (TH_FIN|TH_ACK)) == TH_ACK) { - state[dir] = TCPS_ESTABLISHED; - current_active_connections++; - *age = fr_tcpidletimeout; - } - break; - case TCPS_ESTABLISHED: - if (flags & TH_FIN) { - state[dir] = TCPS_CLOSE_WAIT; - if (!(flags & TH_PUSH) && !dlen && - ostate > TCPS_ESTABLISHED) - *age = fr_tcplastack; - else - *age = fr_tcpclosewait; - } else - *age = fr_tcpidletimeout; - break; - case TCPS_CLOSE_WAIT: - if ((flags & TH_FIN) && !(flags & TH_PUSH) && !dlen && - ostate > TCPS_ESTABLISHED) { - *age = fr_tcplastack; - state[dir] = TCPS_LAST_ACK; - } else - *age = fr_tcpclosewait; - break; - case TCPS_LAST_ACK: - if (flags & TH_ACK) { - state[dir] = TCPS_FIN_WAIT_2; - if (!(flags & TH_PUSH) && !dlen && - ostate > TCPS_ESTABLISHED) - *age = fr_tcplastack; - else { - *age = fr_tcpclosewait; - state[dir] = TCPS_CLOSE_WAIT; - } - } - break; - } -} - - -#if IPFILTER_LOG -void ipstate_log(is, type) -struct ipstate *is; -u_short type; -{ - struct ipslog ipsl; - void *items[1]; - size_t sizes[1]; - int types[1]; - - ipsl.isl_pkts = is->is_pkts; - ipsl.isl_bytes = is->is_bytes; - ipsl.isl_src = is->is_src; - ipsl.isl_dst = is->is_dst; - ipsl.isl_p = is->is_p; - ipsl.isl_flags = is->is_flags; - ipsl.isl_type = type; - if (ipsl.isl_p == IPPROTO_TCP || ipsl.isl_p == IPPROTO_UDP) { - ipsl.isl_sport = is->is_sport; - ipsl.isl_dport = is->is_dport; - } else if (ipsl.isl_p == IPPROTO_ICMP) - ipsl.isl_itype = is->is_icmp.ics_type; - else { - ipsl.isl_ps.isl_filler[0] = 0; - ipsl.isl_ps.isl_filler[1] = 0; - } - items[0] = &ipsl; - sizes[0] = sizeof(ipsl); - types[0] = 0; - - (void) ipllog(IPL_LOGSTATE, 0, items, sizes, types, 1); -} -#endif diff --git a/bsd/netinet/ip_state.h b/bsd/netinet/ip_state.h deleted file mode 100644 index f27f94cb1..000000000 --- a/bsd/netinet/ip_state.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (C) 1995-1997 by Darren Reed. - * - * Redistribution and use in source and binary forms are permitted - * provided that this notice is preserved and due credit is given - * to the original author and the contributors. - * - * @(#)ip_state.h 1.3 1/12/96 (C) 1995 Darren Reed - */ -#ifndef __IP_STATE_H__ -#define __IP_STATE_H__ - -#define IPSTATE_SIZE 257 -#define IPSTATE_MAX 2048 /* Maximum number of states held */ - -#define PAIRS(s1,d1,s2,d2) ((((s1) == (s2)) && ((d1) == (d2))) ||\ - (((s1) == (d2)) && ((d1) == (s2)))) -#define IPPAIR(s1,d1,s2,d2) PAIRS((s1).s_addr, (d1).s_addr, \ - (s2).s_addr, (d2).s_addr) - - -typedef struct udpstate { - u_short us_sport; - u_short us_dport; -} udpstate_t; - -typedef struct icmpstate { - u_short ics_id; - u_short ics_seq; - u_char ics_type; -} icmpstate_t; - -typedef struct tcpstate { - u_short ts_sport; - u_short ts_dport; - u_long ts_seq; - u_long ts_ack; - u_short ts_swin; - u_short ts_dwin; - u_char ts_state[2]; -} tcpstate_t; - -typedef struct ipstate { - struct ipstate *is_next; - u_long is_age; - u_int is_pass; - U_QUAD_T is_pkts; - U_QUAD_T is_bytes; - void *is_ifpin; - void *is_ifpout; - struct in_addr is_src; - struct in_addr is_dst; - u_char is_p; - u_char is_flags; - u_32_t is_opt; - u_32_t is_optmsk; - u_short is_sec; - u_short is_secmsk; - u_short is_auth; - u_short is_authmsk; - union { - icmpstate_t is_ics; - tcpstate_t is_ts; - udpstate_t is_us; - } is_ps; -} ipstate_t; - -#define is_icmp is_ps.is_ics -#define is_tcp is_ps.is_ts -#define is_udp is_ps.is_us -#define is_seq is_tcp.ts_seq -#define is_ack is_tcp.ts_ack -#define is_dwin is_tcp.ts_dwin -#define is_swin is_tcp.ts_swin -#define is_sport is_tcp.ts_sport -#define is_dport is_tcp.ts_dport -#define is_state is_tcp.ts_state - -#define TH_OPENING (TH_SYN|TH_ACK) - - -typedef struct ipslog { - U_QUAD_T isl_pkts; - U_QUAD_T isl_bytes; - struct in_addr isl_src; - struct in_addr isl_dst; - u_char isl_p; - u_char isl_flags; - u_short isl_type; - union { - u_short isl_filler[2]; - u_short isl_ports[2]; - u_short isl_icmp; - } isl_ps; -} ipslog_t; - -#define isl_sport isl_ps.isl_ports[0] -#define isl_dport isl_ps.isl_ports[1] -#define isl_itype isl_ps.isl_icmp - -#define ISL_NEW 0 -#define ISL_EXPIRE 0xffff -#define ISL_FLUSH 0xfffe - - -typedef struct ips_stat { - u_long iss_hits; - u_long iss_miss; - u_long iss_max; - u_long iss_tcp; - u_long iss_udp; - u_long iss_icmp; - u_long iss_nomem; - u_long iss_expire; - u_long iss_fin; - u_long iss_active; - u_long iss_logged; - u_long iss_logfail; - ipstate_t **iss_table; -} ips_stat_t; - - -extern u_long fr_tcpidletimeout; -extern u_long fr_tcpclosewait; -extern u_long fr_tcplastack; -extern u_long fr_tcptimeout; -extern u_long fr_tcpclosed; -extern u_long fr_udptimeout; -extern u_long fr_icmptimeout; -extern int fr_tcpstate __P((ipstate_t *, fr_info_t *, ip_t *, tcphdr_t *)); -extern int fr_addstate __P((ip_t *, fr_info_t *, u_int)); -extern int fr_checkstate __P((ip_t *, fr_info_t *)); -extern void fr_timeoutstate __P((void)); -extern void fr_tcp_age __P((u_long *, u_char *, ip_t *, fr_info_t *, int)); -extern void fr_stateunload __P((void)); -extern void ipstate_log __P((struct ipstate *, u_short)); -#if defined(__NetBSD__) || defined(__OpenBSD__) -extern int fr_state_ioctl __P((caddr_t, u_long, int)); -#else -extern int fr_state_ioctl __P((caddr_t, int, int)); -#endif - -#endif /* __IP_STATE_H__ */ diff --git a/bsd/netinet/ip_var.h b/bsd/netinet/ip_var.h index b994281ca..c7930df60 100644 --- a/bsd/netinet/ip_var.h +++ b/bsd/netinet/ip_var.h @@ -81,6 +81,7 @@ struct ipq { u_short ipq_id; /* sequence id for reassembly */ struct mbuf *ipq_frags; /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; + u_long reserved[4]; /* for future use */ #if IPDIVERT u_short ipq_divert; /* divert protocol port */ u_short ipq_div_cookie; /* divert protocol cookie */ diff --git a/bsd/netinet/raw_ip.c b/bsd/netinet/raw_ip.c index c305d431f..34b69fd68 100644 --- a/bsd/netinet/raw_ip.c +++ b/bsd/netinet/raw_ip.c @@ -153,7 +153,6 @@ rip_input(m, iphlen) register struct inpcb *inp; struct inpcb *last = 0; struct mbuf *opts = 0; - short need_wakeup = 0; ripsrc.sin_addr = ip->ip_src; LIST_FOREACH(inp, &ripcb, inp_list) { @@ -189,7 +188,7 @@ rip_input(m, iphlen) m_freem(opts); } else { /* kprintf("rip_input calling sorwakeup\n"); */ - need_wakeup++; + sorwakeup(last->inp_socket); } opts = 0; } @@ -213,15 +212,13 @@ rip_input(m, iphlen) m_freem(opts); } else { /* kprintf("rip_input calling sorwakeup\n"); */ - need_wakeup++; + sorwakeup(last->inp_socket); } } else { m_freem(m); ipstat.ips_noproto++; ipstat.ips_delivered--; } - if (need_wakeup) - sorwakeup(last->inp_socket); } /* @@ -695,6 +692,11 @@ rip_pcblist SYSCTL_HANDLER_ARGS error = SYSCTL_OUT(req, &xig, sizeof xig); if (error) return error; + /* + * We are done if there is no pcb + */ + if (n == 0) + return 0; inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK); if (inp_list == 0) diff --git a/bsd/netinet/tcp_fsm.h b/bsd/netinet/tcp_fsm.h index 209f06e4b..bc3f5dab8 100644 --- a/bsd/netinet/tcp_fsm.h +++ b/bsd/netinet/tcp_fsm.h @@ -105,10 +105,18 @@ * if all data queued for output is included in the segment. */ static u_char tcp_outflags[TCP_NSTATES] = { - TH_RST|TH_ACK, 0, TH_SYN, TH_SYN|TH_ACK, - TH_ACK, TH_ACK, - TH_FIN|TH_ACK, TH_ACK, TH_FIN|TH_ACK, TH_ACK, TH_ACK, -}; + TH_RST|TH_ACK, /* 0, CLOSED */ + 0, /* 1, LISTEN */ + TH_SYN, /* 2, SYN_SENT */ + TH_SYN|TH_ACK, /* 3, SYN_RECEIVED */ + TH_ACK, /* 4, ESTABLISHED */ + TH_ACK, /* 5, CLOSE_WAIT */ + TH_FIN|TH_ACK, /* 6, FIN_WAIT_1 */ + TH_FIN|TH_ACK, /* 7, CLOSING */ + TH_FIN|TH_ACK, /* 8, LAST_ACK */ + TH_ACK, /* 9, FIN_WAIT_2 */ + TH_ACK, /* 10, TIME_WAIT */ +}; #endif #if KPROF diff --git a/bsd/netinet/tcp_input.c b/bsd/netinet/tcp_input.c index cab8916e1..599c6e0d9 100644 --- a/bsd/netinet/tcp_input.c +++ b/bsd/netinet/tcp_input.c @@ -125,6 +125,7 @@ struct tcphdr tcp_savetcp; static int tcprexmtthresh = 3; tcp_seq tcp_iss; tcp_cc tcp_ccgen; +extern int apple_hwcksum_rx; struct tcpstat tcpstat; SYSCTL_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, @@ -365,9 +366,9 @@ present: ND6_HINT(tp); #endif - KERNEL_DEBUG(DBG_LAYER_END, ((ti->ti_dport << 16) | ti->ti_sport), - (((ti->ti_src.s_addr & 0xffff) << 16) | (ti->ti_dst.s_addr & 0xffff)), - ti->ti_seq, ti->ti_ack, ti->ti_win); + KERNEL_DEBUG(DBG_LAYER_END, ((th->th_dport << 16) | th->th_sport), + (((thtoti(th)->ti_src.s_addr & 0xffff) << 16) | (thtoti(th)->ti_dst.s_addr & 0xffff)), + th->th_seq, th->th_ack, th->th_win); sorwakeup(so); return (flags); @@ -442,9 +443,9 @@ tcp_input(m, off) */ th = mtod(m, struct tcpiphdr *); - KERNEL_DEBUG(DBG_LAYER_BEG, ((ti->ti_dport << 16) | ti->ti_sport), - (((ti->ti_src.s_addr & 0xffff) << 16) | (ti->ti_dst.s_addr & 0xffff)), - ti->ti_seq, ti->ti_ack, ti->ti_win); + KERNEL_DEBUG(DBG_LAYER_BEG, ((th->th_dport << 16) | th->th_sport), + (((thtoti(th)->ti_src.s_addr & 0xffff) << 16) | (thtoti(th)->ti_dst.s_addr & 0xffff)), + th->th_seq, th->th_ack, th->th_win); #if INET6 if (isipv6) { @@ -491,6 +492,8 @@ tcp_input(m, off) if (off > sizeof (struct ip)) { ip_stripoptions(m, (struct mbuf *)0); off = sizeof(struct ip); + if (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16) + m->m_pkthdr.csum_flags = 0; /* invalidate hwcksuming */ } if (m->m_len < lgminh) { if ((m = m_pullup(m, lgminh)) == 0) { @@ -500,17 +503,42 @@ tcp_input(m, off) } ip = mtod(m, struct ip *); ipov = (struct ipovly *)ip; - - /* - * Checksum extended TCP header and data. - */ + th = (struct tcphdr *)((caddr_t)ip + off); tilen = ip->ip_len; len = sizeof (struct ip) + tilen; - bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); - ipov->ih_len = (u_short)tilen; - HTONS(ipov->ih_len); - th = (struct tcphdr *)((caddr_t)ip + off); - th->th_sum = in_cksum(m, len); + + if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { + + if (apple_hwcksum_rx && (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16)) { + u_short pseudo; + bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); + ipov->ih_len = (u_short)tilen; + HTONS(ipov->ih_len); + pseudo = in_cksum(m, sizeof (struct ip)); + th->th_sum = in_addword(pseudo, (m->m_pkthdr.csum_data & 0xFFFF)); + } + else { + if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) + th->th_sum = m->m_pkthdr.csum_data; + else goto dotcpcksum; + } + th->th_sum ^= 0xffff; + + } else { + /* + * Checksum extended TCP header and data. + */ +dotcpcksum: + if (th->th_sum) { + len = sizeof (struct ip) + tilen; + bzero(ipov->ih_x1, sizeof(ipov->ih_x1)); + ipov->ih_len = (u_short)tilen; + HTONS(ipov->ih_len); + th = (struct tcphdr *)((caddr_t)ip + off); + th->th_sum = in_cksum(m, len); + } + } + if (th->th_sum) { tcpstat.tcps_rcvbadsum++; goto drop; @@ -1027,7 +1055,7 @@ findpcb: #endif sbappend(&so->so_rcv, m); KERNEL_DEBUG(DBG_LAYER_END, ((th->th_dport << 16) | th->th_sport), - (((th->th_src.s_addr & 0xffff) << 16) | (th->th_dst.s_addr & 0xffff)), + (((thtoti(th)->ti_src.s_addr & 0xffff) << 16) | (thtoti(th)->ti_dst.s_addr & 0xffff)), th->th_seq, th->th_ack, th->th_win); if (tcp_delack_enabled) { if (last_active_conn_count > DELACK_BITMASK_THRESH) @@ -1187,9 +1215,14 @@ findpcb: tcp_mss(tp, to.to_maxseg, isipv6); /* sets t_maxseg */ if (iss) tp->iss = iss; - else + else { +#ifdef TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/2; tp->iss = tcp_iss; - tcp_iss += TCP_ISSINCR/4; +#else + tp->iss = tcp_rndiss_next(); +#endif /* TCP_COMPAT_42 */ + } tp->irs = th->th_seq; tcp_sendseqinit(tp); tcp_rcvseqinit(tp); @@ -1720,7 +1753,11 @@ trimthenstep6: if (thflags & TH_SYN && tp->t_state == TCPS_TIME_WAIT && SEQ_GT(th->th_seq, tp->rcv_nxt)) { +#ifdef TCP_COMPAT_42 iss = tp->rcv_nxt + TCP_ISSINCR; +#else + iss = tcp_rndiss_next(); +#endif /* TCP_COMPAT_42 */ tp = tcp_close(tp); goto findpcb; } @@ -2179,7 +2216,7 @@ dodata: /* XXX */ if (tp->t_flags & TF_DELACK) { KERNEL_DEBUG(DBG_LAYER_END, ((th->th_dport << 16) | th->th_sport), - (((th->th_src.s_addr & 0xffff) << 16) | (th->th_dst.s_addr & 0xffff)), + (((thtoti(th)->ti_src.s_addr & 0xffff) << 16) | (thtoti(th)->ti_dst.s_addr & 0xffff)), th->th_seq, th->th_ack, th->th_win); } /* diff --git a/bsd/netinet/tcp_output.c b/bsd/netinet/tcp_output.c index 14535b6bb..c648029c6 100644 --- a/bsd/netinet/tcp_output.c +++ b/bsd/netinet/tcp_output.c @@ -131,9 +131,9 @@ tcp_output(tp) KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_START, 0,0,0,0,0); KERNEL_DEBUG(DBG_LAYER_BEG, - ((tp->t_template->th_dport << 16) | tp->t_template->th_sport), - (((tp->t_template->th_src.s_addr & 0xffff) << 16) | - (tp->t_template->th_dst.s_addr & 0xffff)), + ((tp->t_template->tt_dport << 16) | tp->t_template->tt_sport), + (((tp->t_template->tt_src.s_addr & 0xffff) << 16) | + (tp->t_template->tt_dst.s_addr & 0xffff)), 0,0,0); /* @@ -150,6 +150,10 @@ tcp_output(tp) * slow start to get ack "clock" running again. */ tp->snd_cwnd = tp->t_maxseg; + + /* Never send data that's already been acked */ + if (SEQ_GT(tp->snd_una, tp->snd_nxt)) + tp->snd_nxt = tp->snd_una; again: sendalot = 0; off = tp->snd_nxt - tp->snd_una; @@ -711,15 +715,21 @@ send: th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), sizeof(struct tcphdr) + optlen + len); - } else { + } else #endif /* INET6 */ + { + if (len + optlen) ipov->ih_len = htons((u_short)(sizeof (struct tcphdr) + optlen + len)); - th->th_sum = in_cksum(m, (int)(hdrlen + len)); -#if INET6 + m->m_pkthdr.csum_flags = CSUM_TCP; + m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + if (len + optlen) { + th->th_sum = in_addword(th->th_sum, + htons((u_short)(optlen + len))); + } + } -#endif /* INET6 */ /* * In transmit state, time the transmission and arrange for @@ -841,8 +851,11 @@ send: ip->ip_ttl = tp->t_inpcb->inp_ip_ttl; /* XXX */ ip->ip_tos = tp->t_inpcb->inp_ip_tos; /* XXX */ +#define thtoti(x) \ + ((struct tcpiphdr *)(((char *)(x)) - (sizeof (struct ip)))) + KERNEL_DEBUG(DBG_LAYER_END, ((th->th_dport << 16) | th->th_sport), - (((th->th_src.s_addr & 0xffff) << 16) | (th->th_dst.s_addr & 0xffff)), + (((thtoti(th)->ti_src.s_addr & 0xffff) << 16) | (thtoti(th)->ti_dst.s_addr & 0xffff)), th->th_seq, th->th_ack, th->th_win); @@ -871,6 +884,9 @@ send: if (error) { out: if (error == ENOBUFS) { + if (!tp->t_timer[TCPT_REXMT] && + !tp->t_timer[TCPT_PERSIST]) + tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; tcp_quench(tp->t_inpcb, 0); KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, 0,0,0,0,0); return (0); diff --git a/bsd/netinet/tcp_seq.h b/bsd/netinet/tcp_seq.h index 032cff920..5281fc374 100644 --- a/bsd/netinet/tcp_seq.h +++ b/bsd/netinet/tcp_seq.h @@ -101,6 +101,7 @@ #ifdef KERNEL extern tcp_cc tcp_ccgen; /* global connection count */ +#ifdef TCP_COMPAT_42 /* * Increment for tcp_iss each second. * This is designed to increment at the standard 250 KB/s, @@ -116,6 +117,7 @@ extern tcp_cc tcp_ccgen; /* global connection count */ #define TCP_ISSINCR (122*1024 + tcp_random18()) extern tcp_seq tcp_iss; /* tcp initial send seq # */ +#endif /* TCP_COMPAT_42 */ #else #define TCP_ISSINCR (250*1024) /* increment for tcp_iss each second */ #endif /* KERNEL */ diff --git a/bsd/netinet/tcp_subr.c b/bsd/netinet/tcp_subr.c index 45ae7ffed..7cd45d421 100644 --- a/bsd/netinet/tcp_subr.c +++ b/bsd/netinet/tcp_subr.c @@ -109,6 +109,9 @@ #include <sys/kdebug.h> #define DBG_FNC_TCP_CLOSE NETDBG_CODE(DBG_NETTCP, ((5 << 8) | 2)) +#ifndef offsetof /* XXX */ +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) +#endif int tcp_mssdflt = TCP_MSS; @@ -203,7 +206,9 @@ tcp_init() vm_size_t str_size; int i; - tcp_iss = random(); /* wrong, but better than a constant */ +#ifdef TCP_COMPAT_42 + tcp_iss = 1; +#endif /* TCP_COMPAT_42 */ tcp_ccgen = 1; tcp_cleartaocache(); LIST_INIT(&tcb); @@ -241,7 +246,7 @@ tcp_init() tcbinfo.dummy_cb = (caddr_t) &dummy_tcb; in_pcb_nat_init(&tcbinfo, AF_INET, IPPROTO_TCP, SOCK_STREAM); - delack_bitmask = _MALLOC((4 * hashsize)/32, M_PCB, M_NOWAIT); + delack_bitmask = _MALLOC((4 * hashsize)/32, M_PCB, M_WAITOK); if (delack_bitmask == 0) panic("Delack Memory"); @@ -290,6 +295,10 @@ tcp_template(tp) n->tt_win = 0; n->tt_sum = 0; n->tt_urp = 0; + + n->tt_t.th_sum = in_pseudo(n->tt_src.s_addr, n->tt_dst.s_addr, + htons(sizeof(struct tcphdr) + IPPROTO_TCP)); + #if INET6 n->tt_flow = inp->inp_flow & IPV6_FLOWINFO_MASK; if (ip6_auto_flowlabel) { @@ -440,7 +449,6 @@ tcp_respond(tp, iph, th, m, ack, seq, flags, isipv6) else nth->th_win = htons((u_short)win); nth->th_urp = 0; - nth->th_sum = 0; tlen += sizeof (struct tcphdr); #if INET6 if (isipv6) { @@ -466,8 +474,11 @@ tcp_respond(tp, iph, th, m, ack, seq, flags, isipv6) m->m_len = tlen + sizeof(struct ip); m->m_pkthdr.len = tlen + sizeof(struct ip); m->m_pkthdr.rcvif = (struct ifnet *) 0; - bzero(ti->ti_x1, sizeof(ti->ti_x1)); - nth->th_sum = in_cksum(m, tlen + sizeof(struct ip)); + nth->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, + htons((u_short)(tlen + IPPROTO_TCP))); + m->m_pkthdr.csum_flags = CSUM_TCP; + m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum); + ip->ip_len = tlen + sizeof (struct ip); ip->ip_ttl = ip_defttl; #if INET6 @@ -846,6 +857,11 @@ tcp_pcblist SYSCTL_HANDLER_ARGS error = SYSCTL_OUT(req, &xig, sizeof xig); if (error) return error; + /* + * We are done if there is no pcb + */ + if (n == 0) + return 0; inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK); if (inp_list == 0) @@ -996,6 +1012,63 @@ tcp6_ctlinput(cmd, sa, d) } #endif /* INET6 */ +#define TCP_RNDISS_ROUNDS 16 +#define TCP_RNDISS_OUT 7200 +#define TCP_RNDISS_MAX 30000 + +u_int8_t tcp_rndiss_sbox[128]; +u_int16_t tcp_rndiss_msb; +u_int16_t tcp_rndiss_cnt; +long tcp_rndiss_reseed; + +u_int16_t +tcp_rndiss_encrypt(val) + u_int16_t val; +{ + u_int16_t sum = 0, i; + + for (i = 0; i < TCP_RNDISS_ROUNDS; i++) { + sum += 0x79b9; + val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7; + val = ((val & 0xff) << 7) | (val >> 8); + } + + return val; +} + +void +tcp_rndiss_init() +{ + struct timeval time; + + getmicrotime(&time); + read_random(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox)); + + tcp_rndiss_reseed = time.tv_sec + TCP_RNDISS_OUT; + tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000; + tcp_rndiss_cnt = 0; +} + +tcp_seq +tcp_rndiss_next() +{ + u_int32_t tmp; + struct timeval time; + + getmicrotime(&time); + + if (tcp_rndiss_cnt >= TCP_RNDISS_MAX || + time.tv_sec > tcp_rndiss_reseed) + tcp_rndiss_init(); + + tmp = random(); + + /* (tmp & 0x7fff) ensures a 32768 byte gap between ISS */ + return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) | + (tmp & 0x7fff); +} + + /* * When a source quench is received, close congestion window * to one segment. We will gradually open it again as we proceed. @@ -1122,6 +1195,8 @@ tcp_rtlookup(inp) struct rtentry *rt; ro = &inp->inp_route; + if (ro == NULL) + return (NULL); rt = ro->ro_rt; if (rt == NULL || !(rt->rt_flags & RTF_UP)) { /* No route yet, so try to acquire one */ diff --git a/bsd/netinet/tcp_timer.c b/bsd/netinet/tcp_timer.c index 3819a60cf..529e14bb8 100644 --- a/bsd/netinet/tcp_timer.c +++ b/bsd/netinet/tcp_timer.c @@ -307,8 +307,8 @@ tpgone: if (++cur_tw_slot >= N_TIME_WAIT_SLOTS) cur_tw_slot = 0; - tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ #if TCP_COMPAT_42 + tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */ if ((int)tcp_iss < 0) tcp_iss = TCP_ISSINCR; /* XXX */ #endif diff --git a/bsd/netinet/tcp_usrreq.c b/bsd/netinet/tcp_usrreq.c index 75458f08a..2dd2747fe 100644 --- a/bsd/netinet/tcp_usrreq.c +++ b/bsd/netinet/tcp_usrreq.c @@ -728,6 +728,10 @@ tcp_connect(tp, nam, p) else return EADDRINUSE; } + if ((inp->inp_laddr.s_addr == INADDR_ANY ? ifaddr->sin_addr.s_addr : + inp->inp_laddr.s_addr) == sin->sin_addr.s_addr && + inp->inp_lport == sin->sin_port) + return EINVAL; if (inp->inp_laddr.s_addr == INADDR_ANY) inp->inp_laddr = ifaddr->sin_addr; inp->inp_faddr = sin->sin_addr; @@ -749,7 +753,13 @@ tcp_connect(tp, nam, p) tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = tcp_keepinit; - tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; +#ifdef TCP_COMPAT_42 + tp->iss = tcp_iss; + tcp_iss =+ TCP_ISSINCR/2; +#else /* TCP_COMPAT_42 */ + tp->iss = tcp_rndiss_next(); +#endif /* !TCP_COMPAT_42 */ + tcp_sendseqinit(tp); /* @@ -845,7 +855,11 @@ tcp6_connect(tp, nam, p) tcpstat.tcps_connattempt++; tp->t_state = TCPS_SYN_SENT; tp->t_timer[TCPT_KEEP] = tcp_keepinit; +#ifdef TCP_COMPAT_42 tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2; +#else + tp->iss = tcp_rndiss_next(); +#endif /* TCP_COMPAT_42 */ tcp_sendseqinit(tp); /* diff --git a/bsd/netinet/tcp_var.h b/bsd/netinet/tcp_var.h index 480ff21d0..85e975b06 100644 --- a/bsd/netinet/tcp_var.h +++ b/bsd/netinet/tcp_var.h @@ -190,6 +190,7 @@ struct tcpcb { /* RFC 1644 variables */ tcp_cc cc_send; /* send connection count */ tcp_cc cc_recv; /* receive connection count */ + u_long reserved[4]; }; /* @@ -480,6 +481,11 @@ extern struct pr_usrreqs tcp6_usrreqs; #endif /* INET6 */ extern u_long tcp_sendspace; extern u_long tcp_recvspace; +void tcp_rndiss_init __P((void)); +tcp_seq tcp_rndiss_next __P((void)); +u_int16_t tcp_rndiss_encrypt __P((u_int16_t)); + + #endif /* KERNEL */ diff --git a/bsd/netinet/udp_usrreq.c b/bsd/netinet/udp_usrreq.c index 3d123c164..cce4259d4 100644 --- a/bsd/netinet/udp_usrreq.c +++ b/bsd/netinet/udp_usrreq.c @@ -104,6 +104,11 @@ #define DBG_FNC_UDP_INPUT NETDBG_CODE(DBG_NETUDP, (5 << 8)) #define DBG_FNC_UDP_OUTPUT NETDBG_CODE(DBG_NETUDP, (6 << 8) | 1) + +#ifndef offsetof /* XXX */ +#define offsetof(type, member) ((size_t)(&((type *)0)->member)) +#endif + #define __STDC__ 1 /* * UDP protocol implementation. @@ -129,6 +134,8 @@ struct inpcbinfo udbinfo; #define UDBHASHSIZE 16 #endif +extern int apple_hwcksum_rx; + struct udpstat udpstat; /* from udp_var.h */ SYSCTL_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RD, &udpstat, udpstat, ""); @@ -243,6 +250,8 @@ udp_input(m, iphlen) if (iphlen > sizeof (struct ip)) { ip_stripoptions(m, (struct mbuf *)0); iphlen = sizeof(struct ip); + if (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16) + m->m_pkthdr.csum_flags = 0; /* invalidate hwcksum */ } /* @@ -285,9 +294,27 @@ udp_input(m, iphlen) * Checksum extended UDP header and data. */ if (uh->uh_sum) { - bzero(((struct ipovly *)ip)->ih_x1, 9); - ((struct ipovly *)ip)->ih_len = uh->uh_ulen; - uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); + if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) { + if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) + uh->uh_sum = m->m_pkthdr.csum_data; + else { + if (apple_hwcksum_rx && (m->m_pkthdr.csum_flags & CSUM_TCP_SUM16)) { + bzero(((struct ipovly *)ip)->ih_x1, 9); + ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + uh->uh_sum = in_addword(in_cksum(m, sizeof(struct ip)), + m->m_pkthdr.csum_data & 0xFFFF); + } + else { + goto doudpcksum; + } + } + uh->uh_sum ^= 0xffff; + } else { +doudpcksum: + bzero(((struct ipovly *)ip)->ih_x1, 9); + ((struct ipovly *)ip)->ih_len = uh->uh_ulen; + uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); + } if (uh->uh_sum) { udpstat.udps_badsum++; m_freem(m); @@ -633,6 +660,11 @@ udp_pcblist SYSCTL_HANDLER_ARGS error = SYSCTL_OUT(req, &xig, sizeof xig); if (error) return error; + /* + * We are done if there is no pcb + */ + if (n == 0) + return 0; inp_list = _MALLOC(n * sizeof *inp_list, M_TEMP, M_WAITOK); if (inp_list == 0) { @@ -761,11 +793,14 @@ udp_output(inp, m, addr, control, p) /* * Stuff checksum and output datagram. */ - ui->ui_sum = 0; if (udpcksum) { - if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) - ui->ui_sum = 0xffff; - } + ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr, + htons((u_short)len + sizeof(struct udphdr) + IPPROTO_UDP)); + m->m_pkthdr.csum_flags = CSUM_UDP; + m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum); + } + else + ui->ui_sum = 0; ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; ((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */ ((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */ diff --git a/bsd/netinet6/ah_core.c b/bsd/netinet6/ah_core.c index af0762142..f21899828 100644 --- a/bsd/netinet6/ah_core.c +++ b/bsd/netinet6/ah_core.c @@ -221,7 +221,7 @@ ah_keyed_md5_init(state, sav) panic("ah_keyed_md5_init: what?"); state->sav = sav; - state->foo = (void *)_MALLOC(sizeof(MD5_CTX), M_TEMP, M_NOWAIT); + state->foo = (void *)_MALLOC(sizeof(MD5_CTX), M_TEMP, M_WAITOK); if (state->foo == NULL) panic("ah_keyed_md5_init: what?"); MD5Init((MD5_CTX *)state->foo); @@ -334,7 +334,7 @@ ah_keyed_sha1_init(state, sav) panic("ah_keyed_sha1_init: what?"); state->sav = sav; - state->foo = (void *)_MALLOC(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT); + state->foo = (void *)_MALLOC(sizeof(SHA1_CTX), M_TEMP, M_WAITOK); if (!state->foo) panic("ah_keyed_sha1_init: what?"); @@ -458,7 +458,7 @@ ah_hmac_md5_init(state, sav) panic("ah_hmac_md5_init: what?"); state->sav = sav; - state->foo = (void *)_MALLOC(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT); + state->foo = (void *)_MALLOC(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_WAITOK); if (!state->foo) panic("ah_hmac_md5_init: what?"); @@ -575,7 +575,7 @@ ah_hmac_sha1_init(state, sav) state->sav = sav; state->foo = (void *)_MALLOC(64 + 64 + sizeof(SHA1_CTX), - M_TEMP, M_NOWAIT); + M_TEMP, M_WAITOK); if (!state->foo) panic("ah_hmac_sha1_init: what?"); diff --git a/bsd/netinet6/frag6.c b/bsd/netinet6/frag6.c index f9434d42d..020c3d340 100644 --- a/bsd/netinet6/frag6.c +++ b/bsd/netinet6/frag6.c @@ -635,10 +635,6 @@ frag6_slowtimo() { struct ip6q *q6; int s; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif #ifdef __NetBSD__ s = splsoftnet(); #else @@ -689,9 +685,6 @@ frag6_slowtimo() #endif splx(s); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } /* diff --git a/bsd/netinet6/in6.c b/bsd/netinet6/in6.c index ab8b787e4..1a16e4106 100644 --- a/bsd/netinet6/in6.c +++ b/bsd/netinet6/in6.c @@ -583,9 +583,10 @@ in6_control(so, cmd, data, ifp) if (strcmp(ifp->if_name, "lo") == 0) dl_tag = lo_attach_inet(ifp); - +#if NGIF > 0 if (strcmp(ifp->if_name, "gif") == 0) dl_tag = gif_attach_inet(ifp); +#endif /* End of temp code */ ia->ia_ifa.ifa_dlt = dl_tag; @@ -1449,9 +1450,10 @@ in6_ifinit(ifp, ia, sin6, scrub) if (strcmp(ifp->if_name, "lo") == 0) dl_tag = lo_attach_inet(ifp); - +#if NGIF > 0 if (strcmp(ifp->if_name, "gif") == 0) dl_tag = gif_attach_inet(ifp); +#endif /* End of temp code */ ia->ia_ifa.ifa_dlt = dl_tag; #endif @@ -1590,7 +1592,7 @@ in6_addmulti(maddr6, ifp, errorp) * and link it into the interface's multicast list. */ in6m = (struct in6_multi *) - _MALLOC(sizeof(*in6m), M_IPMADDR, M_NOWAIT); + _MALLOC(sizeof(*in6m), M_IPMADDR, M_NOTWAIT); if (in6m == NULL) { splx(s); *errorp = ENOBUFS; diff --git a/bsd/netinet6/in6_ifattach.c b/bsd/netinet6/in6_ifattach.c index 722b8f8b6..b874f6fc2 100644 --- a/bsd/netinet6/in6_ifattach.c +++ b/bsd/netinet6/in6_ifattach.c @@ -473,7 +473,7 @@ in6_ifattach(ifp, type, laddr, noloop) bzero(&ia->ia_dstaddr, sizeof(struct sockaddr_in6)); ia->ia_dstaddr.sin6_len = sizeof(struct sockaddr_in6); ia->ia_dstaddr.sin6_family = AF_INET6; - +#if NGIF > 0 if (strcmp(ifp->if_name, "gif") == 0) { ia->ia_ifa.ifa_dlt = gif_attach_inet(ifp); #if DEBUG @@ -481,6 +481,7 @@ in6_ifattach(ifp, type, laddr, noloop) ifp->if_name, ifp->if_unit, ia, ia->ia_ifa.ifa_dlt); #endif } +#endif break; case IN6_IFT_ARCNET: ia->ia_ifa.ifa_rtrequest = nd6_rtrequest; diff --git a/bsd/netinet6/in6_prefix.c b/bsd/netinet6/in6_prefix.c index 0f746d0ea..a1afb0124 100644 --- a/bsd/netinet6/in6_prefix.c +++ b/bsd/netinet6/in6_prefix.c @@ -1188,6 +1188,19 @@ in6_prefix_ioctl(struct socket *so, u_long cmd, caddr_t data, return error; } +void +in6_rr_timer_funneled(void *ignored_arg) +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + in6_rr_timer(ignored_arg); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + void in6_rr_timer(void *ignored_arg) { @@ -1196,12 +1209,8 @@ in6_rr_timer(void *ignored_arg) #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__APPLE__) long time_second = time.tv_sec; #endif -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif - timeout(in6_rr_timer, (caddr_t)0, ip6_rr_prune * hz); + timeout(in6_rr_timer_funneled, (caddr_t)0, ip6_rr_prune * hz); s = splnet(); /* expire */ @@ -1220,7 +1229,4 @@ in6_rr_timer(void *ignored_arg) rpp = LIST_NEXT(rpp, rp_entry); } splx(s); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } diff --git a/bsd/netinet6/in6_prefix.h b/bsd/netinet6/in6_prefix.h index 906c01989..69013f928 100644 --- a/bsd/netinet6/in6_prefix.h +++ b/bsd/netinet6/in6_prefix.h @@ -82,4 +82,5 @@ LIST_HEAD(rr_prhead, rr_prefix); extern struct rr_prhead rr_prefix; void in6_rr_timer __P((void *)); +void in6_rr_timer_funneled __P((void *)); int delete_each_prefix __P((struct rr_prefix *rpp, u_char origin)); diff --git a/bsd/netinet6/in6_rmx.c b/bsd/netinet6/in6_rmx.c index f94f673dd..3a5eba5ad 100644 --- a/bsd/netinet6/in6_rmx.c +++ b/bsd/netinet6/in6_rmx.c @@ -357,6 +357,19 @@ in6_rtqkill(struct radix_node *rn, void *rock) #define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ static int rtq_timeout = RTQ_TIMEOUT; +static void +in6_rtqtimo_funneled(void *rock) +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); + in6_rtqtimo(rock); +#endif +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + static void in6_rtqtimo(void *rock) { @@ -365,10 +378,6 @@ in6_rtqtimo(void *rock) struct timeval atv; static time_t last_adjusted_timeout = 0; int s; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif arg.found = arg.killed = 0; arg.rnh = rnh; @@ -408,10 +417,7 @@ in6_rtqtimo(void *rock) atv.tv_usec = 0; atv.tv_sec = arg.nextstop; - timeout(in6_rtqtimo, rock, tvtohz(&atv)); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif + timeout(in6_rtqtimo_funneled, rock, tvtohz(&atv)); } /* @@ -446,6 +452,19 @@ in6_mtuexpire(struct radix_node *rn, void *rock) #define MTUTIMO_DEFAULT (60*1) +static void +in6_mtutimo_funneled(void *rock) +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); + in6_mtutimo(rock); +#endif +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + static void in6_mtutimo(void *rock) { @@ -453,10 +472,6 @@ in6_mtutimo(void *rock) struct mtuex_arg arg; struct timeval atv; int s; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif arg.rnh = rnh; arg.nextstop = time_second + MTUTIMO_DEFAULT; @@ -470,10 +485,7 @@ in6_mtutimo(void *rock) printf("invalid mtu expiration time on routing table\n"); arg.nextstop = time_second + 30; /*last resort*/ } - timeout(in6_mtutimo, rock, tvtohz(&atv)); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif + timeout(in6_mtutimo_funneled, rock, tvtohz(&atv)); } #if 0 diff --git a/bsd/netinet6/ip6_fw.c b/bsd/netinet6/ip6_fw.c index 7777c4c6b..0a7943e02 100644 --- a/bsd/netinet6/ip6_fw.c +++ b/bsd/netinet6/ip6_fw.c @@ -14,7 +14,7 @@ * * This software is provided ``AS IS'' without any warranties of any kind. * - * $Id: ip6_fw.c,v 1.2 2000/09/14 20:35:14 lindak Exp $ + * $Id: ip6_fw.c,v 1.3 2001/05/01 21:52:50 lindak Exp $ */ /* @@ -840,8 +840,8 @@ add_entry6(struct ip6_fw_head *chainptr, struct ip6_fw *frwl) u_short nbr = 0; int s; - fwc = _MALLOC(sizeof *fwc, M_IP6FW, M_DONTWAIT); - ftmp = _MALLOC(sizeof *ftmp, M_IP6FW, M_DONTWAIT); + fwc = _MALLOC(sizeof *fwc, M_IP6FW, M_NOWAIT); + ftmp = _MALLOC(sizeof *ftmp, M_IP6FW, M_NOWAIT); if (!fwc || !ftmp) { dprintf(("%s malloc said no\n", err_prefix)); if (fwc) _FREE(fwc, M_IP6FW); diff --git a/bsd/netinet6/ip6_input.c b/bsd/netinet6/ip6_input.c index e933fa07d..0f69d6a6b 100644 --- a/bsd/netinet6/ip6_input.c +++ b/bsd/netinet6/ip6_input.c @@ -261,7 +261,7 @@ ip6_init2(dummy) #endif #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* get EUI64 from somewhere */ @@ -288,11 +288,11 @@ ip6_init2(dummy) #endif /* nd6_timer_init */ - timeout(nd6_timer, (caddr_t)0, hz); + timeout(nd6_timer_funneled, (caddr_t)0, hz); /* router renumbering prefix list maintenance */ - timeout(in6_rr_timer, (caddr_t)0, hz); + timeout(in6_rr_timer_funneled, (caddr_t)0, hz); #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } diff --git a/bsd/netinet6/ip6_mroute.c b/bsd/netinet6/ip6_mroute.c index ec88a48a9..6140af6fe 100644 --- a/bsd/netinet6/ip6_mroute.c +++ b/bsd/netinet6/ip6_mroute.c @@ -1267,6 +1267,20 @@ ip6_mforward(ip6, ifp, m) * Clean up cache entries if upcalls are not serviced * Call from the Slow Timeout mechanism, every half second. */ +static void +expire_upcalls_funneled(unused) + void *unused; +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + expire_upcalls(unused); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + static void expire_upcalls(unused) void *unused; @@ -1275,10 +1289,6 @@ expire_upcalls(unused) struct mf6c *mfc, **nptr; int i; int s; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif #if __NetBSD__ s = splsoftnet(); @@ -1329,10 +1339,7 @@ expire_upcalls(unused) #if defined(__FreeBSD__) && __FreeBSD__ >= 3 expire_upcalls_ch = #endif - timeout(expire_upcalls, (caddr_t)NULL, EXPIRE_TIMEOUT); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif + timeout(expire_upcalls_funneled, (caddr_t)NULL, EXPIRE_TIMEOUT); } /* diff --git a/bsd/netinet6/ipsec.c b/bsd/netinet6/ipsec.c index 06f3ea54d..c494fb4da 100644 --- a/bsd/netinet6/ipsec.c +++ b/bsd/netinet6/ipsec.c @@ -1044,7 +1044,7 @@ ipsec_newpcbpolicy() { struct inpcbpolicy *p; - p = (struct inpcbpolicy *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct inpcbpolicy *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); return p; } @@ -1166,7 +1166,7 @@ ipsec_deepcopy_policy(src) q = &newchain; for (p = src->req; p; p = p->next) { *q = (struct ipsecrequest *)_MALLOC(sizeof(struct ipsecrequest), - M_SECA, M_NOWAIT); + M_SECA, M_WAITOK); if (*q == NULL) goto fail; bzero(*q, sizeof(**q)); diff --git a/bsd/netinet6/mip6.c b/bsd/netinet6/mip6.c index 24c805913..4a2e27c67 100644 --- a/bsd/netinet6/mip6.c +++ b/bsd/netinet6/mip6.c @@ -2763,7 +2763,7 @@ void *arg; /* Not used */ int s; #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* Go through the entire list of Neighbor Advertisement entries. */ @@ -2784,7 +2784,7 @@ void *arg; /* Not used */ timeout(mip6_timer_na, (void *)0, hz); } #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } @@ -2808,7 +2808,7 @@ void *arg; /* Not used */ int s; #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* Go through the entire list of Binding Cache entries. */ @@ -2835,7 +2835,7 @@ void *arg; /* Not used */ timeout(mip6_timer_bc, (void *)0, hz); } #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif return; } @@ -2850,16 +2850,27 @@ void *arg; /* Not used */ * Ret value: - ****************************************************************************** */ + void -mip6_timer_prefix(arg) +mip6_timer_prefix_funneled(arg) void *arg; /* Not used */ { - struct mip6_prefix *pq_entry; /* Current entry in the prefix list */ - int s; #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif + mip6_timer_prefix(arg); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + +void +mip6_timer_prefix(arg) +void *arg; /* Not used */ +{ + struct mip6_prefix *pq_entry; /* Current entry in the prefix list */ + int s; /* Go through the entire list of prefix entries. */ s = splnet(); @@ -2878,9 +2889,6 @@ void *arg; /* Not used */ #endif timeout(mip6_timer_prefix, (void *)0, hz); } -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif return; } diff --git a/bsd/netinet6/mip6_ha.c b/bsd/netinet6/mip6_ha.c index d582cee9e..2ca6725d2 100644 --- a/bsd/netinet6/mip6_ha.c +++ b/bsd/netinet6/mip6_ha.c @@ -794,7 +794,7 @@ struct ifnet *ifp; #if defined(__FreeBSD__) && __FreeBSD__ >= 3 mip6_timer_ll_handle = #endif - timeout(mip6_timer_ll, (void *)0, hz); + timeout(mip6_timer_ll_funneled, (void *)0, hz); } return llp; } @@ -1061,16 +1061,25 @@ struct mip6_ha_list *ha_delete; /* Home Agent entry to delete */ ****************************************************************************** */ void +mip6_timer_ll_funneled(arg) +void *arg; /* Not used */ +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + mip6_timer_ll(arg); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} +void mip6_timer_ll(arg) void *arg; /* Not used */ { struct mip6_link_list *llp; /* Current Link list entry */ struct mip6_ha_list *halp; /* Current Home Agent list entry */ int s; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif /* Go through the entire Home Agent List and delete all entries for which the time has expired. */ @@ -1095,11 +1104,8 @@ void *arg; /* Not used */ #if defined(__FreeBSD__) && __FreeBSD__ >= 3 mip6_timer_ll_handle = #endif - timeout(mip6_timer_ll, (void *)0, hz); + timeout(mip6_timer_ll_funneled, (void *)0, hz); } -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } diff --git a/bsd/netinet6/mip6_mn.c b/bsd/netinet6/mip6_mn.c index d058c9a83..dde4bf515 100644 --- a/bsd/netinet6/mip6_mn.c +++ b/bsd/netinet6/mip6_mn.c @@ -2545,7 +2545,7 @@ void *arg; /* Not used */ #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* Go through the entire output queue and send all packets that have not been sent. */ @@ -2653,7 +2653,7 @@ void *arg; /* Not used */ hz * (MIP6_OUTQ_INTERVAL/10)); } #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } @@ -2688,7 +2688,7 @@ void *arg; /* Not used */ #endif #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* Go through the entire BUL and check if any BU have to be sent. */ @@ -2872,7 +2872,7 @@ void *arg; /* Not used */ } splx(s); #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } @@ -2898,7 +2898,7 @@ void *arg; /* Not used */ int s, start_timer; #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif /* Go through the entire list of event-state machines. */ @@ -2933,7 +2933,7 @@ void *arg; /* Not used */ } splx(s); #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } diff --git a/bsd/netinet6/natpt_tslot.c b/bsd/netinet6/natpt_tslot.c index c8beef536..b3fd9e937 100644 --- a/bsd/netinet6/natpt_tslot.c +++ b/bsd/netinet6/natpt_tslot.c @@ -713,7 +713,7 @@ _expireTSlot(void *ignored_arg) struct timeval atv; #ifdef __APPLE__ boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); + funnel_state = thread_funnel_set(network_flock, TRUE); #endif timeout(_expireTSlot, (caddr_t)0, tSlotTimer); @@ -721,7 +721,7 @@ _expireTSlot(void *ignored_arg) _expireTSlotEntry(&atv); #ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); + (void) thread_funnel_set(network_flock, FALSE); #endif } diff --git a/bsd/netinet6/nd6.c b/bsd/netinet6/nd6.c index ca1bcb13d..766b6c6e1 100644 --- a/bsd/netinet6/nd6.c +++ b/bsd/netinet6/nd6.c @@ -120,6 +120,7 @@ int nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; static struct sockaddr_in6 all1_sa; static void nd6_slowtimo __P((void *)); +static void nd6_slowtimo_funneled __P((void *)); #if MIP6 void (*mip6_expired_defrouter_hook)(struct nd_defrouter *dr) = 0; @@ -147,7 +148,7 @@ nd6_init() nd6_init_done = 1; /* start timer */ - timeout(nd6_slowtimo, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz); + timeout(nd6_slowtimo_funneled, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz); } void @@ -394,6 +395,19 @@ skip1: * ND6 timer routine to expire default route list and prefix list */ void +nd6_timer_funneled(ignored_arg) + void *ignored_arg; +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + nd6_timer(ignored_arg); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} +void nd6_timer(ignored_arg) void *ignored_arg; { @@ -404,17 +418,13 @@ nd6_timer(ignored_arg) #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined (__APPLE__) long time_second = time.tv_sec; #endif -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif #if __NetBSD__ s = splsoftnet(); #else s = splnet(); #endif - timeout(nd6_timer, (caddr_t)0, nd6_prune * hz); + timeout(nd6_timer_funneled, (caddr_t)0, nd6_prune * hz); ln = llinfo_nd6.ln_next; /* XXX BSD/OS separates this code -- itojun */ @@ -583,9 +593,6 @@ nd6_timer(ignored_arg) pr = pr->ndpr_next; } splx(s); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } /* @@ -1809,6 +1816,20 @@ fail: return rt; } +static void +nd6_slowtimo_funneled(ignored_arg) + void *ignored_arg; +{ +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + nd6_slowtimo(ignored_arg); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif +} + static void nd6_slowtimo(ignored_arg) void *ignored_arg; @@ -1816,10 +1837,6 @@ nd6_slowtimo(ignored_arg) int s; register int i; register struct nd_ifinfo *nd6if; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif #ifdef __NetBSD__ s = splsoftnet(); @@ -1827,7 +1844,7 @@ nd6_slowtimo(ignored_arg) s = splnet(); #endif - timeout(nd6_slowtimo, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz); + timeout(nd6_slowtimo_funneled, (caddr_t)0, ND6_SLOWTIMER_INTERVAL * hz); for (i = 1; i < if_index + 1; i++) { nd6if = &nd_ifinfo[i]; if (nd6if->basereachable && /* already initialized */ @@ -1843,9 +1860,6 @@ nd6_slowtimo(ignored_arg) } } splx(s); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } diff --git a/bsd/netinet6/nd6.h b/bsd/netinet6/nd6.h index aa83aa8aa..687eb6894 100644 --- a/bsd/netinet6/nd6.h +++ b/bsd/netinet6/nd6.h @@ -288,6 +288,7 @@ int nd6_options __P((union nd_opts *)); struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *)); void nd6_setmtu __P((struct ifnet *)); void nd6_timer __P((void *)); +void nd6_timer_funneled __P((void *)); void nd6_purge __P((struct ifnet *)); void nd6_free __P((struct rtentry *)); void nd6_nud_hint __P((struct rtentry *, struct in6_addr *)); diff --git a/bsd/netinet6/nd6_nbr.c b/bsd/netinet6/nd6_nbr.c index eca3501f1..a21dfb189 100644 --- a/bsd/netinet6/nd6_nbr.c +++ b/bsd/netinet6/nd6_nbr.c @@ -79,6 +79,7 @@ struct dadq; static struct dadq *nd6_dad_find __P((struct ifaddr *)); static void nd6_dad_timer __P((struct ifaddr *)); +static void nd6_dad_timer_funnel __P((struct ifaddr *)); static void nd6_dad_ns_output __P((struct dadq *, struct ifaddr *)); static void nd6_dad_ns_input __P((struct ifaddr *)); static void nd6_dad_na_input __P((struct ifaddr *)); @@ -1071,7 +1072,7 @@ nd6_dad_start(ifa, tick) #if defined(__FreeBSD__) && __FreeBSD__ >= 3 dp->dad_timer = #endif - timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, + timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa, nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); } else { int ntick; @@ -1084,11 +1085,27 @@ nd6_dad_start(ifa, tick) #if defined(__FreeBSD__) && __FreeBSD__ >= 3 dp->dad_timer = #endif - timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, + timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa, ntick); } } +static void +nd6_dad_timer_funnel(ifa) + struct ifaddr *ifa; +{ + +#ifdef __APPLE__ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); +#endif + nd6_dad_timer(ifa); +#ifdef __APPLE__ + (void) thread_funnel_set(network_flock, FALSE); +#endif + +} + static void nd6_dad_timer(ifa) struct ifaddr *ifa; @@ -1097,10 +1114,6 @@ nd6_dad_timer(ifa) struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa; struct dadq *dp; -#ifdef __APPLE__ - boolean_t funnel_state; - funnel_state = thread_set_funneled(TRUE); -#endif #if __NetBSD__ s = splsoftnet(); /*XXX*/ #else @@ -1153,7 +1166,7 @@ nd6_dad_timer(ifa) #if defined(__FreeBSD__) && __FreeBSD__ >= 3 dp->dad_timer = #endif - timeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa, + timeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa, nd_ifinfo[ifa->ifa_ifp->if_index].retrans * hz / 1000); } else { /* @@ -1229,9 +1242,6 @@ nd6_dad_timer(ifa) done: splx(s); -#ifdef __APPLE__ - (void) thread_set_funneled(funnel_state); -#endif } void @@ -1256,7 +1266,7 @@ nd6_dad_duplicated(ifa) ia->ia6_flags |= IN6_IFF_DUPLICATED; /* We are done with DAD, with duplicated address found. (failure) */ - untimeout((void (*) __P((void *)))nd6_dad_timer, (void *)ifa + untimeout((void (*) __P((void *)))nd6_dad_timer_funnel, (void *)ifa #if defined(__FreeBSD__) && __FreeBSD__ >= 3 , dp->dad_timer #endif diff --git a/bsd/netinet6/nd6_rtr.c b/bsd/netinet6/nd6_rtr.c index 47c588de4..d2c6746d5 100644 --- a/bsd/netinet6/nd6_rtr.c +++ b/bsd/netinet6/nd6_rtr.c @@ -1353,7 +1353,7 @@ in6_ifadd(ifp, in6, addr, prefixlen) } /* make ifaddr */ - ia = (struct in6_ifaddr *)_MALLOC(sizeof(*ia), M_IFADDR, M_DONTWAIT); + ia = (struct in6_ifaddr *)_MALLOC(sizeof(*ia), M_IFADDR, M_NOWAIT); if (ia == NULL) { printf("ENOBUFS in in6_ifadd %d\n", __LINE__); return NULL; diff --git a/bsd/netinet6/raw_ip6.c b/bsd/netinet6/raw_ip6.c index ea812b1de..0baf3af82 100644 --- a/bsd/netinet6/raw_ip6.c +++ b/bsd/netinet6/raw_ip6.c @@ -556,6 +556,10 @@ rip6_attach(struct socket *so, int proto, struct proc *p) #endif /*IPSEC*/ MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *, sizeof(struct icmp6_filter), M_PCB, M_NOWAIT); + + if (inp->in6p_icmp6filt == NULL) + return(ENOBUFS); + ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt); return 0; } diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c index 9db82dcfd..70a9524e6 100644 --- a/bsd/netkey/key.c +++ b/bsd/netkey/key.c @@ -3791,13 +3791,23 @@ key_bbcmp(p1, p2, bits) * scanning SPD and SAD to check status for each entries, * and do to remove or to expire. */ +static void +key_timehandler_funneled(void) +{ + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); + key_timehandler(); + (void) thread_funnel_set(network_flock, FALSE); +} + void key_timehandler(void) { u_int dir; int s; - thread_funnel_set(network_flock, TRUE); + boolean_t funnel_state; + funnel_state = thread_funnel_set(network_flock, TRUE); #if __NetBSD__ s = splsoftnet(); /*called from softclock()*/ #else @@ -4047,11 +4057,10 @@ key_timehandler(void) #ifndef IPSEC_DEBUG2 /* do exchange to tick time !! */ - (void)timeout((void *)key_timehandler, (void *)0, 100); + (void)timeout((void *)key_timehandler_funneled, (void *)0, 100); #endif /* IPSEC_DEBUG2 */ splx(s); - thread_funnel_set(network_funnel, FALSE); return; } @@ -6616,7 +6625,7 @@ key_init() #endif #ifndef IPSEC_DEBUG2 - timeout((void *)key_timehandler, (void *)0, hz); + timeout((void *)key_timehandler_funneled, (void *)0, hz); #endif /*IPSEC_DEBUG2*/ /* initialize key statistics */ diff --git a/bsd/netkey/keydb.c b/bsd/netkey/keydb.c index 9c2bebccf..d9bf27f60 100644 --- a/bsd/netkey/keydb.c +++ b/bsd/netkey/keydb.c @@ -70,7 +70,7 @@ keydb_newsecpolicy() { struct secpolicy *p; - p = (struct secpolicy *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct secpolicy *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); if (!p) return p; bzero(p, sizeof(*p)); @@ -94,7 +94,7 @@ keydb_newsecashead() struct secashead *p; int i; - p = (struct secashead *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct secashead *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); if (!p) return p; bzero(p, sizeof(*p)); @@ -119,7 +119,7 @@ keydb_newsecasvar() { struct secasvar *p; - p = (struct secasvar *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct secasvar *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); if (!p) return p; bzero(p, sizeof(*p)); @@ -179,13 +179,13 @@ keydb_newsecreplay(wsize) { struct secreplay *p; - p = (struct secreplay *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct secreplay *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); if (!p) return p; bzero(p, sizeof(*p)); if (wsize != 0) { - p->bitmap = (caddr_t)_MALLOC(wsize, M_SECA, M_NOWAIT); + p->bitmap = (caddr_t)_MALLOC(wsize, M_SECA, M_WAITOK); if (!p->bitmap) { _FREE(p, M_SECA); return NULL; @@ -214,7 +214,7 @@ keydb_newsecreg() { struct secreg *p; - p = (struct secreg *)_MALLOC(sizeof(*p), M_SECA, M_NOWAIT); + p = (struct secreg *)_MALLOC(sizeof(*p), M_SECA, M_WAITOK); if (p) bzero(p, sizeof(*p)); return p; diff --git a/bsd/netkey/keysock.c b/bsd/netkey/keysock.c index 6f38b7424..ae1bc6203 100644 --- a/bsd/netkey/keysock.c +++ b/bsd/netkey/keysock.c @@ -264,7 +264,7 @@ key_output(m, so) * allocate memory for sadb_msg, and copy to sadb_msg from mbuf * XXX: To be processed directly without a copy. */ - msg = (struct sadb_msg *)_MALLOC(len, M_SECA, M_NOWAIT); + msg = (struct sadb_msg *)_MALLOC(len, M_SECA, M_WAITOK); if (msg == NULL) { #if IPSEC_DEBUG printf("key_output: No more memory.\n"); diff --git a/bsd/nfs/nfs_bio.c b/bsd/nfs/nfs_bio.c index e341a0441..040678d37 100644 --- a/bsd/nfs/nfs_bio.c +++ b/bsd/nfs/nfs_bio.c @@ -553,8 +553,11 @@ again: return (error); } if (bp->b_wcred == NOCRED) { - crhold(cred); - bp->b_wcred = cred; + /* + * NFS has embedded ucred. + * Can not crhold() here as that causes zone corruption + */ + bp->b_wcred = crdup(cred); } np->n_flag |= NMODIFIED; @@ -660,8 +663,11 @@ nfs_getwriteblk(vp, bn, size, p, cred, off, len) if (!bp) return (NULL); if (bp->b_wcred == NOCRED) { - crhold(cred); - bp->b_wcred = cred; + /* + * NFS has embedded ucred. + * Can not crhold() here as that causes zone corruption + */ + bp->b_wcred = crdup(cred); } if ((bp->b_blkno * DEV_BSIZE) + bp->b_dirtyend > np->n_size) { @@ -745,13 +751,22 @@ nfs_getwriteblk(vp, bn, size, p, cred, off, len) error = nfs_readrpc(vp, &uio, cred); if (error) { /* - * If we couldn't read, fall back to writing - * out the old dirty region. - */ - bp->b_proc = p; - if (VOP_BWRITE(bp) == EINTR) - return (NULL); - goto again; + * If we couldn't read, do not do a VOP_BWRITE + * as originally coded. That, could also error + * and looping back to "again" as it was doing + * could have us stuck trying to write same buffer + * again. nfs_write, will get the entire region + * if nfs_readrpc was successful. If not successful + * we should just error out. Errors like ESTALE + * would keep us in this loop rather than transient + * errors justifying a retry. We can return from here + * instead of altering dirty region later in routine. + * We did not write out old dirty region at this point. + */ + bp->b_error = error; + SET(bp->b_flags, B_ERROR); + printf("nfs_getwriteblk: readrpc (2) returned %d", error); + return bp; } else { /* * The read worked. @@ -835,6 +850,7 @@ nfs_vinvalbuf(vp, flags, cred, p, intrflg) register struct nfsnode *np = VTONFS(vp); struct nfsmount *nmp = VFSTONFS(vp->v_mount); int error = 0, slpflag, slptimeo; + int didhold = 0; if ((nmp->nm_flag & NFSMNT_INT) == 0) intrflg = 0; @@ -862,7 +878,16 @@ nfs_vinvalbuf(vp, flags, cred, p, intrflg) np->n_flag |= NFLUSHINPROG; error = vinvalbuf(vp, flags, cred, p, slpflag, 0); while (error) { - if (intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p)) { + /* we seem to be stuck in a loop here if the thread got aborted. + * nfs_flush will return EINTR. Not sure if that will cause + * other consequences due to EINTR having other meanings in NFS + * To handle, no dirty pages, it seems safe to just return from + * here. But if we did have dirty pages, how would we get them + * written out if thread was aborted? Some other strategy is + * necessary. -- EKN + */ + if ((intrflg && nfs_sigintr(nmp, (struct nfsreq *)0, p)) || + ((error == EINTR) && current_thread_aborted())) { np->n_flag &= ~NFLUSHINPROG; if (np->n_flag & NFLUSHWANT) { np->n_flag &= ~NFLUSHWANT; @@ -877,7 +902,11 @@ nfs_vinvalbuf(vp, flags, cred, p, intrflg) np->n_flag &= ~NFLUSHWANT; wakeup((caddr_t)&np->n_flag); } - (void) ubc_clean(vp, 1); /* get the pages out of vm also */ + didhold = ubc_hold(vp); + if (didhold) { + (void) ubc_clean(vp, 1); /* get the pages out of vm also */ + ubc_rele(vp); + } return (0); } @@ -975,14 +1004,20 @@ again: if (ISSET(bp->b_flags, B_READ)) { if (bp->b_rcred == NOCRED && cred != NOCRED) { - crhold(cred); - bp->b_rcred = cred; + /* + * NFS has embedded ucred. + * Can not crhold() here as that causes zone corruption + */ + bp->b_rcred = crdup(cred); } } else { SET(bp->b_flags, B_WRITEINPROG); if (bp->b_wcred == NOCRED && cred != NOCRED) { - crhold(cred); - bp->b_wcred = cred; + /* + * NFS has embedded ucred. + * Can not crhold() here as that causes zone corruption + */ + bp->b_wcred = crdup(cred); } } diff --git a/bsd/nfs/nfs_serv.c b/bsd/nfs/nfs_serv.c index 0cbfa4334..30b112769 100644 --- a/bsd/nfs/nfs_serv.c +++ b/bsd/nfs/nfs_serv.c @@ -2873,6 +2873,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq) int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies = 0; u_quad_t frev, off, toff, verf; u_long *cookies = NULL, *cookiep; + void *file; fhp = &nfh.fh_generic; nfsm_srvmtofh(fhp); @@ -3004,10 +3005,17 @@ again: /* * Probe one of the directory entries to see if the filesystem - * supports VGET. + * supports VGET. See later comment for VFS_VGET changes. */ - if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) { - error = NFSERR_NOTSUPP; + if (vp->v_tag == VT_UFS) + file = (void *) dp->d_fileno; + else { + file = &dp->d_fileno; + } + + if (error = VFS_VGET(vp->v_mount, file, &nvp)) { + if (error == EOPNOTSUPP) /* let others get passed back */ + error = NFSERR_NOTSUPP; vrele(vp); _FREE((caddr_t)cookies, M_TEMP); _FREE((caddr_t)rbuf, M_TEMP); @@ -3032,11 +3040,22 @@ again: nlen = dp->d_namlen; rem = nfsm_rndup(nlen)-nlen; - /* - * For readdir_and_lookup get the vnode using - * the file number. + /* + * Got to get the vnode for lookup per entry. + * HFS+/volfs and others use address of file identifier to VGET + * UFS, nullfs, umapfs use inode (u_int32_t) + * until they are consistent, we must differentiate now. + * UFS is the only one of the latter class that is exported. + * Note this will be pulled out as we resolve the VGET issue + * of which it should use u_in32_t or addresses. */ - if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp)) + + if (vp->v_tag == VT_UFS) + file = (void *) dp->d_fileno; + else + file = &dp->d_fileno; + + if (VFS_VGET(vp->v_mount, file, &nvp)) goto invalid; bzero((caddr_t)nfhp, NFSX_V3FH); nfhp->fh_fsid = diff --git a/bsd/nfs/nfs_socket.c b/bsd/nfs/nfs_socket.c index 22d5a17ba..9c331ce9f 100644 --- a/bsd/nfs/nfs_socket.c +++ b/bsd/nfs/nfs_socket.c @@ -948,19 +948,7 @@ nfs_reply(myrep) return (0); if (error) return (error); - - /* - * This is being checked after nfs_receive, but - * it doesn't hurt to check prior, since nfs_receive - * will dereference r_nmp also. Bullet-proofing code - * since changing funnels since the request to the - * receive can leave us vulnerable for kernel to unmount - * us. - */ - if (!myrep->r_nmp) { - NFSTRACE4(NFSTRC_ECONN, myrep->r_xid, myrep, nmp, 1); - return (ECONNABORTED); - } + /* * If we slept after putting bits otw, then reply may have * arrived. In which case returning is required, or we @@ -973,11 +961,12 @@ nfs_reply(myrep) return (0); } /* - * Get the next Rpc reply off the socket + * Get the next Rpc reply off the socket. Assume myrep->r_nmp + * is still in tact by checks done in nfs_rcvlock. */ error = nfs_receive(myrep, &nam, &mrep); /* - * Bailout asap if nfsmount struct gone (unmounted) + * Bailout asap if nfsmount struct gone (unmounted). */ if (!myrep->r_nmp) { NFSTRACE4(NFSTRC_ECONN, myrep->r_xid, myrep, nmp, 2); @@ -1952,6 +1941,12 @@ nfs_sndlock(flagp, rep) slpflag = 0; slptimeo = 2 * hz; } + /* + * Make sure while we slept that the mountpoint didn't go away. + * nfs_sigintr and callers expect it in tact. + */ + if (!rep->r_nmp) + return (ECONNABORTED); /* don't have lock until out of loop */ } *flagp |= NFSMNT_SNDLOCK; return (0); @@ -2006,6 +2001,12 @@ nfs_rcvlock(rep) slpflag = 0; slptimeo = 2 * hz; } + /* + * Make sure while we slept that the mountpoint didn't go away. + * nfs_sigintr and caller nfs_reply expect it in tact. + */ + if (!rep->r_nmp) + return (ECONNABORTED); /* don't have lock until out of loop */ } /* * nfs_reply will handle it if reply already arrived. diff --git a/bsd/nfs/nfs_syscalls.c b/bsd/nfs/nfs_syscalls.c index 3ec010a93..41f1333ad 100644 --- a/bsd/nfs/nfs_syscalls.c +++ b/bsd/nfs/nfs_syscalls.c @@ -875,7 +875,7 @@ nfssvc_iod_continue(error) */ ut = get_bsdthread_info(current_act()); myiod = ut->uu_state.uu_nfs_myiod; - p = get_bsdtask_info(current_task()); + p = current_proc(); /* * Just loop around doin our stuff until SIGKILL diff --git a/bsd/nfs/nfs_vfsops.c b/bsd/nfs/nfs_vfsops.c index 1df71854c..9c1c7caad 100644 --- a/bsd/nfs/nfs_vfsops.c +++ b/bsd/nfs/nfs_vfsops.c @@ -608,6 +608,11 @@ nfs_mount_diskless_private(ndmntp, mntname, mntflag, vpp, mpp) */ mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); (void)vfs_busy(mp, LK_NOWAIT, 0, procp); LIST_INIT(&mp->mnt_vnodelist); @@ -936,32 +941,43 @@ nfs_unmount(mp, mntflags, p) nmp = VFSTONFS(mp); /* * Goes something like this.. - * - Check for activity on the root vnode (other than ourselves). * - Call vflush() to clear out vnodes for this file system, - * except for the root vnode. + * except for the swap files. Deal with them in 2nd pass. + * It will do vgone making the vnode VBAD at that time. * - Decrement reference on the vnode representing remote root. * - Close the socket * - Free up the data structures - */ - /* + * * We need to decrement the ref. count on the nfsnode representing * the remote root. See comment in mountnfs(). The VFS unmount() * has done vput on this vnode, otherwise we would get deadlock! */ vp = nmp->nm_dvp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - if (vp->v_usecount > 1) { - VOP_UNLOCK(vp, 0, p); - return (EBUSY); - } - + /* * Must handshake with nqnfs_clientd() if it is active. */ nmp->nm_flag |= NFSMNT_DISMINPROG; while (nmp->nm_inprog != NULLVP) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); - error = vflush(mp, vp, flags); + /* + * vflush will check for busy vnodes on mountpoint. + * Will do the right thing for MNT_FORCE. That is, we should + * not get EBUSY back. + */ + error = vflush(mp, vp, SKIPSWAP | flags); + if (mntflags & MNT_FORCE) + error = vflush(mp, NULLVP, flags); + else { + if (vp->v_usecount > 1) { + VOP_UNLOCK(vp, 0, p); + nmp->nm_flag &= ~NFSMNT_DISMINPROG; + return (EBUSY); + } + error = vflush(mp, vp, flags); + } + if (error) { VOP_UNLOCK(vp, 0, p); nmp->nm_flag &= ~NFSMNT_DISMINPROG; @@ -977,9 +993,13 @@ nfs_unmount(mp, mntflags, p) /* * Release the root vnode reference held by mountnfs() + * Note: vflush would have done the vgone for us if we + * didn't skip over it due to mount reference held. */ vput(vp); - vgone(vp); + if (!(mntflags & MNT_FORCE)) + vgone(vp); + mp->mnt_data = 0; /* don't want to end up using stale vp */ nfs_disconnect(nmp); m_freem(nmp->nm_nam); diff --git a/bsd/nfs/nfs_vnops.c b/bsd/nfs/nfs_vnops.c index 06f5961e3..a34b11003 100644 --- a/bsd/nfs/nfs_vnops.c +++ b/bsd/nfs/nfs_vnops.c @@ -324,7 +324,7 @@ static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */ { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */ { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */ - { &vop_strategy_desc, (vop_t *)fifo_badop }, /* strategy */ + { &vop_strategy_desc, (vop_t *)fifo_strategy }, /* strategy */ { &vop_print_desc, (vop_t *)nfs_print }, /* print */ { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */ { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */ @@ -383,41 +383,163 @@ static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO; | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE \ | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP) - + +/* + * the following are needed only by nfs_pageout to know how to handle errors + * see nfs_pageout comments on explanation of actions. + * the errors here are copied from errno.h and errors returned by servers + * are expected to match the same numbers here. If not, our actions maybe + * erroneous. + */ +enum actiontype {NOACTION, DUMP, DUMPANDLOG, RETRY, RETRYWITHSLEEP, SEVER}; + +static int errorcount[ELAST+1]; /* better be zeros when initialized */ + +static const short errortooutcome[ELAST+1] = { + NOACTION, + DUMP, /* EPERM 1 Operation not permitted */ + DUMP, /* ENOENT 2 No such file or directory */ + DUMPANDLOG, /* ESRCH 3 No such process */ + RETRY, /* EINTR 4 Interrupted system call */ + DUMP, /* EIO 5 Input/output error */ + DUMP, /* ENXIO 6 Device not configured */ + DUMPANDLOG, /* E2BIG 7 Argument list too long */ + DUMPANDLOG, /* ENOEXEC 8 Exec format error */ + DUMPANDLOG, /* EBADF 9 Bad file descriptor */ + DUMPANDLOG, /* ECHILD 10 No child processes */ + DUMPANDLOG, /* EDEADLK 11 Resource deadlock avoided - was EAGAIN */ + RETRY, /* ENOMEM 12 Cannot allocate memory */ + DUMP, /* EACCES 13 Permission denied */ + DUMPANDLOG, /* EFAULT 14 Bad address */ + DUMPANDLOG, /* ENOTBLK 15 POSIX - Block device required */ + RETRY, /* EBUSY 16 Device busy */ + DUMP, /* EEXIST 17 File exists */ + DUMP, /* EXDEV 18 Cross-device link */ + DUMP, /* ENODEV 19 Operation not supported by device */ + DUMP, /* ENOTDIR 20 Not a directory */ + DUMP, /* EISDIR 21 Is a directory */ + DUMP, /* EINVAL 22 Invalid argument */ + DUMPANDLOG, /* ENFILE 23 Too many open files in system */ + DUMPANDLOG, /* EMFILE 24 Too many open files */ + DUMPANDLOG, /* ENOTTY 25 Inappropriate ioctl for device */ + DUMPANDLOG, /* ETXTBSY 26 Text file busy - POSIX */ + DUMP, /* EFBIG 27 File too large */ + DUMP, /* ENOSPC 28 No space left on device */ + DUMPANDLOG, /* ESPIPE 29 Illegal seek */ + DUMP, /* EROFS 30 Read-only file system */ + DUMP, /* EMLINK 31 Too many links */ + RETRY, /* EPIPE 32 Broken pipe */ + /* math software */ + DUMPANDLOG, /* EDOM 33 Numerical argument out of domain */ + DUMPANDLOG, /* ERANGE 34 Result too large */ + RETRY, /* EAGAIN/EWOULDBLOCK 35 Resource temporarily unavailable */ + DUMPANDLOG, /* EINPROGRESS 36 Operation now in progress */ + DUMPANDLOG, /* EALREADY 37 Operation already in progress */ + /* ipc/network software -- argument errors */ + DUMPANDLOG, /* ENOTSOC 38 Socket operation on non-socket */ + DUMPANDLOG, /* EDESTADDRREQ 39 Destination address required */ + DUMPANDLOG, /* EMSGSIZE 40 Message too long */ + DUMPANDLOG, /* EPROTOTYPE 41 Protocol wrong type for socket */ + DUMPANDLOG, /* ENOPROTOOPT 42 Protocol not available */ + DUMPANDLOG, /* EPROTONOSUPPORT 43 Protocol not supported */ + DUMPANDLOG, /* ESOCKTNOSUPPORT 44 Socket type not supported */ + DUMPANDLOG, /* ENOTSUP 45 Operation not supported */ + DUMPANDLOG, /* EPFNOSUPPORT 46 Protocol family not supported */ + DUMPANDLOG, /* EAFNOSUPPORT 47 Address family not supported by protocol family */ + DUMPANDLOG, /* EADDRINUSE 48 Address already in use */ + DUMPANDLOG, /* EADDRNOTAVAIL 49 Can't assign requested address */ + /* ipc/network software -- operational errors */ + RETRY, /* ENETDOWN 50 Network is down */ + RETRY, /* ENETUNREACH 51 Network is unreachable */ + RETRY, /* ENETRESET 52 Network dropped connection on reset */ + RETRY, /* ECONNABORTED 53 Software caused connection abort */ + RETRY, /* ECONNRESET 54 Connection reset by peer */ + RETRY, /* ENOBUFS 55 No buffer space available */ + RETRY, /* EISCONN 56 Socket is already connected */ + RETRY, /* ENOTCONN 57 Socket is not connected */ + RETRY, /* ESHUTDOWN 58 Can't send after socket shutdown */ + RETRY, /* ETOOMANYREFS 59 Too many references: can't splice */ + RETRY, /* ETIMEDOUT 60 Operation timed out */ + RETRY, /* ECONNREFUSED 61 Connection refused */ + + DUMPANDLOG, /* ELOOP 62 Too many levels of symbolic links */ + DUMP, /* ENAMETOOLONG 63 File name too long */ + RETRY, /* EHOSTDOWN 64 Host is down */ + RETRY, /* EHOSTUNREACH 65 No route to host */ + DUMP, /* ENOTEMPTY 66 Directory not empty */ + /* quotas & mush */ + DUMPANDLOG, /* PROCLIM 67 Too many processes */ + DUMPANDLOG, /* EUSERS 68 Too many users */ + DUMPANDLOG, /* EDQUOT 69 Disc quota exceeded */ + /* Network File System */ + DUMP, /* ESTALE 70 Stale NFS file handle */ + DUMP, /* EREMOTE 71 Too many levels of remote in path */ + DUMPANDLOG, /* EBADRPC 72 RPC struct is bad */ + DUMPANDLOG, /* ERPCMISMATCH 73 RPC version wrong */ + DUMPANDLOG, /* EPROGUNAVAIL 74 RPC prog. not avail */ + DUMPANDLOG, /* EPROGMISMATCH 75 Program version wrong */ + DUMPANDLOG, /* EPROCUNAVAIL 76 Bad procedure for program */ + + DUMPANDLOG, /* ENOLCK 77 No locks available */ + DUMPANDLOG, /* ENOSYS 78 Function not implemented */ + DUMPANDLOG, /* EFTYPE 79 Inappropriate file type or format */ + DUMPANDLOG, /* EAUTH 80 Authentication error */ + DUMPANDLOG, /* ENEEDAUTH 81 Need authenticator */ + /* Intelligent device errors */ + DUMPANDLOG, /* EPWROFF 82 Device power is off */ + DUMPANDLOG, /* EDEVERR 83 Device error, e.g. paper out */ + DUMPANDLOG, /* EOVERFLOW 84 Value too large to be stored in data type */ + /* Program loading errors */ + DUMPANDLOG, /* EBADEXEC 85 Bad executable */ + DUMPANDLOG, /* EBADARCH 86 Bad CPU type in executable */ + DUMPANDLOG, /* ESHLIBVERS 87 Shared library version mismatch */ + DUMPANDLOG, /* EBADMACHO 88 Malformed Macho file */ +}; + + +static short +nfs_pageouterrorhandler(error) + int error; +{ + if (error > ELAST) + return(DUMP); + else + return(errortooutcome[error]); +} static int nfs3_access_otw(struct vnode *vp, - int wmode, - struct proc *p, - struct ucred *cred) + int wmode, + struct proc *p, + struct ucred *cred) { - const int v3 = 1; - u_int32_t *tl; - int error = 0, attrflag; - - struct mbuf *mreq, *mrep, *md, *mb, *mb2; - caddr_t bpos, dpos, cp2; - register int32_t t1, t2; - register caddr_t cp; - u_int32_t rmode; - struct nfsnode *np = VTONFS(vp); - - nfsstats.rpccnt[NFSPROC_ACCESS]++; - nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); - nfsm_fhtom(vp, v3); - nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); - *tl = txdr_unsigned(wmode); - nfsm_request(vp, NFSPROC_ACCESS, p, cred); - nfsm_postop_attr(vp, attrflag); - if (!error) { - nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); - rmode = fxdr_unsigned(u_int32_t, *tl); - np->n_mode = rmode; - np->n_modeuid = cred->cr_uid; - np->n_modestamp = time_second; - } - nfsm_reqdone; - return error; + const int v3 = 1; + u_int32_t *tl; + int error = 0, attrflag; + + struct mbuf *mreq, *mrep, *md, *mb, *mb2; + caddr_t bpos, dpos, cp2; + register int32_t t1, t2; + register caddr_t cp; + u_int32_t rmode; + struct nfsnode *np = VTONFS(vp); + + nfsstats.rpccnt[NFSPROC_ACCESS]++; + nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); + nfsm_fhtom(vp, v3); + nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); + *tl = txdr_unsigned(wmode); + nfsm_request(vp, NFSPROC_ACCESS, p, cred); + nfsm_postop_attr(vp, attrflag); + if (!error) { + nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); + rmode = fxdr_unsigned(u_int32_t, *tl); + np->n_mode = rmode; + np->n_modeuid = cred->cr_uid; + np->n_modestamp = time_second; + } + nfsm_reqdone; + return error; } /* @@ -436,10 +558,10 @@ nfs_access(ap) } */ *ap; { register struct vnode *vp = ap->a_vp; - int error = 0; - u_long mode, wmode; + int error = 0; + u_long mode, wmode; int v3 = NFS_ISV3(vp); - struct nfsnode *np = VTONFS(vp); + struct nfsnode *np = VTONFS(vp); /* * For nfs v3, do an access rpc, otherwise you are stuck emulating @@ -466,53 +588,52 @@ nfs_access(ap) if (ap->a_mode & VEXEC) mode |= NFSV3ACCESS_EXECUTE; } - /* XXX safety belt, only make blanket request if caching */ - if (nfsaccess_cache_timeout > 0) { - wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY | - NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE | - NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP; - } else { - wmode = mode; - } + /* XXX safety belt, only make blanket request if caching */ + if (nfsaccess_cache_timeout > 0) { + wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY | + NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE | + NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP; + } else + wmode = mode; - /* - * Does our cached result allow us to give a definite yes to - * this request? - */ - if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) && - (ap->a_cred->cr_uid == np->n_modeuid) && - ((np->n_mode & mode) == mode)) { - /* nfsstats.accesscache_hits++; */ - } else { - /* - * Either a no, or a don't know. Go to the wire. - */ - /* nfsstats.accesscache_misses++; */ - error = nfs3_access_otw(vp, wmode, ap->a_p,ap->a_cred); - if (!error) { - if ((np->n_mode & mode) != mode) - error = EACCES; - } - } + /* + * Does our cached result allow us to give a definite yes to + * this request? + */ + if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) && + (ap->a_cred->cr_uid == np->n_modeuid) && + ((np->n_mode & mode) == mode)) { + /* nfsstats.accesscache_hits++; */ + } else { + /* + * Either a no, or a don't know. Go to the wire. + */ + /* nfsstats.accesscache_misses++; */ + error = nfs3_access_otw(vp, wmode, ap->a_p,ap->a_cred); + if (!error) { + if ((np->n_mode & mode) != mode) + error = EACCES; + } + } } else - return (nfsspec_access(ap)); /* NFSv2 case checks for EROFS here*/ - /* CSM - moved EROFS check down per NetBSD rev 1.71. So you - * get the correct error value with layered filesystems. - * EKN - moved the return(error) below this so it does get called.*/ + return (nfsspec_access(ap)); /* NFSv2 case checks for EROFS here */ /* * Disallow write attempts on filesystems mounted read-only; * unless the file is a socket, fifo, or a block or character * device resident on the filesystem. + * CSM - moved EROFS check down per NetBSD rev 1.71. So you + * get the correct error value with layered filesystems. + * EKN - moved the return(error) below this so it does get called. */ if (!error && (ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { switch (vp->v_type) { - case VREG: case VDIR: case VLNK: - error = EROFS; - default: - break; + case VREG: case VDIR: case VLNK: + error = EROFS; + default: + break; + } } - } - return (error); + return (error); } /* @@ -1011,7 +1132,7 @@ nfs_lookup(ap) int lockparent, wantparent, error = 0, attrflag, fhsize; int v3 = NFS_ISV3(dvp); struct proc *p = cnp->cn_proc; - int worldbuildworkaround = 1; + int worldbuildworkaround = 1; if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) @@ -1024,19 +1145,21 @@ nfs_lookup(ap) nmp = VFSTONFS(dvp->v_mount); np = VTONFS(dvp); - if (worldbuildworkaround) { - /* temporary workaround for world builds to not have dvp go - VBAD on during server calls in this routine. When - the real ref counting problem is found take this out. - Note if this was later and before the nfsm_request - set up, the workaround did not work (NOTE other difference - was I only put one VREF in that time. Thus it needs - to be above the cache_lookup branch or with 2 VREFS. Not - sure which. Can't play with world builds right now to see - which. VOP_ACCESS could also make it go to server. - EKN */ - VREF(dvp); /* hang on to this dvp - EKN */ - VREF(dvp); /* hang on tight - EKN */ - } + if (worldbuildworkaround) { + /* + * Temporary workaround for world builds to not have dvp go + * VBAD on during server calls in this routine. When + * the real ref counting problem is found take this out. + * Note if this was later and before the nfsm_request + * set up, the workaround did not work (NOTE other difference + * was I only put one VREF in that time. Thus it needs + * to be above the cache_lookup branch or with 2 VREFS. Not + * sure which. Can't play with world builds right now to see + * which. VOP_ACCESS could also make it go to server. - EKN + */ + VREF(dvp); /* hang on to this dvp - EKN */ + VREF(dvp); /* hang on tight - EKN */ + } if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { struct vattr vattr; @@ -1044,21 +1167,14 @@ nfs_lookup(ap) if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, p))) { *vpp = NULLVP; - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } - return (error); - } + goto error_return; + } - /* got to check to make sure the vnode didn't go away if access went to server */ - if ((*vpp)->v_type == VBAD) { - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } - return(EINVAL); - } + /* got to check to make sure the vnode didn't go away if access went to server */ + if ((*vpp)->v_type == VBAD) { + error = EINVAL; + goto error_return; + } newvp = *vpp; vpid = newvp->v_id; @@ -1082,47 +1198,33 @@ nfs_lookup(ap) if (!error) { if (vpid == newvp->v_id) { if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, p) - && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { - nfsstats.lookupcache_hits++; - if (cnp->cn_nameiop != LOOKUP && - (flags & ISLASTCN)) - cnp->cn_flags |= SAVENAME; - - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } - - return (0); - } - cache_purge(newvp); - } + && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { + nfsstats.lookupcache_hits++; + if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) + cnp->cn_flags |= SAVENAME; + error = 0; /* ignore any from VOP_GETATTR */ + goto error_return; + } + cache_purge(newvp); + } vput(newvp); if (lockparent && dvp != newvp && (flags & ISLASTCN)) VOP_UNLOCK(dvp, 0, p); } error = vn_lock(dvp, LK_EXCLUSIVE, p); *vpp = NULLVP; - if (error) { - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } - return (error); - } + if (error) + goto error_return; } /* - * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server + * Got to check to make sure the vnode didn't go away if VOP_GETATTR went to server * or callers prior to this blocked and had it go VBAD. - */ - if (dvp->v_type == VBAD) { - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } - return(EINVAL); - } + */ + if (dvp->v_type == VBAD) { + error = EINVAL; + goto error_return; + } error = 0; newvp = NULLVP; @@ -1133,16 +1235,8 @@ nfs_lookup(ap) NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); nfsm_fhtom(dvp, v3); nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); - nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); - - /* this two lines set dvp refcounts back to where they were - * before we took extra 2 VREFS to avoid VBAD vnode on dvp - * during server calls for world builds. Remove when real - * fix is found. - EKN */ - if (worldbuildworkaround) { - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - vrele(dvp); /* end of hanging on tight to dvp - EKN */ - } + /* nfsm_request for NFSv2 causes you to goto to nfsmout upon errors */ + nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); if (error) { nfsm_postop_attr(dvp, attrflag); @@ -1157,11 +1251,12 @@ nfs_lookup(ap) if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { if (NFS_CMPFH(np, fhp, fhsize)) { m_freem(mrep); - return (EISDIR); + error = EISDIR; + goto error_return; } if ((error = nfs_nget(dvp->v_mount, fhp, fhsize, &np))) { m_freem(mrep); - return (error); + goto error_return; } newvp = NFSTOV(np); if (v3) { @@ -1174,7 +1269,8 @@ nfs_lookup(ap) cnp->cn_flags |= SAVENAME; if (!lockparent) VOP_UNLOCK(dvp, 0, p); - return (0); + error = 0; + goto error_return; } if (flags & ISDOTDOT) { @@ -1182,13 +1278,13 @@ nfs_lookup(ap) error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); if (error) { vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p); - return (error); + goto error_return; } newvp = NFSTOV(np); if (lockparent && (flags & ISLASTCN) && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { vput(newvp); - return (error); + goto error_return; } } else if (NFS_CMPFH(np, fhp, fhsize)) { VREF(dvp); @@ -1196,7 +1292,7 @@ nfs_lookup(ap) } else { if ((error = nfs_nget(dvp->v_mount, fhp, fhsize, &np))) { m_freem(mrep); - return (error); + goto error_return; } if (!lockparent || !(flags & ISLASTCN)) VOP_UNLOCK(dvp, 0, p); @@ -1233,6 +1329,18 @@ nfs_lookup(ap) if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) cnp->cn_flags |= SAVENAME; } +error_return: + /* + * These "vreles" set dvp refcounts back to where they were + * before we took extra 2 VREFS to avoid VBAD vnode on dvp + * during server calls for world builds. Remove when real + * fix is found. - EKN + */ + if (worldbuildworkaround) { + vrele(dvp); /* end of hanging on tight to dvp - EKN */ + vrele(dvp); /* end of hanging on tight to dvp - EKN */ + } + return (error); } @@ -1803,17 +1911,12 @@ nfs_remove(ap) np->n_attrstamp = 0; vput(dvp); + VOP_UNLOCK(vp, 0, cnp->cn_proc); - if (vp == dvp) - vrele(vp); - else - vput(vp); + if (file_deleted) + ubc_uncache(vp); - if (file_deleted && UBCINFOEXISTS(vp)) { - (void) ubc_uncache(vp); - ubc_release(vp); - /* WARNING vp may not be valid after this */ - } + vrele(vp); return (error); } @@ -1858,11 +1961,11 @@ nfs_removerpc(dvp, name, namelen, cred, proc) if (v3) nfsm_wcc_data(dvp, wccflag); nfsm_reqdone; - if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */ - VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) - VTONFS(dvp)->n_attrstamp = 0; - } + if (dvp->v_type != VBAD) { /* EINVAL set on VBAD vnode */ + VTONFS(dvp)->n_flag |= NMODIFIED; + if (!wccflag) + VTONFS(dvp)->n_attrstamp = 0; + } return (error); } @@ -1906,7 +2009,7 @@ nfs_rename(ap) * XXX Can't sillyrename a directory. */ if (tvp && (tvp->v_usecount>(UBCISVALID(tvp) ? 2 : 1)) && - !VTONFS(tvp)->n_sillyrename && + !VTONFS(tvp)->n_sillyrename && tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { vput(tvp); tvp = NULL; @@ -2197,11 +2300,11 @@ nfs_mkdir(ap) if (v3) nfsm_wcc_data(dvp, wccflag); nfsm_reqdone; - if (dvp->v_type != VBAD) { /* EINVAL set on this case */ - VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) - VTONFS(dvp)->n_attrstamp = 0; - } + if (dvp->v_type != VBAD) { /* EINVAL set on this case */ + VTONFS(dvp)->n_flag |= NMODIFIED; + if (!wccflag) + VTONFS(dvp)->n_attrstamp = 0; + } /* * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry * if we can succeed in looking up the directory. @@ -3068,17 +3171,16 @@ nfs_flush(vp, cred, waitfor, p, commit) u_quad_t off, endoff, toff; struct ucred* wcred = NULL; struct buf **bvec = NULL; - void * object; - kern_return_t kret; - upl_t *upls = NULL; + kern_return_t kret; + upl_t *upls = NULL; #ifndef NFS_COMMITBVECSIZ #define NFS_COMMITBVECSIZ 20 #endif struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; - struct upl_t *upls_on_stack[NFS_COMMITBVECSIZ]; - int bvecsize = 0, bveccount, buplpos; + struct upl_t *upls_on_stack[NFS_COMMITBVECSIZ]; + int bvecsize = 0, bveccount, buplpos; if (nmp->nm_flag & NFSMNT_INT) slpflag = PCATCH; @@ -3098,7 +3200,7 @@ again: off = (u_quad_t)-1; endoff = 0; bvecpos = 0; - buplpos = 0; + buplpos = 0; if (NFS_ISV3(vp) && commit) { s = splbio(); /* @@ -3117,31 +3219,29 @@ again: * If we can't get memory (for whatever reason), we will end up * committing the buffers one-by-one in the loop below. */ - if (bveccount > NFS_COMMITBVECSIZ) { - if (bvec != NULL && bvec != bvec_on_stack) + if (bvec != NULL && bvec != bvec_on_stack) _FREE(bvec, M_TEMP); + if (upls != NULL && upls != (upl_t *) upls_on_stack) + _FREE(upls, M_TEMP); + + bvecsize = NFS_COMMITBVECSIZ; + if (bveccount > NFS_COMMITBVECSIZ) { MALLOC(bvec, struct buf **, - bveccount * sizeof(struct buf *), M_TEMP, M_NOWAIT); - if (bvec == NULL) { + bveccount * sizeof(struct buf *), M_TEMP, M_NOWAIT); + MALLOC(upls, upl_t *, + bveccount * sizeof(upl_t), M_TEMP, M_NOWAIT); + if ((bvec == NULL) || (upls == NULL)) { + if (bvec) + _FREE(bvec, M_TEMP); + if (upls) + _FREE(upls, M_TEMP); bvec = bvec_on_stack; - bvecsize = NFS_COMMITBVECSIZ; + upls = (upl_t *) upls_on_stack; } else bvecsize = bveccount; - /* allocate the upl structure before the loop based on buffers to commit */ - if (upls != NULL && upls != upls_on_stack) - _FREE(upls, M_TEMP); - MALLOC(upls, struct upl_t *, - bveccount * sizeof(upl_t), M_TEMP, M_NOWAIT); - if (upls == NULL) - upls = upls_on_stack; } else { - if (bvec && bvec != bvec_on_stack) - _FREE(bvec, M_TEMP); bvec = bvec_on_stack; - bvecsize = NFS_COMMITBVECSIZ; - if (upls && upls != upls_on_stack) - _FREE(upls, M_TEMP); - upls = upls_on_stack; + upls = (upl_t *) upls_on_stack; } for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { @@ -3163,27 +3263,22 @@ again: SET(bp->b_flags, (B_BUSY | B_WRITEINPROG)); /* - * we need vm_fault_list_request so if vm decides to + * we need ubc_create_upl so if vm decides to * do paging while we are waiting on commit rpc, * that it doesn't pick these pages. */ if (!ISSET(bp->b_flags, B_PAGELIST)) { - /* if pagelist exists, assume vm pages are locked/busy already */ off_t file_offset = ubc_blktooff(vp, bp->b_lblkno); - object = ubc_getobject(vp, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)); - if (object == (void*)NULL) - panic("nfs_getcacheblk: NULL vmobject"); - if(bp->b_bufsize & 0xfff) - panic("nfs_getcacheblk: list request is less than 4k"); - kret = vm_fault_list_request( - object, (vm_object_offset_t)file_offset, - bp->b_bufsize, &(upls[buplpos]), NULL, 0, - (int)(UPL_NO_SYNC | UPL_CLEAN_IN_PLACE |UPL_PRECIOUS | - UPL_SET_INTERNAL)); + kret = ubc_create_upl(vp, + ubc_blktooff(vp, bp->b_lblkno), + bp->b_bufsize, + &(upls[buplpos]), + NULL, + UPL_PRECIOUS); if (kret != KERN_SUCCESS) panic("nfs_getcacheblk: get pagelists failed with (%d)", kret); #ifdef UBC_DEBUG - upl_ubc_alias_set(pl, ioaddr, 1); + upl_ubc_alias_set(upls[buplpos], ioaddr, 1); #endif /* UBC_DEBUG */ buplpos++; /* not same as bvecpos if upl existed already */ } @@ -3234,19 +3329,20 @@ again: if (retv == NFSERR_STALEWRITEVERF) nfs_clearcommit(vp->v_mount); - for (i = 0; i < buplpos; i++) { - /* - * before the VOP_BWRITE and biodone(ASYNC)/brelse, we have to undo - * holding the vm page or we we will deadlock on another vm_fault_list_request. - * Here's a convenient place to put it. - * Better if we could hold it by setting the PAGELIST flag and kernel_upl_map - * as does nfs_writebp. Then normal biodones and brelse will clean it up and - * we can avoid this abort. For now make minimal changse and test this out. - */ - err = kernel_upl_abort(upls[i], NULL); - if (err) - printf("nfs_flush: kernel_upl_abort %d\n", err); - } + for (i = 0; i < buplpos; i++) { + /* + * Before the VOP_BWRITE and biodone(ASYNC)/brelse, we have to undo + * holding the vm page or we we will deadlock on another vm_fault_list_request. + * Here's a convenient place to put it. + * Better if we could hold it by setting the PAGELIST flag and kernel_upl_map + * as does nfs_writebp. Then normal biodones and brelse will clean it up and + * we can avoid this abort. For now make minimal changes. + */ + err = ubc_upl_abort(upls[i], NULL); + if (err) + printf("nfs_flush: kernel_upl_abort %d\n", err); + } + /* * Now, either mark the blocks I/O done or mark the @@ -3275,10 +3371,10 @@ again: /* * Start/do any write(s) that are required. - * There is a window here where B_BUSY protects the buffer. The vm pages have been - * freed up, yet B_BUSY is set. Don't think you will hit any busy/incore problems while - * we sleep, but not absolutely sure. Keep an eye on it. Otherwise we will have to hold - * vm page across this locked. - EKN + * There is a window here where B_BUSY protects the buffer. The vm pages have been + * freed up, yet B_BUSY is set. Don't think you will hit any busy/incore problems while + * we sleep, but not absolutely sure. Keep an eye on it. Otherwise we will have to hold + * vm page across this locked. - EKN */ loop: if (current_thread_aborted()) { @@ -3313,9 +3409,9 @@ loop: continue; bremfree(bp); if (passone || !commit) - SET(bp->b_flags, (B_BUSY|B_ASYNC)); + SET(bp->b_flags, (B_BUSY|B_ASYNC)); else - SET(bp->b_flags, (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT)); + SET(bp->b_flags, (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT)); splx(s); VOP_BWRITE(bp); @@ -3353,8 +3449,8 @@ loop: done: if (bvec != NULL && bvec != bvec_on_stack) _FREE(bvec, M_TEMP); - if (upls != NULL && upls != upls_on_stack) - _FREE(upls, M_TEMP); + if (upls != NULL && upls != (upl_t *) upls_on_stack) + _FREE(upls, M_TEMP); return (error); } @@ -3617,7 +3713,6 @@ nfs_writebp(bp, force) register int oldflags = bp->b_flags, retv = 1; off_t off; upl_t upl; - void * object; kern_return_t kret; struct vnode *vp = bp->b_vp; upl_page_info_t *pl; @@ -3645,52 +3740,44 @@ nfs_writebp(bp, force) if (!ISSET(bp->b_flags, B_META) && UBCISVALID(vp)) { if (!ISSET(bp->b_flags, B_PAGELIST)) { - - off_t file_offset = ubc_blktooff(vp, bp->b_lblkno); - - object = ubc_getobject(vp, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)); - if (object == (void*)NULL) - panic("nfs_writebp: NULL vmobject"); - - if(bp->b_bufsize & 0xfff) - panic("nfs_writebp: list request is with less than 4k"); - - kret = vm_fault_list_request(object, (vm_object_offset_t)file_offset, - bp->b_bufsize, &upl, NULL, 0, - (int)(UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_PRECIOUS | UPL_SET_INTERNAL)); + kret = ubc_create_upl(vp, + ubc_blktooff(vp, bp->b_lblkno), + bp->b_bufsize, + &upl, + &pl, + UPL_PRECIOUS); if (kret != KERN_SUCCESS) { panic("nfs_writebp: get pagelists failed with (%d)", kret); } #ifdef UBC_DEBUG - upl_ubc_alias_set(pl, ioaddr, 2); + upl_ubc_alias_set(upl, ioaddr, 2); #endif /* UBC_DEBUG */ - s = splbio(); + s = splbio(); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - bp->b_pagelist = upl; - SET(bp->b_flags, B_PAGELIST); - splx(s); + bp->b_pagelist = upl; + SET(bp->b_flags, B_PAGELIST); + splx(s); - kret = kernel_upl_map(kernel_map, upl, - (vm_address_t *)&(bp->b_data)); - if (kret != KERN_SUCCESS) { - panic("nfs_writebp: kernel_upl_map() failed with (%d)", kret); - } - if(bp->b_data == 0) - panic("nfs_writebp: upl_map mapped 0"); - if (!upl_page_present(pl, 0)) { - /* - * may be the page got paged out. - * let's just read it in. It is marked - * busy so we should not have any one - * yanking this page underneath the fileIO - */ - panic("nfs_writebp: nopage"); - } - } - } + kret = ubc_upl_map(upl, (vm_address_t *)&(bp->b_data)); + if (kret != KERN_SUCCESS) { + panic("nfs_writebp: ubc_upl_map() failed with (%d)", kret); + } + if(bp->b_data == 0) + panic("nfs_writebp: upl_map mapped 0"); + + if (!upl_page_present(pl, 0)) { + /* + * may be the page got paged out. + * let's just read it in. It is marked + * busy so we should not have any one + * yanking this page underneath the fileIO + */ + panic("nfs_writebp: nopage"); + } + } + } /* * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not @@ -3714,9 +3801,7 @@ nfs_writebp(bp, force) if (retv) { if (force) SET(bp->b_flags, B_WRITEINPROG); - - VOP_STRATEGY(bp); - + VOP_STRATEGY(bp); } if( (oldflags & B_ASYNC) == 0) { @@ -4052,7 +4137,7 @@ nfs_pagein(ap) if (f_offset < 0 || f_offset >= np->n_size || (f_offset & PAGE_MASK_64)) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, + ubc_upl_abort_range(pl, pl_offset, size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (EINVAL); } @@ -4098,10 +4183,8 @@ nfs_pagein(ap) error = VOP_GETATTR(vp, &vattr, cred, p); if (error) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, - size, - UPL_ABORT_ERROR | - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (error); } np->n_mtime = vattr.va_mtime.tv_sec; @@ -4109,18 +4192,16 @@ nfs_pagein(ap) error = VOP_GETATTR(vp, &vattr, cred, p); if (error){ if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_ERROR | - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (error); } if (np->n_mtime != vattr.va_mtime.tv_sec) { error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); if (error){ if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_ERROR | - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (error); } np->n_mtime = vattr.va_mtime.tv_sec; @@ -4129,7 +4210,7 @@ nfs_pagein(ap) } #endif 0 /* Why bother? */ - kernel_upl_map(kernel_map, pl, &ioaddr); + ubc_upl_map(pl, &ioaddr); ioaddr += pl_offset; xsize = size; @@ -4154,11 +4235,10 @@ nfs_pagein(ap) error = nqnfs_getlease(vp, ND_READ, cred, p); } while (error == NQNFS_EXPIRED); if (error){ - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, - size ,UPL_ABORT_ERROR | - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (error); } @@ -4166,10 +4246,9 @@ nfs_pagein(ap) (np->n_flag & NQNFSNONCACHE)) { error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); if (error) { - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) - kernel_upl_abort_range(pl, - pl_offset,size , + ubc_upl_abort_range(pl, pl_offset, size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (error); } @@ -4181,19 +4260,15 @@ nfs_pagein(ap) if (np->n_flag & NQNFSNONCACHE) { error = nfs_readrpc(vp, uio, cred); - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) { if(error) - kernel_upl_abort_range(pl, pl_offset, size , + ubc_upl_abort_range(pl, pl_offset, size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); else - kernel_upl_commit_range(pl, - pl_offset, size, - UPL_COMMIT_CLEAR_DIRTY - | UPL_COMMIT_FREE_ON_EMPTY, - UPL_GET_INTERNAL_PAGE_LIST(pl), - MAX_UPL_TRANSFER); + ubc_upl_commit_range(pl, pl_offset, size, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); } return (error); } @@ -4247,23 +4322,22 @@ nfs_pagein(ap) } while (error == 0 && xsize > 0); - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) { if (error) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); else - kernel_upl_commit_range(pl, pl_offset, size, - UPL_COMMIT_CLEAR_DIRTY - | UPL_COMMIT_FREE_ON_EMPTY, - UPL_GET_INTERNAL_PAGE_LIST(pl), - MAX_UPL_TRANSFER); + ubc_upl_commit_range(pl, pl_offset, size, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); } return (error); } + + /* * Vnode op for pageout using UPL * Derived from nfs_write() @@ -4329,10 +4403,10 @@ nfs_pageout(ap) * will be the same size within a filesystem. nfs_writerpc will * still use nm_wsize when sizing the rpc's. */ - biosize = min(vp->v_mount->mnt_stat.f_iosize, size); + biosize = min(vp->v_mount->mnt_stat.f_iosize, size); - if (biosize & PAGE_MASK) - panic("nfs_pageout(%x): biosize not page aligned", biosize); + if (biosize & PAGE_MASK) + panic("nfs_pageout(%x): biosize not page aligned", biosize); /* @@ -4342,17 +4416,17 @@ nfs_pageout(ap) * vm_fault_list_request in 'getblk' before returning * which would block on the page busy status */ - lbn = f_offset / PAGE_SIZE; /* to match the size getblk uses */ + lbn = f_offset / PAGE_SIZE; /* to match the size getblk uses */ for (iosize = size; iosize > 0; iosize -= PAGE_SIZE, lbn++) { s = splbio(); if (bp = incore(vp, lbn)) { if (ISSET(bp->b_flags, B_BUSY)) { - /* don't panic incore. just tell vm we are busy */ - (void) kernel_upl_abort(pl, NULL); - return(EBUSY); - }; + /* don't panic incore. just tell vm we are busy */ + (void) ubc_upl_abort(pl, NULL); + return(EBUSY); + }; bremfree(bp); SET(bp->b_flags, (B_BUSY | B_INVAL)); @@ -4368,8 +4442,7 @@ nfs_pageout(ap) if (np->n_flag & NWRITEERR) { np->n_flag &= ~NWRITEERR; if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, UPL_ABORT_FREE_ON_EMPTY); return (np->n_error); } if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) @@ -4378,12 +4451,11 @@ nfs_pageout(ap) if (f_offset < 0 || f_offset >= np->n_size || (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, UPL_ABORT_FREE_ON_EMPTY); return (EINVAL); } - kernel_upl_map(kernel_map, pl, &ioaddr); + ubc_upl_map(pl, &ioaddr); if ((f_offset + size) > np->n_size) iosize = np->n_size - f_offset; @@ -4394,8 +4466,8 @@ nfs_pageout(ap) if (size > pgsize) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset + pgsize, size - pgsize, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset + pgsize, size - pgsize, + UPL_ABORT_FREE_ON_EMPTY); } auio.uio_iov = &aiov; auio.uio_iovcnt = 1; @@ -4438,21 +4510,20 @@ nfs_pageout(ap) error = nqnfs_getlease(vp, ND_WRITE, cred, p); } while (error == NQNFS_EXPIRED); if (error) { - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (error); } if (np->n_lrev != np->n_brev || (np->n_flag & NQNFSNONCACHE)) { error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); if (error) { - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) - kernel_upl_abort_range(pl, - pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (error); } np->n_brev = np->n_lrev; @@ -4465,26 +4536,48 @@ nfs_pageout(ap) error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit); if (must_commit) nfs_clearcommit(vp->v_mount); - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); - /* see comments below after other nfs_writerpc and ESTALE */ - if (error == ESTALE) { - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY); - } else { - if (!nocommit) { - if(error) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); - else - kernel_upl_commit_range(pl, - pl_offset, size, - UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY, - UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER); - } - } - return (error); + /* copied from non-nqnfs case below. see there for comments */ + if (!nocommit) { + if (error) { + int abortflags; + short action = nfs_pageouterrorhandler(error); + + switch (action) { + case DUMP: + abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; + break; + case DUMPANDLOG: + abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; + if ((error <= ELAST) && (errorcount[error] % 100 == 0)) + printf("nfs_pageout: unexpected error %d. dumping vm page\n", error); + errorcount[error]++; + break; + case RETRY: + abortflags = UPL_ABORT_FREE_ON_EMPTY; + break; + case RETRYWITHSLEEP: + abortflags = UPL_ABORT_FREE_ON_EMPTY; + (void) tsleep(&lbolt, PSOCK, "nfspageout", 0); /* pri unused. PSOCK for placeholder. */ + break; + case SEVER: /* not implemented */ + default: + printf("nfs_pageout: action %d not expected\n", action); + break; + } + + ubc_upl_abort_range(pl, pl_offset, size, abortflags); + /* return error in all cases above */ + + } else + ubc_upl_commit_range(pl, + pl_offset, size, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); + } + return (error); /* note this early return */ } + nfsstats.pageouts++; lbn = uio->uio_offset / biosize; on = uio->uio_offset & (biosize-1); @@ -4520,12 +4613,10 @@ again: (np->n_flag & NQNFSNONCACHE)) { error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1); if (error) { - kernel_upl_unmap(kernel_map, pl); + ubc_upl_unmap(pl); if (!nocommit) - kernel_upl_abort_range(pl, - pl_offset, - size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (error); } @@ -4553,30 +4644,66 @@ again: } while (uio->uio_resid > 0 && n > 0); cleanup: - kernel_upl_unmap(kernel_map, pl); - /* - * EStale is special. In this case, we want vm to dump out - * the pages. Better yet, sever the object so we don't come - * back here on each page of the object to page out. For now, - * just dump. - * XXX What about !nocommit case? Should ESTALE only be checked - * in that portion? - EKN - */ - if (error == ESTALE) { - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY); - } else { - if (!nocommit) { - if(error) - kernel_upl_abort_range(pl, pl_offset, pgsize, - UPL_ABORT_FREE_ON_EMPTY); - else - kernel_upl_commit_range(pl, pl_offset, pgsize, - UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY, - UPL_GET_INTERNAL_PAGE_LIST(pl), MAX_UPL_TRANSFER); - } + ubc_upl_unmap(pl); + /* + * We've had several different solutions on what to do when the pageout + * gets an error. If we don't handle it, and return an error to the + * caller, vm, it will retry . This can end in endless looping + * between vm and here doing retries of the same page. Doing a dump + * back to vm, will get it out of vm's knowledge and we lose whatever + * data existed. This is risky, but in some cases necessary. For + * example, the initial fix here was to do that for ESTALE. In that case + * the server is telling us that the file is no longer the same. We + * would not want to keep paging out to that. We also saw some 151 + * errors from Auspex server and NFSv3 can return errors higher than + * ELAST. Those along with NFS known server errors we will "dump" from vm. + * Errors we don't expect to occur, we dump and log for further + * analysis. Errors that could be transient, networking ones, + * we let vm "retry". Lastly, errors that we retry, but may have potential + * to storm the network, we "retrywithsleep". "sever" will be used in + * in the future to dump all pages of object for cases like ESTALE. + * All this is the basis for the states returned and first guesses on + * error handling. Tweaking expected as more statistics are gathered. + * Note, in the long run we may need another more robust solution to + * have some kind of persistant store when the vm cannot dump nor keep + * retrying as a solution, but this would be a file architectural change. + */ + + if (!nocommit) { /* otherwise stacked file system has to handle this */ + if (error) { + int abortflags; + short action = nfs_pageouterrorhandler(error); + + switch (action) { + case DUMP: + abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; + break; + case DUMPANDLOG: + abortflags = UPL_ABORT_DUMP_PAGES|UPL_ABORT_FREE_ON_EMPTY; + if ((error <= ELAST) && (errorcount[error] % 100 == 0)) + printf("nfs_pageout: unexpected error %d. dumping vm page\n", error); + errorcount[error]++; + break; + case RETRY: + abortflags = UPL_ABORT_FREE_ON_EMPTY; + break; + case RETRYWITHSLEEP: + abortflags = UPL_ABORT_FREE_ON_EMPTY; + (void) tsleep(&lbolt, PSOCK, "nfspageout", 0); /* pri unused. PSOCK for placeholder. */ + break; + case SEVER: /* not implemented */ + default: + printf("nfs_pageout: action %d not expected\n", action); + break; + } + + ubc_upl_abort_range(pl, pl_offset, size, abortflags); + /* return error in all cases above */ + + } else + ubc_upl_commit_range(pl, pl_offset, pgsize, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); } - return (error); } diff --git a/bsd/ppc/types.h b/bsd/ppc/types.h index 538ded1de..9b5d80b36 100644 --- a/bsd/ppc/types.h +++ b/bsd/ppc/types.h @@ -78,8 +78,8 @@ typedef unsigned long long u_int64_t; typedef int32_t register_t; -typedef int *intptr_t; -typedef unsigned long *uintptr_t; +typedef long int intptr_t; +typedef unsigned long int uintptr_t; #endif /* __ASSEMBLER__ */ #endif /* _MACHTYPES_H_ */ diff --git a/bsd/sys/Makefile b/bsd/sys/Makefile index 4853cddfa..be495b68d 100644 --- a/bsd/sys/Makefile +++ b/bsd/sys/Makefile @@ -26,7 +26,7 @@ DATAFILES = \ ioctl_compat.h ipc.h kernel.h kern_event.h ktrace.h loadable_fs.h lock.h lockf.h mach_swapon.h malloc.h \ kdebug.h linker_set.h md5.h\ mbuf.h mman.h mount.h msgbuf.h mtio.h namei.h netport.h param.h paths.h \ - proc.h protosw.h ptrace.h queue.h reboot.h resource.h resourcevar.h \ + proc.h protosw.h ptrace.h queue.h random.h reboot.h resource.h resourcevar.h \ select.h semaphore.h shm.h signal.h signalvar.h socket.h socketvar.h sockio.h stat.h \ syscall.h sysctl.h syslimits.h syslog.h systm.h termios.h time.h \ timeb.h times.h tprintf.h trace.h tty.h ttychars.h ttycom.h \ diff --git a/bsd/sys/attr.h b/bsd/sys/attr.h index 96881d20c..96eead6f7 100644 --- a/bsd/sys/attr.h +++ b/bsd/sys/attr.h @@ -114,6 +114,7 @@ typedef struct vol_capabilities_attr { #define VOL_CAP_INT_SEARCHFS 0x00000001 #define VOL_CAP_INT_ATTRLIST 0x00000002 #define VOL_CAP_INT_NFSEXPORT 0x00000004 +#define VOL_CAP_INT_READDIRATTR 0x00000008 typedef struct vol_attributes_attr { attribute_set_t validattr; diff --git a/bsd/sys/buf.h b/bsd/sys/buf.h index 25a87d6cf..924ac0fae 100644 --- a/bsd/sys/buf.h +++ b/bsd/sys/buf.h @@ -237,8 +237,8 @@ struct buf *incore __P((struct vnode *, daddr_t)); u_int minphys __P((struct buf *bp)); int physio __P((void (*)(struct buf *), struct buf *, dev_t, int , u_int (*)(struct buf *), struct uio *, int )); int count_busy_buffers __P((void)); -struct buf *alloc_io_buf __P((struct vnode *vp)); -void free_io_buf __P((struct buf *bp)); +struct buf *alloc_io_buf __P((struct vnode *, int)); +void free_io_buf __P((struct buf *)); __END_DECLS /* diff --git a/bsd/sys/cdefs.h b/bsd/sys/cdefs.h index 5622154f3..7f5bb8b99 100644 --- a/bsd/sys/cdefs.h +++ b/bsd/sys/cdefs.h @@ -128,7 +128,9 @@ * these work for GNU C++ (modulo a slight glitch in the C++ grammar * in the distribution version of 2.5.5). */ -#if !defined(__GNUC__) || __GNUC__ < 2 || \ +#if defined(__MWERKS__) && (__MWERKS__ > 0x2400) + /* newer Metrowerks compilers support __attribute__() */ +#elif !defined(__GNUC__) || __GNUC__ < 2 || \ (__GNUC__ == 2 && __GNUC_MINOR__ < 5) #define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ #if defined(__GNUC__) && !defined(__STRICT_ANSI__) diff --git a/bsd/sys/conf.h b/bsd/sys/conf.h index 535881b08..690651ab7 100644 --- a/bsd/sys/conf.h +++ b/bsd/sys/conf.h @@ -89,7 +89,7 @@ typedef int psize_fcn_t __P((dev_t dev)); typedef int read_write_fcn_t __P((dev_t dev, struct uio *uio, int ioflag)); typedef int stop_fcn_t __P((struct tty *tp, int rw)); typedef int reset_fcn_t __P((int uban)); -typedef int select_fcn_t __P((dev_t dev, int which, struct proc *p)); +typedef int select_fcn_t __P((dev_t dev, int which, void * wql, struct proc *p)); typedef int mmap_fcn_t __P(()); typedef int getc_fcn_t __P((dev_t dev)); typedef int putc_fcn_t __P((dev_t dev, char c)); diff --git a/bsd/sys/domain.h b/bsd/sys/domain.h index 1fbc76ed5..c0e3ad112 100644 --- a/bsd/sys/domain.h +++ b/bsd/sys/domain.h @@ -85,6 +85,7 @@ struct domain { int dom_maxrtkey; /* for routing layer */ int dom_protohdrlen; /* Let the protocol tell us */ int dom_refs; /* # socreates outstanding */ + u_long reserved[4]; }; #ifdef KERNEL diff --git a/bsd/sys/fcntl.h b/bsd/sys/fcntl.h index d1af6af91..b54889ea1 100644 --- a/bsd/sys/fcntl.h +++ b/bsd/sys/fcntl.h @@ -202,6 +202,7 @@ #define F_PEOFPOSMODE 3 /* Make it past all of the SEEK pos modes so that */ /* we can keep them in sync should we desire */ +#define F_VOLPOSMODE 4 /* specify volume starting postion */ /* * Advisory file segment locking data type - @@ -234,10 +235,10 @@ struct radvisory { #define LOCK_UN 0x08 /* unlock file */ #endif -/* fstore_t type used by F_DEALLCOATE and F_PREALLCOATE commands */ +/* fstore_t type used by F_DEALLOCATE and F_PREALLOCATE commands */ typedef struct fstore { - u_int32_t fst_flags; /* IN: flags word */ + u_int32_t fst_flags; /* IN: flags word */ int fst_posmode; /* IN: indicates use of offset field */ off_t fst_offset; /* IN: start of the region */ off_t fst_length; /* IN: size of the region */ diff --git a/bsd/sys/file.h b/bsd/sys/file.h index 9ddd3affe..e3c71ed59 100644 --- a/bsd/sys/file.h +++ b/bsd/sys/file.h @@ -91,7 +91,7 @@ struct file { int (*fo_ioctl) __P((struct file *fp, u_long com, caddr_t data, struct proc *p)); int (*fo_select) __P((struct file *fp, int which, - struct proc *p)); + void * wql, struct proc *p)); int (*fo_close) __P((struct file *fp, struct proc *p)); } *f_ops; off_t f_offset; diff --git a/bsd/sys/kdebug.h b/bsd/sys/kdebug.h index b242cecb4..b1103b6d7 100644 --- a/bsd/sys/kdebug.h +++ b/bsd/sys/kdebug.h @@ -97,6 +97,7 @@ __BEGIN_DECLS #define MACH_CALL_CONT 0x3 /* call_continuation() */ #define MACH_CALLOUT 0x4 /* callouts */ #define MACH_STACK_DETACH 0x5 +#define MACH_MAKE_RUNNABLE 0x6 /* make thread runnable */ /* **** The Kernel Debug Sub Classes for Network (DBG_NETWORK) **** */ #define DBG_NETIP 1 /* Internet Protocol */ @@ -218,6 +219,12 @@ do { \ kernel_debug(x,a,b,c,d,e); \ } while(0) +#define KERNEL_DEBUG_CONSTANT1(x,a,b,c,d,e) \ +do { \ + if (kdebug_enable) \ + kernel_debug1(x,a,b,c,d,e); \ +} while(0) + extern void kernel_debug(unsigned int debugid, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5); extern void kernel_debug1(unsigned int debugid, unsigned int arg1, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5); diff --git a/bsd/sys/lock.h b/bsd/sys/lock.h index 0e9783854..7e7015408 100644 --- a/bsd/sys/lock.h +++ b/bsd/sys/lock.h @@ -71,6 +71,21 @@ #endif #define simple_lock_init(l) usimple_lock_init((l),0) +#if defined(simple_lock) +#undef simple_lock +#endif +#define simple_lock(l) ((void) 1) + +#if defined(simple_unlock) +#undef simple_unlock +#endif +#define simple_unlock(l) ((void) 1) + +#if defined(simple_lock_try) +#undef simple_lock_try +#endif +#define simple_lock_try(l) 1 + #else /* KERNEL */ #ifndef _MACHINE_SIMPLE_LOCK_DATA_ diff --git a/bsd/sys/mbuf.h b/bsd/sys/mbuf.h index ebd9ac240..9638bc398 100644 --- a/bsd/sys/mbuf.h +++ b/bsd/sys/mbuf.h @@ -203,6 +203,7 @@ struct mbuf { #define CSUM_IP_VALID 0x0200 /* ... the csum is valid */ #define CSUM_DATA_VALID 0x0400 /* csum_data field is valid */ #define CSUM_PSEUDO_HDR 0x0800 /* csum_data has pseudo hdr */ +#define CSUM_TCP_SUM16 0x1000 /* simple TCP Sum16 computation */ #define CSUM_DELAY_DATA (CSUM_TCP | CSUM_UDP) #define CSUM_DELAY_IP (CSUM_IP) /* XXX add ipv6 here too? */ @@ -244,8 +245,8 @@ struct mbuf { extern decl_simple_lock_data(, mbuf_slock); -#define MBUF_LOCK() simple_lock(&mbuf_slock); -#define MBUF_UNLOCK() simple_unlock(&mbuf_slock); +#define MBUF_LOCK() usimple_lock(&mbuf_slock); +#define MBUF_UNLOCK() usimple_unlock(&mbuf_slock); #define MBUF_LOCKINIT() simple_lock_init(&mbuf_slock); diff --git a/bsd/sys/mount.h b/bsd/sys/mount.h index 4a939095c..61fdd6bb7 100644 --- a/bsd/sys/mount.h +++ b/bsd/sys/mount.h @@ -134,6 +134,11 @@ struct mount { int mnt_maxsymlinklen; /* max size of short symlink */ struct statfs mnt_stat; /* cache of filesystem stats */ qaddr_t mnt_data; /* private data */ + /* Cached values of the IO constraints for the device */ + u_int32_t mnt_maxreadcnt; /* Max. byte count for read */ + u_int32_t mnt_maxwritecnt; /* Max. byte count for write */ + u_int16_t mnt_segreadcnt; /* Max. segment count for read */ + u_int16_t mnt_segwritecnt; /* Max. segment count for write */ }; /* diff --git a/bsd/sys/proc.h b/bsd/sys/proc.h index 4ca9147c9..c6ce52227 100644 --- a/bsd/sys/proc.h +++ b/bsd/sys/proc.h @@ -196,6 +196,8 @@ struct proc { void * exitarg; /* exit arg for proc terminate */ void * vm_shm; /* for sysV shared memory */ sigset_t p_sigpending; /* pended Signals as traced process is blocked. */ + int p_vforkcnt; /* number of outstanding vforks */ + void * p_vforkact; /* activation running this vfork proc */ #if DIAGNOSTIC #if SIGNAL_DEBUG unsigned int lockpc[8]; @@ -296,6 +298,11 @@ struct extern_proc { #define P_REBOOT 0x0200000 /* Process called reboot() */ #define P_TBE 0x0400000 /* Process is TBE */ #define P_SIGTHR 0x0800000 /* signal pending handling thread scheduled */ +#define P_BTRACE 0x1000000 /* process is being branch traced */ +#define P_VFORK 0x2000000 /* process has vfork children */ +#define P_NOATTACH 0x4000000 +#define P_INVFORK 0x8000000 /* proc in vfork */ + /* * Shareable process credentials (always resident). This includes a reference diff --git a/bsd/sys/protosw.h b/bsd/sys/protosw.h index b26fefda7..98c00a565 100644 --- a/bsd/sys/protosw.h +++ b/bsd/sys/protosw.h @@ -116,6 +116,7 @@ struct protosw { /* Implant hooks */ TAILQ_HEAD(pr_sfilter, NFDescriptor) pr_sfilter; struct protosw *pr_next; /* Chain for domain */ + u_long reserved[4]; /* Padding for future use */ }; #define PR_SLOWHZ 2 /* 2 slow timeouts per second */ @@ -244,7 +245,7 @@ struct pr_usrreqs { struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)); int (*pru_sopoll) __P((struct socket *so, int events, - struct ucred *cred)); + struct ucred *cred, void *)); }; diff --git a/bsd/sys/ptrace.h b/bsd/sys/ptrace.h index 5304ecdef..fa63ab9d8 100644 --- a/bsd/sys/ptrace.h +++ b/bsd/sys/ptrace.h @@ -70,6 +70,7 @@ #define PT_STEP 9 /* single step the child */ #define PT_ATTACH 10 /* trace some running process */ #define PT_DETACH 11 /* stop tracing a process */ +#define PT_DENY_ATTACH 31 #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include <machine/ptrace.h> /* machine-specific requests, if any */ diff --git a/iokit/Families/IOGraphics/IOAccelerator.cpp b/bsd/sys/random.h similarity index 81% rename from iokit/Families/IOGraphics/IOAccelerator.cpp rename to bsd/sys/random.h index f50442480..9e5ba135b 100644 --- a/iokit/Families/IOGraphics/IOAccelerator.cpp +++ b/bsd/sys/random.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -20,10 +20,10 @@ * @APPLE_LICENSE_HEADER_END@ */ -#include <IOKit/graphics/IOAccelerator.h> +#ifndef __SYS_RANDOM_H__ +#define __SYS_RANDOM_H__ +#include <dev/random/randomdev.h> -#define super IOService - -OSDefineMetaClassAndStructors(IOAccelerator, IOService) +#endif /* __SYS_RANDOM_H__ */ diff --git a/bsd/sys/select.h b/bsd/sys/select.h index 615d5789e..4d8997d36 100644 --- a/bsd/sys/select.h +++ b/bsd/sys/select.h @@ -57,21 +57,34 @@ #ifndef _SYS_SELECT_H_ #define _SYS_SELECT_H_ +#ifdef KERNEL +__BEGIN_DECLS +#include <kern/wait_queue.h> +__END_DECLS +#endif + /* * Used to maintain information about processes that wish to be * notified when I/O becomes possible. */ struct selinfo { - void *si_thread; /* thread to be notified */ - short si_flags; /* see below */ +#ifdef KERNEL + struct wait_queue wait_queue; /* wait_queue for wait/wakeup */ +#else + char wait_queue[16]; +#endif + u_int si_flags; /* see below */ }; + #define SI_COLL 0x0001 /* collision occurred */ -#define SI_SBSEL 0x0002 /* select socket buffer wanted replaces SB_SEL */ +#define SI_RECORDED 0x0004 /* select has been recorded */ +#define SI_INITED 0x0008 /* selinfo has been inited */ +#define SI_CLEAR 0x0010 /* selinfo has been cleared */ #ifdef KERNEL struct proc; -void selrecord __P((struct proc *selector, struct selinfo *)); +void selrecord __P((struct proc *selector, struct selinfo *, void *)); void selwakeup __P((struct selinfo *)); void selthreadclear __P((struct selinfo *)); #endif diff --git a/bsd/sys/socket.h b/bsd/sys/socket.h index b14277293..080cc3b7c 100644 --- a/bsd/sys/socket.h +++ b/bsd/sys/socket.h @@ -164,8 +164,9 @@ struct linger { #define AF_NATM 31 /* native ATM access */ #define AF_SYSTEM 32 /* Kernel event messages */ #define AF_NETBIOS 33 /* NetBIOS */ +#define AF_PPP 34 /* PPP communication protocol */ -#define AF_MAX 34 +#define AF_MAX 35 /* * Structure used by kernel to store most @@ -247,6 +248,7 @@ struct sockaddr_storage { #define PF_ATM AF_ATM #define PF_SYSTEM AF_SYSTEM #define PF_NETBIOS AF_NETBIOS +#define PF_PPP AF_PPP #define PF_MAX AF_MAX diff --git a/bsd/sys/socketvar.h b/bsd/sys/socketvar.h index c8293aeae..f4968601b 100644 --- a/bsd/sys/socketvar.h +++ b/bsd/sys/socketvar.h @@ -138,14 +138,16 @@ struct socket { struct selinfo sb_sel; /* process selecting read/write */ short sb_flags; /* flags, see below */ short sb_timeo; /* timeout for read/write */ + void *reserved1; /* for future use if needed */ + void *reserved2; } so_rcv, so_snd; #define SB_MAX (256*1024) /* default for max chars in sockbuf */ #define SB_LOCK 0x01 /* lock on data queue */ #define SB_WANT 0x02 /* someone is waiting to lock */ #define SB_WAIT 0x04 /* someone is waiting for data/space */ -#define SB_SEL_XXX 0x08 /* Don't use. replaced by SI_SBSEL in selinfo */ +#define SB_SEL 0x08 /* someone is selecting */ #define SB_ASYNC 0x10 /* ASYNC I/O, need signals */ -#define SB_NOTIFY (SB_WAIT|SB_ASYNC) +#define SB_NOTIFY (SB_WAIT|SB_SEL|SB_ASYNC) #define SB_UPCALL 0x20 /* someone wants an upcall */ #define SB_NOINTR 0x40 /* operations not interruptible */ #define SB_RECV 0x8000 /* this is rcv sb */ @@ -166,6 +168,10 @@ struct socket { /* Plug-in support - make the socket interface overridable */ struct mbuf *so_tail; struct kextcb *so_ext; /* NKE hook */ + void *reserved1; /* for future use if needed */ + void *reserved2; + void *reserved3; + void *reserved4; }; /* @@ -223,83 +229,6 @@ struct xsocket { */ #define sbtoso(sb) (sb->sb_so) -/* - * Do we need to notify the other side when I/O is possible? - */ -#define sb_notify(sb) (((sb)->sb_flags & (SB_WAIT|SB_ASYNC|SB_UPCALL)) != 0 || ((sb)->sb_sel.si_flags & SI_SBSEL) != 0) - -/* - * How much space is there in a socket buffer (so->so_snd or so->so_rcv)? - * This is problematical if the fields are unsigned, as the space might - * still be negative (cc > hiwat or mbcnt > mbmax). Should detect - * overflow and return 0. Should use "lmin" but it doesn't exist now. - */ -#define sbspace(sb) \ - ((long) imin((int)((sb)->sb_hiwat - (sb)->sb_cc), \ - (int)((sb)->sb_mbmax - (sb)->sb_mbcnt))) - -/* do we have to send all at once on a socket? */ -#define sosendallatonce(so) \ - ((so)->so_proto->pr_flags & PR_ATOMIC) - -/* can we read something from so? */ -#define soreadable(so) \ - ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \ - ((so)->so_state & SS_CANTRCVMORE) || \ - (so)->so_comp.tqh_first || (so)->so_error) - -/* can we write something to so? */ -#define sowriteable(so) \ - ((sbspace(&(so)->so_snd) >= (so)->so_snd.sb_lowat && \ - (((so)->so_state&SS_ISCONNECTED) || \ - ((so)->so_proto->pr_flags&PR_CONNREQUIRED)==0)) || \ - ((so)->so_state & SS_CANTSENDMORE) || \ - (so)->so_error) - -/* adjust counters in sb reflecting allocation of m */ -#define sballoc(sb, m) { \ - (sb)->sb_cc += (m)->m_len; \ - (sb)->sb_mbcnt += MSIZE; \ - if ((m)->m_flags & M_EXT) \ - (sb)->sb_mbcnt += (m)->m_ext.ext_size; \ -} - -/* adjust counters in sb reflecting freeing of m */ -#define sbfree(sb, m) { \ - (sb)->sb_cc -= (m)->m_len; \ - (sb)->sb_mbcnt -= MSIZE; \ - if ((m)->m_flags & M_EXT) \ - (sb)->sb_mbcnt -= (m)->m_ext.ext_size; \ -} - -/* - * Set lock on sockbuf sb; sleep if lock is already held. - * Unless SB_NOINTR is set on sockbuf, sleep is interruptible. - * Returns error without lock if sleep is interrupted. - */ -#define sblock(sb, wf) ((sb)->sb_flags & SB_LOCK ? \ - (((wf) == M_WAIT) ? sb_lock(sb) : EWOULDBLOCK) : \ - ((sb)->sb_flags |= SB_LOCK), 0) - -/* release lock on sockbuf sb */ -#define sbunlock(sb) { \ - (sb)->sb_flags &= ~SB_LOCK; \ - if ((sb)->sb_flags & SB_WANT) { \ - (sb)->sb_flags &= ~SB_WANT; \ - wakeup((caddr_t)&(sb)->sb_flags); \ - } \ -} - -#define sorwakeup(so) do { \ - if (sb_notify(&(so)->so_rcv)) \ - sowakeup((so), &(so)->so_rcv); \ - } while (0) - -#define sowwakeup(so) do { \ - if (sb_notify(&(so)->so_snd)) \ - sowakeup((so), &(so)->so_snd); \ - } while (0) - /* * Socket extension mechanism: control block hooks: @@ -370,7 +299,7 @@ int soo_read __P((struct file *fp, struct uio *uio, struct ucred *cred)); int soo_write __P((struct file *fp, struct uio *uio, struct ucred *cred)); int soo_ioctl __P((struct file *fp, u_long cmd, caddr_t data, struct proc *p)); -int soo_select __P((struct file *fp, int which, struct proc *p)); +int soo_select __P((struct file *fp, int which, void * wql, struct proc *p)); int soo_stat __P((struct socket *so, struct stat *ub)); int soo_close __P((struct file *fp, struct proc *p)); @@ -429,7 +358,7 @@ struct socket * int sooptcopyin __P((struct sockopt *sopt, void *buf, size_t len, size_t minlen)); int sooptcopyout __P((struct sockopt *sopt, void *buf, size_t len)); -int sopoll __P((struct socket *so, int events, struct ucred *cred)); +int sopoll __P((struct socket *so, int events, struct ucred *cred, void *wql)); int soreceive __P((struct socket *so, struct sockaddr **paddr, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)); @@ -444,6 +373,27 @@ int sosetopt __P((struct socket *so, struct sockopt *sopt)); int soshutdown __P((struct socket *so, int how)); void sotoxsocket __P((struct socket *so, struct xsocket *xso)); void sowakeup __P((struct socket *so, struct sockbuf *sb)); +int sb_notify __P((struct sockbuf *sb)); +long sbspace __P((struct sockbuf *sb)); +int sosendallatonce __P((struct socket *so)); +int soreadable __P((struct socket *so)); +int sowriteable __P((struct socket *so)); +void sballoc __P((struct sockbuf *sb, struct mbuf *m)); +void sbfree __P((struct sockbuf *sb, struct mbuf *m)); +int sblock __P((struct sockbuf *sb, int wf)); +void sbunlock __P((struct sockbuf *sb)); +void sorwakeup __P((struct socket * so)); +void sowwakeup __P((struct socket * so)); + + + + + + + + + + #endif /* KERNEL */ diff --git a/bsd/sys/sockio.h b/bsd/sys/sockio.h index fe2e3a6f5..de33b3330 100644 --- a/bsd/sys/sockio.h +++ b/bsd/sys/sockio.h @@ -119,6 +119,14 @@ #define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */ #define SIOCGIFPDSTADDR _IOWR('i', 72, struct ifreq) /* get gif pdst addr */ +#ifdef KERNEL_PRIVATE +/* + * temporary control calls to attach/detach IP to/from an ethernet interface + */ +#define SIOCPROTOATTACH _IOWR('i', 80, struct ifreq) /* attach proto to interface */ +#define SIOCPROTODETACH _IOWR('i', 81, struct ifreq) /* detach proto from interface */ +#endif KERNEL_PRIVATE + #define SIOCGIFASYNCMAP _IOWR('i', 124, struct ifreq) /* get ppp asyncmap */ #define SIOCSIFASYNCMAP _IOW('i', 125, struct ifreq) /* set ppp asyncmap */ diff --git a/bsd/sys/syscall.h b/bsd/sys/syscall.h index 9f9d32f89..e9a7194a9 100644 --- a/bsd/sys/syscall.h +++ b/bsd/sys/syscall.h @@ -293,4 +293,5 @@ /* 298 - 323 are reserved */ #define SYS_mlockall 324 #define SYS_munlockall 325 - + /* 326 is reserved */ +#define SYS_issetugid 327 diff --git a/bsd/sys/tty.h b/bsd/sys/tty.h index 277f50849..ba3683a90 100644 --- a/bsd/sys/tty.h +++ b/bsd/sys/tty.h @@ -313,8 +313,8 @@ int ttioctl __P((struct tty *tp, u_long com, caddr_t data, int flag, #endif int ttread __P((struct tty *tp, struct uio *uio, int flag)); void ttrstrt __P((void *tp)); -int ttyselect __P((struct tty *tp, int rw, struct proc *p)); -int ttselect __P((dev_t dev, int rw, struct proc *p)); +int ttyselect __P((struct tty *tp, int rw, void * wql, struct proc *p)); +int ttselect __P((dev_t dev, int rw, void * wql, struct proc *p)); void ttsetwater __P((struct tty *tp)); int ttspeedtab __P((int speed, struct speedtab *table)); int ttstart __P((struct tty *tp)); diff --git a/bsd/sys/types.h b/bsd/sys/types.h index dd19de0ec..a2cb5928d 100644 --- a/bsd/sys/types.h +++ b/bsd/sys/types.h @@ -137,7 +137,7 @@ typedef _BSD_TIME_T_ time_t; * manipulate such bit fields (the filesystem macros use chars). */ #ifndef FD_SETSIZE -#define FD_SETSIZE 256 +#define FD_SETSIZE 1024 #endif typedef int32_t fd_mask; diff --git a/bsd/sys/ubc.h b/bsd/sys/ubc.h index 0b647d1db..db2c18c4a 100644 --- a/bsd/sys/ubc.h +++ b/bsd/sys/ubc.h @@ -50,14 +50,14 @@ extern struct zone *ubc_info_zone; */ struct ubc_info { - void * ui_pager; /* pager */ - void *ui_object; /* VM object corresponding to the pager */ - long ui_flags; /* flags */ - struct vnode *ui_vnode; /* The vnode associated with this ubc_info */ - struct ucred *ui_ucred; /* holds credentials for NFS paging */ - int ui_holdcnt; /* hold the memory object */ - off_t ui_size; /* file size for the vnode */ - long ui_mapped; /* is it currently mapped */ + memory_object_t ui_pager; /* pager */ + memory_object_control_t ui_control; /* VM control for the pager */ + long ui_flags; /* flags */ + struct vnode *ui_vnode; /* The vnode for this ubc_info */ + struct ucred *ui_ucred; /* holds credentials for NFS paging */ + int ui_refcount;/* ref count on the ubc_info */ + off_t ui_size; /* file size for the vnode */ + long ui_mapped; /* is it currently mapped */ }; /* Defines for ui_flags */ @@ -74,7 +74,7 @@ struct ubc_info { __BEGIN_DECLS int ubc_info_init __P((struct vnode *)); -void ubc_info_free __P((struct vnode *)); +void ubc_info_deallocate __P((struct ubc_info *)); int ubc_setsize __P((struct vnode *, off_t)); off_t ubc_getsize __P((struct vnode *)); int ubc_uncache __P((struct vnode *)); @@ -82,9 +82,9 @@ int ubc_umount __P((struct mount *)); void ubc_unmountall __P(()); int ubc_setcred __P((struct vnode *, struct proc *)); struct ucred *ubc_getcred __P((struct vnode *)); -void *ubc_getpager __P((struct vnode *)); -void *ubc_getobject __P((struct vnode *, int)); -int ubc_setpager __P((struct vnode *, void *)); +memory_object_t ubc_getpager __P((struct vnode *)); +memory_object_control_t ubc_getobject __P((struct vnode *, int)); +int ubc_setpager __P((struct vnode *, memory_object_t)); int ubc_setflags __P((struct vnode *, int)); int ubc_clearflags __P((struct vnode *, int)); int ubc_issetflags __P((struct vnode *, int)); @@ -92,13 +92,17 @@ off_t ubc_blktooff __P((struct vnode *, daddr_t)); daddr_t ubc_offtoblk __P((struct vnode *, off_t)); int ubc_clean __P((struct vnode *, int)); int ubc_pushdirty __P((struct vnode *)); +int ubc_pushdirty_range __P((struct vnode *, off_t, off_t)); int ubc_hold __P((struct vnode *)); void ubc_rele __P((struct vnode *)); void ubc_map __P((struct vnode *)); -int ubc_release __P((struct vnode *)); +int ubc_destroy_named __P((struct vnode *)); +int ubc_release_named __P((struct vnode *)); int ubc_invalidate __P((struct vnode *, off_t, size_t)); int ubc_isinuse __P((struct vnode *, int)); +int ubc_page_op __P((struct vnode *, off_t, int, vm_offset_t *, int *)); + /* cluster IO routines */ int cluster_read __P((struct vnode *, struct uio *, off_t, int, int)); int advisory_read __P((struct vnode *, off_t, off_t, int, int)); @@ -110,6 +114,17 @@ int cluster_pageout __P((struct vnode *, upl_t, vm_offset_t, off_t, int, int cluster_pagein __P((struct vnode *, upl_t, vm_offset_t, off_t, int, off_t, int, int)); int cluster_bp __P((struct buf *)); + +/* UPL routines */ +int ubc_create_upl __P((struct vnode *, off_t, long, upl_t *, + upl_page_info_t **, int)); +int ubc_upl_map __P((upl_t, vm_offset_t *)); +int ubc_upl_unmap __P((upl_t)); +int ubc_upl_commit __P((upl_t)); +int ubc_upl_commit_range __P((upl_t, vm_offset_t, vm_size_t, int)); +int ubc_upl_abort __P((upl_t, int)); +int ubc_upl_abort_range __P((upl_t, vm_offset_t, vm_size_t, int)); +upl_page_info_t *ubc_upl_pageinfo __P((upl_t)); __END_DECLS #define UBCINFOMISSING(vp) \ @@ -136,10 +151,8 @@ __END_DECLS panic("%s: lost ubc_info", (fun)); /* Flags for ubc_getobject() */ +#define UBC_FLAGS_NONE 0x0000 #define UBC_HOLDOBJECT 0x0001 -#define UBC_NOREACTIVATE 0x0002 -#define UBC_PAGINGOP 0x0004 - #endif /* _SYS_UBC_H_ */ diff --git a/bsd/sys/user.h b/bsd/sys/user.h index 0abd1ef5d..066d3c8b4 100644 --- a/bsd/sys/user.h +++ b/bsd/sys/user.h @@ -102,6 +102,10 @@ struct uthread { struct timeval atv; int poll; int error; + int count; + int nfcount; + char * wql; + int allocsize; /* select allocated size */ } ss_select; /* saved state for select() */ struct _wait { int f; @@ -119,8 +123,12 @@ struct uthread { int (*uu_continuation)(int); int uu_pri; int uu_timo; - + int uu_flag; + struct proc * uu_proc; + void * uu_userstate; + wait_queue_sub_t uu_wqsub; }; + typedef struct uthread * uthread_t; #endif /* KERNEL */ diff --git a/bsd/sys/utfconv.h b/bsd/sys/utfconv.h index f3f2bfacc..f70f42490 100644 --- a/bsd/sys/utfconv.h +++ b/bsd/sys/utfconv.h @@ -29,7 +29,8 @@ */ #define UTF_REVERSE_ENDIAN 0x01 /* reverse UCS-2 byte order */ #define UTF_NO_NULL_TERM 0x02 /* do not add null termination */ -#define UTF_DECOMPOSED 0x04 /* generate fully decompsed UCS-2 */ +#define UTF_DECOMPOSED 0x04 /* generate fully decomposed UCS-2 */ +#define UTF_PRECOMPOSED 0x08 /* generate precomposed UCS-2 */ __BEGIN_DECLS size_t utf8_encodelen __P((const u_int16_t *, size_t, u_int16_t, int)); diff --git a/bsd/sys/vnode.h b/bsd/sys/vnode.h index 03672ac1a..000f1cf5c 100644 --- a/bsd/sys/vnode.h +++ b/bsd/sys/vnode.h @@ -172,6 +172,9 @@ struct vnode { #define VHASDIRTY 0x100000 /* UBC vnode may have 1 or more */ /* delayed dirty pages that need to be flushed at the next 'sync' */ #define VSWAP 0x200000 /* vnode is being used as swapfile */ +#define VTHROTTLED 0x400000 /* writes or pageouts have been throttled */ + /* wakeup tasks waiting when count falls below threshold */ + /* * Vnode attributes. A field value of VNOVAL represents a field whose value * is unavailable (getattr) or which is not to be changed (setattr). @@ -266,6 +269,7 @@ extern int vttoif_tab[]; #define FREEREMAINDER 0x00000008 /* deallocate allocated but */ /* unfilled blocks */ #define ALLOCATEFROMPEOF 0x00000010 /* allocate from the physical eof */ +#define ALLOCATEFROMVOL 0x00000020 /* allocate from the volume offset */ #if DIAGNOSTIC #define VATTR_NULL(vap) vattr_null(vap) @@ -476,7 +480,7 @@ int vn_rdwr __P((enum uio_rw rw, struct vnode *vp, caddr_t base, int len, off_t offset, enum uio_seg segflg, int ioflg, struct ucred *cred, int *aresid, struct proc *p)); int vn_read __P((struct file *fp, struct uio *uio, struct ucred *cred)); -int vn_select __P((struct file *fp, int which, struct proc *p)); +int vn_select __P((struct file *fp, int which, void * wql, struct proc *p)); int vn_stat __P((struct vnode *vp, struct stat *sb, struct proc *p)); int vn_write __P((struct file *fp, struct uio *uio, struct ucred *cred)); int vop_noislocked __P((struct vop_islocked_args *)); diff --git a/bsd/sys/vnode_if.h b/bsd/sys/vnode_if.h index 6f13d346e..ec4dafa03 100644 --- a/bsd/sys/vnode_if.h +++ b/bsd/sys/vnode_if.h @@ -354,7 +354,7 @@ static __inline int _VOP_READ(struct vnode *vp, struct uio *uio, int ioflag, str int _didhold = ubc_hold(vp); _err = VCALL(vp, VOFFSET(vop_read), &a); if (_didhold) - ubc_rele(vp); + ubc_rele(vp); return (_err); } } @@ -383,7 +383,7 @@ static __inline int _VOP_WRITE(struct vnode *vp, struct uio *uio, int ioflag, st int _didhold = ubc_hold(vp); _err = VCALL(vp, VOFFSET(vop_write), &a); if (_didhold) - ubc_rele(vp); + ubc_rele(vp); return (_err); } } @@ -438,11 +438,12 @@ struct vop_select_args { int a_which; int a_fflags; struct ucred *a_cred; + void * a_wql; struct proc *a_p; }; extern struct vnodeop_desc vop_select_desc; -#define VOP_SELECT(vp, which, fflags, cred, p) _VOP_SELECT(vp, which, fflags, cred, p) -static __inline int _VOP_SELECT(struct vnode *vp, int which, int fflags, struct ucred *cred, struct proc *p) +#define VOP_SELECT(vp, which, fflags, cred, wql, p) _VOP_SELECT(vp, which, fflags, cred, wql, p) +static __inline int _VOP_SELECT(struct vnode *vp, int which, int fflags, struct ucred *cred, void * wql, struct proc *p) { struct vop_select_args a; a.a_desc = VDESC(vop_select); @@ -450,6 +451,7 @@ static __inline int _VOP_SELECT(struct vnode *vp, int which, int fflags, struct a.a_which = which; a.a_fflags = fflags; a.a_cred = cred; + a.a_wql = wql; a.a_p = p; return (VCALL(vp, VOFFSET(vop_select), &a)); } @@ -534,7 +536,7 @@ static __inline int _VOP_FSYNC(struct vnode *vp, struct ucred *cred, int waitfor int _didhold = ubc_hold(vp); _err = VCALL(vp, VOFFSET(vop_fsync), &a); if (_didhold) - ubc_rele(vp); + ubc_rele(vp); return (_err); } } @@ -1027,7 +1029,7 @@ static __inline int _VOP_TRUNCATE(struct vnode *vp, off_t length, int flags, str int _didhold = ubc_hold(vp); _err = VCALL(vp, VOFFSET(vop_truncate), &a); if (_didhold) - ubc_rele(vp); + ubc_rele(vp); return (_err); } } @@ -1038,12 +1040,13 @@ struct vop_allocate_args { off_t a_length; u_int32_t a_flags; off_t *a_bytesallocated; + off_t a_offset; struct ucred *a_cred; struct proc *a_p; }; extern struct vnodeop_desc vop_allocate_desc; -#define VOP_ALLOCATE(vp, length, flags, bytesallocated, cred, p) _VOP_ALLOCATE(vp, length, flags, bytesallocated, cred, p) -static __inline int _VOP_ALLOCATE(struct vnode *vp, off_t length, u_int32_t flags, off_t *bytesallocated, struct ucred *cred, struct proc *p) +#define VOP_ALLOCATE(vp, length, flags, bytesallocated, offset, cred, p) _VOP_ALLOCATE(vp, length, flags, bytesallocated, offset, cred, p) +static __inline int _VOP_ALLOCATE(struct vnode *vp, off_t length, u_int32_t flags, off_t *bytesallocated, off_t offset, struct ucred *cred, struct proc *p) { struct vop_allocate_args a; a.a_desc = VDESC(vop_allocate); @@ -1051,6 +1054,7 @@ static __inline int _VOP_ALLOCATE(struct vnode *vp, off_t length, u_int32_t flag a.a_length = length; a.a_flags = flags; a.a_bytesallocated = bytesallocated; + a.a_offset = offset; a.a_cred = cred; a.a_p = p; return (VCALL(vp, VOFFSET(vop_allocate), &a)); diff --git a/bsd/ufs/ffs/ffs_vfsops.c b/bsd/ufs/ffs/ffs_vfsops.c index 10c78d5fb..4843f6a5f 100644 --- a/bsd/ufs/ffs/ffs_vfsops.c +++ b/bsd/ufs/ffs/ffs_vfsops.c @@ -329,6 +329,7 @@ ffs_reload(mountp, cred, p) struct buf *bp; struct fs *fs, *newfs; int i, blks, size, error; + u_int64_t maxfilesize; /* XXX */ int32_t *lp; #if REV_ENDIAN_FS int rev_endian = (mountp->mnt_flag & MNT_REVEND); @@ -385,6 +386,9 @@ ffs_reload(mountp, cred, p) brelse(bp); mountp->mnt_maxsymlinklen = fs->fs_maxsymlinklen; ffs_oldfscompat(fs); + maxfilesize = (u_int64_t)0x100000000; /* 4GB */ + if (fs->fs_maxfilesize > maxfilesize) /* XXX */ + fs->fs_maxfilesize = maxfilesize; /* XXX */ /* * Step 3: re-read summary information from disk. */ @@ -600,6 +604,13 @@ ffs_mountfs(devvp, mp, p) set_fsblocksize(devvp); } + /* cache the IO attributes */ + error = vfs_init_io_attributes(devvp, mp); + if (error) { + printf("ffs_mountfs: vfs_init_io_attributes returned %d\n", + error); + goto out; + } /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { @@ -916,6 +927,8 @@ loop: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = nvp) { + int didhold = 0; + /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. @@ -939,9 +952,12 @@ loop: goto loop; continue; } + didhold = ubc_hold(vp); if (error = VOP_FSYNC(vp, cred, waitfor, p)) allerror = error; VOP_UNLOCK(vp, 0, p); + if (didhold) + ubc_rele(vp); vrele(vp); simple_lock(&mntvnode_slock); } diff --git a/bsd/ufs/ffs/ffs_vnops.c b/bsd/ufs/ffs/ffs_vnops.c index 8d05efe44..cf6d5ba4d 100644 --- a/bsd/ufs/ffs/ffs_vnops.c +++ b/bsd/ufs/ffs/ffs_vnops.c @@ -301,7 +301,6 @@ ffs_fsync(ap) */ cluster_push(vp); - /* * Flush all dirty buffers associated with a vnode. */ diff --git a/bsd/ufs/mfs/mfs_vfsops.c b/bsd/ufs/mfs/mfs_vfsops.c index 1acebe008..1ae81a5a1 100644 --- a/bsd/ufs/mfs/mfs_vfsops.c +++ b/bsd/ufs/mfs/mfs_vfsops.c @@ -134,6 +134,11 @@ mfs_mountroot() MALLOC_ZONE(mp, struct mount *, sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + mp->mnt_op = &mfs_vfsops; mp->mnt_flag = MNT_RDONLY; MALLOC(mfsp, struct mfsnode *, sizeof(struct mfsnode), M_MFSNODE, M_WAITOK); diff --git a/bsd/ufs/ufs/inode.h b/bsd/ufs/ufs/inode.h index 77a8efde8..3aeaeab6b 100644 --- a/bsd/ufs/ufs/inode.h +++ b/bsd/ufs/ufs/inode.h @@ -143,6 +143,8 @@ struct inode { #define IN_RENAME 0x0010 /* Inode is being renamed. */ #define IN_SHLOCK 0x0020 /* File has shared lock. */ #define IN_EXLOCK 0x0040 /* File has exclusive lock. */ +#define IN_TRANSIT 0x0080 /* inode is getting recycled */ +#define IN_WTRANSIT 0x0100 /* waiting for inode getting recycled */ #ifdef KERNEL /* diff --git a/bsd/ufs/ufs/ufs_ihash.c b/bsd/ufs/ufs/ufs_ihash.c index e2a6fb112..cc463f491 100644 --- a/bsd/ufs/ufs/ufs_ihash.c +++ b/bsd/ufs/ufs/ufs_ihash.c @@ -124,6 +124,16 @@ loop: for (ip = INOHASH(dev, inum)->lh_first; ip; ip = ip->i_hash.le_next) { if (inum == ip->i_number && dev == ip->i_dev) { vp = ITOV(ip); + if (ip->i_flag & IN_TRANSIT) { + /* inode is getting reclaimed wait till + * the operation is complete and return + * error + */ + ip->i_flag |= IN_WTRANSIT; + simple_unlock(&ufs_ihash_slock); + tsleep((caddr_t)ip, PINOD, "ufs_ihashget", 0); + goto loop; + } simple_lock(&vp->v_interlock); simple_unlock(&ufs_ihash_slock); if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, p)) diff --git a/bsd/ufs/ufs/ufs_inode.c b/bsd/ufs/ufs/ufs_inode.c index 0a1a1814c..239b87069 100644 --- a/bsd/ufs/ufs/ufs_inode.c +++ b/bsd/ufs/ufs/ufs_inode.c @@ -106,6 +106,11 @@ ufs_inactive(ap) if (!getinoquota(ip)) (void)chkiq(ip, -1, NOCRED, 0); #endif + /* + * marking inode in transit so that one can get this + * inode from inodecache + */ + ip->i_flag |= IN_TRANSIT; error = VOP_TRUNCATE(vp, (off_t)0, 0, NOCRED, p); ip->i_rdev = 0; mode = ip->i_mode; diff --git a/bsd/ufs/ufs/ufs_readwrite.c b/bsd/ufs/ufs/ufs_readwrite.c index 5b7cb2ac2..0953dc8ce 100644 --- a/bsd/ufs/ufs/ufs_readwrite.c +++ b/bsd/ufs/ufs/ufs_readwrite.c @@ -598,16 +598,16 @@ ffs_pageout(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (EROFS); } fs = ip->I_FS; if (f_offset < 0 || f_offset >= ip->i_size) { if (!nocommit) - kernel_upl_abort_range(pl, pl_offset, size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, pl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (EINVAL); } @@ -671,8 +671,8 @@ ffs_pageout(ap) lupl_offset = size - save_size; resid = round_page(save_size); if (!nocommit) - kernel_upl_abort_range(pl, lupl_offset, - resid, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(pl, lupl_offset, resid, + UPL_ABORT_FREE_ON_EMPTY); if(!error) error= save_error; } diff --git a/bsd/ufs/ufs/ufs_vnops.c b/bsd/ufs/ufs/ufs_vnops.c index b6fae6bc6..c9f3da6c7 100644 --- a/bsd/ufs/ufs/ufs_vnops.c +++ b/bsd/ufs/ufs/ufs_vnops.c @@ -666,6 +666,7 @@ ufs_select(ap) int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */ *ap; { @@ -744,17 +745,13 @@ ufs_remove(ap) ip->i_flag |= IN_CHANGE; } - if (dvp == vp) - vrele(vp); - else - vput(vp); - vput(dvp); + if (dvp != vp) + VOP_UNLOCK(vp, 0, ap->a_cnp->cn_proc); - if (UBCINFOEXISTS(vp)) { - (void) ubc_uncache(vp); - ubc_release(vp); - /* WARNING vp may not be valid after this */ - } + (void) ubc_uncache(vp); + + vrele(vp); + vput(dvp); return (error); diff --git a/bsd/vfs/vfs_bio.c b/bsd/vfs/vfs_bio.c index e11f6cb1d..12199aaed 100644 --- a/bsd/vfs/vfs_bio.c +++ b/bsd/vfs/vfs_bio.c @@ -364,8 +364,11 @@ bio_doread(vp, blkno, size, cred, async, queuetype) /* Start I/O for the buffer (keeping credentials). */ SET(bp->b_flags, B_READ | async); if (cred != NOCRED && bp->b_rcred == NOCRED) { - crhold(cred); - bp->b_rcred = cred; + /* + * NFS has embedded ucred. + * Can not crhold() here as that causes zone corruption + */ + bp->b_rcred = crdup(cred); } VOP_STRATEGY(bp); @@ -633,60 +636,45 @@ brelse(bp) && UBCINFOEXISTS(bp->b_vp) && bp->b_bufsize) { kern_return_t kret; upl_t upl; - upl_page_info_t *pl; int upl_flags; if ( !ISSET(bp->b_flags, B_PAGELIST)) { if ( !ISSET(bp->b_flags, B_INVAL)) { - void *object; - off_t file_offset; - - object = ubc_getobject(bp->b_vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("vmobject for vp is null"); - if (bp->b_bufsize & 0xfff) - panic("list request is with less than 4k"); - - file_offset = ubc_blktooff(bp->b_vp, bp->b_lblkno); - - kret = vm_fault_list_request(object, - (vm_object_offset_t)file_offset, bp->b_bufsize, - &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_PRECIOUS - | UPL_SET_INTERNAL)); + kret = ubc_create_upl(bp->b_vp, + ubc_blktooff(bp->b_vp, bp->b_lblkno), + bp->b_bufsize, + &upl, + NULL, + UPL_PRECIOUS); if (kret != KERN_SUCCESS) panic("brelse: Failed to get pagelists"); #ifdef UBC_DEBUG upl_ubc_alias_set(upl, bp, 5); #endif /* UBC_DEBUG */ } else - upl = (upl_t) 0; + upl = (upl_t) 0; } else { - upl = bp->b_pagelist; - kret = kernel_upl_unmap(kernel_map, upl); + upl = bp->b_pagelist; + kret = ubc_upl_unmap(upl); if (kret != KERN_SUCCESS) panic("kernel_upl_unmap failed"); bp->b_data = 0; } if (upl) { - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - if (bp->b_flags & (B_ERROR | B_INVAL)) { - if (bp->b_flags & (B_READ | B_INVAL)) + if (bp->b_flags & (B_READ | B_INVAL)) upl_flags = UPL_ABORT_DUMP_PAGES; else upl_flags = 0; - kernel_upl_abort(upl, upl_flags); + ubc_upl_abort(upl, upl_flags); } else { - if (ISSET(bp->b_flags, (B_DELWRI | B_WASDIRTY))) - upl_flags = UPL_COMMIT_SET_DIRTY | UPL_COMMIT_FREE_ON_EMPTY; + if (ISSET(bp->b_flags, (B_DELWRI | B_WASDIRTY))) + upl_flags = UPL_COMMIT_SET_DIRTY ; else - upl_flags = UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY; - kernel_upl_commit_range(upl, 0, bp->b_bufsize, - upl_flags - | UPL_COMMIT_INACTIVATE, - pl, MAX_UPL_TRANSFER); + upl_flags = UPL_COMMIT_CLEAR_DIRTY ; + ubc_upl_commit_range(upl, 0, bp->b_bufsize, upl_flags | + UPL_COMMIT_INACTIVATE | UPL_COMMIT_FREE_ON_EMPTY); } s = splbio(); CLR(bp->b_flags, B_PAGELIST); @@ -817,16 +805,13 @@ getblk(vp, blkno, size, slpflag, slptimeo, operation) int s, err; upl_t upl; upl_page_info_t *pl; - void * object; kern_return_t kret; - void *pager; - off_t file_offset; int error=0; int pagedirty = 0; -start: KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 386)) | DBG_FUNC_START, blkno * PAGE_SIZE, size, operation, 0, 0); +start: s = splbio(); if (bp = incore(vp, blkno)) { @@ -887,29 +872,18 @@ start: case BLK_READ: case BLK_WRITE: if (UBCISVALID(bp->b_vp) && bp->b_bufsize) { - - if (bp->b_bufsize & 0xfff) - panic("list request is with less than 4k"); - - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("vmobject for vp is null"); - - file_offset = ubc_blktooff(vp, bp->b_lblkno); - - kret = vm_fault_list_request(object, - (vm_object_offset_t)file_offset, bp->b_bufsize, - &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_PRECIOUS | UPL_SET_INTERNAL)); - + kret = ubc_create_upl(vp, + ubc_blktooff(vp, bp->b_lblkno), + bp->b_bufsize, + &upl, + &pl, + UPL_PRECIOUS); if (kret != KERN_SUCCESS) panic("Failed to get pagelists"); SET(bp->b_flags, B_PAGELIST); bp->b_pagelist = upl; - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - if ( !upl_valid_page(pl, 0)) panic("getblk: incore buffer without valid page"); @@ -918,12 +892,12 @@ start: else CLR(bp->b_flags, B_WASDIRTY); - kret = kernel_upl_map(kernel_map, upl, (vm_address_t *)&(bp->b_data)); + kret = ubc_upl_map(upl, (vm_address_t *)&(bp->b_data)); if (kret != KERN_SUCCESS) { - panic("getblk: kernel_upl_map() " - "failed with (%d)", kret); + panic("getblk: ubc_upl_map() failed with (%d)", + kret); } - if (bp->b_data == 0) panic("kernel_upl_map mapped 0"); + if (bp->b_data == 0) panic("ubc_upl_map mapped 0"); } break; @@ -957,6 +931,13 @@ start: } if ((bp = getnewbuf(slpflag, slptimeo, &queue)) == NULL) goto start; + if (incore(vp, blkno)) { + SET(bp->b_flags, B_INVAL); + binshash(bp, &invalhash); + brelse(bp); + goto start; + } + /* * if it is meta, the queue may be set to other * type so reset as well as mark it to be B_META @@ -967,16 +948,17 @@ start: SET(bp->b_flags, B_META); queue = BQ_META; } + /* + * Insert in the hash so that incore() can find it + */ + binshash(bp, BUFHASH(vp, blkno)); + allocbuf(bp, size); switch (operation) { case BLK_META: /* buffer data is invalid */ - /* - * Insert in the hash so that incore() can find it - */ - binshash(bp, BUFHASH(vp, blkno)); #if !ZALLOC_METADATA if (bp->b_data) panic("bp->b_data is not nul; %x",bp); @@ -1004,27 +986,16 @@ start: case BLK_READ: case BLK_WRITE: - /* - * Insert in the hash so that incore() can find it - */ - binshash(bp, BUFHASH(vp, blkno)); - pager = ubc_getpager(vp); - file_offset = ubc_blktooff(vp, blkno); - - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("vmobject for vp is null"); - if (bp->b_bufsize & 0xfff) - panic("list request is with less than 4k"); if (ISSET(bp->b_flags, B_PAGELIST)) panic("B_PAGELIST in bp=%x",bp); - kret = vm_fault_list_request(object, - (vm_object_offset_t)file_offset, bp->b_bufsize, - &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_PRECIOUS | UPL_SET_INTERNAL)); - + kret = ubc_create_upl(vp, + ubc_blktooff(vp, blkno), + bp->b_bufsize, + &upl, + &pl, + UPL_PRECIOUS); if (kret != KERN_SUCCESS) panic("Failed to get pagelists"); @@ -1035,7 +1006,6 @@ start: bp->b_pagelist = upl; SET(bp->b_flags, B_PAGELIST); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); if (upl_valid_page(pl, 0)) { SET(bp->b_flags, B_CACHE | B_DONE); @@ -1102,9 +1072,9 @@ start: } else { bufstats.bufs_miss++; } - kret = kernel_upl_map(kernel_map, upl, (vm_address_t *)&(bp->b_data)); + kret = ubc_upl_map(upl, (vm_address_t *)&(bp->b_data)); if (kret != KERN_SUCCESS) { - panic("getblk: kernel_upl_map() " + panic("getblk: ubc_upl_map() " "failed with (%d)", kret); } if (bp->b_data == 0) panic("kernel_upl_map mapped 0"); @@ -1558,6 +1528,7 @@ bcleanbuf(struct buf *bp) s = splbio(); /* clear out various other fields */ + bp->b_bufsize = 0; bp->b_data = 0; bp->b_flags = B_BUSY; bp->b_dev = NODEV; @@ -1733,21 +1704,30 @@ vfs_bufstats() } #endif /* DIAGNOSTIC */ +#define NRESERVEDIOBUFS 16 struct buf * -alloc_io_buf(vp) +alloc_io_buf(vp, priv) struct vnode *vp; + int priv; { register struct buf *bp; int s; s = splbio(); + while (niobuf - NRESERVEDIOBUFS < bufstats.bufs_iobufinuse && !priv) { + need_iobuffer = 1; + bufstats.bufs_iobufsleeps++; + (void) tsleep(&need_iobuffer, (PRIBIO+1), "alloc_io_buf", 0); + } + while ((bp = iobufqueue.tqh_first) == NULL) { need_iobuffer = 1; bufstats.bufs_iobufsleeps++; - tsleep(&need_iobuffer, (PRIBIO+1), "alloc_io_buf", 0); + (void) tsleep(&need_iobuffer, (PRIBIO+1), "alloc_io_buf1", 0); } + TAILQ_REMOVE(&iobufqueue, bp, b_freelist); bp->b_timestamp = 0; diff --git a/bsd/vfs/vfs_cluster.c b/bsd/vfs/vfs_cluster.c index c877d4e7e..763ecc533 100644 --- a/bsd/vfs/vfs_cluster.c +++ b/bsd/vfs/vfs_cluster.c @@ -67,11 +67,9 @@ #include <sys/ubc.h> #include <vm/vm_pageout.h> -#include <mach/memory_object_types.h> #include <sys/kdebug.h> - #define CL_READ 0x01 #define CL_ASYNC 0x02 #define CL_COMMIT 0x04 @@ -81,13 +79,14 @@ #define CL_DUMP 0x40 #define CL_NOZERO 0x80 #define CL_PAGEIN 0x100 +#define CL_DEV_MEMORY 0x200 /* * throttle the number of async writes that * can be outstanding on a single vnode * before we issue a synchronous write */ -#define ASYNC_THROTTLE 3 +#define ASYNC_THROTTLE 6 static int cluster_iodone(bp) @@ -103,6 +102,7 @@ cluster_iodone(bp) struct buf *cbp_head; struct buf *cbp_next; struct buf *real_bp; + struct vnode *vp; int commit_size; int pg_offset; @@ -134,6 +134,7 @@ cluster_iodone(bp) upl = cbp->b_pagelist; b_flags = cbp->b_flags; real_bp = cbp->b_real_bp; + vp = cbp->b_vp; while (cbp) { if (cbp->b_vectorcount > 1) @@ -151,6 +152,10 @@ cluster_iodone(bp) cbp = cbp_next; } + if ((vp->v_flag & VTHROTTLED) && (vp->v_numoutput <= (ASYNC_THROTTLE / 3))) { + vp->v_flag &= ~VTHROTTLED; + wakeup((caddr_t)&vp->v_numoutput); + } if ((b_flags & B_NEED_IODONE) && real_bp) { if (error) { real_bp->b_flags |= B_ERROR; @@ -172,10 +177,13 @@ cluster_iodone(bp) if (b_flags & B_PAGEOUT) upl_abort_code = UPL_ABORT_FREE_ON_EMPTY; + else if (b_flags & B_PGIN) + upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_ERROR; else upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_DUMP_PAGES; - kernel_upl_abort_range(upl, upl_offset - pg_offset, commit_size, upl_abort_code); + ubc_upl_abort_range(upl, upl_offset - pg_offset, commit_size, + upl_abort_code); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 20)) | DBG_FUNC_END, upl, upl_offset - pg_offset, commit_size, @@ -189,12 +197,10 @@ cluster_iodone(bp) if (b_flags & B_AGE) upl_commit_flags |= UPL_COMMIT_INACTIVATE; - kernel_upl_commit_range(upl, upl_offset - pg_offset, - commit_size, upl_commit_flags, - UPL_GET_INTERNAL_PAGE_LIST(upl), - MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, upl_offset - pg_offset, commit_size, + upl_commit_flags); - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 20)) | DBG_FUNC_END, + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 20)) | DBG_FUNC_END, upl, upl_offset - pg_offset, commit_size, upl_commit_flags, 0); } @@ -218,25 +224,24 @@ cluster_zero(upl, upl_offset, size, flags, bp) kern_return_t kret; if ( !(flags & CL_NOMAP)) { - kret = kernel_upl_map(kernel_map, upl, &io_addr); + kret = ubc_upl_map(upl, &io_addr); if (kret != KERN_SUCCESS) - panic("cluster_zero: kernel_upl_map() failed with (%d)", kret); + panic("cluster_zero: ubc_upl_map() failed with (%d)", kret); if (io_addr == 0) - panic("cluster_zero: kernel_upl_map mapped 0"); + panic("cluster_zero: ubc_upl_map() mapped 0"); } else io_addr = (vm_offset_t)bp->b_data; bzero((caddr_t)(io_addr + upl_offset), size); if ( !(flags & CL_NOMAP)) { - kret = kernel_upl_unmap(kernel_map, upl); + kret = ubc_upl_unmap(upl); if (kret != KERN_SUCCESS) panic("cluster_zero: kernel_upl_unmap failed"); } } - static int cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) struct vnode *vp; @@ -257,13 +262,20 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) upl_page_info_t *pl; int pg_count; int pg_offset; + int max_iosize; + int max_vectors; + int priv; - if (flags & CL_READ) + if (flags & CL_READ) { io_flags = (B_VECTORLIST | B_READ); - else + + vfs_io_attributes(vp, B_READ, &max_iosize, &max_vectors); + } else { io_flags = (B_VECTORLIST | B_WRITEINPROG); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); + vfs_io_attributes(vp, B_WRITE, &max_iosize, &max_vectors); + } + pl = ubc_upl_pageinfo(upl); if (flags & CL_ASYNC) io_flags |= (B_CALL | B_ASYNC); @@ -271,6 +283,8 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) io_flags |= B_AGE; if (flags & CL_DUMP) io_flags |= B_NOCACHE; + if (flags & CL_PAGEIN) + io_flags |= B_PGIN; KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 22)) | DBG_FUNC_START, @@ -300,8 +314,8 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) daddr_t lblkno; daddr_t blkno; - if (size > MAXPHYSIO) - io_size = MAXPHYSIO; + if (size > max_iosize) + io_size = max_iosize; else io_size = size; @@ -315,8 +329,26 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) (int)f_offset, (int)blkno, io_size, 0, 0); if ( (!(flags & CL_READ) && (long)blkno == -1) || io_size == 0) { - error = EINVAL; - break; + if (flags & CL_PAGEOUT) { + error = EINVAL; + break; + }; + + /* Try paging out the page individually before + giving up entirely and dumping it (it could + be mapped in a "hole" and require allocation + before the I/O: + */ + ubc_upl_abort_range(upl, upl_offset, PAGE_SIZE_64, UPL_ABORT_FREE_ON_EMPTY); + if (ubc_pushdirty_range(vp, f_offset, PAGE_SIZE_64) == 0) { + error = EINVAL; + break; + }; + + upl_offset += PAGE_SIZE_64; + f_offset += PAGE_SIZE_64; + size -= PAGE_SIZE_64; + continue; } lblkno = (daddr_t)(f_offset / PAGE_SIZE_64); /* @@ -329,6 +361,19 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) pg_offset = upl_offset & PAGE_MASK; pg_count = (io_size + pg_offset + (PAGE_SIZE - 1)) / PAGE_SIZE; + if (flags & CL_DEV_MEMORY) { + /* + * currently, can't deal with reading 'holes' in file + */ + if ((long)blkno == -1) { + error = EINVAL; + break; + } + /* + * treat physical requests as one 'giant' page + */ + pg_count = 1; + } if ((flags & CL_READ) && (long)blkno == -1) { /* * if we're reading and blkno == -1, then we've got a @@ -351,12 +396,10 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) else pg_resid = 0; if (flags & CL_COMMIT) - kernel_upl_commit_range(upl, - upl_offset + pg_resid, - pg_count * PAGE_SIZE, - UPL_COMMIT_CLEAR_DIRTY - | UPL_COMMIT_FREE_ON_EMPTY, - pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, + upl_offset + pg_resid, + pg_count * PAGE_SIZE, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); } upl_offset += io_size; f_offset += io_size; @@ -368,22 +411,41 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) } else if (real_bp && (real_bp->b_blkno == real_bp->b_lblkno)) { real_bp->b_blkno = blkno; } + if (pg_count > 1) { + if (pg_count > max_vectors) { + io_size -= (pg_count - max_vectors) * PAGE_SIZE; + + if (io_size < 0) { + io_size = PAGE_SIZE - pg_offset; + pg_count = 1; + } else + pg_count = max_vectors; + } /* * we need to allocate space for the vector list */ - iovp = (struct iovec *)_MALLOC(sizeof(struct iovec) * pg_count, - M_SEGMENT, M_NOWAIT); - if (iovp == (struct iovec *) 0) { - /* - * if the allocation fails, then throttle down to a single page - */ - io_size = PAGE_SIZE - pg_offset; - pg_count = 1; + if (pg_count > 1) { + iovp = (struct iovec *)_MALLOC(sizeof(struct iovec) * pg_count, + M_SEGMENT, M_NOWAIT); + + if (iovp == (struct iovec *) 0) { + /* + * if the allocation fails, then throttle down to a single page + */ + io_size = PAGE_SIZE - pg_offset; + pg_count = 1; + } } } - cbp = alloc_io_buf(vp); + /* Throttle the speculative IO */ + if ((flags & CL_ASYNC) && !(flags & CL_PAGEOUT)) + priv = 0; + else + priv = 1; + + cbp = alloc_io_buf(vp, priv); if (pg_count == 1) /* @@ -397,10 +459,22 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) cbp->b_vectorlist = (void *)iovp; cbp->b_vectorcount = pg_count; - for (i = 0, vsize = io_size; i < pg_count; i++, iovp++) { + if (flags & CL_DEV_MEMORY) { + + iovp->iov_len = io_size; + iovp->iov_base = (caddr_t)upl_phys_page(pl, 0); + + if (iovp->iov_base == (caddr_t) 0) { + free_io_buf(cbp); + error = EINVAL; + } else + iovp->iov_base += upl_offset; + } else { + + for (i = 0, vsize = io_size; i < pg_count; i++, iovp++) { int psize; - psize = PAGE_SIZE - pg_offset; + psize = PAGE_SIZE - pg_offset; if (psize > vsize) psize = vsize; @@ -436,6 +510,7 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) splx(s); } vsize -= psize; + } } if (error) break; @@ -471,7 +546,7 @@ cluster_io(vp, upl, upl_offset, f_offset, size, flags, real_bp) f_offset += io_size; size -= io_size; - if ( !(upl_offset & PAGE_MASK) || size == 0) { + if ( (!(upl_offset & PAGE_MASK) && !(flags & CL_DEV_MEMORY)) || size == 0) { /* * if we have no more I/O to issue or * the current I/O we've prepared fully @@ -485,6 +560,8 @@ start_io: cbp_head->b_flags |= B_COMMIT_UPL; if (flags & CL_PAGEOUT) cbp_head->b_flags |= B_PAGEOUT; + if (flags & CL_PAGEIN) + cbp_head->b_flags |= B_PGIN; if (real_bp) { cbp_head->b_flags |= B_NEED_IODONE; @@ -516,18 +593,22 @@ start_io: } } if (error) { + int abort_size; + for (cbp = cbp_head; cbp;) { struct buf * cbp_next; if (cbp->b_vectorcount > 1) _FREE(cbp->b_vectorlist, M_SEGMENT); + upl_offset -= cbp->b_bcount; + size += cbp->b_bcount; + cbp_next = cbp->b_trans_next; free_io_buf(cbp); cbp = cbp_next; - } - pg_offset = upl_offset & PAGE_MASK; - pg_count = (size + pg_offset + (PAGE_SIZE - 1)) / PAGE_SIZE; + pg_offset = upl_offset & PAGE_MASK; + abort_size = ((size + pg_offset + (PAGE_SIZE - 1)) / PAGE_SIZE) * PAGE_SIZE; if (flags & CL_COMMIT) { int upl_abort_code; @@ -535,14 +616,15 @@ start_io: if (flags & CL_PAGEOUT) upl_abort_code = UPL_ABORT_FREE_ON_EMPTY; else if (flags & CL_PAGEIN) - upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_ERROR; + upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_ERROR; else - upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_DUMP_PAGES; + upl_abort_code = UPL_ABORT_FREE_ON_EMPTY | UPL_ABORT_DUMP_PAGES; - kernel_upl_abort_range(upl, upl_offset - pg_offset, pg_count * PAGE_SIZE, upl_abort_code); + ubc_upl_abort_range(upl, upl_offset - pg_offset, abort_size, + upl_abort_code); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 28)) | DBG_FUNC_NONE, - upl, upl_offset - pg_offset, pg_count * PAGE_SIZE, error, 0); + upl, upl_offset - pg_offset, abort_size, error, 0); } if (real_bp) { real_bp->b_flags |= B_ERROR; @@ -561,9 +643,8 @@ start_io: static int -cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) +cluster_rd_prefetch(vp, f_offset, size, filesize, devblocksize) struct vnode *vp; - void *object; off_t f_offset; u_int size; off_t filesize; @@ -586,13 +667,13 @@ cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) (int)f_offset, 0, 0, 0, 0); return(0); } - if (memory_object_page_op(object, (vm_offset_t)f_offset, 0, 0, 0) == KERN_SUCCESS) { + if (ubc_page_op(vp, f_offset, 0, 0, 0) == KERN_SUCCESS) { KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 49)) | DBG_FUNC_END, (int)f_offset, 0, 0, 0, 0); return(0); } - if (size > MAXPHYSIO) - size = MAXPHYSIO; + if (size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + size = MAX_UPL_TRANSFER * PAGE_SIZE; else size = (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); @@ -601,14 +682,16 @@ cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) pages_in_upl = (size + (PAGE_SIZE - 1)) / PAGE_SIZE; + ubc_create_upl(vp, + f_offset, + pages_in_upl * PAGE_SIZE, + &upl, + &pl, + UPL_FLAGS_NONE); - vm_fault_list_request(object, (vm_object_offset_t)f_offset, pages_in_upl * PAGE_SIZE, &upl, NULL, 0, - UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_SET_INTERNAL); if (upl == (upl_t) 0) return(0); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - /* * scan from the beginning of the upl looking for the first * non-valid page.... this will become the first page in @@ -664,7 +747,7 @@ cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) * at the beginning of the upl.... we need to release these without * modifying there state */ - kernel_upl_abort_range(upl, 0, start_pg * PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, 0, start_pg * PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 50)) | DBG_FUNC_NONE, upl, 0, start_pg * PAGE_SIZE, 0, 0); @@ -675,7 +758,7 @@ cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) * way to the end of the upl... so just release them without modifying * there state */ - kernel_upl_abort_range(upl, last_pg * PAGE_SIZE, (pages_in_upl - last_pg) * PAGE_SIZE, + ubc_upl_abort_range(upl, last_pg * PAGE_SIZE, (pages_in_upl - last_pg) * PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 50)) | DBG_FUNC_NONE, @@ -691,9 +774,8 @@ cluster_rd_prefetch(vp, object, f_offset, size, filesize, devblocksize) static void -cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize) +cluster_rd_ahead(vp, b_lblkno, e_lblkno, filesize, devblocksize) struct vnode *vp; - void *object; daddr_t b_lblkno; daddr_t e_lblkno; off_t filesize; @@ -702,7 +784,8 @@ cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize) daddr_t r_lblkno; off_t f_offset; int size_of_prefetch; - + int max_iosize; + int max_pages; KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 48)) | DBG_FUNC_START, b_lblkno, e_lblkno, vp->v_lastr, 0, 0); @@ -722,13 +805,20 @@ cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize) return; } - vp->v_ralen = vp->v_ralen ? min(MAXPHYSIO/PAGE_SIZE, vp->v_ralen << 1) : 1; + vfs_io_attributes(vp, B_READ, &max_iosize, &max_pages); + + if ((max_iosize / PAGE_SIZE) < max_pages) + max_pages = max_iosize / PAGE_SIZE; + if (max_pages > MAX_UPL_TRANSFER) + max_pages = MAX_UPL_TRANSFER; + + vp->v_ralen = vp->v_ralen ? min(max_pages, vp->v_ralen << 1) : 1; if (((e_lblkno + 1) - b_lblkno) > vp->v_ralen) - vp->v_ralen = min(MAXPHYSIO/PAGE_SIZE, (e_lblkno + 1) - b_lblkno); + vp->v_ralen = min(max_pages, (e_lblkno + 1) - b_lblkno); if (e_lblkno < vp->v_maxra) { - if ((vp->v_maxra - e_lblkno) > ((MAXPHYSIO/PAGE_SIZE) / 4)) { + if ((vp->v_maxra - e_lblkno) > (max_pages / 4)) { KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 48)) | DBG_FUNC_END, vp->v_ralen, vp->v_maxra, vp->v_lastr, 2, 0); @@ -738,7 +828,7 @@ cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize) r_lblkno = max(e_lblkno, vp->v_maxra) + 1; f_offset = (off_t)r_lblkno * PAGE_SIZE_64; - size_of_prefetch = cluster_rd_prefetch(vp, object, f_offset, vp->v_ralen * PAGE_SIZE, filesize, devblocksize); + size_of_prefetch = cluster_rd_prefetch(vp, f_offset, vp->v_ralen * PAGE_SIZE, filesize, devblocksize); if (size_of_prefetch) vp->v_maxra = r_lblkno + (size_of_prefetch - 1); @@ -785,7 +875,8 @@ cluster_pageout(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, fla if (vp->v_mount->mnt_flag & MNT_RDONLY) { if (local_flags & CL_COMMIT) - kernel_upl_abort_range(upl, upl_offset, size, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, upl_offset, size, + UPL_ABORT_FREE_ON_EMPTY); return (EROFS); } /* @@ -796,8 +887,8 @@ cluster_pageout(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, fla */ if (f_offset < 0 || f_offset >= filesize || (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { - if (local_flags & CL_COMMIT) - kernel_upl_abort_range(upl, upl_offset, size, UPL_ABORT_FREE_ON_EMPTY); + if (local_flags & CL_COMMIT) + ubc_upl_abort_range(upl, upl_offset, size, UPL_ABORT_FREE_ON_EMPTY); return (EINVAL); } max_size = filesize - f_offset; @@ -810,10 +901,14 @@ cluster_pageout(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, fla pg_size = (io_size + (PAGE_SIZE - 1)) & ~PAGE_MASK; if (size > pg_size) { - if (local_flags & CL_COMMIT) - kernel_upl_abort_range(upl, upl_offset + pg_size, size - pg_size, + if (local_flags & CL_COMMIT) + ubc_upl_abort_range(upl, upl_offset + pg_size, size - pg_size, UPL_ABORT_FREE_ON_EMPTY); } + while (vp->v_numoutput >= ASYNC_THROTTLE) { + vp->v_flag |= VTHROTTLED; + tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "cluster_pageout", 0); + } return (cluster_io(vp, upl, upl_offset, f_offset, io_size, local_flags, (struct buf *)0)); @@ -835,7 +930,6 @@ cluster_pagein(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, flag off_t max_size; int retval; int local_flags = 0; - void *object = 0; /* @@ -860,8 +954,9 @@ cluster_pagein(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, flag */ if (f_offset < 0 || f_offset >= filesize || (f_offset & PAGE_MASK_64) || (size & PAGE_MASK)) { - if (local_flags & CL_COMMIT) - kernel_upl_abort_range(upl, upl_offset, size, UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); + if (local_flags & CL_COMMIT) + ubc_upl_abort_range(upl, upl_offset, size, + UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY); return (EINVAL); } max_size = filesize - f_offset; @@ -874,12 +969,13 @@ cluster_pagein(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, flag pg_size = (io_size + (PAGE_SIZE - 1)) & ~PAGE_MASK; if (upl == (upl_t) 0) { - object = ubc_getobject(vp, UBC_PAGINGOP|UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("cluster_pagein: ubc_getobject failed"); + ubc_create_upl( vp, + f_offset, + pg_size, + &upl, + NULL, + UPL_FLAGS_NONE); - vm_fault_list_request(object, (vm_offset_t)f_offset, pg_size, &upl, NULL, 0, - UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_SET_INTERNAL); if (upl == (upl_t) 0) return (EINVAL); @@ -887,8 +983,8 @@ cluster_pagein(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, flag size = pg_size; } if (size > pg_size) { - if (local_flags & CL_COMMIT) - kernel_upl_abort_range(upl, upl_offset + pg_size, size - pg_size, + if (local_flags & CL_COMMIT) + ubc_upl_abort_range(upl, upl_offset + pg_size, size - pg_size, UPL_ABORT_FREE_ON_EMPTY); } @@ -904,17 +1000,12 @@ cluster_pagein(vp, upl, upl_offset, f_offset, size, filesize, devblocksize, flag ((f_offset + ((off_t)io_size - 1)) / PAGE_SIZE_64); if (!(flags & UPL_NORDAHEAD) && !(vp->v_flag & VRAOFF)) { - if (object == (void *)0) { - object = ubc_getobject(vp, UBC_PAGINGOP|UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("cluster_pagein: ubc_getobject failed"); - } /* * we haven't read the last page in of the file yet * so let's try to read ahead if we're in * a sequential access pattern */ - cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize); + cluster_rd_ahead(vp, b_lblkno, e_lblkno, filesize, devblocksize); } vp->v_lastr = e_lblkno; } @@ -951,28 +1042,22 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) int devblocksize; int flags; { - void *object; int prev_resid; int clip_size; off_t max_io_size; struct iovec *iov; + vm_offset_t upl_offset; + int upl_size; + int pages_in_pl; + upl_page_info_t *pl; + int upl_flags; + upl_t upl; int retval = 0; - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("cluster_write: ubc_getobject failed"); - - /* - * We set a threshhold of 4 pages to decide if the nocopy - * write loop is worth the trouble... - */ - - if ((!uio) || (uio->uio_resid < 4 * PAGE_SIZE) || - (flags & IO_TAILZEROFILL) || (flags & IO_HEADZEROFILL) || - (uio->uio_segflg != UIO_USERSPACE) || (!(vp->v_flag & VNOCACHE_DATA))) + if ((!uio) || (uio->uio_segflg != UIO_USERSPACE) || (!(vp->v_flag & VNOCACHE_DATA))) { - retval = cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); return(retval); } @@ -986,7 +1071,63 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) iov = uio->uio_iov; } - if (uio->uio_offset & PAGE_MASK_64) + /* + * We check every vector target and if it is physically + * contiguous space, we skip the sanity checks. + */ + + upl_offset = (vm_offset_t)iov->iov_base & ~PAGE_MASK; + upl_size = (upl_offset + PAGE_SIZE +(PAGE_SIZE -1)) & ~PAGE_MASK; + pages_in_pl = 0; + upl_flags = UPL_QUERY_OBJECT_TYPE; + if ((vm_map_get_upl(current_map(), + (vm_offset_t)iov->iov_base & ~PAGE_MASK, + &upl_size, &upl, NULL, &pages_in_pl, &upl_flags, 0)) != KERN_SUCCESS) + { + /* + * the user app must have passed in an invalid address + */ + return (EFAULT); + } + + if (upl_flags & UPL_PHYS_CONTIG) + { + /* + * since the interface to the IOKit below us uses physical block #'s and + * block counts to specify the I/O, we can't handle anything that isn't + * devblocksize aligned + */ + if ((uio->uio_offset & (devblocksize - 1)) || (uio->uio_resid & (devblocksize - 1))) + return(EINVAL); + + if (flags & IO_HEADZEROFILL) + { + flags &= ~IO_HEADZEROFILL; + + if (retval = cluster_write_x(vp, (struct uio *)0, 0, uio->uio_offset, headOff, 0, devblocksize, IO_HEADZEROFILL)) + return(retval); + } + + retval = cluster_phys_write(vp, uio); + + if (uio->uio_resid == 0 && (flags & IO_TAILZEROFILL)) + { + retval = cluster_write_x(vp, (struct uio *)0, 0, tailOff, uio->uio_offset, 0, devblocksize, IO_HEADZEROFILL); + return(retval); + } + } + else if ((uio->uio_resid < 4 * PAGE_SIZE) || (flags & (IO_TAILZEROFILL | IO_HEADZEROFILL))) + { + /* + * We set a threshhold of 4 pages to decide if the nocopy + * write loop is worth the trouble... + * we also come here if we're trying to zero the head and/or tail + * of a partially written page, and the user source is not a physically contiguous region + */ + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + return(retval); + } + else if (uio->uio_offset & PAGE_MASK_64) { /* Bring the file offset write up to a pagesize boundary */ clip_size = (PAGE_SIZE - (uio->uio_offset & PAGE_MASK_64)); @@ -998,7 +1139,7 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) */ prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else if ((int)iov->iov_base & PAGE_MASK_64) @@ -1006,7 +1147,7 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) clip_size = iov->iov_len; prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else @@ -1030,7 +1171,7 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) */ prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else @@ -1039,9 +1180,9 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) clip_size = clip_size & ~(PAGE_MASK); prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags); + retval = cluster_nocopy_write(vp, uio, newEOF, devblocksize, flags); if ((retval == 0) && uio->uio_resid) - retval = cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); + retval = cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } } /* end else */ @@ -1050,8 +1191,7 @@ cluster_write(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) } static -cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) - void *object; +cluster_nocopy_write(vp, uio, newEOF, devblocksize, flags) struct vnode *vp; struct uio *uio; off_t newEOF; @@ -1086,12 +1226,12 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) */ iov = uio->uio_iov; - - while (uio->uio_resid && uio->uio_offset < newEOF && error == 0) { + while (uio->uio_resid && uio->uio_offset < newEOF && error == 0) { io_size = uio->uio_resid; - if (io_size > MAXPHYSIO) - io_size = MAXPHYSIO; + + if (io_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + io_size = MAX_UPL_TRANSFER * PAGE_SIZE; upl_offset = (vm_offset_t)iov->iov_base & PAGE_MASK_64; upl_needed_size = (upl_offset + io_size + (PAGE_SIZE -1)) & ~PAGE_MASK; @@ -1107,9 +1247,12 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) kret = vm_map_get_upl(current_map(), (vm_offset_t)iov->iov_base & ~PAGE_MASK, - &upl_size, &upl, &pl, &pages_in_pl, &upl_flags, force_data_sync); - - pages_in_pl = upl_size / PAGE_SIZE; + &upl_size, + &upl, + NULL, + &pages_in_pl, + &upl_flags, + force_data_sync); if (kret != KERN_SUCCESS) { @@ -1123,24 +1266,27 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) /* do not return kret here */ return(0); } - + + pl = UPL_GET_INTERNAL_PAGE_LIST(upl); + pages_in_pl = upl_size / PAGE_SIZE; + for(i=0; i < pages_in_pl; i++) { if (!upl_valid_page(pl, i)) break; } - + if (i == pages_in_pl) break; - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + UPL_ABORT_FREE_ON_EMPTY); } if (force_data_sync >= 3) { KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 76)) | DBG_FUNC_END, - 0, 0, 0, kret, 0); + i, pages_in_pl, upl_size, kret, 0); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 75)) | DBG_FUNC_END, (int)uio->uio_offset, (int)uio->uio_resid, kret, 2, 0); @@ -1158,7 +1304,7 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) if (io_size == 0) { - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, UPL_ABORT_FREE_ON_EMPTY); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 75)) | DBG_FUNC_END, (int)uio->uio_offset, uio->uio_resid, 0, 3, 0); @@ -1180,9 +1326,10 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) * Flag UPL_POP_DUMP says if the page is found * in the page cache it must be thrown away. */ - memory_object_page_op(object, (vm_offset_t)upl_f_offset, - UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, - 0, 0); + ubc_page_op(vp, + upl_f_offset, + UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, + 0, 0); max_io_size -= PAGE_SIZE; upl_f_offset += PAGE_SIZE; } @@ -1203,9 +1350,8 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) * update the uio structure and commit. */ - kernel_upl_commit_range(upl, (upl_offset & ~PAGE_MASK), upl_size, - UPL_COMMIT_SET_DIRTY | UPL_COMMIT_FREE_ON_EMPTY, - pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + UPL_COMMIT_FREE_ON_EMPTY); iov->iov_base += io_size; iov->iov_len -= io_size; @@ -1213,7 +1359,7 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) uio->uio_offset += io_size; } else { - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, UPL_ABORT_FREE_ON_EMPTY); } @@ -1230,8 +1376,85 @@ cluster_nocopy_write(object, vp, uio, newEOF, devblocksize, flags) } static -cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) - void *object; +cluster_phys_write(vp, uio) + struct vnode *vp; + struct uio *uio; +{ + upl_t upl; + vm_offset_t upl_offset; + int io_size; + int upl_size; + int upl_needed_size; + int pages_in_pl; + int upl_flags; + kern_return_t kret; + struct iovec *iov; + int error = 0; + + /* + * When we enter this routine, we know + * -- the resid will not exceed iov_len + * -- the vector target address is physcially contiguous + */ + + iov = uio->uio_iov; + io_size = iov->iov_len; + upl_offset = (vm_offset_t)iov->iov_base & PAGE_MASK_64; + upl_needed_size = upl_offset + io_size; + + pages_in_pl = 0; + upl_size = upl_needed_size; + upl_flags = UPL_COPYOUT_FROM | UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL; + + kret = vm_map_get_upl(current_map(), + (vm_offset_t)iov->iov_base & ~PAGE_MASK, + &upl_size, &upl, NULL, &pages_in_pl, &upl_flags, 0); + + if (kret != KERN_SUCCESS) + { + /* cluster_phys_write: failed to get pagelist */ + /* note: return kret here */ + return(EINVAL); + } + + /* + * Consider the possibility that upl_size wasn't satisfied. + * This is a failure in the physical memory case. + */ + if (upl_size < upl_needed_size) + { + kernel_upl_abort_range(upl, 0, upl_size, UPL_ABORT_FREE_ON_EMPTY); + return(EINVAL); + } + + /* + * issue a synchronous write to cluster_io + */ + + error = cluster_io(vp, upl, upl_offset, uio->uio_offset, + io_size, CL_DEV_MEMORY, (struct buf *)0); + + if (error == 0) { + /* + * The cluster_io write completed successfully, + * update the uio structure and commit. + */ + + ubc_upl_commit_range(upl, 0, upl_size, UPL_COMMIT_FREE_ON_EMPTY); + + iov->iov_base += io_size; + iov->iov_len -= io_size; + uio->uio_resid -= io_size; + uio->uio_offset += io_size; + } + else + ubc_upl_abort_range(upl, 0, upl_size, UPL_ABORT_FREE_ON_EMPTY); + + return (error); +} + +static +cluster_write_x(vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, flags) struct vnode *vp; struct uio *uio; off_t oldEOF; @@ -1331,19 +1554,21 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 46)) | DBG_FUNC_NONE, (int)zero_off, (int)zero_cnt, (int)zero_off1, (int)zero_cnt1, 0); - if (total_size > (long long)MAXPHYSIO) - total_size = MAXPHYSIO; + if (total_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + total_size = MAX_UPL_TRANSFER * PAGE_SIZE; /* * compute the size of the upl needed to encompass * the requested write... limit each call to cluster_io - * to at most MAXPHYSIO, make sure to account for + * to the maximum UPL size... cluster_io will clip if + * this exceeds the maximum io_size for the device, + * make sure to account for * a starting offset that's not page aligned */ upl_size = (start_offset + total_size + (PAGE_SIZE - 1)) & ~PAGE_MASK; - if (upl_size > MAXPHYSIO) - upl_size = MAXPHYSIO; + if (upl_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + upl_size = MAX_UPL_TRANSFER * PAGE_SIZE; pages_in_upl = upl_size / PAGE_SIZE; io_size = upl_size - start_offset; @@ -1354,23 +1579,22 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, start_blkno = (daddr_t)(upl_f_offset / PAGE_SIZE_64); last_blkno = start_blkno + pages_in_upl; - kret = vm_fault_list_request(object, - (vm_object_offset_t)upl_f_offset, upl_size, &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL)); - + kret = ubc_create_upl(vp, + upl_f_offset, + upl_size, + &upl, + &pl, + UPL_FLAGS_NONE); if (kret != KERN_SUCCESS) panic("cluster_write: failed to get pagelist"); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 41)) | DBG_FUNC_NONE, - upl, (int)upl_f_offset, upl_size, start_offset, 0); - + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 41)) | DBG_FUNC_NONE, + upl, (int)upl_f_offset, upl_size, start_offset, 0); if (start_offset && !upl_valid_page(pl, 0)) { - int read_size; + int read_size; - /* + /* * we're starting in the middle of the first page of the upl * and the page isn't currently valid, so we're going to have * to read it in first... this is a synchronous operation @@ -1384,14 +1608,14 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, retval = cluster_io(vp, upl, 0, upl_f_offset, read_size, CL_READ, (struct buf *)0); if (retval) { - /* + /* * we had an error during the read which causes us to abort * the current cluster_write request... before we do, we need * to release the rest of the pages in the upl without modifying * there state and mark the failed page in error */ - kernel_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_DUMP_PAGES); - kernel_upl_abort(upl, 0); + ubc_upl_abort_range(upl, 0, PAGE_SIZE, UPL_ABORT_DUMP_PAGES); + ubc_upl_abort(upl, 0); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 45)) | DBG_FUNC_NONE, upl, 0, 0, retval, 0); @@ -1419,14 +1643,15 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, retval = cluster_io(vp, upl, upl_offset, upl_f_offset + upl_offset, read_size, CL_READ, (struct buf *)0); if (retval) { - /* + /* * we had an error during the read which causes us to abort - * the current cluster_write request... before we do, we need - * to release the rest of the pages in the upl without modifying - * there state and mark the failed page in error + * the current cluster_write request... before we do, we + * need to release the rest of the pages in the upl without + * modifying there state and mark the failed page in error */ - kernel_upl_abort_range(upl, upl_offset, PAGE_SIZE, UPL_ABORT_DUMP_PAGES); - kernel_upl_abort(upl, 0); + ubc_upl_abort_range(upl, upl_offset, PAGE_SIZE, + UPL_ABORT_DUMP_PAGES); + ubc_upl_abort(upl, 0); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 45)) | DBG_FUNC_NONE, upl, 0, 0, retval, 0); @@ -1434,8 +1659,8 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, } } } - if ((kret = kernel_upl_map(kernel_map, upl, &io_address)) != KERN_SUCCESS) - panic("cluster_write: kernel_upl_map failed\n"); + if ((kret = ubc_upl_map(upl, &io_address)) != KERN_SUCCESS) + panic("cluster_write: ubc_upl_map failed\n"); xfer_resid = io_size; io_offset = start_offset; @@ -1477,9 +1702,9 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, retval = uiomove((caddr_t)(io_address + io_offset), bytes_to_move, uio); if (retval) { - if ((kret = kernel_upl_unmap(kernel_map, upl)) != KERN_SUCCESS) + if ((kret = ubc_upl_unmap(upl)) != KERN_SUCCESS) panic("cluster_write: kernel_upl_unmap failed\n"); - kernel_upl_abort(upl, UPL_ABORT_DUMP_PAGES); + ubc_upl_abort(upl, UPL_ABORT_DUMP_PAGES); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 45)) | DBG_FUNC_NONE, upl, 0, 0, retval, 0); @@ -1537,7 +1762,7 @@ cluster_write_x(object, vp, uio, oldEOF, newEOF, headOff, tailOff, devblocksize, (int)upl_f_offset + io_size, upl_size - io_size, 0, 0, 0); } - if ((kret = kernel_upl_unmap(kernel_map, upl)) != KERN_SUCCESS) + if ((kret = ubc_upl_unmap(upl)) != KERN_SUCCESS) panic("cluster_write: kernel_upl_unmap failed\n"); io_size_before_rounding = io_size; @@ -1658,8 +1883,8 @@ check_delay: if (must_push) cluster_push(vp); - if (io_size_before_rounding < MAXPHYSIO && !(flags & IO_SYNC)) { - vp->v_clen = MAXPHYSIO / PAGE_SIZE; + if (io_size_before_rounding < (MAX_UPL_TRANSFER * PAGE_SIZE) && !(flags & IO_SYNC)) { + vp->v_clen = MAX_UPL_TRANSFER; vp->v_cstart = start_blkno; vp->v_lastw = last_blkno; vp->v_ciosiz = io_size; @@ -1668,14 +1893,11 @@ check_delay: } finish_io: if (can_delay) { - kernel_upl_commit_range(upl, 0, upl_size, - UPL_COMMIT_SET_DIRTY - | UPL_COMMIT_FREE_ON_EMPTY, - pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, 0, upl_size, + UPL_COMMIT_SET_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); continue; } - - if ((flags & IO_SYNC) || (vp->v_numoutput > ASYNC_THROTTLE)) + if (flags & IO_SYNC) io_flags = CL_COMMIT | CL_AGE; else io_flags = CL_COMMIT | CL_AGE | CL_ASYNC; @@ -1683,6 +1905,10 @@ finish_io: if (vp->v_flag & VNOCACHE_DATA) io_flags |= CL_DUMP; + while (vp->v_numoutput >= ASYNC_THROTTLE) { + vp->v_flag |= VTHROTTLED; + tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "cluster_write", 0); + } retval = cluster_io(vp, upl, 0, upl_f_offset, io_size, io_flags, (struct buf *)0); } @@ -1700,17 +1926,18 @@ cluster_read(vp, uio, filesize, devblocksize, flags) int devblocksize; int flags; { - void *object; int prev_resid; int clip_size; off_t max_io_size; struct iovec *iov; + vm_offset_t upl_offset; + int upl_size; + int pages_in_pl; + upl_page_info_t *pl; + int upl_flags; + upl_t upl; int retval = 0; - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("cluster_read: ubc_getobject failed"); - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 32)) | DBG_FUNC_START, (int)uio->uio_offset, uio->uio_resid, (int)filesize, devblocksize, 0); @@ -1719,14 +1946,12 @@ cluster_read(vp, uio, filesize, devblocksize, flags) * read loop is worth the trouble... */ - if ((!((vp->v_flag & VNOCACHE_DATA) && (uio->uio_segflg == UIO_USERSPACE))) - || (uio->uio_resid < 4 * PAGE_SIZE)) + if (!((vp->v_flag & VNOCACHE_DATA) && (uio->uio_segflg == UIO_USERSPACE))) { - retval = cluster_read_x(object, vp, uio, filesize, devblocksize, flags); + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 32)) | DBG_FUNC_END, (int)uio->uio_offset, uio->uio_resid, vp->v_lastr, retval, 0); return(retval); - } while (uio->uio_resid && uio->uio_offset < filesize && retval == 0) @@ -1739,7 +1964,41 @@ cluster_read(vp, uio, filesize, devblocksize, flags) iov = uio->uio_iov; } - if (uio->uio_offset & PAGE_MASK_64) + /* + * We check every vector target and if it is physically + * contiguous space, we skip the sanity checks. + */ + + upl_offset = (vm_offset_t)iov->iov_base & ~PAGE_MASK; + upl_size = (upl_offset + PAGE_SIZE +(PAGE_SIZE -1)) & ~PAGE_MASK; + pages_in_pl = 0; + upl_flags = UPL_QUERY_OBJECT_TYPE; + if((vm_map_get_upl(current_map(), + (vm_offset_t)iov->iov_base & ~PAGE_MASK, + &upl_size, &upl, NULL, &pages_in_pl, &upl_flags, 0)) != KERN_SUCCESS) + { + /* + * the user app must have passed in an invalid address + */ + return (EFAULT); + } + + if (upl_flags & UPL_PHYS_CONTIG) + { + retval = cluster_phys_read(vp, uio, filesize); + } + else if (uio->uio_resid < 4 * PAGE_SIZE) + { + /* + * We set a threshhold of 4 pages to decide if the nocopy + * read loop is worth the trouble... + */ + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 32)) | DBG_FUNC_END, + (int)uio->uio_offset, uio->uio_resid, vp->v_lastr, retval, 0); + return(retval); + } + else if (uio->uio_offset & PAGE_MASK_64) { /* Bring the file offset read up to a pagesize boundary */ clip_size = (PAGE_SIZE - (int)(uio->uio_offset & PAGE_MASK_64)); @@ -1751,7 +2010,7 @@ cluster_read(vp, uio, filesize, devblocksize, flags) */ prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_read_x(object, vp, uio, filesize, devblocksize, flags); + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else if ((int)iov->iov_base & PAGE_MASK_64) @@ -1759,7 +2018,7 @@ cluster_read(vp, uio, filesize, devblocksize, flags) clip_size = iov->iov_len; prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_read_x(object, vp, uio, filesize, devblocksize, flags); + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else @@ -1783,7 +2042,7 @@ cluster_read(vp, uio, filesize, devblocksize, flags) */ prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_read_x(object,vp, uio, filesize, devblocksize, flags); + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } else @@ -1792,9 +2051,9 @@ cluster_read(vp, uio, filesize, devblocksize, flags) clip_size = clip_size & ~(PAGE_MASK); prev_resid = uio->uio_resid; uio->uio_resid = clip_size; - retval = cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags); + retval = cluster_nocopy_read(vp, uio, filesize, devblocksize, flags); if ((retval==0) && uio->uio_resid) - retval = cluster_read_x(object,vp, uio, filesize, devblocksize, flags); + retval = cluster_read_x(vp, uio, filesize, devblocksize, flags); uio->uio_resid = prev_resid - (clip_size - uio->uio_resid); } } /* end else */ @@ -1807,8 +2066,7 @@ cluster_read(vp, uio, filesize, devblocksize, flags) } static -cluster_read_x(object, vp, uio, filesize, devblocksize, flags) - void *object; +cluster_read_x(vp, uio, filesize, devblocksize, flags) struct vnode *vp; struct uio *uio; off_t filesize; @@ -1841,14 +2099,16 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) /* * compute the size of the upl needed to encompass * the requested read... limit each call to cluster_io - * to at most MAXPHYSIO, make sure to account for + * to the maximum UPL size... cluster_io will clip if + * this exceeds the maximum io_size for the device, + * make sure to account for * a starting offset that's not page aligned */ start_offset = (int)(uio->uio_offset & PAGE_MASK_64); upl_f_offset = uio->uio_offset - (off_t)start_offset; max_size = filesize - uio->uio_offset; - if (uio->uio_resid < max_size) + if ((off_t)((unsigned int)uio->uio_resid) < max_size) io_size = uio->uio_resid; else io_size = max_size; @@ -1865,8 +2125,10 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) int xsize; vm_offset_t paddr; - if (memory_object_page_op(object, (vm_offset_t)upl_f_offset, UPL_POP_SET | UPL_POP_BUSY, - &paddr, 0) != KERN_SUCCESS) + if (ubc_page_op(vp, + upl_f_offset, + UPL_POP_SET | UPL_POP_BUSY, + &paddr, 0) != KERN_SUCCESS) break; xsize = PAGE_SIZE - start_offset; @@ -1876,7 +2138,8 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) retval = uiomove((caddr_t)(paddr + start_offset), xsize, uio); - memory_object_page_op(object, (vm_offset_t)upl_f_offset, UPL_POP_CLR | UPL_POP_BUSY, 0, 0); + ubc_page_op(vp, upl_f_offset, + UPL_POP_CLR | UPL_POP_BUSY, 0, 0); io_size -= xsize; start_offset = (int) @@ -1904,7 +2167,7 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) * let's try to read ahead if we're in * a sequential access pattern */ - cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize); + cluster_rd_ahead(vp, b_lblkno, e_lblkno, filesize, devblocksize); vp->v_lastr = e_lblkno; break; @@ -1913,23 +2176,22 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) } #endif upl_size = (start_offset + io_size + (PAGE_SIZE - 1)) & ~PAGE_MASK; - if (upl_size > MAXPHYSIO) - upl_size = MAXPHYSIO; + if (upl_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + upl_size = MAX_UPL_TRANSFER * PAGE_SIZE; pages_in_upl = upl_size / PAGE_SIZE; KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 33)) | DBG_FUNC_START, upl, (int)upl_f_offset, upl_size, start_offset, 0); - kret = vm_fault_list_request(object, - (vm_object_offset_t)upl_f_offset, upl_size, &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL)); - + kret = ubc_create_upl(vp, + upl_f_offset, + upl_size, + &upl, + &pl, + UPL_FLAGS_NONE); if (kret != KERN_SUCCESS) panic("cluster_read: failed to get pagelist"); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 33)) | DBG_FUNC_END, upl, (int)upl_f_offset, upl_size, start_offset, 0); @@ -2011,14 +2273,14 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) * pre-fetch I/O... the I/O wait time will overlap * with the copying of the data */ - cluster_rd_prefetch(vp, object, uio->uio_offset + val_size, size_of_prefetch, filesize, devblocksize); + cluster_rd_prefetch(vp, uio->uio_offset + val_size, size_of_prefetch, filesize, devblocksize); } else { if (!(vp->v_flag & VRAOFF) && !(vp->v_flag & VNOCACHE_DATA)) /* * let's try to read ahead if we're in * a sequential access pattern */ - cluster_rd_ahead(vp, object, b_lblkno, e_lblkno, filesize, devblocksize); + cluster_rd_ahead(vp, b_lblkno, e_lblkno, filesize, devblocksize); vp->v_lastr = e_lblkno; } #ifdef ppc @@ -2058,13 +2320,13 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) } else #endif { - if ((kret = kernel_upl_map(kernel_map, upl, &io_address)) != KERN_SUCCESS) - panic("cluster_read: kernel_upl_map failed\n"); + if ((kret = ubc_upl_map(upl, &io_address)) != KERN_SUCCESS) + panic("cluster_read: ubc_upl_map() failed\n"); retval = uiomove((caddr_t)(io_address + start_offset), val_size, uio); - if ((kret = kernel_upl_unmap(kernel_map, upl)) != KERN_SUCCESS) - panic("cluster_read: kernel_upl_unmap failed\n"); + if ((kret = ubc_upl_unmap(upl)) != KERN_SUCCESS) + panic("cluster_read: ubc_upl_unmap() failed\n"); } } if (start_pg < last_pg) { @@ -2079,15 +2341,13 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) upl, start_pg * PAGE_SIZE, io_size, error, 0); if (error || (vp->v_flag & VNOCACHE_DATA)) - kernel_upl_abort_range(upl, start_pg * PAGE_SIZE, io_size, + ubc_upl_abort_range(upl, start_pg * PAGE_SIZE, io_size, UPL_ABORT_DUMP_PAGES | UPL_ABORT_FREE_ON_EMPTY); else - kernel_upl_commit_range(upl, - start_pg * PAGE_SIZE, io_size, - UPL_COMMIT_CLEAR_DIRTY + ubc_upl_commit_range(upl, start_pg * PAGE_SIZE, io_size, + UPL_COMMIT_CLEAR_DIRTY | UPL_COMMIT_FREE_ON_EMPTY - | UPL_COMMIT_INACTIVATE, - pl, MAX_UPL_TRANSFER); + | UPL_COMMIT_INACTIVATE); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 35)) | DBG_FUNC_END, upl, start_pg * PAGE_SIZE, io_size, error, 0); @@ -2102,59 +2362,64 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) * there state */ if (error) - kernel_upl_abort(upl, 0); + ubc_upl_abort(upl, 0); else { - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 35)) | DBG_FUNC_START, + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 35)) | DBG_FUNC_START, upl, -1, pages_in_upl - (last_pg - start_pg), 0, 0); - if (start_pg) { - /* - * we found some already valid pages at the beginning of the upl - * commit these back to the inactive list with reference cleared - */ - for (cur_pg = 0; cur_pg < start_pg; cur_pg++) { - commit_flags = UPL_COMMIT_FREE_ON_EMPTY | UPL_COMMIT_INACTIVATE; + if (start_pg) { + /* + * we found some already valid pages at the beginning of + * the upl commit these back to the inactive list with + * reference cleared + */ + for (cur_pg = 0; cur_pg < start_pg; cur_pg++) { + commit_flags = UPL_COMMIT_FREE_ON_EMPTY + | UPL_COMMIT_INACTIVATE; if (upl_dirty_page(pl, cur_pg)) - commit_flags |= UPL_COMMIT_SET_DIRTY; + commit_flags |= UPL_COMMIT_SET_DIRTY; if ( !(commit_flags & UPL_COMMIT_SET_DIRTY) && (vp->v_flag & VNOCACHE_DATA)) - kernel_upl_abort_range(upl, cur_pg * PAGE_SIZE, PAGE_SIZE, - UPL_ABORT_DUMP_PAGES | UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, cur_pg * PAGE_SIZE, PAGE_SIZE, + UPL_ABORT_DUMP_PAGES | UPL_ABORT_FREE_ON_EMPTY); else - kernel_upl_commit_range(upl, cur_pg * PAGE_SIZE, - PAGE_SIZE, commit_flags, pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, cur_pg * PAGE_SIZE, + PAGE_SIZE, commit_flags); } } if (last_pg < uio_last) { - /* - * we found some already valid pages immediately after the pages we issued - * I/O for, commit these back to the inactive list with reference cleared - */ - for (cur_pg = last_pg; cur_pg < uio_last; cur_pg++) { - commit_flags = UPL_COMMIT_FREE_ON_EMPTY | UPL_COMMIT_INACTIVATE; + /* + * we found some already valid pages immediately after the + * pages we issued I/O for, commit these back to the + * inactive list with reference cleared + */ + for (cur_pg = last_pg; cur_pg < uio_last; cur_pg++) { + commit_flags = UPL_COMMIT_FREE_ON_EMPTY + | UPL_COMMIT_INACTIVATE; if (upl_dirty_page(pl, cur_pg)) - commit_flags |= UPL_COMMIT_SET_DIRTY; + commit_flags |= UPL_COMMIT_SET_DIRTY; if ( !(commit_flags & UPL_COMMIT_SET_DIRTY) && (vp->v_flag & VNOCACHE_DATA)) - kernel_upl_abort_range(upl, cur_pg * PAGE_SIZE, PAGE_SIZE, - UPL_ABORT_DUMP_PAGES | UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, cur_pg * PAGE_SIZE, PAGE_SIZE, + UPL_ABORT_DUMP_PAGES | UPL_ABORT_FREE_ON_EMPTY); else - kernel_upl_commit_range(upl, cur_pg * PAGE_SIZE, - PAGE_SIZE, commit_flags, pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, cur_pg * PAGE_SIZE, + PAGE_SIZE, commit_flags); } } if (uio_last < pages_in_upl) { - /* - * there were some invalid pages beyond the valid pages that we didn't - * issue an I/O for, just release them unchanged + /* + * there were some invalid pages beyond the valid pages + * that we didn't issue an I/O for, just release them + * unchanged */ - kernel_upl_abort(upl, 0); + ubc_upl_abort(upl, 0); } - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 35)) | DBG_FUNC_END, - upl, -1, -1, 0, 0); + KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 35)) | DBG_FUNC_END, + upl, -1, -1, 0, 0); } } if (retval == 0) @@ -2165,8 +2430,7 @@ cluster_read_x(object, vp, uio, filesize, devblocksize, flags) } static -cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) - void *object; +cluster_nocopy_read(vp, uio, filesize, devblocksize, flags) struct vnode *vp; struct uio *uio; off_t filesize; @@ -2206,7 +2470,12 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) iov = uio->uio_iov; while (uio->uio_resid && uio->uio_offset < filesize && retval == 0) { - io_size = uio->uio_resid; + max_io_size = filesize - uio->uio_offset; + + if (max_io_size < (off_t)((unsigned int)uio->uio_resid)) + io_size = max_io_size; + else + io_size = uio->uio_resid; /* * We don't come into this routine unless @@ -2220,27 +2489,25 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) * First look for pages already in the cache * and move them to user space. */ - while (io_size && retval == 0) { - + while (io_size && (retval == 0)) { upl_f_offset = uio->uio_offset; /* * If this call fails, it means the page is not * in the page cache. */ - if (memory_object_page_op(object, (vm_offset_t)upl_f_offset, - UPL_POP_SET | UPL_POP_BUSY, - &paddr, 0) != KERN_SUCCESS) + if (ubc_page_op(vp, upl_f_offset, + UPL_POP_SET | UPL_POP_BUSY, &paddr, 0) != KERN_SUCCESS) break; retval = uiomove((caddr_t)(paddr), PAGE_SIZE, uio); - memory_object_page_op(object, (vm_offset_t)upl_f_offset, - UPL_POP_CLR | UPL_POP_BUSY, 0, 0); + ubc_page_op(vp, upl_f_offset, + UPL_POP_CLR | UPL_POP_BUSY, 0, 0); io_size -= PAGE_SIZE; KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 71)) | DBG_FUNC_NONE, - (int)uio->uio_offset, io_size, uio->uio_resid, 0, 0); + (int)uio->uio_offset, io_size, uio->uio_resid, 0, 0); } uio->uio_segflg = segflg; @@ -2262,8 +2529,8 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) } max_io_size = io_size; - if (max_io_size > MAXPHYSIO) - max_io_size = MAXPHYSIO; + if (max_io_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + max_io_size = MAX_UPL_TRANSFER * PAGE_SIZE; start_upl_f_offset = uio->uio_offset; /* this is page aligned in the file */ upl_f_offset = start_upl_f_offset; @@ -2272,24 +2539,24 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) while(io_size < max_io_size) { - if(memory_object_page_op(object, (vm_offset_t)upl_f_offset, - UPL_POP_SET | UPL_POP_BUSY, &paddr, 0) == KERN_SUCCESS) + if(ubc_page_op(vp, upl_f_offset, + UPL_POP_SET | UPL_POP_BUSY, &paddr, 0) == KERN_SUCCESS) { - memory_object_page_op(object, (vm_offset_t)upl_f_offset, - UPL_POP_CLR | UPL_POP_BUSY, 0, 0); - break; + ubc_page_op(vp, upl_f_offset, + UPL_POP_CLR | UPL_POP_BUSY, 0, 0); + break; } - /* - * Build up the io request parameters. - */ + /* + * Build up the io request parameters. + */ - io_size += PAGE_SIZE; - upl_f_offset += PAGE_SIZE; - } + io_size += PAGE_SIZE; + upl_f_offset += PAGE_SIZE; + } - if (io_size == 0) - return(retval); + if (io_size == 0) + return(retval); upl_offset = (vm_offset_t)iov->iov_base & PAGE_MASK_64; upl_needed_size = (upl_offset + io_size + (PAGE_SIZE -1)) & ~PAGE_MASK; @@ -2305,9 +2572,7 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) kret = vm_map_get_upl(current_map(), (vm_offset_t)iov->iov_base & ~PAGE_MASK, - &upl_size, &upl, &pl, &pages_in_pl, &upl_flags, force_data_sync); - - pages_in_pl = upl_size / PAGE_SIZE; + &upl_size, &upl, NULL, &pages_in_pl, &upl_flags, force_data_sync); if (kret != KERN_SUCCESS) { @@ -2322,6 +2587,9 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) return(retval); } + pages_in_pl = upl_size / PAGE_SIZE; + pl = UPL_GET_INTERNAL_PAGE_LIST(upl); + for(i=0; i < pages_in_pl; i++) { if (!upl_valid_page(pl, i)) @@ -2330,8 +2598,8 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) if (i == pages_in_pl) break; - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, - UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + UPL_ABORT_FREE_ON_EMPTY); } if (force_data_sync >= 3) @@ -2351,7 +2619,7 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) if (io_size == 0) { - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, UPL_ABORT_FREE_ON_EMPTY); return(retval); } @@ -2375,10 +2643,8 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) * update the uio structure and commit. */ - kernel_upl_commit_range(upl, (upl_offset & ~PAGE_MASK), upl_size, - UPL_COMMIT_SET_DIRTY - | UPL_COMMIT_FREE_ON_EMPTY, - pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + UPL_COMMIT_SET_DIRTY | UPL_COMMIT_FREE_ON_EMPTY); iov->iov_base += io_size; iov->iov_len -= io_size; @@ -2386,7 +2652,7 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) uio->uio_offset += io_size; } else { - kernel_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, + ubc_upl_abort_range(upl, (upl_offset & ~PAGE_MASK), upl_size, UPL_ABORT_FREE_ON_EMPTY); } @@ -2406,6 +2672,91 @@ cluster_nocopy_read(object, vp, uio, filesize, devblocksize, flags) } +static +cluster_phys_read(vp, uio, filesize) + struct vnode *vp; + struct uio *uio; + off_t filesize; +{ + upl_t upl; + vm_offset_t upl_offset; + off_t max_size; + int io_size; + int upl_size; + int upl_needed_size; + int pages_in_pl; + int upl_flags; + kern_return_t kret; + struct iovec *iov; + int error; + + /* + * When we enter this routine, we know + * -- the resid will not exceed iov_len + * -- the target address is physically contiguous + */ + + iov = uio->uio_iov; + + max_size = filesize - uio->uio_offset; + + if (max_size < (off_t)((unsigned int)iov->iov_len)) + io_size = max_size; + else + io_size = iov->iov_len; + + upl_offset = (vm_offset_t)iov->iov_base & PAGE_MASK_64; + upl_needed_size = upl_offset + io_size; + + pages_in_pl = 0; + upl_size = upl_needed_size; + upl_flags = UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL; + + kret = vm_map_get_upl(current_map(), + (vm_offset_t)iov->iov_base & ~PAGE_MASK, + &upl_size, &upl, NULL, &pages_in_pl, &upl_flags, 0); + + if (kret != KERN_SUCCESS) + { + /* cluster_phys_read: failed to get pagelist */ + return(EINVAL); + } + + /* + * Consider the possibility that upl_size wasn't satisfied. + */ + if (upl_size < upl_needed_size) + { + ubc_upl_abort_range(upl, 0, upl_size, UPL_ABORT_FREE_ON_EMPTY); + return(EINVAL); + } + + /* + * issue a synchronous read to cluster_io + */ + + error = cluster_io(vp, upl, upl_offset, uio->uio_offset, + io_size, CL_READ| CL_NOZERO | CL_DEV_MEMORY, (struct buf *)0); + + if (error == 0) + { + /* + * The cluster_io read completed successfully, + * update the uio structure and commit. + */ + + ubc_upl_commit_range(upl, 0, upl_size, UPL_COMMIT_FREE_ON_EMPTY); + + iov->iov_base += io_size; + iov->iov_len -= io_size; + uio->uio_resid -= io_size; + uio->uio_offset += io_size; + } + else + ubc_upl_abort_range(upl, 0, upl_size, UPL_ABORT_FREE_ON_EMPTY); + + return (error); +} /* * generate advisory I/O's in the largest chunks possible @@ -2418,7 +2769,6 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) int resid; int devblocksize; { - void *object; upl_page_info_t *pl; upl_t upl; vm_offset_t upl_offset; @@ -2437,10 +2787,6 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) if (!UBCINFOEXISTS(vp)) return(EINVAL); - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("advisory_read: ubc_getobject failed"); - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 60)) | DBG_FUNC_START, (int)f_offset, resid, (int)filesize, devblocksize, 0); @@ -2448,7 +2794,9 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) /* * compute the size of the upl needed to encompass * the requested read... limit each call to cluster_io - * to at most MAXPHYSIO, make sure to account for + * to the maximum UPL size... cluster_io will clip if + * this exceeds the maximum io_size for the device, + * make sure to account for * a starting offset that's not page aligned */ start_offset = (int)(f_offset & PAGE_MASK_64); @@ -2461,19 +2809,19 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) io_size = max_size; upl_size = (start_offset + io_size + (PAGE_SIZE - 1)) & ~PAGE_MASK; - if (upl_size > MAXPHYSIO) - upl_size = MAXPHYSIO; + if (upl_size > (MAX_UPL_TRANSFER * PAGE_SIZE)) + upl_size = MAX_UPL_TRANSFER * PAGE_SIZE; pages_in_upl = upl_size / PAGE_SIZE; - kret = vm_fault_list_request(object, - (vm_object_offset_t)upl_f_offset, upl_size, &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL)); - + kret = ubc_create_upl(vp, + upl_f_offset, + upl_size, + &upl, + &pl, + UPL_FLAGS_NONE); if (kret != KERN_SUCCESS) panic("advisory_read: failed to get pagelist"); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 61)) | DBG_FUNC_NONE, upl, (int)upl_f_offset, upl_size, start_offset, 0); @@ -2526,18 +2874,19 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) * at the beginning of the upl.... we need to release these without * modifying there state */ - kernel_upl_abort_range(upl, 0, start_pg * PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, 0, start_pg * PAGE_SIZE, + UPL_ABORT_FREE_ON_EMPTY); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 62)) | DBG_FUNC_NONE, - upl, 0, start_pg * PAGE_SIZE, 0, 0); + upl, 0, start_pg * PAGE_SIZE, 0, 0); } if (last_pg < pages_in_upl) { /* * the set of pages that we issued an I/O for did not extend all the - * way to the end of the upl... so just release them without modifying + * way to the end of the upl..so just release them without modifying * there state */ - kernel_upl_abort_range(upl, last_pg * PAGE_SIZE, (pages_in_upl - last_pg) * PAGE_SIZE, + ubc_upl_abort_range(upl, last_pg * PAGE_SIZE, (pages_in_upl - last_pg) * PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); KERNEL_DEBUG((FSDBG_CODE(DBG_FSRW, 63)) | DBG_FUNC_NONE, @@ -2561,7 +2910,6 @@ advisory_read(vp, filesize, f_offset, resid, devblocksize) cluster_push(vp) struct vnode *vp; { - void *object; upl_page_info_t *pl; upl_t upl; vm_offset_t upl_offset; @@ -2589,18 +2937,15 @@ cluster_push(vp) if (size > upl_size || (upl_size - size) > PAGE_SIZE) panic("cluster_push: v_ciosiz doesn't match size of cluster\n"); - object = ubc_getobject(vp, UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("cluster_push: ubc_getobject failed"); - - kret = vm_fault_list_request(object, - (vm_object_offset_t)upl_f_offset, upl_size, &upl, NULL, 0, - (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL)); + kret = ubc_create_upl(vp, + upl_f_offset, + upl_size, + &upl, + &pl, + UPL_FLAGS_NONE); if (kret != KERN_SUCCESS) panic("cluster_push: failed to get pagelist"); - pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - last_pg = 0; while (size) { @@ -2610,9 +2955,10 @@ cluster_push(vp) break; } if (start_pg > last_pg) { - io_size = (start_pg - last_pg) * PAGE_SIZE; + io_size = (start_pg - last_pg) * PAGE_SIZE; - kernel_upl_abort_range(upl, last_pg * PAGE_SIZE, io_size, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(upl, last_pg * PAGE_SIZE, io_size, + UPL_ABORT_FREE_ON_EMPTY); if (io_size < size) size -= io_size; @@ -2627,14 +2973,15 @@ cluster_push(vp) io_size = min(size, (last_pg - start_pg) * PAGE_SIZE); - if (vp->v_numoutput > ASYNC_THROTTLE) - io_flags = CL_COMMIT | CL_AGE; + if (vp->v_flag & VNOCACHE_DATA) + io_flags = CL_COMMIT | CL_AGE | CL_ASYNC | CL_DUMP; else io_flags = CL_COMMIT | CL_AGE | CL_ASYNC; - if (vp->v_flag & VNOCACHE_DATA) - io_flags |= CL_DUMP; - + while (vp->v_numoutput >= ASYNC_THROTTLE) { + vp->v_flag |= VTHROTTLED; + tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "cluster_push", 0); + } cluster_io(vp, upl, upl_offset, upl_f_offset + upl_offset, io_size, io_flags, (struct buf *)0); size -= io_size; diff --git a/bsd/vfs/vfs_lookup.c b/bsd/vfs/vfs_lookup.c index f7eb1ca2a..0626ad15b 100644 --- a/bsd/vfs/vfs_lookup.c +++ b/bsd/vfs/vfs_lookup.c @@ -405,6 +405,11 @@ dirloop: if ((dp->v_flag & VROOT) == 0 || (cnp->cn_flags & NOCROSSMOUNT)) break; + if (dp->v_mount == NULL) { /* forced umount */ + error = EBADF; + goto bad; + } + tdp = dp; dp = dp->v_mount->mnt_vnodecovered; vput(tdp); @@ -428,7 +433,7 @@ unionlookup: printf("not found\n"); #endif if ((error == ENOENT) && - (dp->v_flag & VROOT) && + (dp->v_flag & VROOT) && (dp->v_mount != NULL) && (dp->v_mount->mnt_flag & MNT_UNION)) { tdp = dp; dp = dp->v_mount->mnt_vnodecovered; @@ -696,7 +701,7 @@ bad: } -#define NUMPARMS 7 +#define NUMPARMS 23 kdebug_lookup(dp, cnp) struct vnode *dp; @@ -704,6 +709,7 @@ kdebug_lookup(dp, cnp) { register int i, n; register int dbg_namelen; + register int save_dbg_namelen; register char *dbg_nameptr; long dbg_parms[NUMPARMS]; char dbg_buf[4]; @@ -716,6 +722,7 @@ kdebug_lookup(dp, cnp) if (dbg_namelen > sizeof(dbg_parms)) dbg_namelen = sizeof(dbg_parms); dbg_nameptr -= dbg_namelen; + save_dbg_namelen = dbg_namelen; i = 0; @@ -744,8 +751,15 @@ kdebug_lookup(dp, cnp) else dbg_parms[i++] = 0; } + KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE, dp, dbg_parms[0], dbg_parms[1], dbg_parms[2], 0); - KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE, - dbg_parms[3], dbg_parms[4], dbg_parms[5], dbg_parms[6], 0); + + for (dbg_namelen = save_dbg_namelen-12, i=3; + dbg_namelen > 0; + dbg_namelen -=(4 * sizeof(long))) + { + KERNEL_DEBUG_CONSTANT((FSDBG_CODE(DBG_FSRW,36)) | DBG_FUNC_NONE, + dbg_parms[i++], dbg_parms[i++], dbg_parms[i++], dbg_parms[i++], 0); + } } diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c index 216c1a0e4..fd99cca8d 100644 --- a/bsd/vfs/vfs_subr.c +++ b/bsd/vfs/vfs_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -89,6 +89,10 @@ #include <miscfs/specfs/specdev.h> +#include <mach/mach_types.h> +#include <mach/memory_object_types.h> + + enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD, @@ -100,7 +104,7 @@ int vttoif_tab[9] = { static void vfree(struct vnode *vp); static void vinactive(struct vnode *vp); -extern int vnreclaim(int count); +static int vnreclaim(int count); extern kern_return_t adjust_vm_object_cache(vm_size_t oval, vm_size_t nval); @@ -207,7 +211,7 @@ unsigned long vnodetarget; /* target for vnreclaim() */ * cache. Having too few vnodes on the free list causes serious disk * thrashing as we cycle through them. */ -#define VNODE_FREE_MIN 100 /* freelist should have at least these many */ +#define VNODE_FREE_MIN 300 /* freelist should have at least these many */ /* * We need to get vnodes back from the VM object cache when a certain # @@ -226,7 +230,7 @@ unsigned long vnodetarget; /* target for vnreclaim() */ /* * Initialize the vnode management data structures. */ -void +__private_extern__ void vntblinit() { extern struct lock__bsd__ exchangelock; @@ -252,7 +256,7 @@ vntblinit() } /* Reset the VM Object Cache with the values passed in */ -kern_return_t +__private_extern__ kern_return_t reset_vmobjectcache(unsigned int val1, unsigned int val2) { vm_size_t oval = val1 - VNODE_FREE_MIN; @@ -334,6 +338,11 @@ vfs_rootmountalloc(fstypename, devname, mpp) return (ENODEV); mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); (void)vfs_busy(mp, LK_NOWAIT, 0, p); LIST_INIT(&mp->mnt_vnodelist); @@ -908,12 +917,14 @@ loop: } /* - * Grab a particular vnode from the free list, increment its - * reference count and lock it. The vnode lock bit is set the - * vnode is being eliminated in vgone. The process is awakened - * when the transition is completed, and an error returned to - * indicate that the vnode is no longer usable (possibly having - * been changed to a new file system type). + * Get a reference on a particular vnode and lock it if requested. + * If the vnode was on the inactive list, remove it from the list. + * If the vnode was on the free list, remove it from the list and + * move it to inactive list as needed. + * The vnode lock bit is set if the vnode is being eliminated in + * vgone. The process is awakened when the transition is completed, + * and an error returned to indicate that the vnode is no longer + * usable (possibly having been changed to a new file system type). */ int vget(vp, flags, p) @@ -934,7 +945,7 @@ vget(vp, flags, p) if ((vp->v_flag & VXLOCK) || (vp->v_flag & VORECLAIM)) { vp->v_flag |= VXWANT; simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vget", 0); + (void)tsleep((caddr_t)vp, PINOD, "vget", 0); return (ENOENT); } @@ -945,13 +956,13 @@ vget(vp, flags, p) if (ISSET(vp->v_flag, VTERMINATE)) { SET(vp->v_flag, VTERMWANT); simple_unlock(&vp->v_interlock); - tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vclean", 0); + (void)tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vclean", 0); return (ENOENT); } simple_lock(&vnode_free_list_slock); - /* If on the free list, remove it from there */ if (vp->v_usecount == 0) { + /* If on the free list, remove it from there */ if (VONLIST(vp)) VREMFREE("vget", vp); } else { @@ -966,74 +977,99 @@ vget(vp, flags, p) VINACTIVECHECK("vget", vp, 0); simple_unlock(&vnode_free_list_slock); + if (++vp->v_usecount <= 0) panic("vget: v_usecount"); - if (flags & LK_TYPE_MASK) { - if (error = vn_lock(vp, flags | LK_INTERLOCK, p)) { - /* - * If the vnode was not active in the first place - * must not call vrele() as VOP_INACTIVE() is not - * required. - * So inlined part of vrele() here. - */ - simple_lock(&vp->v_interlock); - if (--vp->v_usecount == 1) { - if (UBCINFOEXISTS(vp)) { - vinactive(vp); - simple_unlock(&vp->v_interlock); - return (error); - } - } - if (vp->v_usecount > 0) { - simple_unlock(&vp->v_interlock); - return (error); - } - if (vp->v_usecount < 0) - panic("vget: negative usecount (%d)", vp->v_usecount); - vfree(vp); - simple_unlock(&vp->v_interlock); + /* + * Recover named reference as needed + */ + if (UBCISVALID(vp) && !ubc_issetflags(vp, UI_HASOBJREF)) { + simple_unlock(&vp->v_interlock); + if (ubc_getobject(vp, UBC_HOLDOBJECT)) { + error = ENOENT; + goto errout; } - return (error); + simple_lock(&vp->v_interlock); + } + + if (flags & LK_TYPE_MASK) { + if (error = vn_lock(vp, flags | LK_INTERLOCK, p)) + goto errout; + return (0); } + if ((flags & LK_INTERLOCK) == 0) + simple_unlock(&vp->v_interlock); + return (0); + +errout: /* - * If this is a valid UBC vnode, if usecount is 1 and if - * this vnode was mapped in the past, it is likely - * that ubc_info freed due to the memory object getting recycled. - * Just re-initialize the ubc_info. + * If the vnode was not active in the first place + * must not call vrele() as VOP_INACTIVE() is not + * required. + * So inlined part of vrele() here. */ - if ((vp->v_usecount == 1) && UBCISVALID(vp)) { - if (UBCINFOMISSING(vp)) - panic("vget: lost ubc_info"); - - if (ISSET(vp->v_flag, VTERMINATE)) { - /* - * vnode is being terminated. - * wait for vnode_pager_no_senders() to clear - * VTERMINATE - */ - SET(vp->v_flag, VTERMWANT); + simple_lock(&vp->v_interlock); + if (--vp->v_usecount == 1) { + if (UBCINFOEXISTS(vp)) { + vinactive(vp); simple_unlock(&vp->v_interlock); - tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vclean", 0); - /* return error */ - return (ENOENT); + return (error); } - - if ((!UBCINFOEXISTS(vp)) && ISSET(vp->v_flag, VWASMAPPED)) { - simple_unlock(&vp->v_interlock); - ubc_info_init(vp); - simple_lock(&vp->v_interlock); - } else - panic("vget: stolen ubc_info"); - - if (!ubc_issetflags(vp, UI_HASOBJREF)) - if (ubc_getobject(vp, (UBC_NOREACTIVATE|UBC_HOLDOBJECT))) - panic("vget: null object"); } -out: - if ((flags & LK_INTERLOCK) == 0) + if (vp->v_usecount > 0) { simple_unlock(&vp->v_interlock); + return (error); + } + if (vp->v_usecount < 0) + panic("vget: negative usecount (%d)", vp->v_usecount); + vfree(vp); + simple_unlock(&vp->v_interlock); + return (error); +} + +/* + * Get a pager reference on the particular vnode. + * + * This is called from ubc_info_init() and it is asumed that + * the vnode is neither on the free list on on the inactive list. + * It is also assumed that the vnode is neither being recycled + * by vgonel nor being terminated by vnode_pager_vrele(). + * + * The vnode interlock is NOT held by the caller. + */ +__private_extern__ int +vnode_pager_vget(vp) + struct vnode *vp; +{ + simple_lock(&vp->v_interlock); + if (UBCINFOMISSING(vp)) + panic("vnode_pager_vget: stolen ubc_info"); + + if (!UBCINFOEXISTS(vp)) + panic("vnode_pager_vget: lost ubc_info"); + + if ((vp->v_flag & VXLOCK) || (vp->v_flag & VORECLAIM)) + panic("vnode_pager_vget: already being reclaimd"); + + if (ISSET(vp->v_flag, VTERMINATE)) + panic("vnode_pager_vget: already being terminated"); + + simple_lock(&vnode_free_list_slock); + /* The vnode should not be on ANY list */ + if (VONLIST(vp)) + panic("vnode_pager_vget: still on the list"); + + /* The vnode should not be on the inactive list here */ + VINACTIVECHECK("vnode_pager_vget", vp, 0); + simple_unlock(&vnode_free_list_slock); + + /* After all those checks, now do the real work :-) */ + if (++vp->v_usecount <= 0) + panic("vnode_pager_vget: v_usecount"); + simple_unlock(&vp->v_interlock); + return (0); } @@ -1242,10 +1278,6 @@ vput(vp) { struct proc *p = current_proc(); /* XXX */ -#if DIAGNOSTIC - if (vp == NULL) - panic("vput: null vp"); -#endif simple_lock(&vp->v_interlock); if (--vp->v_usecount == 1) { if (UBCINFOEXISTS(vp)) { @@ -1298,10 +1330,6 @@ vrele(vp) { struct proc *p = current_proc(); /* XXX */ -#if DIAGNOSTIC - if (vp == NULL) - panic("vrele: null vp"); -#endif simple_lock(&vp->v_interlock); if (--vp->v_usecount == 1) { if (UBCINFOEXISTS(vp)) { @@ -1361,7 +1389,6 @@ void vagevp(vp) struct vnode *vp; { - assert(vp); simple_lock(&vp->v_interlock); vp->v_flag |= VAGE; simple_unlock(&vp->v_interlock); @@ -1417,7 +1444,7 @@ vflush(mp, skipvp, flags) struct vnode *skipvp; int flags; { - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); struct vnode *vp, *nvp; int busy = 0; @@ -1509,7 +1536,9 @@ vclean(vp, flags, p) { int active; void *obj; + kern_return_t kret; int removed = 0; + int didhold; /* * if the vnode is not obtained by calling getnewvnode() we @@ -1559,42 +1588,40 @@ vclean(vp, flags, p) } /* Clean the pages in VM. */ - if ((active) && UBCINFOEXISTS(vp)) { + if (active && (flags & DOCLOSE)) + VOP_CLOSE(vp, IO_NDELAY, NOCRED, p); + + /* Clean the pages in VM. */ + didhold = ubc_hold(vp); + if ((active) && (didhold)) (void)ubc_clean(vp, 0); /* do not invalidate */ - } /* * Clean out any buffers associated with the vnode. */ if (flags & DOCLOSE) { if (vp->v_tag == VT_NFS) - nfs_vinvalbuf(vp, V_SAVE, NOCRED, p, 0); - else - vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); - } - /* - * If purging an active vnode, it must be closed and - * deactivated before being reclaimed. Note that the - * VOP_INACTIVE will unlock the vnode. - */ - if (active) { - if (flags & DOCLOSE) - VOP_CLOSE(vp, IO_NDELAY, NOCRED, p); + nfs_vinvalbuf(vp, V_SAVE, NOCRED, p, 0); + else + vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + } + + if (active) VOP_INACTIVE(vp, p); - } else { - /* - * Any other processes trying to obtain this lock must first - * wait for VXLOCK to clear, then call the new lock operation. - */ + else VOP_UNLOCK(vp, 0, p); + + /* Destroy ubc named reference */ + if (didhold) { + ubc_rele(vp); + ubc_destroy_named(vp); } + /* * Reclaim the vnode. */ if (VOP_RECLAIM(vp, p)) panic("vclean: cannot reclaim"); - if (active) - vrele(vp); cache_purge(vp); if (vp->v_vnlock) { if ((vp->v_vnlock->lk_flags & LK_DRAINED) == 0) @@ -1607,41 +1634,6 @@ vclean(vp, flags, p) vp->v_op = dead_vnodeop_p; vp->v_tag = VT_NON; - /* - * v_data is reclaimed by VOP_RECLAIM, all the vnode - * operation generated by the code below would be directed - * to the deadfs - */ - if (UBCINFOEXISTS(vp)) { - /* vnode is dying, destroy the object */ - if (ubc_issetflags(vp, UI_HASOBJREF)) { - obj = ubc_getobject(vp, UBC_NOREACTIVATE); - if (obj == NULL) - panic("vclean: null object"); - if (ISSET(vp->v_flag, VTERMINATE)) - panic("vclean: already teminating"); - SET(vp->v_flag, VTERMINATE); - - ubc_clearflags(vp, UI_HASOBJREF); - memory_object_destroy(obj, 0); - - /* - * memory_object_destroy() is asynchronous with respect - * to vnode_pager_no_senders(). - * wait for vnode_pager_no_senders() to clear - * VTERMINATE - */ - while (ISSET(vp->v_flag, VTERMINATE)) { - SET(vp->v_flag, VTERMWANT); - tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vclean", 0); - } - if (UBCINFOEXISTS(vp)) { - ubc_info_free(vp); - vp->v_ubcinfo = UBC_NOINFO; /* catch bad accesses */ - } - } - } - /* * Done with purge, notify sleepers of the grim news. */ @@ -1650,6 +1642,9 @@ vclean(vp, flags, p) vp->v_flag &= ~VXWANT; wakeup((caddr_t)vp); } + + if (active) + vrele(vp); } /* @@ -1664,7 +1659,7 @@ vop_revoke(ap) } */ *ap; { struct vnode *vp, *vq; - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); #if DIAGNOSTIC if ((ap->a_flags & REVOKEALL) == 0) @@ -1683,7 +1678,7 @@ vop_revoke(ap) while (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); + (void)tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); } return (0); } @@ -1748,7 +1743,7 @@ void vgone(vp) struct vnode *vp; { - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); simple_lock(&vp->v_interlock); vgonel(vp, p); @@ -1782,7 +1777,7 @@ vgonel(vp, p) while (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vgone", 0); + (void)tsleep((caddr_t)vp, PINOD, "vgone", 0); } return; } @@ -1967,7 +1962,7 @@ vprint(label, vp) void printlockedvnodes() { - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); struct mount *mp, *nmp; struct vnode *vp; @@ -2149,11 +2144,11 @@ vfs_mountedon(vp) * Unmount all filesystems. The list is traversed in reverse order * of mounting to avoid dependencies. */ -void +__private_extern__ void vfs_unmountall() { struct mount *mp, *nmp; - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); /* * Since this only runs when rebooting, it is not interlocked. @@ -2166,7 +2161,7 @@ vfs_unmountall() /* * Build hash lists of net addresses and hang them off the mount point. - * Called by ufs_mount() to set up the lists of export addresses. + * Called by vfs_export() to set up the lists of export addresses. */ static int vfs_hang_addrlist(mp, nep, argp) @@ -2343,7 +2338,7 @@ vfs_export_lookup(mp, nep, nam) * try to reclaim vnodes from the memory * object cache */ -int +static int vm_object_cache_reclaim(int count) { int cnt; @@ -2360,7 +2355,7 @@ vm_object_cache_reclaim(int count) * and then try to reclaim some vnodes from the memory * object cache */ -int +static int vnreclaim(int count) { int cnt, i, loopcnt; @@ -2368,6 +2363,7 @@ vnreclaim(int count) struct vnode *vp; int err; struct proc *p; + kern_return_t kret; i = 0; loopcnt = 0; @@ -2390,163 +2386,123 @@ restart: for (vp = TAILQ_FIRST(&vnode_inactive_list); (vp != NULLVP) && (i < count); vp = TAILQ_NEXT(vp, v_freelist)) { + + if (!simple_lock_try(&vp->v_interlock)) + continue; - if (simple_lock_try(&vp->v_interlock)) { - if (vp->v_usecount != 1) - panic("vnreclaim: v_usecount"); + if (vp->v_usecount != 1) + panic("vnreclaim: v_usecount"); - if(!UBCINFOEXISTS(vp)) { - if (vp->v_type == VBAD) { - VREMINACTIVE("vnreclaim", vp); - simple_unlock(&vp->v_interlock); - continue; - } else - panic("non UBC vnode on inactive list"); - /* Should not reach here */ - } - - /* If vnode is already being reclaimed, wait */ - if ((vp->v_flag & VXLOCK) || (vp->v_flag & VORECLAIM)) { - vp->v_flag |= VXWANT; + if(!UBCINFOEXISTS(vp)) { + if (vp->v_type == VBAD) { + VREMINACTIVE("vnreclaim", vp); simple_unlock(&vp->v_interlock); - simple_unlock(&vnode_free_list_slock); - (void)tsleep((caddr_t)vp, PINOD, "vocr", 0); - goto restart; - } + continue; + } else + panic("non UBC vnode on inactive list"); + /* Should not reach here */ + } - VREMINACTIVE("vnreclaim", vp); + /* If vnode is already being reclaimed, wait */ + if ((vp->v_flag & VXLOCK) || (vp->v_flag & VORECLAIM)) { + vp->v_flag |= VXWANT; + simple_unlock(&vp->v_interlock); simple_unlock(&vnode_free_list_slock); + (void)tsleep((caddr_t)vp, PINOD, "vocr", 0); + goto restart; + } - /* held vnodes must not be reclaimed */ - if (vp->v_ubcinfo->ui_holdcnt) { /* XXX */ - vinactive(vp); - simple_unlock(&vp->v_interlock); - goto restart; - } + VREMINACTIVE("vnreclaim", vp); + simple_unlock(&vnode_free_list_slock); - if (ubc_issetflags(vp, UI_WASMAPPED)) { - /* - * We should not reclaim as it is likely - * to be in use. Let it die a natural death. - * Release the UBC reference if one exists - * and put it back at the tail. - */ - if (ubc_issetflags(vp, UI_HASOBJREF)) { - obj = ubc_getobject(vp, UBC_NOREACTIVATE); - if (obj == NULL) - panic("vnreclaim: null object"); - /* release the reference gained by ubc_info_init() */ - ubc_clearflags(vp, UI_HASOBJREF); - simple_unlock(&vp->v_interlock); - vm_object_deallocate(obj); - /* - * The vnode interlock was release. - * vm_object_deallocate() might have blocked. - * It is possible that the object was terminated. - * It is also possible that the vnode was - * reactivated. Evaluate the state again. - */ - if (UBCINFOEXISTS(vp)) { - simple_lock(&vp->v_interlock); - if ((vp->v_usecount == 1) && !VONLIST(vp)) - vinactive(vp); - simple_unlock(&vp->v_interlock); - } - } else { - vinactive(vp); - simple_unlock(&vp->v_interlock); - } - } else { - VORECLAIM_ENABLE(vp); - - /* - * scrub the dirty pages and invalidate the buffers - */ - p = current_proc(); - err = vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK, p); - if (err) { - /* cannot reclaim */ + if (ubc_issetflags(vp, UI_WASMAPPED)) { + /* + * We should not reclaim as it is likely + * to be in use. Let it die a natural death. + * Release the UBC reference if one exists + * and put it back at the tail. + */ + simple_unlock(&vp->v_interlock); + if (ubc_release_named(vp)) { + if (UBCINFOEXISTS(vp)) { simple_lock(&vp->v_interlock); - vinactive(vp); - VORECLAIM_DISABLE(vp); + if (vp->v_usecount == 1 && !VONLIST(vp)) + vinactive(vp); simple_unlock(&vp->v_interlock); - goto restart; } - simple_lock(&vp->v_interlock); - if(vp->v_usecount != 1) - panic("VOCR: usecount race"); + } else { + simple_lock(&vp->v_interlock); + vinactive(vp); simple_unlock(&vp->v_interlock); + } + } else { + int didhold; - /* - * If the UBC reference on the memory object - * was already lost, regain it. This will - * keep the memory object alive for rest of the - * reclaim and finally this reference would - * be lost by memory_object_destroy() - */ - obj = ubc_getobject(vp, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)); - if (obj == (void *)NULL) - panic("vnreclaim: null object"); - - /* clean up the state in VM without invalidating */ - (void)ubc_clean(vp, 0); + VORECLAIM_ENABLE(vp); - /* flush and invalidate buffers associated with the vnode */ - if (vp->v_tag == VT_NFS) - nfs_vinvalbuf(vp, V_SAVE, NOCRED, p, 0); - else - vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); - - /* - * It is not necessary to call ubc_uncache() - * here because memory_object_destroy() marks - * the memory object non cachable already - * - * Need to release the vnode lock before calling - * vm_object_deallocate() to avoid deadlock - * when the vnode goes through vop_inactive - * - * Note: for the v_usecount == 1 case, VOP_INACTIVE - * has not yet been called. Call it now while vp is - * still locked, it will also release the lock. - */ - if (vp->v_usecount == 1) - VOP_INACTIVE(vp, p); - else - VOP_UNLOCK(vp, 0, p); - - /* - * This vnode is ready to be reclaimed. - * Terminate the memory object. - * memory_object_destroy() will result in - * vnode_pager_no_senders(). - * That will release the pager reference - * and the vnode will move to the free list. - */ - if (ISSET(vp->v_flag, VTERMINATE)) - panic("vnreclaim: already teminating"); - SET(vp->v_flag, VTERMINATE); - - memory_object_destroy(obj, 0); - - /* - * memory_object_destroy() is asynchronous with respect - * to vnode_pager_no_senders(). - * wait for vnode_pager_no_senders() to clear - * VTERMINATE - */ - while (ISSET(vp->v_flag, VTERMINATE)) { - SET(vp->v_flag, VTERMWANT); - tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "vnreclaim", 0); - } + /* + * scrub the dirty pages and invalidate the buffers + */ + p = current_proc(); + err = vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK, p); + if (err) { + /* cannot reclaim */ simple_lock(&vp->v_interlock); + vinactive(vp); VORECLAIM_DISABLE(vp); i++; simple_unlock(&vp->v_interlock); + goto restart; } - /* inactive list lock was released, must restart */ - goto restart; + + /* keep the vnode alive so we can kill it */ + simple_lock(&vp->v_interlock); + if(vp->v_usecount != 1) + panic("VOCR: usecount race"); + vp->v_usecount++; + simple_unlock(&vp->v_interlock); + + /* clean up the state in VM without invalidating */ + didhold = ubc_hold(vp); + if (didhold) + (void)ubc_clean(vp, 0); + + /* flush and invalidate buffers associated with the vnode */ + if (vp->v_tag == VT_NFS) + nfs_vinvalbuf(vp, V_SAVE, NOCRED, p, 0); + else + vinvalbuf(vp, V_SAVE, NOCRED, p, 0, 0); + + /* + * Note: for the v_usecount == 2 case, VOP_INACTIVE + * has not yet been called. Call it now while vp is + * still locked, it will also release the lock. + */ + if (vp->v_usecount == 2) + VOP_INACTIVE(vp, p); + else + VOP_UNLOCK(vp, 0, p); + + if (didhold) + ubc_rele(vp); + + /* + * destroy the ubc named reference. + * If we can't because it is held for I/Os + * in progress, just put it back on the inactive + * list and move on. Otherwise, the paging reference + * is toast (and so is this vnode?). + */ + if (ubc_destroy_named(vp)) { + i++; + } + simple_lock(&vp->v_interlock); + VORECLAIM_DISABLE(vp); + simple_unlock(&vp->v_interlock); + vrele(vp); /* release extra use we added here */ } + /* inactive list lock was released, must restart */ + goto restart; } simple_unlock(&vnode_free_list_slock); @@ -2566,7 +2522,7 @@ out: * AGE the vnode so that it gets recycled quickly. * Check lock status to decide whether to call vput() or vrele(). */ -void +__private_extern__ void vnode_pager_vrele(struct vnode *vp) { @@ -2613,22 +2569,22 @@ vnode_pager_vrele(struct vnode *vp) if (!ISSET(vp->v_flag, VTERMINATE)) SET(vp->v_flag, VTERMINATE); if (UBCINFOEXISTS(vp)) { + struct ubc_info *uip = vp->v_ubcinfo; + if (ubc_issetflags(vp, UI_WASMAPPED)) SET(vp->v_flag, VWASMAPPED); - if ((vp->v_ubcinfo->ui_holdcnt) /* XXX */ - && !(vp->v_flag & VXLOCK)) - panic("vnode_pager_vrele: freeing held ubc_info"); - - simple_unlock(&vp->v_interlock); - ubc_info_free(vp); vp->v_ubcinfo = UBC_NOINFO; /* catch bad accesses */ + simple_unlock(&vp->v_interlock); + ubc_info_deallocate(uip); } else { if ((vp->v_type == VBAD) && ((vp)->v_ubcinfo != UBC_INFO_NULL) && ((vp)->v_ubcinfo != UBC_NOINFO)) { - simple_unlock(&vp->v_interlock); - ubc_info_free(vp); + struct ubc_info *uip = vp->v_ubcinfo; + vp->v_ubcinfo = UBC_NOINFO; /* catch bad accesses */ + simple_unlock(&vp->v_interlock); + ubc_info_deallocate(uip); } else { simple_unlock(&vp->v_interlock); } @@ -2659,7 +2615,7 @@ int walk_vnodes_debug=0; void walk_allvnodes() { - struct proc *p = current_proc(); /* XXX */ + struct proc *p = current_proc(); struct mount *mp, *nmp; struct vnode *vp; int cnt = 0; @@ -2697,3 +2653,100 @@ walk_allvnodes() printf("%d - inactive\n", cnt); } #endif /* DIAGNOSTIC */ + +void +vfs_io_attributes(vp, flags, iosize, vectors) + struct vnode *vp; + int flags; /* B_READ or B_WRITE */ + int *iosize; + int *vectors; +{ + struct mount *mp; + + /* start with "reasonable" defaults */ + *iosize = MAXPHYS; + *vectors = 32; + + mp = vp->v_mount; + if (mp != NULL) { + switch (flags) { + case B_READ: + *iosize = mp->mnt_maxreadcnt; + *vectors = mp->mnt_segreadcnt; + break; + case B_WRITE: + *iosize = mp->mnt_maxwritecnt; + *vectors = mp->mnt_segwritecnt; + break; + default: + break; + } + } + + return; +} + +#include <dev/disk.h> + +int +vfs_init_io_attributes(devvp, mp) + struct vnode *devvp; + struct mount *mp; +{ + int error; + off_t readblockcnt; + off_t writeblockcnt; + off_t readsegcnt; + off_t writesegcnt; + u_long blksize; + + u_int64_t temp; + + struct proc *p = current_proc(); + struct ucred *cred = p->p_ucred; + + if ((error = VOP_IOCTL(devvp, DKIOCGETMAXBLOCKCOUNTREAD, + (caddr_t)&readblockcnt, 0, cred, p))) + return (error); + + if ((error = VOP_IOCTL(devvp, DKIOCGETMAXBLOCKCOUNTWRITE, + (caddr_t)&writeblockcnt, 0, cred, p))) + return (error); + + if ((error = VOP_IOCTL(devvp, DKIOCGETMAXSEGMENTCOUNTREAD, + (caddr_t)&readsegcnt, 0, cred, p))) + return (error); + + if ((error = VOP_IOCTL(devvp, DKIOCGETMAXSEGMENTCOUNTWRITE, + (caddr_t)&writesegcnt, 0, cred, p))) + return (error); + + if ((error = VOP_IOCTL(devvp, DKIOCGETBLOCKSIZE, + (caddr_t)&blksize, 0, cred, p))) + return (error); + + temp = readblockcnt * blksize; + temp = (temp > UINT32_MAX) ? (UINT32_MAX / blksize) * blksize : temp; + mp->mnt_maxreadcnt = (u_int32_t)temp; + + temp = writeblockcnt * blksize; + temp = (temp > UINT32_MAX) ? (UINT32_MAX / blksize) * blksize : temp; + mp->mnt_maxwritecnt = (u_int32_t)temp; + + temp = (readsegcnt > UINT16_MAX) ? UINT16_MAX : readsegcnt; + mp->mnt_segreadcnt = (u_int16_t)temp; + + temp = (writesegcnt > UINT16_MAX) ? UINT16_MAX : writesegcnt; + mp->mnt_segwritecnt = (u_int16_t)temp; + +#if 0 + printf("--- IO attributes for mount point 0x%08x ---\n", mp); + printf("\tmnt_maxreadcnt = 0x%x", mp->mnt_maxreadcnt); + printf("\tmnt_maxwritecnt = 0x%x\n", mp->mnt_maxwritecnt); + printf("\tmnt_segreadcnt = 0x%x", mp->mnt_segreadcnt); + printf("\tmnt_segwritecnt = 0x%x\n", mp->mnt_segwritecnt); +#endif /* 0 */ + + return (error); +} + diff --git a/bsd/vfs/vfs_support.c b/bsd/vfs/vfs_support.c index 24a1fa77a..3eeabf3ef 100644 --- a/bsd/vfs/vfs_support.c +++ b/bsd/vfs/vfs_support.c @@ -375,6 +375,7 @@ struct vop_select_args /* { int a_which; int a_fflags; struct ucred *a_cred; + void *a_wql; struct proc *a_p; } */; @@ -1045,6 +1046,7 @@ struct vop_allocate_args /* { off_t a_length; u_int32_t a_flags; off_t *a_bytesallocated; + off_t a_offset; struct ucred *a_cred; struct proc *a_p; } */; @@ -1153,14 +1155,14 @@ struct vop_pagein_args /* { int nop_pagein(struct vop_pagein_args *ap) { - kernel_upl_abort(ap->a_pl, UPL_ABORT_ERROR); + ubc_upl_abort(ap->a_pl, UPL_ABORT_ERROR); return (0); } int err_pagein(struct vop_pagein_args *ap) { - kernel_upl_abort(ap->a_pl, UPL_ABORT_ERROR); + ubc_upl_abort(ap->a_pl, UPL_ABORT_ERROR); return (EOPNOTSUPP); } @@ -1178,14 +1180,14 @@ struct vop_pageout_args /* { int nop_pageout(struct vop_pageout_args *ap) { - kernel_upl_abort(ap->a_pl, UPL_ABORT_ERROR); + ubc_upl_abort(ap->a_pl, UPL_ABORT_ERROR); return (0); } int err_pageout(struct vop_pageout_args *ap) { - kernel_upl_abort(ap->a_pl, UPL_ABORT_ERROR); + ubc_upl_abort(ap->a_pl, UPL_ABORT_ERROR); return (EOPNOTSUPP); } diff --git a/bsd/vfs/vfs_syscalls.c b/bsd/vfs/vfs_syscalls.c index a7e2dd53e..b5b5e1248 100644 --- a/bsd/vfs/vfs_syscalls.c +++ b/bsd/vfs/vfs_syscalls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1995-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -258,6 +258,11 @@ mount(p, uap, retval) mp = (struct mount *)_MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, (u_long)sizeof(struct mount)); + + /* Initialize the default IO constraints */ + mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; + mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; + lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); (void)vfs_busy(mp, LK_NOWAIT, 0, p); mp->mnt_op = vfsp->vfc_vfsops; @@ -278,10 +283,12 @@ update: mp->mnt_flag |= MNT_RDONLY; else if (mp->mnt_flag & MNT_RDONLY) mp->mnt_kern_flag |= MNTK_WANTRDWR; - mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | - MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_UNKNOWNPERMISSIONS); - mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | - MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_UNKNOWNPERMISSIONS); + mp->mnt_flag &= ~(MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | + MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | + MNT_UNKNOWNPERMISSIONS | MNT_DONTBROWSE | MNT_AUTOMOUNTED); + mp->mnt_flag |= uap->flags & (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | + MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | + MNT_UNKNOWNPERMISSIONS | MNT_DONTBROWSE | MNT_AUTOMOUNTED); /* * Mount the filesystem. */ @@ -528,7 +535,8 @@ sync(p, uap, retval) extern unsigned int dp_pgins, dp_pgouts; if(print_vmpage_stat) { vm_countdirtypages(); - printf("VP: %d: %d: %d: %d: %d\n", vp_pgodirty, vp_pgoclean, vp_pagein, dp_pgins, dp_pgouts); + printf("VP: %d: %d: %d: %d: %d\n", vp_pgodirty, vp_pgoclean, vp_pagein, + dp_pgins, dp_pgouts); } } #if DIAGNOSTIC @@ -595,8 +603,8 @@ statfs(p, uap, retval) if (error = VFS_STATFS(mp, sp, p)) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -/* return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); */ - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)-sizeof(sp->f_reserved3)-sizeof(sp->f_reserved4))); + return (copyout((caddr_t)sp, (caddr_t)uap->buf, + sizeof(*sp)-sizeof(sp->f_reserved3)-sizeof(sp->f_reserved4))); } /* @@ -627,8 +635,8 @@ fstatfs(p, uap, retval) if (error = VFS_STATFS(mp, sp, p)) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; -/* return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); */ - return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp)-sizeof(sp->f_reserved3)-sizeof(sp->f_reserved4))); + return (copyout((caddr_t)sp, (caddr_t)uap->buf, + sizeof(*sp)-sizeof(sp->f_reserved3)-sizeof(sp->f_reserved4))); } /* @@ -726,7 +734,9 @@ ogetfsstat(p, uap, retval) continue; } sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp) - sizeof(sp->f_reserved3) - sizeof(sp->f_reserved4))) + error = copyout((caddr_t)sp, sfsp, + sizeof(*sp) - sizeof(sp->f_reserved3) - sizeof(sp->f_reserved4)); + if (error) return (error); sfsp += sizeof(*sp) - sizeof(sp->f_reserved4); } @@ -897,18 +907,17 @@ open(p, uap, retval) register struct filedesc *fdp = p->p_fd; register struct file *fp; register struct vnode *vp; - int flags, cmode; + int flags, cmode, oflags; struct file *nfp; int type, indx, error; struct flock lf; struct nameidata nd; extern struct fileops vnops; - /* CERT advisory patch applied from FreeBSD */ - /* Refer to Radar#2262895 A. Ramesh */ - flags = FFLAGS(uap->flags); - if ((flags & (FREAD | FWRITE))==0) + oflags = uap->flags; + if ((oflags & O_ACCMODE) == O_ACCMODE) return(EINVAL); + flags = FFLAGS(uap->flags); if (error = falloc(p, &nfp, &indx)) return (error); fp = nfp; @@ -1256,7 +1265,7 @@ _unlink(p, uap, retval, nodelbusy) struct nameidata nd; NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, uap->path, p); - /* with hfs semantics, busy files cannot be deleted */ + /* with Carbon semantics, busy files cannot be deleted */ if (nodelbusy) nd.ni_cnd.cn_flags |= NODELETEBUSY; if (error = namei(&nd)) @@ -1305,7 +1314,7 @@ unlink(p, uap, retval) } /* - * Delete a name from the filesystem using HFS semantics. + * Delete a name from the filesystem using Carbon semantics. */ int delete(p, uap, retval) @@ -1883,8 +1892,8 @@ chown(p, uap, retval) vp = nd.ni_vp; /* - XXX A TEMPORARY HACK FOR NOW: Try to track console_user - by looking for chown() calls on /dev/console from a console process: + * XXX A TEMPORARY HACK FOR NOW: Try to track console_user + * by looking for chown() calls on /dev/console from a console process. */ if ((vp) && (vp->v_specinfo) && (major(vp->v_specinfo->si_rdev) == CONSMAJOR) && @@ -2000,8 +2009,8 @@ truncate(p, uap, retval) int error; struct nameidata nd; - if (uap->length < 0) - return(EINVAL); + if (uap->length < 0) + return(EINVAL); NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); if (error = namei(&nd)) return (error); @@ -2042,8 +2051,8 @@ ftruncate(p, uap, retval) struct file *fp; int error; - if (uap->length < 0) - return(EINVAL); + if (uap->length < 0) + return(EINVAL); if (error = fdgetf(p, uap->fd, &fp)) return (error); @@ -2054,7 +2063,6 @@ ftruncate(p, uap, retval) if (fp->f_type != DTYPE_VNODE) return (EINVAL); - if ((fp->f_flag & FWRITE) == 0) return (EINVAL); vp = (struct vnode *)fp->f_data; @@ -2264,6 +2272,7 @@ rename(p, uap, retval) struct nameidata fromnd, tond; int error; int mntrename; + int casesense,casepres; mntrename = FALSE; @@ -2297,10 +2306,36 @@ rename(p, uap, retval) error = EINVAL; /* * If source is the same as the destination (that is the - * same inode number) then there is nothing to do. + * same inode number) then there is nothing to do... + * EXCEPT if the + * underlyning file system supports case insensitivity and is case preserving. Then + * a special case is made, i.e. foo -> Foo. + * + * Only file systems that support the pathconf selectors _PC_CASE_SENSITIVE and + * _PC_CASE_PRESERVING can have this exception, and then they would need to + * handle the special case of getting the same vnode as target and source. + * NOTE: Then the target is unlocked going into VOP_RENAME, so not to cause + * locking problems. There is a single reference on tvp. */ - if (fvp == tvp) + if (fvp == tvp) { error = -1; + /* + * Check to see if just changing case, if: + * - file system is case insensitive + * - and also case preserving + * _ same parent directories (so changing case by different links is not supported) + * For instance: mv a/foo a/Foo + */ + if ((tond.ni_dvp == fromnd.ni_dvp) && + (VOP_PATHCONF(tdvp, _PC_CASE_SENSITIVE, &casesense) == 0) && + (VOP_PATHCONF(tdvp, _PC_CASE_PRESERVING, &casepres) == 0) && + (casesense == 0) && + (casepres == 1)) { + /* Since the target is locked...unlock it and lose a ref */ + vput(tvp); + error = 0; + } + } /* * Allow the renaming of mount points. @@ -2632,7 +2667,8 @@ unionread: VOP_UNLOCK(lvp, 0, p); fp->f_data = (caddr_t) lvp; fp->f_offset = 0; - error = vn_close(vp, FREAD, fp->f_cred, p); + error = VOP_CLOSE(vp, FREAD, fp->f_cred, p); + vrele(vp); if (error) return (error); vp = lvp; @@ -2740,7 +2776,8 @@ unionread: VOP_UNLOCK(lvp, 0, p); fp->f_data = (caddr_t) lvp; fp->f_offset = 0; - error = vn_close(vp, FREAD, fp->f_cred, p); + error = VOP_CLOSE(vp, FREAD, fp->f_cred, p); + vrele(vp); if (error) return (error); vp = lvp; @@ -2841,6 +2878,7 @@ getvnode(p, fd, fpp) *fpp = fp; return (0); } + /* * HFS/HFS PlUS SPECIFIC SYSTEM CALLS * The following 10 system calls are designed to support features @@ -3573,3 +3611,26 @@ FSCtl_Exit: return error; } /* end of fsctl system call */ + +/* + * An in-kernel sync for power management to call. + */ +__private_extern__ int +sync_internal(void) +{ + boolean_t funnel_state; + int error; + + struct sync_args data; + + int retval[2]; + + funnel_state = thread_funnel_set(kernel_flock, TRUE); + + error = sync(current_proc(), &data, &retval); + + thread_funnel_set(kernel_flock, funnel_state); + + return (error); +} /* end of sync_internal call */ + diff --git a/bsd/vfs/vfs_utfconv.c b/bsd/vfs/vfs_utfconv.c index 44f726355..b0173cfb4 100644 --- a/bsd/vfs/vfs_utfconv.c +++ b/bsd/vfs/vfs_utfconv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -45,11 +45,15 @@ */ -#define UCS_TO_UTF_LEN(c) ((c) < 0x0080 ? 1 : ((c) < 0x0800 ? 2 : 3)) +#define UCS_TO_UTF8_LEN(c) ((c) < 0x0080 ? 1 : ((c) < 0x0800 ? 2 : 3)) + +#define UCS_ALT_NULL 0x2400 static u_int16_t ucs_decompose __P((u_int16_t, u_int16_t *)); +static u_int16_t ucs_combine(u_int16_t base, u_int16_t comb); + /* * utf8_encodelen - Calculates the UTF-8 encoding length for a UCS-2 filename @@ -81,12 +85,12 @@ utf8_encodelen(ucsp, ucslen, altslash, flags) if (swapbytes) ucs_ch = NXSwapShort(ucs_ch); - if (altslash && ucs_ch == '/') - ucs_ch = altslash; - if (ucs_ch == '\0') - ucs_ch = 0xc080; + if (ucs_ch == '/') + ucs_ch = altslash ? altslash : '_'; + else if (ucs_ch == '\0') + ucs_ch = UCS_ALT_NULL; - len += UCS_TO_UTF_LEN(ucs_ch); + len += UCS_TO_UTF8_LEN(ucs_ch); } return (len); @@ -97,7 +101,7 @@ utf8_encodelen(ucsp, ucslen, altslash, flags) * utf8_encodestr - Encodes a UCS-2 (Unicode) string to UTF-8 * * NOTES: - * The resulting UTF-8 string is not null terminated. + * The resulting UTF-8 string is NULL terminated. * * If '/' chars are allowed on disk then an alternate * (replacement) char must be provided in altslash. @@ -105,6 +109,10 @@ utf8_encodelen(ucsp, ucslen, altslash, flags) * input flags: * UTF_REVERSE_ENDIAN: UCS-2 byteorder is opposite current runtime * UTF_NO_NULL_TERM: don't add NULL termination to UTF-8 output + * + * result: + * ENAMETOOLONG: Name didn't fit; only buflen bytes were encoded + * EINVAL: Illegal char found; char was replaced by an '_'. */ int utf8_encodestr(ucsp, ucslen, utf8p, utf8len, buflen, altslash, flags) const u_int16_t * ucsp; @@ -118,9 +126,11 @@ int utf8_encodestr(ucsp, ucslen, utf8p, utf8len, buflen, altslash, flags) u_int8_t * bufstart; u_int8_t * bufend; u_int16_t ucs_ch; + u_int16_t extra[2] = {0}; int charcnt; int swapbytes = (flags & UTF_REVERSE_ENDIAN); - int nullterm = ((flags & UTF_NO_NULL_TERM) == 0); + int nullterm = ((flags & UTF_NO_NULL_TERM) == 0); + int decompose = (flags & UTF_DECOMPOSED); int result = 0; bufstart = utf8p; @@ -130,14 +140,34 @@ int utf8_encodestr(ucsp, ucslen, utf8p, utf8len, buflen, altslash, flags) charcnt = ucslen / 2; while (charcnt-- > 0) { - ucs_ch = *ucsp++; + if (!decompose) + ucs_ch = swapbytes ? NXSwapShort(*ucsp++) : *ucsp++; + else if (extra[0]) { + ucs_ch = extra[0]; extra[0] = 0; + } else if (extra[1]) { + ucs_ch = extra[1]; extra[1] = 0; + } else { + ucs_ch = swapbytes ? NXSwapShort(*ucsp++) : *ucsp++; + ucs_ch = ucs_decompose(ucs_ch, &extra[0]); + if (extra[0]) + charcnt++; + if (extra[1]) + charcnt++; + } - if (swapbytes) - ucs_ch = NXSwapShort(ucs_ch); - if (altslash && ucs_ch == '/') - ucs_ch = altslash; + /* Slash and NULL are not permitted */ + if (ucs_ch == '/') { + if (altslash) + ucs_ch = altslash; + else { + ucs_ch = '_'; + result = EINVAL; + } + } else if (ucs_ch == '\0') { + ucs_ch = UCS_ALT_NULL; + } - if ((ucs_ch < 0x0080) && (ucs_ch != '\0')) { + if (ucs_ch < 0x0080) { if (utf8p >= bufend) { result = ENAMETOOLONG; break; @@ -149,7 +179,6 @@ int utf8_encodestr(ucsp, ucslen, utf8p, utf8len, buflen, altslash, flags) result = ENAMETOOLONG; break; } - /* NOTE: NULL maps to 0xC080 */ *utf8p++ = (ucs_ch >> 6) | 0xc0; *utf8p++ = (ucs_ch & 0x3f) | 0x80; @@ -185,6 +214,10 @@ int utf8_encodestr(ucsp, ucslen, utf8p, utf8len, buflen, altslash, flags) * input flags: * UTF_REV_ENDIAN: UCS-2 byteorder is oposite current runtime * UTF_DECOMPOSED: UCS-2 output string must be fully decompsed + * + * result: + * ENAMETOOLONG: Name didn't fit; only ucslen chars were decoded. + * EINVAL: Illegal UTF-8 sequence found. */ int utf8_decodestr(utf8p, utf8len, ucsp, ucslen, buflen, altslash, flags) @@ -201,10 +234,11 @@ utf8_decodestr(utf8p, utf8len, ucsp, ucslen, buflen, altslash, flags) u_int16_t ucs_ch; u_int8_t byte; int result = 0; - int decompose, swapbytes; + int decompose, precompose, swapbytes; - decompose = (flags & UTF_DECOMPOSED); - swapbytes = (flags & UTF_REVERSE_ENDIAN); + decompose = (flags & UTF_DECOMPOSED); + precompose = (flags & UTF_PRECOMPOSED); + swapbytes = (flags & UTF_REVERSE_ENDIAN); bufstart = ucsp; bufend = (u_int16_t *)((u_int8_t *)ucsp + buflen); @@ -220,17 +254,17 @@ utf8_decodestr(utf8p, utf8len, ucsp, ucslen, buflen, altslash, flags) ucs_ch = byte; } else { switch (byte & 0xf0) { - /* 2 byte sequence*/ + /* 2 byte sequence */ case 0xc0: case 0xd0: /* extract bits 6 - 10 from first byte */ - ucs_ch = (byte & 0x1F) << 6; - if ((ucs_ch < 0x0080) && (*utf8p != 0x80)) { + ucs_ch = (byte & 0x1F) << 6; + if (ucs_ch < 0x0080) { result = EINVAL; /* seq not minimal */ goto stop; } break; - /* 3 byte sequence*/ + /* 3 byte sequence */ case 0xe0: /* extract bits 12 - 15 from first byte */ ucs_ch = (byte & 0x0F) << 6; @@ -246,7 +280,7 @@ utf8_decodestr(utf8p, utf8len, ucsp, ucslen, buflen, altslash, flags) ucs_ch <<= 6; if (ucs_ch < 0x0800) { - result = EINVAL; /* seq not minimal */ + result = EINVAL; /* sequence not minimal */ goto stop; } break; @@ -264,24 +298,38 @@ utf8_decodestr(utf8p, utf8len, ucsp, ucslen, buflen, altslash, flags) ucs_ch += (byte & 0x3F); if (decompose) { - u_int16_t comb_ch; + u_int16_t comb_ch[2]; - ucs_ch = ucs_decompose(ucs_ch, &comb_ch); - - if (comb_ch) { - if (swapbytes) - *ucsp++ = NXSwapShort(ucs_ch); - else - *ucsp++ = ucs_ch; + ucs_ch = ucs_decompose(ucs_ch, &comb_ch[0]); + if (comb_ch[0]) { + *ucsp++ = swapbytes ? NXSwapShort(ucs_ch) : ucs_ch; if (ucsp >= bufend) { result = ENAMETOOLONG; goto stop; } - - ucs_ch = comb_ch; + ucs_ch = comb_ch[0]; + if (comb_ch[1]) { + *ucsp++ = swapbytes ? NXSwapShort(ucs_ch) : ucs_ch; + if (ucsp >= bufend) { + result = ENAMETOOLONG; + goto stop; + } + ucs_ch = comb_ch[1]; + } + } + } else if (precompose && (ucsp != bufstart)) { + u_int16_t composite, base; + + base = swapbytes ? NXSwapShort(*(ucsp - 1)) : *(ucsp - 1); + composite = ucs_combine(base, ucs_ch); + if (composite) { + --ucsp; + ucs_ch = composite; } } + if (ucs_ch == UCS_ALT_NULL) + ucs_ch = '\0'; } if (ucs_ch == altslash) @@ -305,43 +353,162 @@ stop: * from the combining_char table and add 0x0300 to it. */ -static unsigned char primary_char[64] = { - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, +static unsigned char primary_char[8*36] = { + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x43, + + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, /* CF */ - 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, + 0x00, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x00, - 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, + 0x00, 0x55, 0x55, 0x55, 0x55, 0x59, 0x00, 0x00, /* DF */ - 0xD8, 0x55, 0x55, 0x55, 0x55, 0x59, 0xDE, 0xDF, + 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x00, 0x63, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xE6, 0x63, + 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, /* EF */ - 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, + 0x00, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x00, - 0xF0, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0xF7, + 0x00, 0x75, 0x75, 0x75, 0x75, 0x79, 0x00, 0x79, /* FF */ - 0xF8, 0x75, 0x75, 0x75, 0x75, 0x79, 0xFE, 0x79, + 0x41, 0x61, 0x41, 0x61, 0x41, 0x61, 0x43, 0x63, + + 0x43, 0x63, 0x43, 0x63, 0x43, 0x63, 0x44, 0x64, /* 10F */ + + 0x00, 0x00, 0x45, 0x65, 0x45, 0x65, 0x45, 0x65, + + 0x45, 0x65, 0x45, 0x65, 0x47, 0x67, 0x47, 0x67, /* 11F */ + + 0x47, 0x67, 0x47, 0x67, 0x48, 0x68, 0x00, 0x00, + + 0x49, 0x69, 0x49, 0x69, 0x49, 0x69, 0x49, 0x69, + + 0x49, 0x00, 0x00, 0x00, 0x4A, 0x6A, 0x4B, 0x6B, + + 0x00, 0x4C, 0x6C, 0x4C, 0x6C, 0x4C, 0x6C, 0x00, /* 13F */ + + 0x00, 0x00, 0x00, 0x4E, 0x6E, 0x4E, 0x6E, 0x4E, + + 0x6E, 0x00, 0x00, 0x00, 0x4F, 0x6F, 0x4F, 0x6F, + + 0x4F, 0x6F, 0x00, 0x00, 0x52, 0x72, 0x52, 0x72, + + 0x52, 0x72, 0x53, 0x73, 0x53, 0x73, 0x53, 0x73, /* 15F */ + + 0x53, 0x73, 0x54, 0x74, 0x54, 0x74, 0x00, 0x00, + + 0x55, 0x75, 0x55, 0x75, 0x55, 0x75, 0x55, 0x75, + + 0x55, 0x75, 0x55, 0x75, 0x57, 0x77, 0x59, 0x79, + + 0x59, 0x5A, 0x7A, 0x5A, 0x7A, 0x5A, 0x7A, 0x00, /* 17F */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19F */ + + 0x4F, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + + 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1BF */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x61, 0x49, + + 0x69, 0x4F, 0x6F, 0x55, 0x75, 0xDC, 0xFC, 0xDC, + + 0xFC, 0xDC, 0xFC, 0xDC, 0xFC, 0x00, 0xC4, 0xE4 /* 1DF */ + }; -static unsigned char combining_char[64] = { +static unsigned char combining_char[8*36] = { 0x00, 0x01, 0x02, 0x03, 0x08, 0x0A, 0xFF, 0x27, - 0x00, 0x01, 0x02, 0x08, 0x00, 0x01, 0x02, 0x08, + 0x00, 0x01, 0x02, 0x08, 0x00, 0x01, 0x02, 0x08, /* CF */ 0xFF, 0x03, 0x00, 0x01, 0x02, 0x03, 0x08, 0xFF, - 0xFF, 0x00, 0x01, 0x02, 0x08, 0x01, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0x02, 0x08, 0x01, 0xFF, 0xFF, /* DF */ 0x00, 0x01, 0x02, 0x03, 0x08, 0x0A, 0xFF, 0x27, - 0x00, 0x01, 0x02, 0x08, 0x00, 0x01, 0x02, 0x08, + 0x00, 0x01, 0x02, 0x08, 0x00, 0x01, 0x02, 0x08, /* EF */ 0xFF, 0x03, 0x00, 0x01, 0x02, 0x03, 0x08, 0xFF, - 0xFF, 0x00, 0x01, 0x02, 0x08, 0x01, 0xFF, 0x08 + 0xFF, 0x00, 0x01, 0x02, 0x08, 0x01, 0xFF, 0x08, /* FF */ + + 0x04, 0x04, 0x06, 0x06, 0x28, 0x28, 0x01, 0x01, + + 0x02, 0x02, 0x07, 0x07, 0x0C, 0x0C, 0x0C, 0x0C, + + 0x00, 0x00, 0x04, 0x04, 0x06, 0x06, 0x07, 0x07, + + 0x28, 0x28, 0x0C, 0x0C, 0x02, 0x02, 0x06, 0x06, + + 0x07, 0x07, 0x27, 0x27, 0x02, 0x02, 0x00, 0x00, + + 0x03, 0x03, 0x04, 0x04, 0x06, 0x06, 0x28, 0x28, + + 0x07, 0x00, 0x00, 0x00, 0x02, 0x02, 0x27, 0x27, + + 0x00, 0x01, 0x01, 0x27, 0x27, 0x0C, 0x0C, 0x00, /* 13F */ + + 0x00, 0x00, 0x00, 0x01, 0x01, 0x27, 0x27, 0x0C, + + 0x0C, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x06, + + 0x0B, 0x0B, 0x00, 0x00, 0x01, 0x01, 0x27, 0x27, + + 0x0C, 0x0C, 0x01, 0x01, 0x02, 0x02, 0x27, 0x27, + + 0x0C, 0x0C, 0x27, 0x27, 0x0C, 0x0C, 0x00, 0x00, + + 0x03, 0x03, 0x04, 0x04, 0x06, 0x06, 0x0A, 0x0A, /* 16F */ + + 0x0B, 0x0B, 0x28, 0x28, 0x02, 0x02, 0x02, 0x02, + + 0x08, 0x01, 0x01, 0x07, 0x07, 0x0C, 0x0C, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 17F */ + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 19F */ + + 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, + + 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x0C, /* 1CF */ + + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x01, + + 0x01, 0x0C, 0x0C, 0x00, 0x00, 0x00, 0x04, 0x04 /* 1DF */ }; +/* CYRILLIC codepoints 0x0400 ~ 0x04FF */ +static const unsigned long __CyrillicDecompBitmap[] = { + 0x40000040, 0x00000040, 0x00004000, 0x00000000, /* 0x0400 */ + 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* 0x0480 */ +}; + /* CJK codepoints 0x3000 ~ 0x30FF */ static const unsigned long __CJKDecompBitmap[] = { 0x00000000, 0x00000000, 0x000AAAAA, 0xA540DB6C, /* 0x3000 */ @@ -358,7 +525,7 @@ static const unsigned long __CJKDecompBitmap[] = { * composed character into its correct decomposed * sequence. * - * Currently only MacRoman and MacJapanese chars + * Currently only Tier-1 and Tier-2 languages * are handled. Other composed characters are * passed unchanged. */ @@ -367,46 +534,82 @@ ucs_decompose(register u_int16_t ch, u_int16_t *cmb) { u_int16_t base; - *cmb = 0; + cmb[0] = 0; + cmb[1] = 0; - if ((ch <= 0x00FF) && (ch >= 0x00C0)) { - ch -= 0x00C0; + if (ch < 0x00C0) { + base = ch; + } else if (ch <= 0x01DF) { - base = (u_int16_t) primary_char[ch]; - - if (base <= 'z') { - *cmb = (u_int16_t)0x0300 + (u_int16_t)combining_char[ch]; + base = (u_int16_t) primary_char[ch - 0x00C0]; + + if (base == 0) + base = ch; + else { + if ((base < 0x00C0) || (primary_char[base - 0x00C0] == 0)) + cmb[0] = (u_int16_t)0x0300 + (u_int16_t)combining_char[ch - 0x00C0]; + else { + u_int16_t tch = base; + + base = (u_int16_t)primary_char[tch - 0x00C0]; + cmb[0] = (u_int16_t)0x0300 + (u_int16_t)combining_char[tch - 0x00C0]; + cmb[1] = (u_int16_t)0x0300 + (u_int16_t)combining_char[ch - 0x00C0]; + } + } + } else if ((ch >= 0x0400) && (ch <= 0x04FF) && + IS_DECOMPOSABLE(__CyrillicDecompBitmap, ch - 0x0400)) { + + /* Handle CYRILLIC LETTERs */ + switch(ch) { + case 0x0401: base = 0x0415; cmb[0] = 0x0308; break; /* */ + case 0x0419: base = 0x0418; cmb[0] = 0x0306; break; /* */ + case 0x0439: base = 0x0438; cmb[0] = 0x0306; break; /* */ + case 0x0451: base = 0x0435; cmb[0] = 0x0308; break; /* */ + + default: + /* Should not be hit from bit map table */ + base = ch; } + } else if (ch == 0x1E3F) { + base = 0x006D; cmb[0] = 0x0301; /* LATIN SMALL LETTER M WITH ACUTE */ } else if ((ch > 0x3000) && (ch < 0x3100) && IS_DECOMPOSABLE(__CJKDecompBitmap, ch - 0x3000)) { - + /* Handle HIRAGANA LETTERs */ switch(ch) { - case 0x3071: base = 0x306F; *cmb = 0x309A; break; /* PA */ - case 0x3074: base = 0x3072; *cmb = 0x309A; break; /* PI */ - case 0x3077: base = 0x3075; *cmb = 0x309A; break; /* PU */ - case 0x307A: base = 0x3078; *cmb = 0x309A; break; /* PE */ - - case 0x307D: base = 0x307B; *cmb = 0x309A; break; /* PO */ - case 0x3094: base = 0x3046; *cmb = 0x3099; break; /* VU */ - case 0x30D1: base = 0x30CF; *cmb = 0x309A; break; /* PA */ - case 0x30D4: base = 0x30D2; *cmb = 0x309A; break; /* PI */ - - case 0x30D7: base = 0x30D5; *cmb = 0x309A; break; /* PU */ - case 0x30DA: base = 0x30D8; *cmb = 0x309A; break; /* PE */ - case 0x30DD: base = 0x30DB; *cmb = 0x309A; break; /* PO */ - case 0x30F4: base = 0x30A6; *cmb = 0x3099; break; /* VU */ - - case 0x30F7: base = 0x30EF; *cmb = 0x3099; break; /* VA */ - case 0x30F8: base = 0x30F0; *cmb = 0x3099; break; /* VI */ - case 0x30F9: base = 0x30F1; *cmb = 0x3099; break; /* VE */ - case 0x30FA: base = 0x30F2; *cmb = 0x3099; break; /* VO */ + case 0x3071: base = 0x306F; cmb[0] = 0x309A; break; /* PA */ + case 0x3074: base = 0x3072; cmb[0] = 0x309A; break; /* PI */ + case 0x3077: base = 0x3075; cmb[0] = 0x309A; break; /* PU */ + case 0x307A: base = 0x3078; cmb[0] = 0x309A; break; /* PE */ + + case 0x307D: base = 0x307B; cmb[0] = 0x309A; break; /* PO */ + case 0x3094: base = 0x3046; cmb[0] = 0x3099; break; /* VU */ + case 0x30D1: base = 0x30CF; cmb[0] = 0x309A; break; /* PA */ + case 0x30D4: base = 0x30D2; cmb[0] = 0x309A; break; /* PI */ + + case 0x30D7: base = 0x30D5; cmb[0] = 0x309A; break; /* PU */ + case 0x30DA: base = 0x30D8; cmb[0] = 0x309A; break; /* PE */ + case 0x30DD: base = 0x30DB; cmb[0] = 0x309A; break; /* PO */ + case 0x30F4: base = 0x30A6; cmb[0] = 0x3099; break; /* VU */ + + case 0x30F7: base = 0x30EF; cmb[0] = 0x3099; break; /* VA */ + case 0x30F8: base = 0x30F0; cmb[0] = 0x3099; break; /* VI */ + case 0x30F9: base = 0x30F1; cmb[0] = 0x3099; break; /* VE */ + case 0x30FA: base = 0x30F2; cmb[0] = 0x3099; break; /* VO */ default: /* the rest (41 of them) have a simple conversion */ base = ch - 1; - *cmb = 0x3099; + cmb[0] = 0x3099; } + } else if ((ch >= 0xAC00) && (ch < 0xD7A4)) { + /* Hangul */ + ch -= 0xAC00; + base = 0x1100 + (ch / (21*28)); + cmb[0] = 0x1161 + (ch % (21*28)) / 28; + + if (ch % 28) + cmb[1] = 0x11A7 + (ch % 28); } else { base = ch; } @@ -414,3 +617,270 @@ ucs_decompose(register u_int16_t ch, u_int16_t *cmb) return (base); } + +static const short diacrit_tbl[8*6] = { + /* 300 - 307 */ 0, 58, 116, 174, 232, -1, 290, 348, + /* 308 - 30F */ 406, -1, 464, 522, 580, -1, -1, -1, + /* 310 - 317 */ -1, -1, -1, -1, -1, -1, -1, -1, + /* 318 - 31F */ -1, -1, -1, 638, -1, -1, -1, -1, + /* 320 - 327 */ -1, -1, -1, -1, -1, -1, -1, 696, + /* 328 - 32F */ 754, -1, -1, -1, -1, -1, -1, -1 +}; + +static const u_int16_t composite_tbl[58*14] = { + /* + * A B C D E F G H I J K L M + * N O P Q R S T U V W X Y Z + * [ \ ] ^ _ ` + * a b c d e f g h i j k l m + * n o p q r s t u v w x y z + */ + + /* + * 0x300 - grave accent + */ + 0x0C0, 0, 0, 0,0x0C8, 0, 0, 0,0x0CC, 0, 0, 0, 0, + 0,0x0D2, 0, 0, 0, 0, 0,0x0D9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x0E0, 0, 0, 0,0x0E8, 0, 0, 0,0x0EC, 0, 0, 0, 0, + 0,0x0F2, 0, 0, 0, 0, 0,0x0F9, 0, 0, 0, 0, 0, + /* + * 0x301 - acute accent + */ + 0x0C1, 0,0x106, 0,0x0C9, 0, 0, 0,0x0CD, 0, 0,0x139, 0, + 0x143,0x0D3, 0, 0,0x154,0x15A, 0,0x0DA, 0, 0, 0,0x0DD,0x179, + 0, 0, 0, 0, 0, 0, + 0x0E1, 0,0x107, 0,0x0E9, 0, 0, 0,0x0ED, 0, 0,0x13A,0x1E3F, + 0x144,0x0F3, 0, 0,0x155,0x15B, 0,0x0FA, 0, 0, 0,0x0FD,0x17A, + /* + * 0x302 - circumflex accent + */ + 0x0C2, 0,0x108, 0,0x0CA, 0,0x11C,0x124,0x0CE,0x134, 0, 0, 0, + 0,0x0D4, 0, 0, 0,0x15C, 0,0x0DB, 0,0x174, 0,0x176, 0, + 0, 0, 0, 0, 0, 0, + 0x0E2, 0,0x109, 0,0x0EA, 0,0x11D,0x125,0x0EE,0x135, 0, 0, 0, + 0,0x0F4, 0, 0, 0,0x15D, 0,0x0FB, 0,0x175, 0,0x177, 0, + /* + * 0x303 - tilde + */ + 0x0C3, 0, 0, 0, 0, 0, 0, 0,0x128, 0, 0, 0, 0, + 0x0D1,0x0D5, 0, 0, 0, 0, 0,0x168, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x0E3, 0, 0, 0, 0, 0, 0, 0,0x129, 0, 0, 0, 0, + 0x0F1,0x0F5, 0, 0, 0, 0, 0,0x169, 0, 0, 0, 0, 0, + /* + * 0x304 - macron + */ + 0x100, 0, 0, 0,0x112, 0, 0, 0,0x12A, 0, 0, 0, 0, + 0,0x14C, 0, 0, 0, 0, 0,0x16A, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x101, 0, 0, 0,0x113, 0, 0, 0,0x12B, 0, 0, 0, 0, + 0,0x14D, 0, 0, 0, 0, 0,0x16B, 0, 0, 0, 0, 0, + /* + * 0x306 - breve + */ + 0x102, 0, 0, 0,0x114, 0,0x11E, 0,0x12C, 0, 0, 0, 0, + 0,0x14E, 0, 0, 0, 0, 0,0x16C, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x103, 0, 0, 0,0x115, 0,0x11F, 0,0x12D, 0, 0, 0, 0, + 0,0x14F, 0, 0, 0, 0, 0,0x16D, 0, 0, 0, 0, 0, + /* + * 0x307 - dot above + */ + 0, 0,0x10A, 0,0x116, 0,0x120, 0,0x130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x17B, + 0, 0, 0, 0, 0, 0, + 0, 0,0x10B, 0,0x117, 0,0x121, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x17C, + /* + * 0x308 - diaeresis + */ + 0x0C4, 0, 0, 0,0x0CB, 0, 0, 0,0x0CF, 0, 0, 0, 0, + 0,0x0D6, 0, 0, 0, 0, 0,0x0DC, 0, 0, 0,0x178, 0, + 0, 0, 0, 0, 0, 0, + 0x0E4, 0, 0, 0,0x0EB, 0, 0, 0,0x0EF, 0, 0, 0, 0, + 0,0x0F6, 0, 0, 0, 0, 0,0x0FC, 0, 0, 0,0x0FF, 0, + /* + * 0x30A - ring above + */ + 0x0C5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0x16E, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x0E5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0x16F, 0, 0, 0, 0, 0, + /* + * 0x30B - double aute accent + */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x150, 0, 0, 0, 0, 0,0x170, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x151, 0, 0, 0, 0, 0,0x171, 0, 0, 0, 0, 0, + /* + * 0x30C - caron + */ + 0x1CD, 0,0x10C,0x10E,0x11A, 0, 0, 0,0x1CF, 0, 0,0x13D, 0, + 0x147,0x1D1, 0, 0,0x158,0x160,0x164,0x1D3, 0, 0, 0, 0,0x17D, + 0, 0, 0, 0, 0, 0, + 0x1CE, 0,0x10D,0x10F,0x11B, 0, 0, 0,0x1D0, 0, 0,0x13E, 0, + 0x148,0x1D2, 0, 0,0x159,0x161,0x165,0x1D4, 0, 0, 0, 0,0x17E, + /* + * 0x31B - horn + */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x1A0, 0, 0, 0, 0, 0,0x1AF, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,0x1A1, 0, 0, 0, 0, 0,0x1B0, 0, 0, 0, 0, 0, + /* + * 0x327 - cedilla + */ + 0, 0,0x0C7, 0, 0, 0,0x122, 0, 0, 0,0x136,0x13B, 0, + 0x145, 0, 0, 0,0x156,0x15E,0x162, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0,0x0E7, 0, 0, 0,0x123, 0, 0, 0,0x137,0x13C, 0, + 0x146, 0, 0, 0,0x157,0x15F,0x163, 0, 0, 0, 0, 0, 0, + /* + * 0x328 - ogonek + */ + 0x104, 0, 0, 0,0x118, 0, 0, 0,0x12E, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0x172, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0x105, 0, 0, 0,0x119, 0, 0, 0,0x12F, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,0x173, 0, 0, 0, 0, 0, +}; + + +/* CJK codepoints 0x3000 ~ 0x30FF */ +static const unsigned long __CJKCombBitmap[] = { + 0x00000000, 0x00000000, 0x02155555, 0x4A812490, /* 0x3000 */ + 0x00000004, 0x02155555, 0x4A812490, 0x0001E004, /* 0x3080 */ +}; +#define CAN_COMBINE(table,unicodeVal) \ + (table[(unicodeVal) / 32] & (1 << (31 - ((unicodeVal) % 32)))) + + +/* + * ucs_combine - generate a precomposed UCS-2 char + * + * Precomposed Unicode characters are required for some volume + * formats and network protocols. ucs_combine will combine a + * decomposed character sequence into a single precomposed + * (composite) character. + * + * Currently only decomcomposed sequences from Apple's Tier 1 + * and Tier 2 languages are handled. + * + * INPUT: + * base - base character + * comb - combining character + * OUTPUT: + * result - precomposed char or zero if not combinable + */ +static u_int16_t +ucs_combine(u_int16_t base, u_int16_t comb) +{ + /* Get out early if we can */ + if (comb < 0x0300) + return (0); + + /* Try ordinary diacritics (0x300 - 0x32F) */ + if (comb <= 0x032F) { + int index; + + if (base >= 'A' && base <= 'z') { + index = diacrit_tbl[comb - 0x0300]; + if (index < 0 ) return (0); + + return (composite_tbl[index + (base - 'A')]); + } + + /* Handle Cyrillic and some 3 char latin sequences */ + switch (comb) { + case 0x0300: + switch (base) { + case 0x00DC: return (0x01DB); + case 0x00FC: return (0x01DC); + } break; + case 0x0301: + switch (base) { + case 0x00DC: return (0x01D7); + case 0x00FC: return (0x01D8); + } break; + case 0x0304: + switch (base) { + case 0x00DC: return (0x01D5); + case 0x00FC: return (0x01D6); + case 0x00C4: return (0x01DE); + case 0x00E4: return (0x01DF); + } break; + case 0x0306: + switch (base) { + case 0x0418: return (0x0419); + case 0x0438: return (0x0439); + } break; + case 0x0308: + switch (base) { + case 0x0415: return (0x0401); + case 0x0435: return (0x0451); + } break; + case 0x030C: + switch (base) { + case 0x00DC: return (0x01D9); + case 0x00FC: return (0x01DA); + } break; + } + return (0); + } + + /* Now try HANGUL */ + if (comb < 0x1161) + return (0); + + /* 2 char Hangul sequences */ + if ((comb <= 0x1175) && (base >= 0x1100 && base <= 0x1112)) + return (0xAC00 + ((base - 0x1100)*(21*28)) + ((comb - 0x1161)*28)); + + /* 3 char Hangul sequences */ + if ((comb >= 0x11A8 && comb <= 0x11C2) && + (base >= 0xAC00 && base <= 0xD788)) { + if ((base - 0xAC00) % 28) + return (0); + else + return (base + (comb - 0x11A7)); + } + + /* Now try HIRAGANA and KATAKANA */ + if ((comb == 0x3099 || comb == 0x309A) && + (base > 0x3000 && base < 0x3100) && + CAN_COMBINE(__CJKCombBitmap, base - 0x3000)) { + if (comb == 0x309A) { + switch(base) { + case 0x306F: return (0x3071); /* PA */ + case 0x3072: return (0x3074); /* PI */ + case 0x3075: return (0x3077); /* PU */ + case 0x3078: return (0x307A); /* PE */ + case 0x307B: return (0x307D); /* PO */ + case 0x30CF: return (0x30D1); /* PA */ + case 0x30D2: return (0x30D4); /* PI */ + case 0x30D5: return (0x30D7); /* PU */ + case 0x30D8: return (0x30DA); /* PE */ + case 0x30DB: return (0x30DD); /* PO */ + default: return (0); + } + } else /* 0x3099 */ { + switch (base) { + case 0x3046: return (0x3094); /* VU */ + case 0x30A6: return (0x30F4); /* VU */ + case 0x30EF: return (0x30F7); /* VA */ + case 0x30F0: return (0x30F8); /* VI */ + case 0x30F1: return (0x30F9); /* VE */ + case 0x30F2: return (0x30FA); /* VO */ + default: return (base + 1); /* 41 code points here */ + } + } + } + + return (0); +} + diff --git a/bsd/vfs/vfs_vnops.c b/bsd/vfs/vfs_vnops.c index 9c7b9d919..a16dfb167 100644 --- a/bsd/vfs/vfs_vnops.c +++ b/bsd/vfs/vfs_vnops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -59,9 +59,6 @@ * * @(#)vfs_vnops.c 8.14 (Berkeley) 6/15/95 * - * History - * 10-20-1997 Umesh Vaishampayan - * Fixed the count to be off_t rather than int. */ #include <sys/param.h> @@ -77,9 +74,6 @@ #include <sys/ioctl.h> #include <sys/tty.h> #include <sys/ubc.h> -#include <mach/kern_return.h> -#include <mach/memory_object_control.h> -#include <mach/vm_prot.h> struct fileops vnops = { vn_read, vn_write, vn_ioctl, vn_select, vn_closefile }; @@ -171,18 +165,28 @@ vn_open(ndp, fmode, cmode) if (fmode & O_TRUNC) { VOP_UNLOCK(vp, 0, p); /* XXX */ VOP_LEASE(vp, p, cred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ + (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); /* XXX */ VATTR_NULL(vap); vap->va_size = 0; if (error = VOP_SETATTR(vp, vap, cred, p)) goto bad; } - if (error = VOP_OPEN(vp, fmode, cred, p)) - goto bad; + +#if DIAGNOSTIC if (UBCINFOMISSING(vp)) - panic("vn_open: ubc_info_init"); - if (UBCINFOEXISTS(vp) && !ubc_hold(vp)) - panic("vn_open: hold"); + panic("vn_open: ubc_info_init"); +#endif /* DIAGNOSTIC */ + + if (UBCINFOEXISTS(vp) && !ubc_hold(vp)) { + error = ENOENT; + goto bad; + } + + if (error = VOP_OPEN(vp, fmode, cred, p)) { + ubc_rele(vp); + goto bad; + } + if (fmode & FWRITE) if (++vp->v_writecount <= 0) panic("vn_open: v_writecount"); @@ -223,9 +227,6 @@ vn_close(vp, flags, cred, p) struct proc *p; { int error; - vm_map_t user_map; - vm_offset_t addr, addr1; - vm_size_t size, pageoff; if (flags & FWRITE) vp->v_writecount--; @@ -256,7 +257,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, p) /* FIXME XXX */ if ((ioflg & IO_NODELOCKED) == 0) - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; aiov.iov_base = base; @@ -296,7 +297,7 @@ vn_read(fp, uio, cred) off_t count; VOP_LEASE(vp, p, cred, LEASE_READ); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); uio->uio_offset = fp->f_offset; count = uio->uio_resid; @@ -329,7 +330,7 @@ vn_write(fp, uio, cred) (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS))) ioflag |= IO_SYNC; VOP_LEASE(vp, p, cred, LEASE_WRITE); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + (void)vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); uio->uio_offset = fp->f_offset; count = uio->uio_resid; @@ -465,14 +466,15 @@ vn_ioctl(fp, com, data, p) /* * File table vnode select routine. */ -vn_select(fp, which, p) +vn_select(fp, which, wql, p) struct file *fp; int which; + void * wql; struct proc *p; { - return (VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, - fp->f_cred, p)); + return(VOP_SELECT(((struct vnode *)fp->f_data), which, fp->f_flag, + fp->f_cred, wql, p)); } /* @@ -494,7 +496,7 @@ vn_lock(vp, flags, p) while (vp->v_flag & VXLOCK) { vp->v_flag |= VXWANT; simple_unlock(&vp->v_interlock); - tsleep((caddr_t)vp, PINOD, "vn_lock", 0); + (void)tsleep((caddr_t)vp, PINOD, "vn_lock", 0); } error = ENOENT; } else { diff --git a/bsd/vfs/vnode_if.src b/bsd/vfs/vnode_if.src index 309b052b4..6fac8a143 100644 --- a/bsd/vfs/vnode_if.src +++ b/bsd/vfs/vnode_if.src @@ -251,6 +251,7 @@ vop_select { IN int which; IN int fflags; IN struct ucred *cred; + IN void * wql; IN struct proc *p; }; @@ -564,6 +565,7 @@ vop_allocate { IN off_t length; IN u_int32_t flags; OUT off_t *bytesallocated; + IN off_t offset; IN struct ucred *cred; IN struct proc *p; }; diff --git a/bsd/vm/dp_backing_file.c b/bsd/vm/dp_backing_file.c index 137e53eb6..359d95fd1 100644 --- a/bsd/vm/dp_backing_file.c +++ b/bsd/vm/dp_backing_file.c @@ -85,7 +85,7 @@ macx_swapon( register int error; kern_return_t kr; mach_port_t backing_store; - mach_port_t default_pager_port = MACH_PORT_NULL; + memory_object_default_t default_pager; int i; boolean_t funnel_state; @@ -156,7 +156,8 @@ macx_swapon( * Look to see if we are already paging to this file. */ /* make certain the copy send of kernel call will work */ - kr = host_default_memory_manager(host_priv_self(), &default_pager_port, 0); + default_pager = MEMORY_OBJECT_DEFAULT_NULL; + kr = host_default_memory_manager(host_priv_self(), &default_pager, 0); if(kr != KERN_SUCCESS) { error = EAGAIN; VOP_UNLOCK(vp, 0, p); @@ -164,10 +165,12 @@ macx_swapon( goto swapon_bailout; } - kr = default_pager_backing_store_create(default_pager_port, + kr = default_pager_backing_store_create(default_pager, -1, /* default priority */ 0, /* default cluster size */ &backing_store); + memory_object_default_deallocate(default_pager); + if(kr != KERN_SUCCESS) { error = ENOMEM; VOP_UNLOCK(vp, 0, p); diff --git a/bsd/vm/vm_unix.c b/bsd/vm/vm_unix.c index 41d4714bc..77d7d02dc 100644 --- a/bsd/vm/vm_unix.c +++ b/bsd/vm/vm_unix.c @@ -76,9 +76,22 @@ vslock(addr, len) caddr_t addr; int len; { - vm_map_wire(current_map(), trunc_page(addr), +kern_return_t kret; + kret = vm_map_wire(current_map(), trunc_page(addr), round_page(addr+len), VM_PROT_READ | VM_PROT_WRITE ,FALSE); + + switch (kret) { + case KERN_SUCCESS: + return (0); + case KERN_INVALID_ADDRESS: + case KERN_NO_SPACE: + return (ENOMEM); + case KERN_PROTECTION_FAILURE: + return (EACCES); + default: + return (EINVAL); + } } vsunlock(addr, len, dirtied) @@ -91,6 +104,7 @@ vsunlock(addr, len, dirtied) vm_page_t pg; #endif /* FIXME ] */ vm_offset_t vaddr, paddr; + kern_return_t kret; #if FIXME /* [ */ if (dirtied) { @@ -106,8 +120,19 @@ vsunlock(addr, len, dirtied) #ifdef lint dirtied++; #endif /* lint */ - vm_map_unwire(current_map(), trunc_page(addr), + kret = vm_map_unwire(current_map(), trunc_page(addr), round_page(addr+len), FALSE); + switch (kret) { + case KERN_SUCCESS: + return (0); + case KERN_INVALID_ADDRESS: + case KERN_NO_SPACE: + return (ENOMEM); + case KERN_PROTECTION_FAILURE: + return (EACCES); + default: + return (EINVAL); + } } #if defined(sun) || BALANCE || defined(m88k) @@ -195,39 +220,6 @@ swapon() return(EOPNOTSUPP); } -thread_t -procdup( - struct proc *child, - struct proc *parent) -{ - thread_t thread; - task_t task; - kern_return_t result; - - if (parent->task == kernel_task) - result = task_create_local(TASK_NULL, FALSE, FALSE, &task); - else - result = task_create_local(parent->task, TRUE, FALSE, &task); - if (result != KERN_SUCCESS) - printf("fork/procdup: task_create failed. Code: 0x%x\n", result); - child->task = task; - /* task->proc = child; */ - set_bsdtask_info(task, child); - result = thread_create(task, &thread); - if (result != KERN_SUCCESS) - printf("fork/procdup: thread_create failed. Code: 0x%x\n", result); - -#if FIXME /* [ */ - thread_deallocate(thread); // extra ref - - /* - * Don't need to lock thread here because it can't - * possibly execute and no one else knows about it. - */ - /* compute_priority(thread, FALSE); */ -#endif /* ] */ - return(thread); -} kern_return_t pid_for_task(t, x) @@ -238,7 +230,7 @@ pid_for_task(t, x) task_t t1; extern task_t port_name_to_task(mach_port_t t); int pid = -1; - kern_return_t err; + kern_return_t err = KERN_SUCCESS; boolean_t funnel_state; funnel_state = thread_funnel_set(kernel_flock, TRUE); @@ -246,6 +238,7 @@ pid_for_task(t, x) if (t1 == TASK_NULL) { err = KERN_FAILURE; + goto pftout; } else { p = get_bsdtask_info(t1); if (p) { @@ -256,8 +249,8 @@ pid_for_task(t, x) } } task_deallocate(t1); - (void) copyout((char *) &pid, (char *) x, sizeof(*x)); pftout: + (void) copyout((char *) &pid, (char *) x, sizeof(*x)); thread_funnel_set(kernel_flock, funnel_state); return(err); } @@ -289,8 +282,7 @@ task_for_pid(target_tport, pid, t) t1 = port_name_to_task(target_tport); if (t1 == TASK_NULL) { (void ) copyout((char *)&t1, (char *)t, sizeof(mach_port_t)); - error = KERN_FAILURE; - goto tfpout; + return(KERN_FAILURE); } funnel_state = thread_funnel_set(kernel_flock, TRUE); @@ -338,6 +330,7 @@ struct load_shared_file_args { int *flags; }; +int ws_disabled = 1; int load_shared_file( @@ -359,8 +352,7 @@ load_shared_file( kern_return_t kr; struct vattr vattr; - void *object; - void *file_object; + memory_object_control_t file_control; sf_mapping_t *map_list; caddr_t local_base; int local_flags; @@ -434,8 +426,8 @@ load_shared_file( } - file_object = ubc_getobject(vp, (UBC_NOREACTIVATE|UBC_HOLDOBJECT)); - if (file_object == (void *)NULL) { + file_control = ubc_getobject(vp, UBC_HOLDOBJECT); + if (file_control == MEMORY_OBJECT_CONTROL_NULL) { error = EINVAL; goto lsf_bailout_free_vput; } @@ -551,7 +543,7 @@ load_shared_file( if((kr = copyin_shared_file((vm_offset_t)mapped_file_addr, mapped_file_size, (vm_offset_t *)&local_base, - map_cnt, map_list, file_object, + map_cnt, map_list, file_control, &task_mapping_info, &local_flags))) { switch (kr) { case KERN_FAILURE: @@ -575,7 +567,7 @@ load_shared_file( error = EINVAL; }; if((caller_flags & ALTERNATE_LOAD_SITE) && systemLogDiags) { - printf("load_shared_file: Failed to load shared file! error: 0x%x, Base_address: 0x%x, number of mappings: %d, file_object 0x%x\n", error, local_base, map_cnt, file_object); + printf("load_shared_file: Failed to load shared file! error: 0x%x, Base_address: 0x%x, number of mappings: %d, file_control 0x%x\n", error, local_base, map_cnt, file_control); for(i=0; i<map_cnt; i++) { printf("load_shared_file: Mapping%d, mapping_offset: 0x%x, size: 0x%x, file_offset: 0x%x, protection: 0x%x\n" , i, map_list[i].mapping_offset, diff --git a/bsd/vm/vnode_pager.c b/bsd/vm/vnode_pager.c index 6500724f2..dede2616d 100644 --- a/bsd/vm/vnode_pager.c +++ b/bsd/vm/vnode_pager.c @@ -66,6 +66,17 @@ unsigned int vp_pgoclean=0; unsigned int dp_pgouts=0; /* Default pager pageouts */ unsigned int dp_pgins=0; /* Default pager pageins */ +vm_object_offset_t +vnode_pager_get_filesize(struct vnode *vp) +{ + if (UBCINVALID(vp)) { + return (vm_object_offset_t) 0; + } + + return (vm_object_offset_t) ubc_getsize(vp); + +} + pager_return_t vnode_pageout(struct vnode *vp, upl_t upl, @@ -86,9 +97,8 @@ vnode_pageout(struct vnode *vp, struct buf *bp; boolean_t funnel_state; int haveupl=0; - void * object; upl_page_info_t *pl; - upl_t vpupl; + upl_t vpupl = NULL; funnel_state = thread_funnel_set(kernel_flock, TRUE); @@ -122,20 +132,16 @@ vnode_pageout(struct vnode *vp, } goto out; } - - object = ubc_getobject(vp, UBC_PAGINGOP|UBC_NOREACTIVATE); - if (object == NULL) - panic("vnode_pageout: null object"); - vp_size = ubc_getsize(vp); - - vm_fault_list_request(object, - f_offset, isize, &vpupl, NULL, 0, - UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_COPYOUT_FROM | UPL_SET_INTERNAL); + ubc_create_upl( vp, + f_offset, + isize, + &vpupl, + &pl, + UPL_COPYOUT_FROM); if (vpupl == (upl_t) 0) - panic("vnode_pageout: null upl returned"); - - pl = UPL_GET_INTERNAL_PAGE_LIST(vpupl); + return PAGER_ABSENT; + vp_size = ubc_getsize(vp); if (vp_size == 0) { while (isize) { @@ -156,8 +162,7 @@ start0: f_offset += PAGE_SIZE; isize -= PAGE_SIZE; } - kernel_upl_commit_range(vpupl, 0, size, UPL_COMMIT_FREE_ON_EMPTY, - pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(vpupl, 0, size, UPL_COMMIT_FREE_ON_EMPTY); error = 0; goto out; @@ -170,7 +175,8 @@ start0: int num_of_pages; if ( !upl_valid_page(pl, pg_index)) { - kernel_upl_abort_range(vpupl, offset, PAGE_SIZE, UPL_ABORT_FREE_ON_EMPTY); + ubc_upl_abort_range(vpupl, offset, PAGE_SIZE, + UPL_ABORT_FREE_ON_EMPTY); offset += PAGE_SIZE; isize -= PAGE_SIZE; @@ -205,8 +211,8 @@ start: if (bp) brelse(bp); - kernel_upl_commit_range(vpupl, offset, PAGE_SIZE, - UPL_COMMIT_FREE_ON_EMPTY, pl, MAX_UPL_TRANSFER); + ubc_upl_commit_range(vpupl, offset, PAGE_SIZE, + UPL_COMMIT_FREE_ON_EMPTY); offset += PAGE_SIZE; isize -= PAGE_SIZE; @@ -263,10 +269,11 @@ vnode_pagein( int result = PAGER_SUCCESS; struct proc *p = current_proc(); int error = 0; + int xfer_size; boolean_t funnel_state; int haveupl=0; - void * object; - upl_t vpupl; + upl_t vpupl = NULL; + off_t local_offset; unsigned int ioaddr; funnel_state = thread_funnel_set(kernel_flock, TRUE); @@ -295,22 +302,36 @@ vnode_pagein( } } else { - object = ubc_getobject(vp, UBC_PAGINGOP|UBC_NOREACTIVATE); - if (object == (void *)NULL) - panic("vnode_pagein: null object"); - vm_fault_list_request(object, f_offset, size, &vpupl, NULL, 0, - UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL); - - if (vpupl == (upl_t) 0) - panic("vnode_pagein: null upl returned"); + local_offset = 0; + while (size) { + if((size > 4096) && (vp->v_tag == VT_NFS)) { + xfer_size = 4096; + size = size - xfer_size; + } else { + xfer_size = size; + size = 0; + } + ubc_create_upl( vp, + f_offset+local_offset, + xfer_size, + &vpupl, + NULL, + UPL_FLAGS_NONE); + if (vpupl == (upl_t) 0) { + result = PAGER_ABSENT; + error = PAGER_ABSENT; + goto out; + } - vp_pagein++; + vp_pagein++; - /* By defn callee will commit or abort upls */ - if (error = VOP_PAGEIN(vp, vpupl, (vm_offset_t) 0, - (off_t)f_offset, size,p->p_ucred, flags & ~UPL_NOCOMMIT)) { - result = PAGER_ERROR; - error = PAGER_ERROR; + /* By defn callee will commit or abort upls */ + if (error = VOP_PAGEIN(vp, vpupl, (vm_offset_t) 0, + (off_t)f_offset+local_offset, xfer_size,p->p_ucred, flags & ~UPL_NOCOMMIT)) { + result = PAGER_ERROR; + error = PAGER_ERROR; + } + local_offset += PAGE_SIZE_64; } } out: @@ -342,10 +363,10 @@ vnode_pager_shutdown() } } -void * + +void * upl_get_internal_page_list(upl_t upl) { - return(UPL_GET_INTERNAL_PAGE_LIST(upl)); + return(UPL_GET_INTERNAL_PAGE_LIST(upl)); } - diff --git a/bsd/vm/vnode_pager.h b/bsd/vm/vnode_pager.h index aaa8146a2..45b21e9fb 100644 --- a/bsd/vm/vnode_pager.h +++ b/bsd/vm/vnode_pager.h @@ -38,8 +38,6 @@ #include <mach/boolean.h> #include <vm/vm_pager.h> -void vnode_pager_init(); - vm_pager_t vnode_pager_setup(); boolean_t vnode_has_page(); boolean_t vnode_pager_active(); diff --git a/iokit/Drivers/ata/drvApplePIIXATA/AppleATAPIIX.cpp b/iokit/Drivers/ata/drvApplePIIXATA/AppleATAPIIX.cpp index fab734b9c..a8a659a8e 100644 --- a/iokit/Drivers/ata/drvApplePIIXATA/AppleATAPIIX.cpp +++ b/iokit/Drivers/ata/drvApplePIIXATA/AppleATAPIIX.cpp @@ -336,7 +336,7 @@ AppleATAPIIX::configure(IOService * forProvider, // IOSleep(1000); - provider = OSDynamicCast(IOPCIDevice, forProvider); + provider = (IOPCIDevice *)forProvider->metaCast("IOPCIDevice"); if (!provider) return false; diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.cpp b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.cpp deleted file mode 100644 index b0c7168f7..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include "AppleADBButtons.h" -#include "AppleADBKeyboard.h" -#include <IOKit/IOLib.h> -#include <IOKit/pwr_mgt/IOPM.h> -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOHIDParameter.h> - -#define super IOHIKeyboard -OSDefineMetaClassAndStructors(AppleADBButtons,IOHIKeyboard) - -bool displayWranglerFound( OSObject *, void *, IOService * ); -void button_data ( IOService * us, UInt8 adbCommand, IOByteCount length, UInt8 * data ); -void asyncFunc ( void * ); - -// ********************************************************************************** -// start -// -// ********************************************************************************** -bool AppleADBButtons::start ( IOService * theNub ) -{ - int i; - - for ( i = 0; i < kMax_registrations; i++ ) { - keycodes[i] = kNullKey; - downHandlers[i] = NULL; - } - - adbDevice = (IOADBDevice *)theNub; - - if( !super::start(theNub)) - return false; - - if( !adbDevice->seizeForClient(this, button_data) ) { - IOLog("%s: Seize failed\n", getName()); - return false; - } - - addNotification( gIOPublishNotification,serviceMatching("IODisplayWrangler"), // look for the display wrangler - (IOServiceNotificationHandler)displayWranglerFound, this, 0 ); - _initial_handler_id = adbDevice->handlerID(); - -return true; -} - -UInt64 AppleADBButtons::getGUID() -{ - return(kAppleOnboardGUID); -} - -// ********************************************************************************** -// displayWranglerFound -// -// The Display Wrangler has appeared. We will be calling its -// ActivityTickle method when there is user activity. -// ********************************************************************************** -bool displayWranglerFound( OSObject * us, void * ref, IOService * yourDevice ) -{ - if ( yourDevice != NULL ) { - ((AppleADBButtons *)us)->displayManager = yourDevice; - } - return true; -} - -UInt32 AppleADBButtons::interfaceID() -{ - return NX_EVS_DEVICE_INTERFACE_ADB; -} - -UInt32 AppleADBButtons::deviceType() -{ - //if initial id is 31 then this is a post-WallStreet PowerBook, so - //look for a AppleADBKeyboard driver and return the handler ID from it. - //Note though that the ADB keyboard driver may not exist. - if (_initial_handler_id == 31) - { - mach_timespec_t t; - AppleADBKeyboard *adbkeyboard; - - t.tv_sec = 2; - t.tv_nsec = 0; - adbkeyboard = (AppleADBKeyboard *)waitForService(serviceMatching("AppleADBKeyboard"), &t); - if (adbkeyboard) - { - return adbkeyboard->deviceType(); - } - - } - - return adbDevice->handlerID(); -} - -// ********************************************************************************** -// registerForButton -// -// Clients call here, specifying a button and a routine to call when that -// button is pressed or released. -// ********************************************************************************** -IOReturn AppleADBButtons::registerForButton ( unsigned int keycode, IOService * registrant, button_handler handler, bool down ) -{ - int i; - - for ( i = 0; i < kMax_registrations; i++ ) { - if ( keycodes[i] == kNullKey ) { - if ( down ) { - registrants[i] = registrant; - downHandlers[i] = handler; - keycodes[i] = keycode; - break; - } - } - } - return kIOReturnSuccess; -} - -// ********************************************************************************** -// button_data -// -// ********************************************************************************** -void button_data ( IOService * us, UInt8 adbCommand, IOByteCount length, UInt8 * data ) -{ -((AppleADBButtons *)us)->packet(data,length,adbCommand); -} - - -// ********************************************************************************** -// packet -// -// ********************************************************************************** -IOReturn AppleADBButtons::packet (UInt8 * data, IOByteCount, UInt8 adbCommand ) -{ - unsigned int keycode; - bool down; - - keycode = *data; - down = ((keycode & 0x80) == 0); - keycode &= 0x7f; - dispatchButtonEvent(keycode,down); - - keycode = *(data + 1); - if( keycode != 0xff ) { - down = ((keycode & 0x80) == 0); - keycode &= 0x7f; - dispatchButtonEvent(keycode,down); - } - - if ( displayManager != NULL ) { // if there is a display manager, tell - displayManager->activityTickle(kIOPMSuperclassPolicy1); // it there is user activity - } - - return kIOReturnSuccess; -} - - -// ********************************************************************************** -// dispatchButtonEvent -// -// Look for any registered handlers for this button and notify them. -// ********************************************************************************** -void AppleADBButtons::dispatchButtonEvent (unsigned int keycode, bool down ) -{ - int i; - AbsoluteTime now; - - if (_initial_handler_id == 0xc0) //For Apple ADB AV and ColorSync monitors - { - switch (keycode) - { - case kVolume_up_AV: - keycode = kVolume_up; - break; - case kVolume_down_AV: - keycode = kVolume_down; - break; - case kMute_AV: - keycode = kMute; - break; - default: - //No other volume codes are available for OS X - break; - } - } - - clock_get_uptime(&now); - - for ( i = 0; i < kMax_registrations; i++ ) { - if ( keycodes[i] == keycode ) { - if ( down ) { - if (downHandlers[i] != NULL ) { - thread_call_func((thread_call_func_t)downHandlers[i], - (thread_call_param_t)registrants[i], - true); - } - } - } - } - - //Only dispatch keycodes that this driver understands. - // See appleADBButtonsKeyMap[] for the list. - switch (keycode) - { - case kVolume_up: - case kVolume_down: - case kMute: - case kEject: - case kBrightness_up: - case kBrightness_down: - case kNum_lock_on_laptops: - dispatchKeyboardEvent(keycode, down, now); - break; - default: //Don't dispatch anything else - break; - } -} - -const unsigned char *AppleADBButtons::defaultKeymapOfLength(UInt32 *length) -{ - static const unsigned char appleADBButtonsKeyMap[] = { - 0x00, 0x00, // chars - 0x00, // no modifier keys - 0x00, // no defs - 0x00, // no seqs - 0x07, // 6 special keys - NX_KEYTYPE_SOUND_UP, kVolume_up, - NX_KEYTYPE_SOUND_DOWN, kVolume_down, - NX_KEYTYPE_MUTE, kMute, - NX_KEYTYPE_BRIGHTNESS_UP, kBrightness_up, - NX_KEYTYPE_BRIGHTNESS_DOWN, kBrightness_down, - NX_KEYTYPE_NUM_LOCK, kNum_lock_on_laptops, - NX_KEYTYPE_EJECT, kEject - }; - - *length = sizeof(appleADBButtonsKeyMap); - - return appleADBButtonsKeyMap; -} - -IOReturn AppleADBButtons::setParamProperties(OSDictionary *dict) -{ - dict->removeObject(kIOHIDKeyMappingKey); - - return super::setParamProperties(dict); -} diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h deleted file mode 100644 index 467ea3a25..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _APPLEADBBUTTONS_H -#define _APPLEADBBUTTONS_H - -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/hidsystem/IOHIKeyboard.h> -#include <IOKit/adb/IOADBDevice.h> - -#define kVolume_up 0x06 -#define kVolume_down 0x07 -#define kMute 0x08 -#define kVolume_up_AV 0x03 //Apple ADB AV monitors have different button codes -#define kVolume_down_AV 0x02 -#define kMute_AV 0x01 -#define kBrightness_up 0x09 -#define kBrightness_down 0x0a -#define kEject 0x0b -#define kNum_lock_on_laptops 0x7f - -#define kMax_registrations 10 -#define kMax_keycode 0x0a -#define kNullKey 0xFF - -typedef void (*button_handler)(void * ); - -class AppleADBButtons : public IOHIKeyboard -{ - OSDeclareDefaultStructors(AppleADBButtons) - -private: - - unsigned int keycodes[kMax_registrations]; - void * registrants[kMax_registrations]; - button_handler downHandlers[kMax_registrations]; - - void dispatchButtonEvent (unsigned int, bool ); - UInt32 _initial_handler_id; - -public: - - const unsigned char * defaultKeymapOfLength (UInt32 * length ); - UInt32 interfaceID(); - UInt32 deviceType(); - UInt64 getGUID(); - -public: - - IOService * displayManager; // points to display manager - IOADBDevice * adbDevice; - - bool start ( IOService * theNub ); - IOReturn packet (UInt8 * data, IOByteCount length, UInt8 adbCommand ); - IOReturn registerForButton ( unsigned int, IOService *, button_handler, bool ); - - IOReturn setParamProperties(OSDictionary *dict); -}; - -#endif /* _APPLEADBBUTTONS_H */ diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp deleted file mode 100644 index 1c064379f..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 23 Jul 98 - start IOKit - * suurballe 17 Nov 98 - ported to C++ - */ - -#include <assert.h> -#include <IOKit/IOLib.h> - -#include "AppleADBDisplay.h" - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IODisplay -OSDefineMetaClassAndStructors( AppleADBDisplay, IODisplay ) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn AppleADBDisplay::findADBDisplayInfoForType( UInt16 deviceType ) -{ - char stringBuf[ 32 ]; - OSNumber * off; - OSString * key; - OSData * data; - - sprintf( stringBuf, "adb%dWiggle", deviceType); - if( (off = OSDynamicCast( OSNumber, getProperty( stringBuf )))) - wiggleLADAddr = off->unsigned32BitValue(); - else - wiggleLADAddr = kWiggleLADAddr; - - sprintf( stringBuf, "adb%dModes", deviceType); - key = OSDynamicCast( OSString, getProperty( stringBuf )); - - if( key && (data = OSDynamicCast( OSData, getProperty( key )))) { - modeList = (UInt32 *) data->getBytesNoCopy(); - numModes = data->getLength() / sizeof( UInt32); - } - if( modeList ) - return(kIOReturnSuccess); - else - return( -49 ); -} - - -IOReturn AppleADBDisplay::getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ) -{ - IOReturn err; - IODisplayConnect * connect; - IOFramebuffer * framebuffer; - int timingNum; - IOTimingInformation info; - - *flags = 0; - - connect = getConnection(); - assert( connect ); - framebuffer = connect->getFramebuffer(); - assert( framebuffer ); - - err = framebuffer->getTimingInfoForDisplayMode( mode, &info ); - - if( kIOReturnSuccess == err) { - for( timingNum = 0; timingNum < numModes; timingNum++ ) { - if( info.appleTimingID == modeList[ timingNum ] ) { - *flags = timingNum - ? ( kDisplayModeValidFlag | kDisplayModeSafeFlag ) - : ( kDisplayModeValidFlag | kDisplayModeSafeFlag - | kDisplayModeDefaultFlag ); - break; - } - } - } - - return( err ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn AppleADBDisplay::doConnect( void ) -{ - IOReturn err; - UInt16 value; - UInt32 retries = 9; - IOByteCount length; - - while ( retries-- ) { - - value = 0x6000 | (adbDevice->address() << 8); - length = sizeof( value); - err = adbDevice->writeRegister( 3, (UInt8 *) &value, &length ); - if( err) - continue; - - /* IOSleep(10); */ - /* IODelay(1000); */ - length = sizeof( value); - err = adbDevice->readRegister( 3, (UInt8 *) &value, &length ); - if( err) - continue; - - if( (value & 0xf000) == 0x6000 ) - break; - else - err = kIOReturnNotAttached; - } - - if( err) - kprintf("%s: %d\n", __FUNCTION__, err); - - return(err); -} - -static void autoPollHandler( IOService * self, UInt8 adbCommand, - IOByteCount length, UInt8 * data ) -{ - ((AppleADBDisplay *)self)->packet( adbCommand, length, data ); -} - -void AppleADBDisplay::packet( UInt8 adbCommand, - IOByteCount length, UInt8 * data ) -{ - if( length && (*data == waitAckValue) ) - waitAckValue = 0; -} - -IOReturn AppleADBDisplay::writeWithAcknowledge( UInt8 regNum, - UInt16 data, UInt8 ackValue ) -{ - IOReturn err; - enum { kTimeoutMS = 400 }; - UInt32 timeout; - IOByteCount length; - - waitAckValue = ackValue; - - length = sizeof(data); - err = adbDevice->writeRegister( regNum, (UInt8 *) &data, &length ); - - if( !err) { - timeout = kTimeoutMS / 50; - while( waitAckValue && timeout-- ) - IOSleep( 50 ); - - if( waitAckValue ) - err = -3; - } - waitAckValue = 0; - - return( err ); -} - -IOReturn AppleADBDisplay::setLogicalRegister( UInt16 address, UInt16 data ) -{ - IOReturn err = -1; - UInt32 reconnects = 3; - - while( err && reconnects-- ) { - err = writeWithAcknowledge( kADBReg1, address, kReg2DataRdy); - if( err == kIOReturnSuccess ) - err = writeWithAcknowledge( kADBReg2, data, kReg2DataAck); - - if( err ) { - if( doConnect() ) - break; - } - } - if( err) - kprintf( "%s: %x, %d\n", __FUNCTION__, address, err); - - return( err); -} - -IOReturn AppleADBDisplay::getLogicalRegister( UInt16 address, UInt16 * data ) -{ - IOReturn err = -1; - UInt32 reconnects = 3; - UInt16 value; - IOByteCount length; - - while ( err && reconnects--) { - err = writeWithAcknowledge( kADBReg1, address, kReg2DataRdy); - if( err == kIOReturnSuccess ) { - length = sizeof( value); - err = adbDevice->readRegister( 2, (UInt8 *)&value, &length); - *data = value & 0xff; // actually only 8 bits - } - if( err) { - if ( doConnect()) - break; - } - } - if( err) - kprintf( "%s: %x=%x, %d\n", __FUNCTION__, address, *data, err); - - return err; -} - -void AppleADBDisplay::setWiggle( bool active ) -{ - setLogicalRegister( wiggleLADAddr, (active ? 1 : 0)); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool AppleADBDisplay::start( IOService * nub ) -{ - IOReturn err; - UInt16 data, deviceType; - - if( !super::start( nub)) - return false; - - if( OSDynamicCast( IODisplayConnect, nub )) - return( true ); - - assert( OSDynamicCast( IOADBDevice, nub )); - adbDevice = (IOADBDevice *) nub; - - if( !adbDevice->seizeForClient( this, &autoPollHandler) ) { - IOLog("%s: sieze failed\n", getName()); - return( false); - } - - do { - err = doConnect(); - if( err ) - continue; - - err = setLogicalRegister( 0xff, 0xff); - if( err) - continue; - - err = getLogicalRegister( 0xff, &data); - if( err) - continue; - - err = getLogicalRegister( 0xff, &deviceType); - if( err) - continue; - - kprintf("%s: found AVType %d\n", - adbDevice->getName(), deviceType ); - - err = findADBDisplayInfoForType( deviceType ); - if( err) - continue; - - avDisplayID = deviceType; - setWiggle( false); - - registerService(); - return( true ); - - } while( false ); - - adbDevice->releaseFromClient( this ); - return( false ); -} - - -bool AppleADBDisplay::tryAttach( IODisplayConnect * connect ) -{ - IOReturn err; - bool attached = false; - UInt32 sense, extSense; - IOFramebuffer * framebuffer; - IOIndex fbConnect; - UInt32 senseType; - enum { - kRSCFour = 4, - kRSCSix = 6, - kESCFourNTSC = 0x0A, - kESCSixStandard = 0x2B, - }; - - do { - - framebuffer = connect->getFramebuffer(); - fbConnect = connect->getConnection(); - assert( framebuffer ); - - if( kIOReturnSuccess != framebuffer->getAttributeForConnection( - fbConnect, - kConnectionSupportsAppleSense, NULL )) - continue; - - err = framebuffer->getAppleSense( fbConnect, - &senseType, &sense, &extSense, 0 ); - if( err) - continue; - if( (sense != kRSCSix) || (extSense != kESCSixStandard) ) // straight-6 - continue; - - setWiggle( true ); - err = framebuffer->getAppleSense( fbConnect, - &senseType, &sense, &extSense, 0 ); - setWiggle( false ); - if( err) - continue; - if( (sense != kRSCFour) || (extSense != kESCFourNTSC) ) // straight-4 - continue; - - kprintf( "%s: attached to %s\n", - adbDevice->getName(), framebuffer->getName() ); - - attached = true; - - } while( false); - - return( attached); -} - - -IOService * AppleADBDisplay::probe( IOService * nub, SInt32 * score ) -{ - IODisplayConnect * connect; - - // both ADB device & display connections come here! - - do { - if( OSDynamicCast( IOADBDevice, nub)) - continue; - - if( (connect = OSDynamicCast( IODisplayConnect, nub)) - && tryAttach( connect)) - continue; - - nub = 0; - - } while( false ); - - if( nub) - return( super::probe( nub, score )); - else - return( 0 ); -} - - - diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.h b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.h deleted file mode 100644 index 2c909182e..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 23 Jul 98 - start IOKit - * suurballe 17 Nov 98 - ported to C++ - */ - -#include <IOKit/adb/IOADBDevice.h> -#include <IOKit/graphics/IODisplay.h> - - -#define kOrgDisplayAddr 0x7 // Original display ADB address - -#define kTelecasterADBHandlerID 0x03 -#define kSmartDisplayADBHandlerID 0xc0 - -#define kADBReg0 0x0 // Device register zero -#define kADBReg1 0x1 // Device register one -#define kADBReg2 0x2 // Device register two -#define kADBReg3 0x3 // Device register three - -#define kReg2DataRdy 0xFD // data (to be read) ready -#define kReg2DataAck 0xFE // data (just written) OK -#define kWiggleLADAddr 0x04 // 0x0f on Telecaster & Sousa? - -#if 0 - -#define kNoDevice -1 -#define kTelecaster 0 -#define kSousaSoundUnit 1 -#define kHammerhead 2 -#define kOrca 3 -#define kWhaler 4 -#define kWarriorEZ 5 -#define kManta 6 -#define kLastDeviceType kManta - -#define kDisplayLocalRemoteLADAddr 0x02 // lad address used in SetDisplayRemoteMode -#define kAudioKeypadEnableLADAddr 0x7D - -#define kUnknown -1 -#define kLocal 0 -#define kRemote 1 - -#endif - -class AppleADBDisplay: public IODisplay -{ - OSDeclareDefaultStructors(AppleADBDisplay) - -private: - - IOADBDevice * adbDevice; - volatile UInt8 waitAckValue; - UInt8 wiggleLADAddr; - SInt16 avDisplayID; - int numModes; - UInt32 * modeList; - - virtual IOReturn findADBDisplayInfoForType( UInt16 deviceType ); - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ); - virtual IOReturn doConnect( void ); - virtual IOReturn writeWithAcknowledge( UInt8 regNum, UInt16 data, - UInt8 ackValue ); - virtual IOReturn setLogicalRegister( UInt16 address, UInt16 data ); - virtual IOReturn getLogicalRegister( UInt16 address, UInt16 * data ); - virtual void setWiggle( bool active ); - virtual bool tryAttach( IODisplayConnect * connect ); - -public: - - virtual bool start( IOService * nub ); - virtual IOService * probe( IOService * nub, SInt32 * score ); - - virtual void packet( UInt8 adbCommand, - IOByteCount length, UInt8 * data ); - -}; diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.cpp b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.cpp deleted file mode 100644 index d5026c422..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * 18 June 1998 - * Start IOKit version. - */ - -#include "AppleADBKeyboard.h" -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/IOLib.h> -#include <IOKit/IODeviceTreeSupport.h> -#define super IOHIKeyboard -OSDefineMetaClassAndStructors(AppleADBKeyboard,IOHIKeyboard) - - -static void new_kbd_data ( IOService * us, UInt8 adbCommand, IOByteCount length, UInt8 * data ); -static void asyncSetLEDFunc ( thread_call_param_t, thread_call_param_t ); - -//Convert raw ADB codes to MacOS 9 KMAP virtual key codes in dispatchKeyboardEvent() -static unsigned char kmapConvert[] = - { - //00,00,00,00, These 4 are in System resource, but are unused - 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, - 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F, - 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, - 0x30,0x31,0x32,0x33,0x34,0x35,0x3B,0x37,0x38,0x39,0x3A,0x7B,0x7C,0x7D,0x7E,0x3F, - 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F, - 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F, - 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x3C,0x3D,0x3E,0x36,0x7F, - 00,00 - }; - - -// ********************************************************************************** -// start -// -// ********************************************************************************** -bool AppleADBKeyboard::start ( IOService * theNub ) -{ - -adbDevice = (IOADBDevice *)theNub; -if( !adbDevice->seizeForClient(this, new_kbd_data) ) { - IOLog("%s: Seize failed\n", getName()); - return false; -} - -turnLEDon = ADBKS_LED_CAPSLOCK | ADBKS_LED_NUMLOCK | ADBKS_LED_SCROLLLOCK; //negative logic -setAlphaLockFeedback(false); -setNumLockFeedback(false); - - -clock_interval_to_absolutetime_interval( 4, kSecondScale, &rebootTime); -clock_interval_to_absolutetime_interval( 1, kSecondScale, &debuggerTime); - -return super::start(theNub); -} - - -// ********************************************************************************** -// interfaceID -// -// ********************************************************************************** -UInt32 AppleADBKeyboard::interfaceID ( void ) -{ -return NX_EVS_DEVICE_INTERFACE_ADB; -} - - -// ********************************************************************************** -// deviceType -// -// ********************************************************************************** -UInt32 AppleADBKeyboard::deviceType ( void ) -{ - UInt32 id; //We need handler ID to remap adjustable JIS keyboard - IORegistryEntry *regEntry; - OSData * data = 0; - UInt32 *dataptr; - - id = adbDevice->handlerID(); - if (id == 18) //Adjustable JIS - { - kmapConvert[0x32] = 0x35; //tilde to ESC - } - - if ((id == kgestaltPwrBkEKDomKbd) || (id == kgestaltPwrBkEKISOKbd) || - (id == kgestaltPwrBkEKJISKbd) || (id == kgestaltPwrBk99JISKbd)) - { - if( (regEntry = IORegistryEntry::fromPath( "/pci@f2000000/mac-io/via-pmu/adb/keyboard", gIODTPlane ))) - { - data = OSDynamicCast(OSData, regEntry->getProperty( "keyboard-id", gIODTPlane, kIORegistryIterateRecursively )); - if (data) - { - dataptr = (UInt32 *)data->getBytesNoCopy(); - id = *dataptr; //make sure no byte swapping - } - regEntry->release(); - } - } - - return id; -} - - -// ********************************************************************************** -// setAlphaLockFeedback -// This is usually called on a call-out thread after the caps-lock key is pressed. -// ADB operations to PMU are synchronous, and this is must not be done -// on the call-out thread since that is the PMU driver workloop thread, and -// it will block itself. -// -// Therefore, we schedule the ADB write to disconnect the call-out thread -// and the one that initiates the ADB write. -// -// ********************************************************************************** -void AppleADBKeyboard::setAlphaLockFeedback ( bool to ) -{ - if (to) - turnLEDon &= ~ADBKS_LED_CAPSLOCK; //Inverse logic applies here - else - turnLEDon |= ADBKS_LED_CAPSLOCK; - - if ( ! isInactive() ) { - thread_call_func(asyncSetLEDFunc, (thread_call_param_t)this, true); - } -} - -void AppleADBKeyboard::setNumLockFeedback ( bool to ) -{ - if (to) //LED on means clear that bit - turnLEDon &= ~ ADBKS_LED_NUMLOCK; - else - turnLEDon |= ADBKS_LED_NUMLOCK; - - if ( ! isInactive() ) { - thread_call_func(asyncSetLEDFunc, (thread_call_param_t)this, true); - } -} - - - -// ********************************************************************************** -// asyncSetLEDFunc -// -// Called asynchronously to turn on/off the capslock and numlock LED -// -// ********************************************************************************** -static void asyncSetLEDFunc ( thread_call_param_t self, thread_call_param_t ) -{ - -UInt16 value; -IOByteCount length = sizeof( UInt16); - - - value = ((AppleADBKeyboard*)self)->turnLEDon; - ((AppleADBKeyboard*)self)->adbDevice->writeRegister(2, (UInt8 *)&value, &length); -} - -/********************************************************************** -Get LED status by reading hardware. Register 2 has 16 bits. -**********************************************************************/ -unsigned AppleADBKeyboard::getLEDStatus (void ) -{ - UInt8 data[8]; //8 bytes max for ADB read (talk) operation - IOByteCount length = 8; - - bzero(data, 8); - LEDStatus = 0; - adbDevice->readRegister(2, data, &length); - - if ((data[1] & ADBKS_LED_NUMLOCK) == 0) - LEDStatus |= ADBKS_LED_NUMLOCK; - if ((data[1] & ADBKS_LED_CAPSLOCK) == 0) - LEDStatus |= ADBKS_LED_CAPSLOCK; - if ((data[1] & ADBKS_LED_SCROLLLOCK) == 0) - LEDStatus |= ADBKS_LED_SCROLLLOCK; - - return LEDStatus; -} - -// ********************************************************************************** -// new_kbd_data -// -// ********************************************************************************** -static void new_kbd_data ( IOService * us, UInt8 adbCommand, IOByteCount length, UInt8 * data ) -{ -((AppleADBKeyboard *)us)->packet(data,length,adbCommand); -} - -// ********************************************************************************** -// dispatchKeyboardEvent -// -// ********************************************************************************** -extern "C" { -void Debugger( const char * ); -void boot(int paniced, int howto, char * command); -#define RB_HALT 0x08 /* don't reboot, just halt */ -} - -static void AppleADBKeyboardReboot( thread_call_param_t arg, thread_call_param_t ) -{ - boot( 0, (int) arg, 0 ); -} - -void AppleADBKeyboard::dispatchKeyboardEvent(unsigned int keyCode, - /* direction */ bool goingDown, - /* timeStamp */ AbsoluteTime time) -{ - if( !goingDown && programmerKey) { - programmerKey = false; - EVK_KEYUP( ADBK_CONTROL, _keyState); - SUB_ABSOLUTETIME( &time, &programmerKeyTime ); - if( CMP_ABSOLUTETIME( &time, &rebootTime) >= 0) { - - thread_call_func( AppleADBKeyboardReboot, - (void *) RB_HALT, true ); - } else if( CMP_ABSOLUTETIME( &time, &debuggerTime) >= 0) { - Debugger("Programmer Key"); - } - - } else if( (keyCode == ADBK_POWER) - && (EVK_IS_KEYDOWN( ADBK_CONTROL, _keyState))) { - - if( !programmerKey) { - programmerKey = true; - programmerKeyTime = time; - } - return; - } - - super::dispatchKeyboardEvent( kmapConvert[keyCode], goingDown, time ); - -} - -// ********************************************************************************** -// packet -// -// ********************************************************************************** -IOReturn AppleADBKeyboard::packet (UInt8 * data, IOByteCount, UInt8 adbCommand ) -{ -unsigned int keycode1, keycode2; -bool down; -AbsoluteTime now; - -keycode1 = *data; -down = ((keycode1 & 0x80) == 0); -keycode1 &= 0x7f; -if(keycode1 == 0x7e) keycode1 = ADBK_POWER; -clock_get_uptime(&now); - -dispatchKeyboardEvent(keycode1,down,now); - -keycode2 = *(data + 1); -if( keycode2 != 0xff ) { - down = ((keycode2 & 0x80) == 0); - keycode2 &= 0x7f; - if( keycode2 == 0x7e) keycode2 = ADBK_POWER; - if( (keycode1 != ADBK_POWER) || (keycode2 != ADBK_POWER)) - dispatchKeyboardEvent(keycode2,down,now); -} - -return kIOReturnSuccess; -} - - -// ********************************************************************************** -// maxKeyCodes -// -// ********************************************************************************** -UInt32 AppleADBKeyboard::maxKeyCodes ( void ) -{ -return 0x80; -} - -//Get key values from ev_keymap.h -bool AppleADBKeyboard:: doesKeyLock ( unsigned key) -{ - switch (key) { - case NX_KEYTYPE_CAPS_LOCK: - return true; - case NX_KEYTYPE_NUM_LOCK: - return false; - default: - return false; - } -} - - -// ********************************************************************************** -// defaultKeymapOfLength -// -// ********************************************************************************** -const unsigned char * AppleADBKeyboard::defaultKeymapOfLength (UInt32 * length ) -{ -static const unsigned char appleUSAKeyMap[] = { - 0x00,0x00, - 0x08, //8 modifier keys - 0x00,0x01,0x39, //NX_MODIFIERKEY_ALPHALOCK - 0x01,0x01,0x38, //NX_MODIFIERKEY_SHIFT virtual from KMAP - 0x02,0x01,0x3b, //NX_MODIFIERKEY_CONTROL - 0x03,0x01,0x3a, //NX_MODIFIERKEY_ALTERNATE - 0x04,0x01,0x37, //NX_MODIFIERKEY_COMMAND - 0x05,0x15,0x52,0x41,0x4c,0x53,0x54,0x55,0x45,0x58,0x57,0x56,0x5b,0x5c, - 0x43,0x4b,0x51,0x7b,0x7d,0x7e,0x7c,0x4e,0x59, //NX_MODIFIERKEY_NUMERICPAD - 0x06,0x01,0x72, //NX_MODIFIERKEY_HELP 7th modifier here - 0x07,0x01,0x3f, //NX_MODIFIERKEY_SECONDARYFN 8th modifier - 0x7f,0x0d,0x00,0x61, - 0x00,0x41,0x00,0x01,0x00,0x01,0x00,0xca,0x00,0xc7,0x00,0x01,0x00,0x01,0x0d,0x00, - 0x73,0x00,0x53,0x00,0x13,0x00,0x13,0x00,0xfb,0x00,0xa7,0x00,0x13,0x00,0x13,0x0d, - 0x00,0x64,0x00,0x44,0x00,0x04,0x00,0x04,0x01,0x44,0x01,0xb6,0x00,0x04,0x00,0x04, - 0x0d,0x00,0x66,0x00,0x46,0x00,0x06,0x00,0x06,0x00,0xa6,0x01,0xac,0x00,0x06,0x00, - 0x06,0x0d,0x00,0x68,0x00,0x48,0x00,0x08,0x00,0x08,0x00,0xe3,0x00,0xeb,0x00,0x00, - 0x18,0x00,0x0d,0x00,0x67,0x00,0x47,0x00,0x07,0x00,0x07,0x00,0xf1,0x00,0xe1,0x00, - 0x07,0x00,0x07,0x0d,0x00,0x7a,0x00,0x5a,0x00,0x1a,0x00,0x1a,0x00,0xcf,0x01,0x57, - 0x00,0x1a,0x00,0x1a,0x0d,0x00,0x78,0x00,0x58,0x00,0x18,0x00,0x18,0x01,0xb4,0x01, - 0xce,0x00,0x18,0x00,0x18,0x0d,0x00,0x63,0x00,0x43,0x00,0x03,0x00,0x03,0x01,0xe3, - 0x01,0xd3,0x00,0x03,0x00,0x03,0x0d,0x00,0x76,0x00,0x56,0x00,0x16,0x00,0x16,0x01, - 0xd6,0x01,0xe0,0x00,0x16,0x00,0x16,0x02,0x00,0x3c,0x00,0x3e,0x0d,0x00,0x62,0x00, - 0x42,0x00,0x02,0x00,0x02,0x01,0xe5,0x01,0xf2,0x00,0x02,0x00,0x02,0x0d,0x00,0x71, - 0x00,0x51,0x00,0x11,0x00,0x11,0x00,0xfa,0x00,0xea,0x00,0x11,0x00,0x11,0x0d,0x00, - 0x77,0x00,0x57,0x00,0x17,0x00,0x17,0x01,0xc8,0x01,0xc7,0x00,0x17,0x00,0x17,0x0d, - 0x00,0x65,0x00,0x45,0x00,0x05,0x00,0x05,0x00,0xc2,0x00,0xc5,0x00,0x05,0x00,0x05, - 0x0d,0x00,0x72,0x00,0x52,0x00,0x12,0x00,0x12,0x01,0xe2,0x01,0xd2,0x00,0x12,0x00, - 0x12,0x0d,0x00,0x79,0x00,0x59,0x00,0x19,0x00,0x19,0x00,0xa5,0x01,0xdb,0x00,0x19, - 0x00,0x19,0x0d,0x00,0x74,0x00,0x54,0x00,0x14,0x00,0x14,0x01,0xe4,0x01,0xd4,0x00, - 0x14,0x00,0x14,0x0a,0x00,0x31,0x00,0x21,0x01,0xad,0x00,0xa1,0x0e,0x00,0x32,0x00, - 0x40,0x00,0x32,0x00,0x00,0x00,0xb2,0x00,0xb3,0x00,0x00,0x00,0x00,0x0a,0x00,0x33, - 0x00,0x23,0x00,0xa3,0x01,0xba,0x0a,0x00,0x34,0x00,0x24,0x00,0xa2,0x00,0xa8,0x0e, - 0x00,0x36,0x00,0x5e,0x00,0x36,0x00,0x1e,0x00,0xb6,0x00,0xc3,0x00,0x1e,0x00,0x1e, - 0x0a,0x00,0x35,0x00,0x25,0x01,0xa5,0x00,0xbd,0x0a,0x00,0x3d,0x00,0x2b,0x01,0xb9, - 0x01,0xb1,0x0a,0x00,0x39,0x00,0x28,0x00,0xac,0x00,0xab,0x0a,0x00,0x37,0x00,0x26, - 0x01,0xb0,0x01,0xab,0x0e,0x00,0x2d,0x00,0x5f,0x00,0x1f,0x00,0x1f,0x00,0xb1,0x00, - 0xd0,0x00,0x1f,0x00,0x1f,0x0a,0x00,0x38,0x00,0x2a,0x00,0xb7,0x00,0xb4,0x0a,0x00, - 0x30,0x00,0x29,0x00,0xad,0x00,0xbb,0x0e,0x00,0x5d,0x00,0x7d,0x00,0x1d,0x00,0x1d, - 0x00,0x27,0x00,0xba,0x00,0x1d,0x00,0x1d,0x0d,0x00,0x6f,0x00,0x4f,0x00,0x0f,0x00, - 0x0f,0x00,0xf9,0x00,0xe9,0x00,0x0f,0x00,0x0f,0x0d,0x00,0x75,0x00,0x55,0x00,0x15, - 0x00,0x15,0x00,0xc8,0x00,0xcd,0x00,0x15,0x00,0x15,0x0e,0x00,0x5b,0x00,0x7b,0x00, - 0x1b,0x00,0x1b,0x00,0x60,0x00,0xaa,0x00,0x1b,0x00,0x1b,0x0d,0x00,0x69,0x00,0x49, - 0x00,0x09,0x00,0x09,0x00,0xc1,0x00,0xf5,0x00,0x09,0x00,0x09,0x0d,0x00,0x70,0x00, - 0x50,0x00,0x10,0x00,0x10,0x01,0x70,0x01,0x50,0x00,0x10,0x00,0x10,0x10,0x00,0x0d, - 0x00,0x03,0x0d,0x00,0x6c,0x00,0x4c,0x00,0x0c,0x00,0x0c,0x00,0xf8,0x00,0xe8,0x00, - 0x0c,0x00,0x0c,0x0d,0x00,0x6a,0x00,0x4a,0x00,0x0a,0x00,0x0a,0x00,0xc6,0x00,0xae, - 0x00,0x0a,0x00,0x0a,0x0a,0x00,0x27,0x00,0x22,0x00,0xa9,0x01,0xae,0x0d,0x00,0x6b, - 0x00,0x4b,0x00,0x0b,0x00,0x0b,0x00,0xce,0x00,0xaf,0x00,0x0b,0x00,0x0b,0x0a,0x00, - 0x3b,0x00,0x3a,0x01,0xb2,0x01,0xa2,0x0e,0x00,0x5c,0x00,0x7c,0x00,0x1c,0x00,0x1c, - 0x00,0xe3,0x00,0xeb,0x00,0x1c,0x00,0x1c,0x0a,0x00,0x2c,0x00,0x3c,0x00,0xcb,0x01, - 0xa3,0x0a,0x00,0x2f,0x00,0x3f,0x01,0xb8,0x00,0xbf,0x0d,0x00,0x6e,0x00,0x4e,0x00, - 0x0e,0x00,0x0e,0x00,0xc4,0x01,0xaf,0x00,0x0e,0x00,0x0e,0x0d,0x00,0x6d,0x00,0x4d, - 0x00,0x0d,0x00,0x0d,0x01,0x6d,0x01,0xd8,0x00,0x0d,0x00,0x0d,0x0a,0x00,0x2e,0x00, - 0x3e,0x00,0xbc,0x01,0xb3,0x02,0x00,0x09,0x00,0x19,0x0c,0x00,0x20,0x00,0x00,0x00, - 0x80,0x00,0x00,0x0a,0x00,0x60,0x00,0x7e,0x00,0x60,0x01,0xbb,0x02,0x00,0x7f,0x00, - 0x08,0xff,0x02,0x00,0x1b,0x00,0x7e,0xff,0xff,0xff,0xff,0xff, - /* - 0x00,0x01,0xac,0x00, - 0x01,0xae,0x00,0x01,0xaf,0x00,0x01,0xad, - */ - 0xff, 0xff, 0xff, 0xff, - 0xff,0xff,0x00,0x00,0x2e,0xff,0x00,0x00, - 0x2a,0xff,0x00,0x00,0x2b,0xff,0x00,0x00,0x1b,0xff,0xff,0xff,0x0e,0x00,0x2f,0x00, - 0x5c,0x00,0x2f,0x00,0x1c,0x00,0x2f,0x00,0x5c,0x00,0x00,0x0a,0x00,0x00,0x00,0x0d, //XX03 - 0xff,0x00,0x00,0x2d,0xff,0xff,0x0e,0x00,0x3d,0x00,0x7c,0x00,0x3d,0x00,0x1c,0x00, - 0x3d,0x00,0x7c,0x00,0x00,0x18,0x46,0x00,0x00,0x30,0x00,0x00,0x31,0x00,0x00,0x32, - 0x00,0x00,0x33,0x00,0x00,0x34,0x00,0x00,0x35,0x00,0x00,0x36,0x00,0x00,0x37,0xff, - 0x00,0x00,0x38,0x00,0x00,0x39,0xff,0xff,0xff,0x00,0xfe,0x24,0x00,0xfe,0x25,0x00, - 0xfe,0x26,0x00,0xfe,0x22,0x00,0xfe,0x27,0x00,0xfe,0x28,0xff,0x00,0xfe,0x2a,0xff, - 0x00,0xfe,0x32,0xff,0x00,0xfe,0x33,0xff,0x00,0xfe,0x29,0xff,0x00,0xfe,0x2b,0xff, - 0x00,0xfe,0x34,0xff,0x00,0xfe,0x2e,0x00,0xfe,0x30,0x00,0xfe,0x2d,0x00,0xfe,0x23, - 0x00,0xfe,0x2f,0x00,0xfe,0x21,0x00,0xfe,0x31,0x00,0xfe,0x20, - //A.W. Added following 4 lines to fix wakeup on PowerBooks. - 0x00,0x01,0xac, //ADB=0x7b is left arrow - 0x00,0x01,0xae, //ADB = 0x7c is right arrow - 0x00,0x01,0xaf, //ADB=0x7d is down arrow. - 0x00,0x01,0xad, //ADB=0x7e is up arrow - 0x0f,0x02,0xff,0x04, - 0x00,0x31,0x02,0xff,0x04,0x00,0x32,0x02,0xff,0x04,0x00,0x33,0x02,0xff,0x04,0x00, - 0x34,0x02,0xff,0x04,0x00,0x35,0x02,0xff,0x04,0x00,0x36,0x02,0xff,0x04,0x00,0x37, - 0x02,0xff,0x04,0x00,0x38,0x02,0xff,0x04,0x00,0x39,0x02,0xff,0x04,0x00,0x30,0x02, - 0xff,0x04,0x00,0x2d,0x02,0xff,0x04,0x00,0x3d,0x02,0xff,0x04,0x00,0x70,0x02,0xff, - 0x04,0x00,0x5d,0x02,0xff,0x04,0x00,0x5b, -0x06, // following are 6 special keys -0x05,0x72, //NX_KEYTYPE_HELP is 5, ADB code is 0x72 -0x06,0x7f, //NX_POWER_KEY is 6, ADB code is 0x7f -0x07,0x4a, //NX_KEYTYPE_MUTE is 7, ADB code is 0x4a -0x08,0x3e, //NX_UP_ARROW_KEY is 8, ADB is 3e raw, 7e virtual (KMAP) -0x09,0x3d, //NX_DOWN_ARROW_KEY is 9, ADB is 0x3d raw, 7d virtual -0x0a,0x47 //NX_KEYTYPE_NUM_LOCK is 10, ADB combines with CLEAR key for numlock - }; - -*length = sizeof(appleUSAKeyMap); -return appleUSAKeyMap; -} - - - diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.h b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.h deleted file mode 100644 index 038d15c0b..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/adb/IOADBDevice.h> -#include <IOKit/hidsystem/IOHIKeyboard.h> - -enum { - kgestaltPwrBkEKDomKbd = 0xc3, - kgestaltPwrBkEKISOKbd = 0xc4, - kgestaltPwrBkEKJISKbd = 0xc5, - kgestaltPwrBk99JISKbd = 0xc9 -}; - -class AppleADBKeyboard : public IOHIKeyboard -{ -OSDeclareDefaultStructors(AppleADBKeyboard) - -private: - -void setAlphaLockFeedback ( bool to ); -void setNumLockFeedback ( bool to ); -UInt32 maxKeyCodes ( void ); -const unsigned char * defaultKeymapOfLength (UInt32 * length ); -UInt32 interfaceID ( void ); -bool doesKeyLock ( unsigned key); -unsigned getLEDStatus (void ); -bool programmerKey; -AbsoluteTime programmerKeyTime; -AbsoluteTime rebootTime; -AbsoluteTime debuggerTime; - -public: - -UInt32 deviceType ( void ); -IOADBDevice * adbDevice; -UInt16 turnLEDon; // used by setAlphaLockFeedback mechanism -UInt16 LEDStatus; //For ADB device TALK commands - -bool start ( IOService * theNub ); -IOReturn packet (UInt8 * data, IOByteCount length, UInt8 adbCommand ); -void dispatchKeyboardEvent(unsigned int keyCode, - /* direction */ bool goingDown, - /* timeStamp */ AbsoluteTime time); -}; - -/* - * Special key values - */ - -#define ADBK_LEFT 0x3B -#define ADBK_RIGHT 0x3C -#define ADBK_UP 0x3E -#define ADBK_DOWN 0x3D -#define ADBK_PGUP 0x74 -#define ADBK_PGDN 0x79 -#define ADBK_HOME 0x73 -#define ADBK_END 0x77 -#define ADBK_CONTROL 0x36 -#define ADBK_CONTROL_R 0x7D -#define ADBK_FLOWER 0x37 -#define ADBK_SHIFT 0x38 -#define ADBK_SHIFT_R 0x7B -#define ADBK_CAPSLOCK 0x39 -#define ADBK_OPTION 0x3A -#define ADBK_OPTION_R 0x7C -#define ADBK_NUMLOCK 0x47 -#define ADBK_SPACE 0x31 -#define ADBK_F 0x03 -#define ADBK_O 0x1F -#define ADBK_P 0x23 -#define ADBK_Q 0x0C -#define ADBK_V 0x09 -#define ADBK_1 0x12 -#define ADBK_2 0x13 -#define ADBK_3 0x14 -#define ADBK_4 0x15 -#define ADBK_5 0x17 -#define ADBK_6 0x16 -#define ADBK_7 0x1A -#define ADBK_8 0x1C -#define ADBK_9 0x19 -#define ADBK_0 0x1D -#define ADBK_POWER 0x7f /* actual 0x7f 0x7f */ - -#define ADBK_KEYVAL(key) ((key) & 0x7f) -#define ADBK_PRESS(key) (((key) & 0x80) == 0) -#define ADBK_KEYDOWN(key) (key) -#define ADBK_KEYUP(key) ((key) | 0x80) -#define ADBK_MODIFIER(key) ((((key) & 0x7f) == ADBK_SHIFT) || \ - (((key) & 0x7f) == ADBK_SHIFT_R) || \ - (((key) & 0x7f) == ADBK_CONTROL) || \ - (((key) & 0x7f) == ADBK_CONTROL_R) || \ - (((key) & 0x7f) == ADBK_FLOWER) || \ - (((key) & 0x7f) == ADBK_OPTION) || \ - (((key) & 0x7f) == ADBK_OPTION_R) || \ - (((key) & 0x7f) == ADBK_NUMLOCK) || \ - (((key) & 0x7f) == ADBK_CAPSLOCK)) - -/* ADB Keyboard Status - ADB Register 2 */ - -#define ADBKS_LED_NUMLOCK 0x0001 -#define ADBKS_LED_CAPSLOCK 0x0002 -#define ADBKS_LED_SCROLLLOCK 0x0004 -#define ADBKS_SCROLL_LOCK 0x0040 -#define ADBKS_NUMLOCK 0x0080 -/* Bits 3 to 5 are reserved */ -#define ADBKS_APPLE_CMD 0x0100 -#define ADBKS_OPTION 0x0200 -#define ADBKS_SHIFT 0x0400 -#define ADBKS_CONTROL 0x0800 -#define ADBKS_CAPSLOCK 0x1000 -#define ADBKS_RESET 0x2000 -#define ADBKS_DELETE 0x4000 -/* bit 16 is reserved */ diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.cpp b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.cpp deleted file mode 100644 index 208e52007..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * 18 June 1998 Start IOKit version. - * 18 Nov 1998 suurballe port to C++ - * 4 Oct 1999 decesare Revised for Type 4 support and sub-classed drivers. - * 1 Feb 2000 tsherman Added extended mouse functionality (implemented in setParamProperties) - */ - -#include "AppleADBMouse.h" -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOPlatformExpert.h> - -// Globals to remember enhanced trackpad values @ sleep and restore @ wake. -UInt8 glob_clicking = 0x19; -UInt8 glob_dragging = 0x14; -UInt8 glob_draglock = 0xB2; - -// **************************************************************************** -// NewMouseData -// -// **************************************************************************** -static void NewMouseData(IOService * target, UInt8 adbCommand, IOByteCount length, UInt8 * data) -{ - ((AppleADBMouse *)target)->packet(adbCommand, length, data); -} - - -// **************************************************************************** - -#undef super -#define super IOHIPointing - -OSDefineMetaClassAndStructors(AppleADBMouse, IOHIPointing); - - -// **************************************************************************** -// probe -// -// **************************************************************************** -IOService * AppleADBMouse::probe(IOService * provider, SInt32 * score) -{ - adbDevice = (IOADBDevice *)provider; - - return this; -} - - -// **************************************************************************** -// start -// -// **************************************************************************** -bool AppleADBMouse::start(IOService * provider) -{ - if(!super::start(provider)) return false; - - if(!adbDevice->seizeForClient(this, NewMouseData)) { - IOLog("%s: Seize failed\n", getName()); - return false; - } - - return true; -} - - -// **************************************************************************** -// interfaceID -// -// **************************************************************************** -UInt32 AppleADBMouse::interfaceID(void) -{ - return NX_EVS_DEVICE_INTERFACE_ADB; -} - - -// **************************************************************************** -// deviceType -// -// **************************************************************************** -UInt32 AppleADBMouse::deviceType ( void ) -{ - return adbDevice->handlerID(); -} - - -// **************************************************************************** -// resolution -// -// **************************************************************************** -IOFixed AppleADBMouse::resolution(void) -{ - return _resolution; -} - - -// **************************************************************************** -// buttonCount -// -// **************************************************************************** -IOItemCount AppleADBMouse::buttonCount(void) -{ - return _buttonCount; -} - - -// **************************************************************************** -// packet -// -// **************************************************************************** -void AppleADBMouse::packet(UInt8 /*adbCommand*/, - IOByteCount /*length*/, UInt8 * data) -{ - int dx, dy; - UInt32 buttonState = 0; - AbsoluteTime now; - - dy = data[0] & 0x7f; - dx = data[1] & 0x7f; - - if (dy & 0x40) dy |= 0xffffffc0; - if (dx & 0x40) dx |= 0xffffffc0; - - if ((data[0] & 0x80) == 0) buttonState |= 1; - - clock_get_uptime(&now); - dispatchRelativePointerEvent(dx, dy, buttonState, now); -} - - -// **************************************************************************** - -#undef super -#define super AppleADBMouse - -OSDefineMetaClassAndStructors(AppleADBMouseType1, AppleADBMouse); - -IOService * AppleADBMouseType1::probe(IOService * provider, SInt32 * score) -{ - if (!super::probe(provider, score)) return 0; - - return this; -} - -bool AppleADBMouseType1::start(IOService * provider) -{ - if (adbDevice->setHandlerID(1) != kIOReturnSuccess) return false; - - _resolution = 100 << 16; - _buttonCount = 1; - - return super::start(provider); -} - - -// **************************************************************************** - -#undef super -#define super AppleADBMouse - -OSDefineMetaClassAndStructors(AppleADBMouseType2, AppleADBMouse); - -IOService * AppleADBMouseType2::probe(IOService * provider, SInt32 * score) -{ - if (!super::probe(provider, score)) return 0; - - if (adbDevice->setHandlerID(2) != kIOReturnSuccess) return 0; - - return this; -} - -bool AppleADBMouseType2::start(IOService * provider) -{ - if (adbDevice->setHandlerID(2) != kIOReturnSuccess) return false; - - _resolution = 200 << 16; - _buttonCount = 1; - - return super::start(provider); -} - - -// **************************************************************************** - -#undef super -#define super AppleADBMouse - -OSDefineMetaClassAndStructors(AppleADBMouseType4, AppleADBMouse); - -IOService * AppleADBMouseType4::probe(IOService * provider, SInt32 * score) -{ - UInt8 data[8]; - IOByteCount length = 8; - - if (!super::probe(provider, score)) return 0; - - if (adbDevice->setHandlerID(4) != kIOReturnSuccess) { - adbDevice->setHandlerID(adbDevice->defaultHandlerID()); - return 0; - } - - // To be a Type 4 Extended Mouse, register 1 must return 8 bytes. - if (adbDevice->readRegister(1, data, &length) != kIOReturnSuccess) return 0; - if (length != 8) return 0; - - // Save the device's Extended Mouse Info. - deviceSignature = ((UInt32 *)data)[0]; - deviceResolution = ((UInt16 *)data)[2]; - deviceClass = data[6]; - deviceNumButtons = data[7]; - - return this; -} - -bool AppleADBMouseType4::start(IOService * provider) -{ - UInt8 adbdata[8]; - IOByteCount adblength = 8; - typeTrackpad = FALSE; - - if (adbDevice->setHandlerID(4) != kIOReturnSuccess) return false; - - _resolution = deviceResolution << 16; - _buttonCount = deviceNumButtons; - - adbDevice->readRegister(1, adbdata, &adblength); - if( (adbdata[0] == 't') && (adbdata[1] = 'p') && (adbdata[2] == 'a') && (adbdata[3] == 'd') ) - { - IOLog("Trackpad detected, "); - typeTrackpad = TRUE; - enableEnhancedMode(); - } - - return super::start(provider); -} - -void AppleADBMouseType4::packet(UInt8 /*adbCommand*/, IOByteCount length, UInt8 * data) -{ - int dx, dy, cnt, numExtraBytes; - UInt32 buttonState = 0; - AbsoluteTime now; - - numExtraBytes = length - 2; - - dy = data[0] & 0x7f; - dx = data[1] & 0x7f; - - if ((data[0] & 0x80) == 0) buttonState |= 1; - if ((deviceNumButtons > 1) && ((data[1] & 0x80) == 0)) - { - if(typeTrackpad == TRUE) - buttonState |= 1; - else - buttonState |= 2; - } - - for (cnt = 0; cnt < numExtraBytes; cnt++) { - dy |= ((data[2 + cnt] >> 4) & 7) << (7 + (cnt * 3)); - dx |= ((data[2 + cnt]) & 7) << (7 + (cnt * 3)); - - if ((deviceNumButtons > (cnt + 2)) && ((data[2 + cnt] & 0x80) == 0)) - buttonState |= 4 << (cnt * 2); - if ((deviceNumButtons > (cnt + 2 + 1)) && ((data[2 + cnt] & 0x08) == 0)) - buttonState |= 4 << (cnt * 2 + 1); - } - - if (dy & (0x40 << (numExtraBytes * 3))) - dy |= (0xffffffc0 << (numExtraBytes * 3)); - if (dx & (0x40 << (numExtraBytes * 3))) - dx |= (0xffffffc0 << (numExtraBytes * 3)); - - clock_get_uptime(&now); - dispatchRelativePointerEvent(dx, dy, buttonState, now); -} - -OSData * AppleADBMouseType4::copyAccelerationTable() -{ - char keyName[10]; - - strcpy( keyName, "accl" ); - keyName[4] = (deviceSignature >> 24); - keyName[5] = (deviceSignature >> 16); - keyName[6] = (deviceSignature >> 8); - keyName[7] = (deviceSignature >> 0); - keyName[8] = 0; - - OSData * data = OSDynamicCast( OSData, - getProperty( keyName )); - if( data) - data->retain(); - else - data = super::copyAccelerationTable(); - - return( data ); -} - -// **************************************************************************** -// enableEnhancedMode -// -// **************************************************************************** - -bool AppleADBMouseType4::enableEnhancedMode() -{ - UInt8 adbdata[8]; - IOByteCount adblength = 8; - - IOLog("enableEnhancedMode called.\n"); - adbDevice->readRegister(1, adbdata, &adblength); - - if((adbdata[6] != 0x0D)) - { - adbdata[6] = 0xD; - if (adbDevice->writeRegister(1, adbdata, &adblength) != 0) - return FALSE; - if (adbDevice->readRegister(1, adbdata, &adblength) != 0) - return FALSE; - if (adbdata[6] != 0x0D) - { - IOLog("AppleADBMouseType4 deviceClass = %d (non-Extended Mode)\n", adbdata[6]); - return FALSE; - } - IOLog("AppleADBMouseType4 deviceClass = %d (Extended Mode)\n", adbdata[6]); - - // Set ADB Extended Features to default values. - //adbdata[0] = 0x19; - adbdata[0] = glob_clicking; - //adbdata[1] = 0x14; - adbdata[1] = glob_dragging; - adbdata[2] = 0x19; - //adbdata[3] = 0xB2; - adbdata[3] = glob_draglock; - adbdata[4] = 0xB2; - adbdata[5] = 0x8A; - adbdata[6] = 0x1B; - adbdata[7] = 0x50; - adblength = 8; - - adbDevice->writeRegister(2, adbdata, &adblength); - - /* Add IORegistry entries for Enhanced mode */ - Clicking = FALSE; - Dragging = FALSE; - DragLock = FALSE; - - setProperty("Clicking", (unsigned long long)Clicking, sizeof(Clicking)*8); - setProperty("Dragging", (unsigned long long)Dragging, sizeof(Dragging)*8); - setProperty("DragLock", (unsigned long long)DragLock, sizeof(DragLock)*8); - - return TRUE; - } - - return FALSE; -} - -// **************************************************************************** -// setParamProperties -// -// **************************************************************************** -IOReturn AppleADBMouseType4::setParamProperties( OSDictionary * dict ) -{ - OSData * data; - IOReturn err = kIOReturnSuccess; - UInt8 adbdata[8]; - IOByteCount adblength; - - //IOLog("AppleADBMouseType4::setParamProperties starting here\n"); - - if( (data = OSDynamicCast(OSData, dict->getObject("Clicking"))) && (typeTrackpad == TRUE) ) - { - adblength = sizeof(adbdata); - adbDevice->readRegister(2, adbdata, &adblength); - glob_clicking = (adbdata[0] & 0x7F) | (*( (UInt8 *) data->getBytesNoCopy() ))<<7; - adbdata[0] = glob_clicking; - setProperty("Clicking", (unsigned long long)((adbdata[0]&0x80)>>7), sizeof(adbdata[0])*8); - adbDevice->writeRegister(2, adbdata, &adblength); - } - - if( (data = OSDynamicCast(OSData, dict->getObject("Dragging"))) && (typeTrackpad == TRUE) ) - { - adblength = sizeof(adbdata); - adbDevice->readRegister(2, adbdata, &adblength); - glob_dragging = (adbdata[1] & 0x7F) | (*( (UInt8 *) data->getBytesNoCopy() ))<<7; - adbdata[1] = glob_dragging; - setProperty("Dragging", (unsigned long long)((adbdata[1]&0x80)>>7), sizeof(adbdata[1])*8); - adbDevice->writeRegister(2, adbdata, &adblength); - } - - if( (data = OSDynamicCast(OSData, dict->getObject("DragLock"))) && (typeTrackpad == TRUE) ) - { - adblength = sizeof(adbdata); - adbDevice->readRegister(2, adbdata, &adblength); - adbdata[3] = *((UInt8 *) data->getBytesNoCopy()); - - if(adbdata[3]) - { - setProperty("DragLock", (unsigned long long)adbdata[3], sizeof(adbdata[3])*8); - glob_draglock = 0xFF; - adbdata[3] = glob_draglock; - adblength = sizeof(adbdata); - adbDevice->writeRegister(2, adbdata, &adblength); - } - else - { - setProperty("DragLock", (unsigned long long)adbdata[3], sizeof(adbdata[3])*8); - glob_draglock = 0xB2; - adbdata[3] = glob_draglock; - adblength = sizeof(adbdata); - adbDevice->writeRegister(2, adbdata, &adblength); - } - } - -#if 0 - // For debugging purposes - adblength = 8; - adbDevice->readRegister(2, adbdata, &adblength); - IOLog("adbdata[0] = 0x%x\n", adbdata[0]); - IOLog("adbdata[1] = 0x%x\n", adbdata[1]); - IOLog("adbdata[2] = 0x%x\n", adbdata[2]); - IOLog("adbdata[3] = 0x%x\n", adbdata[3]); - IOLog("adbdata[4] = 0x%x\n", adbdata[4]); - IOLog("adbdata[5] = 0x%x\n", adbdata[5]); - IOLog("adbdata[6] = 0x%x\n", adbdata[6]); - IOLog("adbdata[7] = 0x%x\n", adbdata[7]); -#endif - - if (err == kIOReturnSuccess) - { - //IOLog("AppleADBMouseType4::setParamProperties ending here\n"); - return super::setParamProperties(dict); - } - - IOLog("AppleADBMouseType4::setParamProperties failing here\n"); - return( err ); -} - diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.h b/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.h deleted file mode 100644 index 668aadf6d..000000000 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * 18 June 1998 sdouglas Start IOKit version. - * 18 Nov 1998 suurballe port to C++ - * 4 Oct 1999 decesare Revised for Type 4 support and sub-classed drivers. - */ - -#include <IOKit/adb/IOADBDevice.h> -#include <IOKit/hidsystem/IOHIPointing.h> - -#define TRUE 1 -#define FALSE 0 - -class AppleADBMouse: public IOHIPointing -{ - OSDeclareDefaultStructors(AppleADBMouse); - -protected: - IOADBDevice * adbDevice; - IOFixed _resolution; - IOItemCount _buttonCount; - -public: - virtual IOService * probe(IOService * provider, SInt32 * score); - virtual bool start(IOService * provider); - virtual UInt32 interfaceID(void); - virtual UInt32 deviceType(void); - virtual IOFixed resolution(void); - virtual IOItemCount buttonCount(void); - virtual void packet(UInt8 adbCommand, IOByteCount length, UInt8 * data); -}; - - -class AppleADBMouseType1 : public AppleADBMouse -{ - OSDeclareDefaultStructors(AppleADBMouseType1); - -public: - virtual IOService * probe(IOService * provider, SInt32 * score); - virtual bool start(IOService * provider); -}; - - -class AppleADBMouseType2 : public AppleADBMouse -{ - OSDeclareDefaultStructors(AppleADBMouseType2); - -public: - virtual IOService * probe(IOService * provider, SInt32 * score); - virtual bool start(IOService * provider); -}; - - -class AppleADBMouseType4 : public AppleADBMouse -{ - OSDeclareDefaultStructors(AppleADBMouseType4); - -private: - bool Clicking, Dragging, DragLock, typeTrackpad; - virtual IOReturn setParamProperties( OSDictionary * dict ); - bool enableEnhancedMode(); - -protected: - UInt32 deviceSignature; - UInt16 deviceResolution; - UInt8 deviceClass; - UInt8 deviceNumButtons; - -public: - virtual IOService * probe(IOService * provider, SInt32 * score); - virtual bool start(IOService * provider); - virtual void packet(UInt8 adbCommand, IOByteCount length, UInt8 * data); - virtual OSData * copyAccelerationTable(); -}; diff --git a/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.cpp b/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.cpp deleted file mode 100644 index 10b69712a..000000000 --- a/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.cpp +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOLLEvent.h> -#include "ApplePS2Keyboard.h" - -// ============================================================================= -// ApplePS2Keyboard Class Implementation -// - -#define super IOHIKeyboard -OSDefineMetaClassAndStructors(ApplePS2Keyboard, IOHIKeyboard); - -UInt32 ApplePS2Keyboard::deviceType() { return NX_EVS_DEVICE_TYPE_KEYBOARD; }; -UInt32 ApplePS2Keyboard::interfaceID() { return NX_EVS_DEVICE_INTERFACE_ACE; }; - -UInt32 ApplePS2Keyboard::maxKeyCodes() { return KBV_NUM_KEYCODES; }; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Keyboard::init(OSDictionary * properties) -{ - // - // Initialize this object's minimal state. This is invoked right after this - // object is instantiated. - // - - if (!super::init(properties)) return false; - - _device = 0; - _extendCount = 0; - _interruptHandlerInstalled = false; - _ledState = 0; - - for (int index = 0; index < KBV_NUNITS; index++) _keyBitVector[index] = 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ApplePS2Keyboard * ApplePS2Keyboard::probe(IOService * provider, SInt32 * score) -{ - // - // The driver has been instructed to verify the presence of the actual - // hardware we represent. We are guaranteed by the controller that the - // keyboard clock is enabled and the keyboard itself is disabled (thus - // it won't send any asynchronous scan codes that may mess up the - // responses expected by the commands we send it). This is invoked - // after the init. - // - - ApplePS2KeyboardDevice * device = (ApplePS2KeyboardDevice *)provider; - PS2Request * request = device->allocateRequest(); - bool success; - - if (!super::probe(provider, score)) return 0; - - // - // Check to see if the keyboard responds to a basic diagnostic echo. - // - - // (diagnostic echo command) - request->commands[0].command = kPS2C_WriteDataPort; - request->commands[0].inOrOut = kDP_TestKeyboardEcho; - request->commands[1].command = kPS2C_ReadDataPortAndCompare; - request->commands[1].inOrOut = 0xEE; - request->commandsCount = 2; - device->submitRequestAndBlock(request); - - // (free the request) - success = (request->commandsCount == 2); - device->freeRequest(request); - - return (success) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Keyboard::start(IOService * provider) -{ - // - // The driver has been instructed to start. This is called after a - // successful attach. - // - - if (!super::start(provider)) return false; - - // - // Maintain a pointer to and retain the provider object. - // - - _device = (ApplePS2KeyboardDevice *)provider; - _device->retain(); - - // - // Install our driver's interrupt handler, for asynchronous data delivery. - // - - _device->installInterruptAction(this, - (PS2InterruptAction)&ApplePS2Keyboard::interruptOccurred); - _interruptHandlerInstalled = true; - - // - // Initialize the keyboard LED state. - // - - setLEDs(_ledState); - - // - // Enable the keyboard clock (should already be so), the keyboard IRQ line, - // and the keyboard Kscan -> scan code translation mode. - // - - setCommandByte(kCB_EnableKeyboardIRQ | kCB_TranslateMode, - kCB_DisableKeyboardClock); - - // - // Finally, we enable the keyboard itself, so that it may start reporting - // key events. - // - - setKeyboardEnable(true); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::stop(IOService * provider) -{ - // - // The driver has been instructed to stop. Note that we must break all - // connections to other service objects now (ie. no registered actions, - // no pointers and retains to objects, etc), if any. - // - - assert(_device == provider); - - // - // Disable the keyboard itself, so that it may stop reporting key events. - // - - setKeyboardEnable(false); - - // - // Disable the keyboard clock and the keyboard IRQ line. - // - - setCommandByte(kCB_DisableKeyboardClock, kCB_EnableKeyboardIRQ); - - // - // Uninstall the interrupt handler. - // - - if ( _interruptHandlerInstalled ) _device->uninstallInterruptAction(); - _interruptHandlerInstalled = false; - - // - // Release the pointer to the provider object. - // - - _device->release(); - _device = 0; - - super::stop(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::interruptOccurred(UInt8 scanCode) // PS2InterruptAction -{ - // - // This will be invoked automatically from our device when asynchronous - // keyboard data needs to be delivered. Process the keyboard data. Do - // NOT send any BLOCKING commands to our device in this context. - // - - if (scanCode == kSC_Acknowledge) - IOLog("%s: Unexpected acknowledge from PS/2 controller.\n", getName()); - else if (scanCode == kSC_Resend) - IOLog("%s: Unexpected resend request from PS/2 controller.\n", getName()); - else - dispatchKeyboardEventWithScancode(scanCode); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Keyboard::dispatchKeyboardEventWithScancode(UInt8 scanCode) -{ - // - // Parses the given scan code, updating all necessary internal state, and - // should a new key be detected, the key event is dispatched. - // - // Returns true if a key event was indeed dispatched. - // - - unsigned int keyCode; - bool goingDown; - AbsoluteTime now; - - // - // See if this scan code introduces an extended key sequence. If so, note - // it and then return. Next time we get a key we'll finish the sequence. - // - - if (scanCode == kSC_Extend) - { - _extendCount = 1; - return false; - } - - // - // See if this scan code introduces an extended key sequence for the Pause - // Key. If so, note it and then return. The next time we get a key, drop - // it. The next key we get after that finishes the Pause Key sequence. - // - // The sequence actually sent to us by the keyboard for the Pause Key is: - // - // 1. E1 Extended Sequence for Pause Key - // 2. 1D Useless Data, with Up Bit Cleared - // 3. 45 Pause Key, with Up Bit Cleared - // 4. E1 Extended Sequence for Pause Key - // 5. 9D Useless Data, with Up Bit Set - // 6. C5 Pause Key, with Up Bit Set - // - // The reason items 4 through 6 are sent with the Pause Key is because the - // keyboard hardware never generates a release code for the Pause Key and - // the designers are being smart about it. The sequence above translates - // to this parser as two separate events, as it should be -- one down key - // event and one up key event (for the Pause Key). - // - - if (scanCode == kSC_Pause) - { - _extendCount = 2; - return false; - } - - // - // Convert the scan code into a key code. - // - - if (_extendCount == 0) - keyCode = scanCode & ~kSC_UpBit; - else - { - _extendCount--; - if (_extendCount) return false; - - // - // Convert certain extended codes on the PC keyboard into single scancodes. - // Refer to the conversion table in defaultKeymapOfLength. - // - - switch (scanCode & ~kSC_UpBit) - { - case 0x1D: keyCode = 0x60; break; // ctrl - case 0x38: keyCode = 0x61; break; // alt - case 0x1C: keyCode = 0x62; break; // enter - case 0x35: keyCode = 0x63; break; // / - case 0x48: keyCode = 0x64; break; // up arrow - case 0x50: keyCode = 0x65; break; // down arrow - case 0x4B: keyCode = 0x66; break; // left arrow - case 0x4D: keyCode = 0x67; break; // right arrow - case 0x52: keyCode = 0x68; break; // insert - case 0x53: keyCode = 0x69; break; // delete - case 0x49: keyCode = 0x6A; break; // page up - case 0x51: keyCode = 0x6B; break; // page down - case 0x47: keyCode = 0x6C; break; // home - case 0x4F: keyCode = 0x6D; break; // end - case 0x37: keyCode = 0x6E; break; // PrintScreen - case 0x45: keyCode = 0x6F; break; // Pause - case 0x5B: keyCode = 0x70; break; // Left Windows - case 0x5C: keyCode = 0x71; break; // Right Windows - case 0x5D: keyCode = 0x72; break; // Application - case 0x2A: // header or trailer for PrintScreen - default: return false; - } - } - - if (keyCode == 0) return false; - - // - // Update our key bit vector, which maintains the up/down status of all keys. - // - - goingDown = !(scanCode & kSC_UpBit); - - if (goingDown) - { - // - // Verify that this is not an autorepeated key -- discard it if it is. - // - - if (KBV_IS_KEYDOWN(keyCode, _keyBitVector)) return false; - - KBV_KEYDOWN(keyCode, _keyBitVector); - } - else - { - KBV_KEYUP(keyCode, _keyBitVector); - } - - // - // We have a valid key event -- dispatch it to our superclass. - // - - clock_get_uptime(&now); - - dispatchKeyboardEvent(keyCode, /*direction*/ goingDown, /*timeStamp*/ now); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::setAlphaLockFeedback(bool locked) -{ - // - // Set the keyboard LEDs to reflect the state of alpha (caps) lock. - // - // It is safe to issue this request from the interrupt/completion context. - // - - _ledState = locked ? (_ledState | kLED_CapsLock):(_ledState & ~kLED_CapsLock); - setLEDs(_ledState); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::setLEDs(UInt8 ledState) -{ - // - // Asynchronously instructs the controller to set the keyboard LED state. - // - // It is safe to issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - - // (set LEDs command) - request->commands[0].command = kPS2C_WriteDataPort; - request->commands[0].inOrOut = kDP_SetKeyboardLEDs; - request->commands[1].command = kPS2C_ReadDataPortAndCompare; - request->commands[1].inOrOut = kSC_Acknowledge; - request->commands[2].command = kPS2C_WriteDataPort; - request->commands[2].inOrOut = ledState; - request->commands[3].command = kPS2C_ReadDataPortAndCompare; - request->commands[3].inOrOut = kSC_Acknowledge; - request->commandsCount = 4; - _device->submitRequest(request); // asynchronous, auto-free'd -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::setKeyboardEnable(bool enable) -{ - // - // Instructs the keyboard to start or stop the reporting of key events. - // Be aware that while the keyboard is enabled, asynchronous key events - // may arrive in the middle of command sequences sent to the controller, - // and may get confused for expected command responses. - // - // It is safe to issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - - // (keyboard enable/disable command) - request->commands[0].command = kPS2C_WriteDataPort; - request->commands[0].inOrOut = (enable)?kDP_Enable:kDP_SetDefaultsAndDisable; - request->commands[1].command = kPS2C_ReadDataPortAndCompare; - request->commands[1].inOrOut = kSC_Acknowledge; - request->commandsCount = 2; - _device->submitRequest(request); // asynchronous, auto-free'd -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Keyboard::setCommandByte(UInt8 setBits, UInt8 clearBits) -{ - // - // Sets the bits setBits and clears the bits clearBits "atomically" in the - // controller's Command Byte. Since the controller does not provide such - // a read-modify-write primitive, we resort to a test-and-set try loop. - // - // Do NOT issue this request from the interrupt/completion context. - // - - UInt8 commandByte; - UInt8 commandByteNew; - PS2Request * request = _device->allocateRequest(); - - do - { - // (read command byte) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_GetCommandByte; - request->commands[1].command = kPS2C_ReadDataPort; - request->commands[1].inOrOut = 0; - request->commandsCount = 2; - _device->submitRequestAndBlock(request); - - // - // Modify the command byte as requested by caller. - // - - commandByte = request->commands[1].inOrOut; - commandByteNew = (commandByte | setBits) & (~clearBits); - - // ("test-and-set" command byte) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_GetCommandByte; - request->commands[1].command = kPS2C_ReadDataPortAndCompare; - request->commands[1].inOrOut = commandByte; - request->commands[2].command = kPS2C_WriteCommandPort; - request->commands[2].inOrOut = kCP_SetCommandByte; - request->commands[3].command = kPS2C_WriteDataPort; - request->commands[3].inOrOut = commandByteNew; - request->commandsCount = 4; - _device->submitRequestAndBlock(request); - - // - // Repeat this loop if last command failed, that is, if the old command byte - // was modified since we first read it. - // - - } while (request->commandsCount != 4); - - _device->freeRequest(request); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const unsigned char * ApplePS2Keyboard::defaultKeymapOfLength(UInt32 * length) -{ - // - // Returns the default x86 keymap string. - // - // The following keys are multi-byte sequences on the x86 keyboard. They get - // mapped into a single scan code for our purposes. Here is the mapping: - // PC Key PC Code NeXT Code - // Right-Ctrl E0-1D 0x60 - // Right-Alt E0-38 0x61 - // Keypad-Enter E0-1C 0x62 - // Keypad-/ E0-35 0x63 - // Up-Arrow E0-48 0x64 - // Down-Arrow E0-50 0x65 - // Left-Arrow E0-4B 0x66 - // Right-Arrow E0-4D 0x67 - // Insert E0-52 0x68 - // Delete E0-53 0x69 - // Page Up E0-49 0x6A - // Page Down E0-51 0x6B - // Home E0-47 0x6C - // End E0-4F 0x6D - // - // Because there is no Command key on the x86 keyboard, we've split the ALT - // keys up. We'll use Left-Alt as Command, and Right-Alt as ALT. - // - - #define CTRL(c) ((c)&037) - #define NX_MODIFIERKEY_ALPHALOCK 0 - #define NX_MODIFIERKEY_SHIFT 1 - #define NX_MODIFIERKEY_CONTROL 2 - #define NX_MODIFIERKEY_ALTERNATE 3 - #define NX_MODIFIERKEY_COMMAND 4 - #define NX_MODIFIERKEY_NUMERICPAD 5 - #define NX_MODIFIERKEY_HELP 6 - - static const unsigned char defaultKeymapForPC[] = - { - 0x00, 0x00, // char file format - - 6, // MODIFIER KEY DEFINITIONS (6) - 0x01, 0x02, 0x2A, 0x36, // Shift, 2 keys - 0x02, 0x02, 0x1D, 0x60, // Ctrl, 2 keys - 0x03, 0x01, 0x61, // Alt, 1 key - 0x04, 0x01, 0x38, // Cmd, 1 key - 0x05, 0x15, 0x52, 0x53, 0x62, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, - 0x4E, 0x47, 0x48, 0x49, 0x45, 0x63, 0x37, 0x4A, - 0x64, 0x65, 0x66, 0x67, // NumPad, 21 keys - 0x06, 0x01, 0x3B, // Help, 1 key - - 104, // KEY DEFINITIONS - 0xff, // Key 0x00 unassigned - // Key 0x01 modifier key mask bits (0x02) - (1<<NX_MODIFIERKEY_SHIFT), - NX_ASCIISET, CTRL('['), // no flags - NX_ASCIISET, '~', // Shift - // Key 0x02 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '1', // no flags - NX_ASCIISET, '!', // Shift - NX_SYMBOLSET, 0xad, // Alt - NX_ASCIISET, 0xa1, // Shift Alt - // Key 0x03 modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '2', // no flags - NX_ASCIISET, '@', // Shift - NX_ASCIISET, CTRL('@'), // Ctrl - NX_ASCIISET, CTRL('@'), // Shift Ctrl - NX_ASCIISET, 0xb2, // Alt - NX_ASCIISET, 0xb3, // Shift Alt - NX_ASCIISET, CTRL('@'), // Ctrl Alt - NX_ASCIISET, CTRL('@'), // Shift Ctrl Alt - // Key 0x04 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '3', // no flags - NX_ASCIISET, '#', // Shift - NX_ASCIISET, 0xa3, // Alt - NX_SYMBOLSET, 0xba, // Shift Alt - // Key 0x05 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '4', // no flags - NX_ASCIISET, '$', // Shift - NX_ASCIISET, 0xa2, // Alt - NX_ASCIISET, 0xa8, // Shift Alt - // Key 0x06 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '5', // no flags - NX_ASCIISET, '%', // Shift - NX_SYMBOLSET, 0xa5, // Alt - NX_ASCIISET, 0xbd, // Shift Alt - // Key 0x07 modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '6', // no flags - NX_ASCIISET, '^', // Shift - NX_ASCIISET, CTRL('^'), // Ctrl - NX_ASCIISET, CTRL('^'), // Shift Ctrl - NX_ASCIISET, 0xb6, // Alt - NX_ASCIISET, 0xc3, // Shift Alt - NX_ASCIISET, CTRL('^'), // Ctrl Alt - NX_ASCIISET, CTRL('^'), // Shift Ctrl Alt - // Key 0x08 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '7', // no flags - NX_ASCIISET, '&', // Shift - NX_ASCIISET, 0xb7, // Alt - NX_SYMBOLSET, 0xab, // Shift Alt - // Key 0x09 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '8', // no flags - NX_ASCIISET, '*', // Shift - NX_SYMBOLSET, 0xb0, // Alt - NX_ASCIISET, 0xb4, // Shift Alt - // Key 0x0A modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '9', // no flags - NX_ASCIISET, '(', // Shift - NX_ASCIISET, 0xac, // Alt - NX_ASCIISET, 0xab, // Shift Alt - // Key 0x0B modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '0', // no flags - NX_ASCIISET, ')', // Shift - NX_ASCIISET, 0xad, // Alt - NX_ASCIISET, 0xbb, // Shift Alt - // Key 0x0C modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '-', // no flags - NX_ASCIISET, '_', // Shift - NX_ASCIISET, CTRL('_'), // Ctrl - NX_ASCIISET, CTRL('_'), // Shift Ctrl - NX_ASCIISET, 0xb1, // Alt - NX_ASCIISET, 0xd0, // Shift Alt - NX_ASCIISET, CTRL('_'), // Ctrl Alt - NX_ASCIISET, CTRL('_'), // Shift Ctrl Alt - // Key 0x0D modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '=', // no flags - NX_ASCIISET, '+', // Shift - NX_SYMBOLSET, 0xb9, // Alt - NX_SYMBOLSET, 0xb1, // Shift Alt - // Key 0x0E modifier key mask bits (0x02) - (1<<NX_MODIFIERKEY_SHIFT), - NX_ASCIISET, 0x7f, // no flags - NX_ASCIISET, '\b', // Shift - // Key 0x0f modifier key mask bits (0x02) - (1<<NX_MODIFIERKEY_SHIFT), - NX_ASCIISET, '\t', // no flags - NX_ASCIISET, CTRL('Y'), // Shift - // Key 0x10 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'q', // no flags - NX_ASCIISET, 'Q', // AlphaShift - NX_ASCIISET, CTRL('Q'), // Ctrl - NX_ASCIISET, CTRL('Q'), // AlphaShift Ctrl - NX_ASCIISET, 0xfa, // Alt - NX_ASCIISET, 0xea, // AlphaShift Alt - NX_ASCIISET, CTRL('Q'), // Ctrl Alt - NX_ASCIISET, CTRL('Q'), // AlphaShift Ctrl Alt - // Key 0x11 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'w', // no flags - NX_ASCIISET, 'W', // AlphaShift - NX_ASCIISET, CTRL('W'), // Ctrl - NX_ASCIISET, CTRL('W'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xc8, // Alt - NX_SYMBOLSET, 0xc7, // AlphaShift Alt - NX_ASCIISET, CTRL('W'), // Ctrl Alt - NX_ASCIISET, CTRL('W'), // AlphaShift Ctrl Alt - // Key 0x12 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'e', // no flags - NX_ASCIISET, 'E', // AlphaShift - NX_ASCIISET, CTRL('E'), // Ctrl - NX_ASCIISET, CTRL('E'), // AlphaShift Ctrl - NX_ASCIISET, 0xc2, // Alt - NX_ASCIISET, 0xc5, // AlphaShift Alt - NX_ASCIISET, CTRL('E'), // Ctrl Alt - NX_ASCIISET, CTRL('E'), // AlphaShift Ctrl Alt - // Key 0x13 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'r', // no flags - NX_ASCIISET, 'R', // AlphaShift - NX_ASCIISET, CTRL('R'), // Ctrl - NX_ASCIISET, CTRL('R'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xe2, // Alt - NX_SYMBOLSET, 0xd2, // AlphaShift Alt - NX_ASCIISET, CTRL('R'), // Ctrl Alt - NX_ASCIISET, CTRL('R'), // AlphaShift Ctrl Alt - // Key 0x14 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 't', // no flags - NX_ASCIISET, 'T', // AlphaShift - NX_ASCIISET, CTRL('T'), // Ctrl - NX_ASCIISET, CTRL('T'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xe4, // Alt - NX_SYMBOLSET, 0xd4, // AlphaShift Alt - NX_ASCIISET, CTRL('T'), // Ctrl Alt - NX_ASCIISET, CTRL('T'), // AlphaShift Ctrl Alt - // Key 0x15 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'y', // no flags - NX_ASCIISET, 'Y', // AlphaShift - NX_ASCIISET, CTRL('Y'), // Ctrl - NX_ASCIISET, CTRL('Y'), // AlphaShift Ctrl - NX_ASCIISET, 0xa5, // Alt - NX_SYMBOLSET, 0xdb, // AlphaShift Alt - NX_ASCIISET, CTRL('Y'), // Ctrl Alt - NX_ASCIISET, CTRL('Y'), // AlphaShift Ctrl Alt - // Key 0x16 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'u', // no flags - NX_ASCIISET, 'U', // AlphaShift - NX_ASCIISET, CTRL('U'), // Ctrl - NX_ASCIISET, CTRL('U'), // AlphaShift Ctrl - NX_ASCIISET, 0xc8, // Alt - NX_ASCIISET, 0xcd, // AlphaShift Alt - NX_ASCIISET, CTRL('U'), // Ctrl Alt - NX_ASCIISET, CTRL('U'), // AlphaShift Ctrl Alt - // Key 0x17 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'i', // no flags - NX_ASCIISET, 'I', // AlphaShift - NX_ASCIISET, '\t', // Ctrl - NX_ASCIISET, '\t', // AlphaShift Ctrl - NX_ASCIISET, 0xc1, // Alt - NX_ASCIISET, 0xf5, // AlphaShift Alt - NX_ASCIISET, '\t', // Ctrl Alt - NX_ASCIISET, '\t', // AlphaShift Ctrl Alt - // Key 0x18 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'o', // no flags - NX_ASCIISET, 'O', // AlphaShift - NX_ASCIISET, CTRL('O'), // Ctrl - NX_ASCIISET, CTRL('O'), // AlphaShift Ctrl - NX_ASCIISET, 0xf9, // Alt - NX_ASCIISET, 0xe9, // AlphaShift Alt - NX_ASCIISET, CTRL('O'), // Ctrl Alt - NX_ASCIISET, CTRL('O'), // AlphaShift Ctrl Alt - // Key 0x19 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'p', // no flags - NX_ASCIISET, 'P', // AlphaShift - NX_ASCIISET, CTRL('P'), // Ctrl - NX_ASCIISET, CTRL('P'), // AlphaShift Ctrl - NX_SYMBOLSET, 0x70, // Alt - NX_SYMBOLSET, 0x50, // AlphaShift Alt - NX_ASCIISET, CTRL('P'), // Ctrl Alt - NX_ASCIISET, CTRL('P'), // AlphaShift Ctrl Alt - // Key 0x1A modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '[', // no flags - NX_ASCIISET, '{', // Shift - NX_ASCIISET, CTRL('['), // Ctrl - NX_ASCIISET, CTRL('['), // Shift Ctrl - NX_ASCIISET, '`', // Alt - NX_ASCIISET, 0xaa, // Shift Alt - NX_ASCIISET, CTRL('['), // Ctrl Alt - NX_ASCIISET, CTRL('['), // Shift Ctrl Alt - // Key 0x1B modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, ']', // no flags - NX_ASCIISET, '}', // Shift - NX_ASCIISET, CTRL(']'), // Ctrl - NX_ASCIISET, CTRL(']'), // Shift Ctrl - NX_ASCIISET, '\'', // Alt - NX_ASCIISET, 0xba, // Shift Alt - NX_ASCIISET, CTRL(']'), // Ctrl Alt - NX_ASCIISET, CTRL(']'), // Shift Ctrl Alt - // Key 0x1C modifier key mask bits (0x10) - (1<<NX_MODIFIERKEY_COMMAND), - NX_ASCIISET, '\r', // no flags - NX_ASCIISET, CTRL('C'), // Cmd - 0xff, // Key 0x1D unassigned - Left Control - // Key 0x1E modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'a', // no flags - NX_ASCIISET, 'A', // AlphaShift - NX_ASCIISET, CTRL('A'), // Ctrl - NX_ASCIISET, CTRL('A'), // AlphaShift Ctrl - NX_ASCIISET, 0xca, // Alt - NX_ASCIISET, 0xc7, // AlphaShift Alt - NX_ASCIISET, CTRL('A'), // Ctrl Alt - NX_ASCIISET, CTRL('A'), // AlphaShift Ctrl Alt - // Key 0x1F modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 's', // no flags - NX_ASCIISET, 'S', // AlphaShift - NX_ASCIISET, CTRL('S'), // Ctrl - NX_ASCIISET, CTRL('S'), // AlphaShift Ctrl - NX_ASCIISET, 0xfb, // Alt - NX_ASCIISET, 0xa7, // AlphaShift Alt - NX_ASCIISET, CTRL('S'), // Ctrl Alt - NX_ASCIISET, CTRL('S'), // AlphaShift Ctrl Alt - // Key 0x20 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'd', // no flags - NX_ASCIISET, 'D', // AlphaShift - NX_ASCIISET, CTRL('D'), // Ctrl - NX_ASCIISET, CTRL('D'), // AlphaShift Ctrl - NX_SYMBOLSET, 0x44, // Alt - NX_SYMBOLSET, 0xb6, // AlphaShift Alt - NX_ASCIISET, CTRL('D'), // Ctrl Alt - NX_ASCIISET, CTRL('D'), // AlphaShift Ctrl Alt - // Key 0x21 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'f', // no flags - NX_ASCIISET, 'F', // AlphaShift - NX_ASCIISET, CTRL('F'), // Ctrl - NX_ASCIISET, CTRL('F'), // AlphaShift Ctrl - NX_ASCIISET, 0xa6, // Alt - NX_SYMBOLSET, 0xac, // AlphaShift Alt - NX_ASCIISET, CTRL('F'), // Ctrl Alt - NX_ASCIISET, CTRL('F'), // AlphaShift Ctrl Alt - // Key 0x22 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'g', // no flags - NX_ASCIISET, 'G', // AlphaShift - NX_ASCIISET, CTRL('G'), // Ctrl - NX_ASCIISET, CTRL('G'), // AlphaShift Ctrl - NX_ASCIISET, 0xf1, // Alt - NX_ASCIISET, 0xe1, // AlphaShift Alt - NX_ASCIISET, CTRL('G'), // Ctrl Alt - NX_ASCIISET, CTRL('G'), // AlphaShift Ctrl Alt - // Key 0x23 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'h', // no flags - NX_ASCIISET, 'H', // AlphaShift - NX_ASCIISET, '\b', // Ctrl - NX_ASCIISET, '\b', // AlphaShift Ctrl - NX_ASCIISET, 0xe3, // Alt - NX_ASCIISET, 0xeb, // AlphaShift Alt - NX_ASCIISET, CTRL('@'), // Ctrl Alt - 0x18, CTRL('@'), // AlphaShift Ctrl Alt - // Key 0x24 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'j', // no flags - NX_ASCIISET, 'J', // AlphaShift - NX_ASCIISET, '\n', // Ctrl - NX_ASCIISET, '\n', // AlphaShift Ctrl - NX_ASCIISET, 0xc6, // Alt - NX_ASCIISET, 0xae, // AlphaShift Alt - NX_ASCIISET, '\n', // Ctrl Alt - NX_ASCIISET, '\n', // AlphaShift Ctrl Alt - // Key 0x25 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'k', // no flags - NX_ASCIISET, 'K', // AlphaShift - NX_ASCIISET, CTRL('K'), // Ctrl - NX_ASCIISET, CTRL('K'), // AlphaShift Ctrl - NX_ASCIISET, 0xce, // Alt - NX_ASCIISET, 0xaf, // AlphaShift Alt - NX_ASCIISET, CTRL('K'), // Ctrl Alt - NX_ASCIISET, CTRL('K'), // AlphaShift Ctrl Alt - // Key 0x26 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'l', // no flags - NX_ASCIISET, 'L', // AlphaShift - NX_ASCIISET, '\f', // Ctrl - NX_ASCIISET, '\f', // AlphaShift Ctrl - NX_ASCIISET, 0xf8, // Alt - NX_ASCIISET, 0xe8, // AlphaShift Alt - NX_ASCIISET, '\f', // Ctrl Alt - NX_ASCIISET, '\f', // AlphaShift Ctrl Alt - // Key 0x27 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, ';', // no flags - NX_ASCIISET, ':', // Shift - NX_SYMBOLSET, 0xb2, // Alt - NX_SYMBOLSET, 0xa2, // Shift Alt - // Key 0x28 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '\'', // no flags - NX_ASCIISET, '"', // Shift - NX_ASCIISET, 0xa9, // Alt - NX_SYMBOLSET, 0xae, // Shift Alt - // Key 0x29 modifier key mask bits (0x02) - (1<<NX_MODIFIERKEY_SHIFT), - NX_ASCIISET, '`', // no flags - NX_ASCIISET, '~', // Shift - 0xff, // Key 0x2A unassigned - Left Shift - // Key 0x2B modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '\\', // no flags - NX_ASCIISET, '|', // Shift - NX_ASCIISET, CTRL('\\'), // Ctrl - NX_ASCIISET, CTRL('\\'), // Shift Ctrl - NX_ASCIISET, 0xe3, // Alt - NX_ASCIISET, 0xeb, // Shift Alt - NX_ASCIISET, CTRL('\\'), // Ctrl Alt - NX_ASCIISET, CTRL('\\'), // Shift Ctrl Alt - // Key 0x2C modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'z', // no flags - NX_ASCIISET, 'Z', // AlphaShift - NX_ASCIISET, CTRL('Z'), // Ctrl - NX_ASCIISET, CTRL('Z'), // AlphaShift Ctrl - NX_ASCIISET, 0xcf, // Alt - NX_SYMBOLSET, 0x57, // AlphaShift Alt - NX_ASCIISET, CTRL('Z'), // Ctrl Alt - NX_ASCIISET, CTRL('Z'), // AlphaShift Ctrl Alt - // Key 0x2D modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'x', // no flags - NX_ASCIISET, 'X', // AlphaShift - NX_ASCIISET, CTRL('X'), // Ctrl - NX_ASCIISET, CTRL('X'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xb4, // Alt - NX_SYMBOLSET, 0xce, // AlphaShift Alt - NX_ASCIISET, CTRL('X'), // Ctrl Alt - NX_ASCIISET, CTRL('X'), // AlphaShift Ctrl Alt - // Key 0x2E modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'c', // no flags - NX_ASCIISET, 'C', // AlphaShift - NX_ASCIISET, CTRL('C'), // Ctrl - NX_ASCIISET, CTRL('C'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xe3, // Alt - NX_SYMBOLSET, 0xd3, // AlphaShift Alt - NX_ASCIISET, CTRL('C'), // Ctrl Alt - NX_ASCIISET, CTRL('C'), // AlphaShift Ctrl Alt - // Key 0x2F modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'v', // no flags - NX_ASCIISET, 'V', // AlphaShift - NX_ASCIISET, CTRL('V'), // Ctrl - NX_ASCIISET, CTRL('V'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xd6, // Alt - NX_SYMBOLSET, 0xe0, // AlphaShift Alt - NX_ASCIISET, CTRL('V'), // Ctrl Alt - NX_ASCIISET, CTRL('V'), // AlphaShift Ctrl Alt - // Key 0x30 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'b', // no flags - NX_ASCIISET, 'B', // AlphaShift - NX_ASCIISET, CTRL('B'), // Ctrl - NX_ASCIISET, CTRL('B'), // AlphaShift Ctrl - NX_SYMBOLSET, 0xe5, // Alt - NX_SYMBOLSET, 0xf2, // AlphaShift Alt - NX_ASCIISET, CTRL('B'), // Ctrl Alt - NX_ASCIISET, CTRL('B'), // AlphaShift Ctrl Alt - // Key 0x31 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'n', // no flags - NX_ASCIISET, 'N', // AlphaShift - NX_ASCIISET, CTRL('N'), // Ctrl - NX_ASCIISET, CTRL('N'), // AlphaShift Ctrl - NX_ASCIISET, 0xc4, // Alt - NX_SYMBOLSET, 0xaf, // AlphaShift Alt - NX_ASCIISET, CTRL('N'), // Ctrl Alt - NX_ASCIISET, CTRL('N'), // AlphaShift Ctrl Alt - // Key 0x32 modifier key mask bits (0x0d) - (1<<NX_MODIFIERKEY_ALPHALOCK)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, 'm', // no flags - NX_ASCIISET, 'M', // AlphaShift - NX_ASCIISET, '\r', // Ctrl - NX_ASCIISET, '\r', // AlphaShift Ctrl - NX_SYMBOLSET, 0x6d, // Alt - NX_SYMBOLSET, 0xd8, // AlphaShift Alt - NX_ASCIISET, '\r', // Ctrl Alt - NX_ASCIISET, '\r', // AlphaShift Ctrl Alt - // Key 0x33 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, ',', // no flags - NX_ASCIISET, '<', // Shift - NX_ASCIISET, 0xcb, // Alt - NX_SYMBOLSET, 0xa3, // Shift Alt - // Key 0x34 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '.', // no flags - NX_ASCIISET, '>', // Shift - NX_ASCIISET, 0xbc, // Alt - NX_SYMBOLSET, 0xb3, // Shift Alt - // Key 0x35 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '/', // no flags - NX_ASCIISET, '?', // Shift - NX_SYMBOLSET, 0xb8, // Alt - NX_ASCIISET, 0xbf, // Shift Alt - 0xff, // Key 0x36 unassigned - Right Shift - // Key 0x37 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '*', // all - 0xff, // Key 0x38 unassigned - Left Alt - // Key 0x39 modifier key mask bits (0x0c) - (1<<NX_MODIFIERKEY_CONTROL)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, ' ', // no flags - NX_ASCIISET, CTRL('@'), // Ctrl - NX_ASCIISET, 0x80, // Alt - NX_ASCIISET, CTRL('@'), // Ctrl Alt - 0xff, // Key 0x3A unassigned - CAPS LOCK - 0xff, // Key 0x3B unassigned - F1 - 0xff, // Key 0x3C unassigned - F2 - 0xff, // Key 0x3D unassigned - F3 - 0xff, // Key 0x3E unassigned - F4 - 0xff, // Key 0x3F unassigned - F5 - 0xff, // Key 0x40 unassigned - F6 - 0xff, // Key 0x41 unassigned - F7 - 0xff, // Key 0x42 unassigned - F8 - 0xff, // Key 0x43 unassigned - F9 - 0xff, // Key 0x44 unassigned - F10 - // Key 0x45 modifier key mask bits (0x0a) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '`', // no flags - NX_ASCIISET, '~', // Shift - NX_ASCIISET, '`', // Alt - NX_SYMBOLSET, 0xbb, // Shift Alt - 0xff, // Key 0x46 unassigned - // Key 0x47 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '7', // all - // Key 0x48 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '8', // all - // Key 0x49 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '9', // all - // Key 0x4A modifier key mask bits (0x00) - 0, - NX_SYMBOLSET, 0x2d, // all - // Key 0x4B modifier key mask bits (0x00) - 0, - NX_ASCIISET, '4', // all - // Key 0x4C modifier key mask bits (0x00) - 0, - NX_ASCIISET, '5', // all - // Key 0x4D modifier key mask bits (0x00) - 0, - NX_ASCIISET, '6', // all - // Key 0x4E modifier key mask bits (0x00) - 0, - NX_ASCIISET, '+', // all - // Key 0x4F modifier key mask bits (0x00) - 0, - NX_ASCIISET, '1', // all - // Key 0x50 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '2', // all - // Key 0x51 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '3', // all - // Key 0x52 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '0', // all - // Key 0x53 modifier key mask bits (0x00) - 0, - NX_ASCIISET, '.', // all - 0xff, // Key 0x54 unassigned - 0xff, // Key 0x55 unassigned - 0xff, // Key 0x56 unassigned - 0xff, // Key 0x57 unassigned - F11 - 0xff, // Key 0x58 unassigned - F12 - 0xff, // Key 0x59 unassigned - 0xff, // Key 0x5A unassigned - 0xff, // Key 0x5B unassigned - 0xff, // Key 0x5C unassigned - 0xff, // Key 0x5D unassigned - 0xff, // Key 0x5E unassigned - 0xff, // Key 0x5F unassigned - 0xff, // Key 0x60 unassigned - Right Ctrl - 0xff, // Key 0x61 unassigned - Right Alt - // Key 0x62 modifier key mask bits (0x00) - 0, - NX_ASCIISET, CTRL('C'), // all - // Key 0x63 modifier key mask bits (0x0e) - (1<<NX_MODIFIERKEY_SHIFT)|(1<<NX_MODIFIERKEY_CONTROL)| - (1<<NX_MODIFIERKEY_ALTERNATE), - NX_ASCIISET, '/', // no flags - NX_ASCIISET, '\\', // Shift - NX_ASCIISET, '/', // Ctrl - NX_ASCIISET, CTRL('\\'), // Shift Ctrl - NX_ASCIISET, '/', // Alt - NX_ASCIISET, '\\', // Shift Alt - NX_ASCIISET, CTRL('@'), // Ctrl Alt - 0x0a, CTRL('@'), // Shift Ctrl Alt - // Key 0x64 modifier key mask bits (0x00) - 0, - NX_SYMBOLSET, 0xad, // all - // Key 0x65 modifier key mask bits (0x00) - 0, - NX_SYMBOLSET, 0xaf, // all - // Key 0x66 modifier key mask bits (0x00) - 0, - NX_SYMBOLSET, 0xac, // all - // Key 0x67 modifier key mask bits (0x00) - 0, - NX_SYMBOLSET, 0xae, // all - 0, // Sequence Definitions - 9, // special keys - 0x00, 0x68, // Sound Up - 0x01, 0x69, // Sound Down - 0x02, 0x6A, // Brightness Up - 0x03, 0x6B, // Brightness Down - 0x04, 0x3A, // Caps Lock - 0x05, 0x3B, // Help Key - 0x06, 0x47, // Power Key - 0x07, 0x48, // Up Arrow - 0x08, 0x50 // Down Arrow - }; - - *length = sizeof(defaultKeymapForPC); - return defaultKeymapForPC; -} diff --git a/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.h b/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.h deleted file mode 100644 index 0db532e58..000000000 --- a/iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2KEYBOARD_H -#define _APPLEPS2KEYBOARD_H - -#include <IOKit/ps2/ApplePS2KeyboardDevice.h> -#include <IOKit/hidsystem/IOHIKeyboard.h> - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Definitions used to keep track of key state. Key up/down state is tracked -// in a bit list. Bits are set for key-down, and cleared for key-up. The bit -// vector and macros for it's manipulation are defined here. -// - -#define KBV_NUM_KEYCODES 128 -#define KBV_BITS_PER_UNIT 32 // for UInt32 -#define KBV_BITS_MASK 31 -#define KBV_BITS_SHIFT 5 // 1<<5 == 32, for cheap divide -#define KBV_NUNITS ((KBV_NUM_KEYCODES + \ - (KBV_BITS_PER_UNIT-1))/KBV_BITS_PER_UNIT) - -#define KBV_KEYDOWN(n, bits) \ - (bits)[((n)>>KBV_BITS_SHIFT)] |= (1 << ((n) & KBV_BITS_MASK)) - -#define KBV_KEYUP(n, bits) \ - (bits)[((n)>>KBV_BITS_SHIFT)] &= ~(1 << ((n) & KBV_BITS_MASK)) - -#define KBV_IS_KEYDOWN(n, bits) \ - (((bits)[((n)>>KBV_BITS_SHIFT)] & (1 << ((n) & KBV_BITS_MASK))) != 0) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ApplePS2Keyboard Class Declaration -// - -class ApplePS2Keyboard : public IOHIKeyboard -{ - OSDeclareDefaultStructors(ApplePS2Keyboard); - -private: - ApplePS2KeyboardDevice * _device; - UInt32 _keyBitVector[KBV_NUNITS]; - UInt8 _extendCount; - UInt8 _interruptHandlerInstalled:1; - UInt8 _ledState; - - virtual bool dispatchKeyboardEventWithScancode(UInt8 scanCode); - virtual void setCommandByte(UInt8 setBits, UInt8 clearBits); - virtual void setLEDs(UInt8 ledState); - virtual void setKeyboardEnable(bool enable); - -protected: - virtual const unsigned char * defaultKeymapOfLength(UInt32 * length); - virtual void setAlphaLockFeedback(bool locked); - virtual UInt32 maxKeyCodes(); - -public: - virtual bool init(OSDictionary * properties); - virtual ApplePS2Keyboard * probe(IOService * provider, SInt32 * score); - - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); - - virtual void interruptOccurred(UInt8 scanCode); - - virtual UInt32 deviceType(); - virtual UInt32 interfaceID(); -}; - -#endif /* _APPLEPS2KEYBOARD_H */ diff --git a/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.cpp b/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.cpp deleted file mode 100644 index 3afd11552..000000000 --- a/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include "ApplePS2Mouse.h" - -// ============================================================================= -// ApplePS2Mouse Class Implementation -// - -#define super IOHIPointing -OSDefineMetaClassAndStructors(ApplePS2Mouse, IOHIPointing); - -UInt32 ApplePS2Mouse::deviceType() { return NX_EVS_DEVICE_TYPE_MOUSE; }; -UInt32 ApplePS2Mouse::interfaceID() { return NX_EVS_DEVICE_INTERFACE_BUS_ACE; }; - -IOItemCount ApplePS2Mouse::buttonCount() { return 3; }; -IOFixed ApplePS2Mouse::resolution() { return _resolution; }; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Mouse::init(OSDictionary * properties) -{ - // - // Initialize this object's minimal state. This is invoked right after this - // object is instantiated. - // - - if (!super::init(properties)) return false; - - _device = 0; - _interruptHandlerInstalled = false; - _packetByteCount = 0; - _packetLength = kPacketLengthStandard; - _resolution = (150) << 16; // (default is 150 dpi; 6 counts/mm) - _type = kMouseTypeStandard; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ApplePS2Mouse * ApplePS2Mouse::probe(IOService * provider, SInt32 * score) -{ - // - // The driver has been instructed to verify the presence of the actual - // hardware we represent. We are guaranteed by the controller that the - // mouse clock is enabled and the mouse itself is disabled (thus it - // won't send any asynchronous mouse data that may mess up the - // responses expected by the commands we send it). - // - - ApplePS2MouseDevice * device = (ApplePS2MouseDevice *)provider; - PS2Request * request = device->allocateRequest(); - bool success; - - if (!super::probe(provider, score)) return 0; - - // - // Check to see if acknowledges are being received for commands to the mouse. - // - - // (get information command) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_TransmitToMouse; - request->commands[1].command = kPS2C_WriteDataPort; - request->commands[1].inOrOut = kDP_GetMouseInformation; - request->commands[2].command = kPS2C_ReadDataPortAndCompare; - request->commands[2].inOrOut = kSC_Acknowledge; - request->commands[3].command = kPS2C_ReadDataPort; - request->commands[3].inOrOut = 0; - request->commands[4].command = kPS2C_ReadDataPort; - request->commands[4].inOrOut = 0; - request->commands[5].command = kPS2C_ReadDataPort; - request->commands[5].inOrOut = 0; - request->commandsCount = 6; - device->submitRequestAndBlock(request); - - // (free the request) - success = (request->commandsCount == 6); - device->freeRequest(request); - - return (success) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Mouse::start(IOService * provider) -{ - // - // The driver has been instructed to start. This is called after a - // successful probe and match. - // - - if (!super::start(provider)) return false; - - // - // Maintain a pointer to and retain the provider object. - // - - _device = (ApplePS2MouseDevice *)provider; - _device->retain(); - - // - // Install our driver's interrupt handler, for asynchronous data delivery. - // - - _device->installInterruptAction(this, - (PS2InterruptAction)&ApplePS2Mouse::interruptOccurred); - _interruptHandlerInstalled = true; - - // - // Obtain our mouse's resolution and sampling rate. - // - - switch (getMouseInformation() & 0x00FF00) - { - case 0x0000: _resolution = (25) << 16; break; // 25 dpi - case 0x0100: _resolution = (50) << 16; break; // 50 dpi - case 0x0200: _resolution = (100) << 16; break; // 100 dpi - case 0x0300: _resolution = (200) << 16; break; // 200 dpi - default: _resolution = (150) << 16; break; // 150 dpi - } - - // - // Enable the Intellimouse mode, should this be an Intellimouse. - // - - if ( setIntellimouseMode() == true ) - { - _packetLength = kPacketLengthIntellimouse; - _type = kMouseTypeIntellimouse; - } - - // - // Enable the mouse clock (should already be so) and the mouse IRQ line. - // - - setCommandByte(kCB_EnableMouseIRQ, kCB_DisableMouseClock); - - // - // Finally, we enable the mouse itself, so that it may start reporting - // mouse events. - // - - setMouseEnable(true); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::stop(IOService * provider) -{ - // - // The driver has been instructed to stop. Note that we must break all - // connections to other service objects now (ie. no registered actions, - // no pointers and retains to objects, etc), if any. - // - - assert(_device == provider); - - // - // Disable the mouse itself, so that it may stop reporting mouse events. - // - - setMouseEnable(false); - - // - // Disable the mouse clock and the mouse IRQ line. - // - - setCommandByte(kCB_DisableMouseClock, kCB_EnableMouseIRQ); - - // - // Uninstall the interrupt handler. - // - - if ( _interruptHandlerInstalled ) _device->uninstallInterruptAction(); - _interruptHandlerInstalled = false; - - // - // Release the pointer to the provider object. - // - - _device->release(); - _device = 0; - - super::stop(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::interruptOccurred(UInt8 data) // PS2InterruptAction -{ - // - // This will be invoked automatically from our device when asynchronous mouse - // needs to be delivered. Process the mouse data. Do NOT send any BLOCKING - // commands to our device in this context. - // - // We ignore all bytes until we see the start of a packet, otherwise the mouse - // packets may get out of sequence and things will get very confusing. - // - - if (_packetByteCount == 0 && ((data == kSC_Acknowledge) || !(data & 0x08))) - { - IOLog("%s: Unexpected data from PS/2 controller.\n", getName()); - return; - } - - // - // Add this byte to the packet buffer. If the packet is complete, that is, - // we have the three bytes, dispatch this packet for processing. - // - - _packetBuffer[_packetByteCount++] = data; - - if (_packetByteCount == _packetLength) - { - dispatchRelativePointerEventWithPacket(_packetBuffer); - _packetByteCount = 0; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::dispatchRelativePointerEventWithPacket(UInt8 * packet) -{ - // - // Process the three byte mouse packet that was retreived from the mouse. - // The format of the bytes is as follows: - // - // 7 6 5 4 3 2 1 0 - // YO XO YS XS 1 M R L - // X7 X6 X5 X4 X3 X3 X1 X0 - // Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 - // Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 <- fourth byte returned only for Intellimouse type - // - - UInt32 buttons = 0; - SInt32 dx; - SInt32 dy; - SInt32 dz; - AbsoluteTime now; - - if ( !(packet[0] & 0x1) ) buttons |= 0x1; // left button (bit 0 in packet) - if ( !(packet[0] & 0x2) ) buttons |= 0x2; // right button (bit 1 in packet) - if ( !(packet[0] & 0x4) ) buttons |= 0x4; // middle button (bit 2 in packet) - - dx = ((packet[0] & 0x10) ? 0xffffff00 : 0 ) | packet[1]; - dy = -(((packet[0] & 0x20) ? 0xffffff00 : 0 ) | packet[2]); - dz = (SInt32)((SInt8)packet[3]); - - clock_get_uptime(&now); - - dispatchRelativePointerEvent(dx, dy, buttons, now); - - return; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::setMouseEnable(bool enable) -{ - // - // Instructs the mouse to start or stop the reporting of mouse events. - // Be aware that while the mouse is enabled, asynchronous mouse events - // may arrive in the middle of command sequences sent to the controller, - // and may get confused for expected command responses. - // - // It is safe to issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - - // (mouse enable/disable command) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_TransmitToMouse; - request->commands[1].command = kPS2C_WriteDataPort; - request->commands[1].inOrOut = (enable)?kDP_Enable:kDP_SetDefaultsAndDisable; - request->commands[2].command = kPS2C_ReadDataPortAndCompare; - request->commands[2].inOrOut = kSC_Acknowledge; - request->commandsCount = 3; - _device->submitRequest(request); // asynchronous, auto-free'd -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::setMouseSampleRate(UInt8 sampleRate) -{ - // - // Instructs the mouse to change its sampling rate to the given value, in - // reports per second. - // - // It is safe to issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - - // (set mouse sample rate command) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_TransmitToMouse; - request->commands[1].command = kPS2C_WriteDataPort; - request->commands[1].inOrOut = kDP_SetMouseSampleRate; - request->commands[2].command = kPS2C_ReadDataPortAndCompare; - request->commands[2].inOrOut = kSC_Acknowledge; - request->commands[3].command = kPS2C_WriteCommandPort; - request->commands[3].inOrOut = kCP_TransmitToMouse; - request->commands[4].command = kPS2C_WriteDataPort; - request->commands[4].inOrOut = sampleRate; - request->commands[5].command = kPS2C_ReadDataPortAndCompare; - request->commands[5].inOrOut = kSC_Acknowledge; - request->commandsCount = 6; - _device->submitRequest(request); // asynchronous, auto-free'd -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Mouse::setIntellimouseMode() -{ - // - // Determines whether this mouse is a Microsoft Intellimouse, and if it is, - // it enables it (the mouse will send 4 byte packets for mouse events from - // then on). Returns true if the Intellimouse mode was succesfully enabled. - // - // Do NOT issue this request from the interrupt/completion context. - // - - UInt32 mouseInfo; - bool isIntellimouse; - - // - // Obtain the current sample rate, in order that we may restore it after - // the Intellimouse command sequence completes. - // - - mouseInfo = getMouseInformation(); - - if (mouseInfo == (UInt32)(-1)) return false; - - // - // Generate the special command sequence to enable the 'Intellimouse' mode. - // The sequence is to set the sampling rate to 200, 100, then 80, at which - // point the mouse will start sending 4 byte packets for mouse events and - // return a mouse ID of 3. - // - - setMouseSampleRate(200); - setMouseSampleRate(100); - setMouseSampleRate(80 ); - - // - // Determine whether we have an Intellimouse by asking for the mouse's ID. - // - - isIntellimouse = ( getMouseID() == kMouseTypeIntellimouse ); - - // - // Restore the original sampling rate, before we obliterated it. - // - - setMouseSampleRate(mouseInfo & 0x0000FF); - - return isIntellimouse; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 ApplePS2Mouse::getMouseInformation() -{ - // - // Asks the mouse to transmit its three information bytes. Should the - // mouse not respond, a value of (UInt32)(-1) is returned. - // - // Do NOT issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - UInt32 returnValue = (UInt32)(-1); - - // (get information command) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_TransmitToMouse; - request->commands[1].command = kPS2C_WriteDataPort; - request->commands[1].inOrOut = kDP_GetMouseInformation; - request->commands[2].command = kPS2C_ReadDataPortAndCompare; - request->commands[2].inOrOut = kSC_Acknowledge; - request->commands[3].command = kPS2C_ReadDataPort; - request->commands[3].inOrOut = 0; - request->commands[4].command = kPS2C_ReadDataPort; - request->commands[4].inOrOut = 0; - request->commands[5].command = kPS2C_ReadDataPort; - request->commands[5].inOrOut = 0; - request->commandsCount = 6; - _device->submitRequestAndBlock(request); - - if (request->commandsCount == 6) // success? - { - returnValue = ((UInt32)request->commands[3].inOrOut << 16) | - ((UInt32)request->commands[4].inOrOut << 8 ) | - ((UInt32)request->commands[5].inOrOut); - } - _device->freeRequest(request); - - return returnValue; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt8 ApplePS2Mouse::getMouseID() -{ - // - // Asks the mouse to transmit its identification byte. Should the mouse - // not respond, a value of (UInt8)(-1) is returned. - // - // Note that some documentation on PS/2 mice implies that two identification - // bytes are returned and not one. This was proven to be false in my tests. - // - // Do NOT issue this request from the interrupt/completion context. - // - - PS2Request * request = _device->allocateRequest(); - UInt8 returnValue = (UInt8)(-1); - - // (get information command) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_TransmitToMouse; - request->commands[1].command = kPS2C_WriteDataPort; - request->commands[1].inOrOut = kDP_GetId; - request->commands[2].command = kPS2C_ReadDataPortAndCompare; - request->commands[2].inOrOut = kSC_Acknowledge; - request->commands[3].command = kPS2C_ReadDataPort; - request->commands[3].inOrOut = 0; - request->commandsCount = 4; - _device->submitRequestAndBlock(request); - - if (request->commandsCount == 4) // success? - returnValue = request->commands[3].inOrOut; - - _device->freeRequest(request); - - return returnValue; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Mouse::setCommandByte(UInt8 setBits, UInt8 clearBits) -{ - // - // Sets the bits setBits and clears the bits clearBits "atomically" in the - // controller's Command Byte. Since the controller does not provide such - // a read-modify-write primitive, we resort to a test-and-set try loop. - // - // Do NOT issue this request from the interrupt/completion context. - // - - UInt8 commandByte; - UInt8 commandByteNew; - PS2Request * request = _device->allocateRequest(); - - do - { - // (read command byte) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_GetCommandByte; - request->commands[1].command = kPS2C_ReadDataPort; - request->commands[1].inOrOut = 0; - request->commandsCount = 2; - _device->submitRequestAndBlock(request); - - // - // Modify the command byte as requested by caller. - // - - commandByte = request->commands[1].inOrOut; - commandByteNew = (commandByte | setBits) & (~clearBits); - - // ("test-and-set" command byte) - request->commands[0].command = kPS2C_WriteCommandPort; - request->commands[0].inOrOut = kCP_GetCommandByte; - request->commands[1].command = kPS2C_ReadDataPortAndCompare; - request->commands[1].inOrOut = commandByte; - request->commands[2].command = kPS2C_WriteCommandPort; - request->commands[2].inOrOut = kCP_SetCommandByte; - request->commands[3].command = kPS2C_WriteDataPort; - request->commands[3].inOrOut = commandByteNew; - request->commandsCount = 4; - _device->submitRequestAndBlock(request); - - // - // Repeat this loop if last command failed, that is, if the old command byte - // was modified since we first read it. - // - - } while (request->commandsCount != 4); - - _device->freeRequest(request); -} diff --git a/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.h b/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.h deleted file mode 100644 index ae211bcf4..000000000 --- a/iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2MOUSE_H -#define _APPLEPS2MOUSE_H - -#include <IOKit/ps2/ApplePS2MouseDevice.h> -#include <IOKit/hidsystem/IOHIPointing.h> - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Local Declarations -// - -#define kPacketLengthMax 4 -#define kPacketLengthStandard 3 -#define kPacketLengthIntellimouse 4 - -typedef enum -{ - kMouseTypeStandard = 0x00, - kMouseTypeIntellimouse = 0x03 -} PS2MouseId; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ApplePS2Mouse Class Declaration -// - -class ApplePS2Mouse : public IOHIPointing -{ - OSDeclareDefaultStructors(ApplePS2Mouse); - -private: - ApplePS2MouseDevice * _device; - unsigned _interruptHandlerInstalled:1; - UInt8 _packetBuffer[kPacketLengthMax]; - UInt32 _packetByteCount; - UInt32 _packetLength; - IOFixed _resolution; // (dots per inch) - PS2MouseId _type; - - virtual void dispatchRelativePointerEventWithPacket(UInt8 * packet); - virtual UInt8 getMouseID(); - virtual UInt32 getMouseInformation(); - virtual void setCommandByte(UInt8 setBits, UInt8 clearBits); - virtual bool setIntellimouseMode(); - virtual void setMouseEnable(bool enable); - virtual void setMouseSampleRate(UInt8 sampleRate); - -protected: - virtual IOItemCount buttonCount(); - virtual IOFixed resolution(); - -public: - virtual bool init(OSDictionary * properties); - virtual ApplePS2Mouse * probe(IOService * provider, SInt32 * score); - - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); - - virtual void interruptOccurred(UInt8 data); - - virtual UInt32 deviceType(); - virtual UInt32 interfaceID(); -}; - -#endif /* _APPLEPS2MOUSE_H */ diff --git a/iokit/Drivers/network/AppleBPF/AppleBPF.cpp b/iokit/Drivers/network/AppleBPF/AppleBPF.cpp deleted file mode 100644 index b31f0fffb..000000000 --- a/iokit/Drivers/network/AppleBPF/AppleBPF.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * AppleBPF.cpp - BPF driver class implementation. - * - */ - -// Need to check with Simon on User/Client interface and how to do -// PostLoad, and check on IOBSD (IONeededResource) - -#include <assert.h> -#include <IOKit/IOLib.h> -#include "AppleBPF.h" - -extern "C" { -#include <sys/time.h> -#include <net/bpf.h> -#include <net/bpfdesc.h> -#include <sys/malloc.h> -} - -//------------------------------------------------------------------------ - -#define super IOService -OSDefineMetaClassAndStructors(AppleBPF, IOService); - -//------------------------------------------------------------------------ - - -// ----------------------------------------------------------------------- -// -// This is the first method to be called when an object of this class is -// instantiated. -// -bool AppleBPF::init(OSDictionary * properties) -{ - if (!super::init(properties)) - { IOLog("BPF: super init failed\n"); - return false; - } - - // Do class specific initialization here. Probably not necessary for - // this driver. - -// IOLog("BPF: super init succeeded\n"); - return true; // return 'true' for success, 'false' for failure. -} - -// ----------------------------------------------------------------------- -// -// The driver has been matched, start it up. Do most initialization and -// resource allocation here. -// -bool AppleBPF::start(IOService * provider) -{ int i; - OSNumber *val; - extern struct bpf_d *bpf_dtab; - extern int nbpfilter; - - if (!super::start(provider)) - { IOLog("BPF: super start failed\n"); - return false; - } - - val = OSDynamicCast(OSNumber, getObject("IODevCount")); - if (val == 0) - nbpfilter = DEFAULT_BPF_DEV_COUNT; - else - nbpfilter = val->unsigned32BitValue(); - -// bpfops.bpf_tap = bpf_tap; -// bpfops.bpf_mtap = bpf_mtap; - - bpf_dtab = (struct bpf_d *)IOMalloc(sizeof (struct bpf_d) * nbpfilter); - if (bpf_dtab == NULL) - { IOLog("%s: couldn't get memory for descriptor table\n", - getName()); - return false; - } - - /* - * Mark all the descriptors free - */ - for (i = 0; i < nbpfilter; ++i) - D_MARKFREE(&bpf_dtab[i]); - -// IOLog("AppleBPF::start() called\n"); - - return true; // return 'true' for success, 'false' for failure. -} - -// ----------------------------------------------------------------------- -// -// Release all resources before the driver goes away. -// -void AppleBPF::stop(IOService * provider) -{ extern struct bpf_d *bpf_dtab; - extern int nbpfilter; - - IOFree((void *)bpf_dtab, sizeof (struct bpf_d) * nbpfilter); -} diff --git a/iokit/Drivers/network/AppleBPF/bpf.c b/iokit/Drivers/network/AppleBPF/bpf.c deleted file mode 100644 index d808edb53..000000000 --- a/iokit/Drivers/network/AppleBPF/bpf.c +++ /dev/null @@ -1,1290 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1990, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf.c 8.4 (Berkeley) 1/9/95 - */ - -#define BPFDRV - -#ifndef BPFDRV -#include <net/bpfilter.h> -#endif /* not BPFDRV */ - -#include <string.h> -#include <sys/param.h> -#include <sys/systm.h> -#if 0 -#ifdef BPFDRV -#include <machine/spl.h> -#endif /* BPFDRV */ -#endif -#include <sys/mbuf.h> -#include <sys/buf.h> -#include <sys/time.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/ioctl.h> - -#include <sys/file.h> -#if defined(sparc) && BSD < 199103 -#include <sys/stream.h> -#endif -#include <sys/tty.h> -#include <sys/uio.h> - -#include <sys/protosw.h> -#include <sys/socket.h> -#include <net/if.h> - -#include <net/bpf.h> -#include <net/bpfdesc.h> - -#include <sys/errno.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <sys/kernel.h> - -/* - * Older BSDs don't have kernel malloc. - */ -#if BSD < 199103 -extern bcopy(); -static caddr_t bpf_alloc(); -#include <net/bpf_compat.h> -#define BPF_BUFSIZE (MCLBYTES-8) -#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio) -#else -#include <sys/malloc.h> -#define BPF_BUFSIZE 4096 -#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio) -#endif - -#define PRINET 26 /* interruptible */ - -/* - * The default read buffer size is patchable. - */ -#ifndef BPFDRV -int bpf_bufsize = BPF_BUFSIZE; -#else -extern int bpf_bufsize; -#endif /* BPFDRV */ - -/* - * bpf_iflist is the list of interfaces; each corresponds to an ifnet - * bpf_dtab holds the descriptors, indexed by minor device # - */ -#ifdef BPFDRV -extern struct bpf_if *bpf_iflist; -extern struct bpf_d *bpf_dtab; -extern int nbpfilter; -#else -struct bpf_if *bpf_iflist; -struct bpf_d bpf_dtab[NBPFILTER]; -int nbpfilter = NBPFILTER; -#endif - -#ifdef BPFDRV -#if BSD >= 199207 -/* - * bpfilterattach() is called at boot time in new systems. We do - * nothing here since old systems will not call this. - */ -/* ARGSUSED */ -void -bpfilterattach(n) - int n; -{ -} -#endif -#endif /* BPFDRV */ - -static int bpf_allocbufs __P((struct bpf_d *)); -static int bpf_allocbufs __P((struct bpf_d *)); -static void bpf_freed __P((struct bpf_d *)); -static void bpf_freed __P((struct bpf_d *)); -static void bpf_ifname __P((struct ifnet *, struct ifreq *)); -static void bpf_ifname __P((struct ifnet *, struct ifreq *)); -static void bpf_mcopy __P((const void *, void *, u_int)); -static int bpf_movein __P((struct uio *, int, - struct mbuf **, struct sockaddr *, int *)); -static int bpf_setif __P((struct bpf_d *, struct ifreq *)); -static int bpf_setif __P((struct bpf_d *, struct ifreq *)); -static __inline void - bpf_wakeup __P((struct bpf_d *)); -static void catchpacket __P((struct bpf_d *, u_char *, u_int, - u_int, void (*)(const void *, void *, u_int))); -static void reset_d __P((struct bpf_d *)); - -#ifdef BPFDRV -static int -bpf_movein(uio, linktype, mp, sockp, datlen) - register struct uio *uio; - int linktype, *datlen; - register struct mbuf **mp; - register struct sockaddr *sockp; -{ - struct mbuf *m; - int error; - int len; - int hlen; - - /* - * Build a sockaddr based on the data link layer type. - * We do this at this level because the ethernet header - * is copied directly into the data field of the sockaddr. - * In the case of SLIP, there is no header and the packet - * is forwarded as is. - * Also, we are careful to leave room at the front of the mbuf - * for the link level header. - */ - switch (linktype) { - - case DLT_SLIP: - sockp->sa_family = AF_INET; - hlen = 0; - break; - - case DLT_PPP: - sockp->sa_family = AF_UNSPEC; - hlen = 0; - break; - - case DLT_EN10MB: - sockp->sa_family = AF_UNSPEC; - /* XXX Would MAXLINKHDR be better? */ - hlen = sizeof(struct ether_header); - break; - - case DLT_FDDI: - sockp->sa_family = AF_UNSPEC; - /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */ - hlen = 24; - break; - - case DLT_NULL: - sockp->sa_family = AF_UNSPEC; - hlen = 0; - break; - - default: - return (EIO); - } - - len = uio->uio_resid; - *datlen = len - hlen; - if ((unsigned)len > MCLBYTES) - return (EIO); - - MGETHDR(m, M_WAIT, MT_DATA); - if (m == 0) - return (ENOBUFS); - if (len > MHLEN) { -#if BSD >= 199103 - MCLGET(m, M_WAIT); - if ((m->m_flags & M_EXT) == 0) { -#else - MCLGET(m); - if (m->m_len != MCLBYTES) { -#endif - error = ENOBUFS; - goto bad; - } - } - m->m_len = len; - m->m_pkthdr.len = len; - *mp = m; - /* - * Make room for link header. - */ - if (hlen != 0) { - m->m_len -= hlen; - m->m_pkthdr.len -= hlen; -#if BSD >= 199103 - m->m_data += hlen; /* XXX */ -#else - m->m_off += hlen; -#endif - error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio); - if (error) - goto bad; - } - error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio); - if (!error) - return (0); - bad: - m_freem(m); - return (error); -} - -/* - * Attach file to the bpf interface, i.e. make d listen on bp. - * Must be called at splimp. - */ -static void -bpf_attachd(d, bp) - struct bpf_d *d; - struct bpf_if *bp; -{ - /* - * Point d at bp, and add d to the interface's list of listeners. - * Finally, point the driver's bpf cookie at the interface so - * it will divert packets to bpf. - */ - d->bd_bif = bp; - d->bd_next = bp->bif_dlist; - bp->bif_dlist = d; - -/* *bp->bif_driverp = bp; */ -} - -/* - * Detach a file from its interface. - */ -static void -bpf_detachd(d) - struct bpf_d *d; -{ - struct bpf_d **p; - struct bpf_if *bp; - - bp = d->bd_bif; - /* - * Check if this descriptor had requested promiscuous mode. - * If so, turn it off. - */ - if (d->bd_promisc) { - d->bd_promisc = 0; - if (ifpromisc(bp->bif_ifp, 0)) - /* - * Something is really wrong if we were able to put - * the driver into promiscuous mode, but can't - * take it out. - */ - panic("bpf: ifpromisc failed"); - } - /* Remove d from the interface's descriptor list. */ - p = &bp->bif_dlist; - while (*p != d) { - p = &(*p)->bd_next; - if (*p == 0) - panic("bpf_detachd: descriptor not in list"); - } - *p = (*p)->bd_next; - if (bp->bif_dlist == 0) - /* - * Let the driver know that there are no more listeners. - */ - /* *d->bd_bif->bif_driverp = 0 */; - d->bd_bif = 0; -} -#endif /* BPFDRV */ - -#ifdef BPFDRV -/* - * Open ethernet device. Returns ENXIO for illegal minor device number, - * EBUSY if file is open by another process. - */ -/* ARGSUSED */ -int -bpfopen(dev, flag) - dev_t dev; - int flag; -{ - register struct bpf_d *d; - - if (minor(dev) >= nbpfilter) - return (ENXIO); - /* - * Each minor can be opened by only one process. If the requested - * minor is in use, return EBUSY. - */ - d = &bpf_dtab[minor(dev)]; - if (!D_ISFREE(d)) - return (EBUSY); - - /* Mark "free" and do most initialization. */ - bzero((char *)d, sizeof(*d)); - d->bd_bufsize = bpf_bufsize; - - return (0); -} - -/* - * Close the descriptor by detaching it from its interface, - * deallocating its buffers, and marking it free. - */ -/* ARGSUSED */ -int -bpfclose(dev, flag) - dev_t dev; - int flag; -{ - register struct bpf_d *d = &bpf_dtab[minor(dev)]; - register int s; - - s = splimp(); - if (d->bd_bif) - bpf_detachd(d); - splx(s); - bpf_freed(d); - - return (0); -} - -/* - * Support for SunOS, which does not have tsleep. - */ -#if BSD < 199103 -static -bpf_timeout(arg) - caddr_t arg; -{ - struct bpf_d *d = (struct bpf_d *)arg; - d->bd_timedout = 1; - wakeup(arg); -} - -#define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan) - -int -bpf_sleep(d) - register struct bpf_d *d; -{ - register int rto = d->bd_rtout; - register int st; - - if (rto != 0) { - d->bd_timedout = 0; - timeout(bpf_timeout, (caddr_t)d, rto); - } - st = sleep((caddr_t)d, PRINET|PCATCH); - if (rto != 0) { - if (d->bd_timedout == 0) - untimeout(bpf_timeout, (caddr_t)d); - else if (st == 0) - return EWOULDBLOCK; - } - return (st != 0) ? EINTR : 0; -} -#else -#define BPF_SLEEP tsleep -#endif - -/* - * Rotate the packet buffers in descriptor d. Move the store buffer - * into the hold slot, and the free buffer into the store slot. - * Zero the length of the new store buffer. - */ -#define ROTATE_BUFFERS(d) \ - (d)->bd_hbuf = (d)->bd_sbuf; \ - (d)->bd_hlen = (d)->bd_slen; \ - (d)->bd_sbuf = (d)->bd_fbuf; \ - (d)->bd_slen = 0; \ - (d)->bd_fbuf = 0; -/* - * bpfread - read next chunk of packets from buffers - */ -int -bpfread(dev, uio) - dev_t dev; - register struct uio *uio; -{ - register struct bpf_d *d = &bpf_dtab[minor(dev)]; - int error; - int s; - - /* - * Restrict application to use a buffer the same size as - * as kernel buffers. - */ - if (uio->uio_resid != d->bd_bufsize) - return (EINVAL); - - s = splimp(); - /* - * If the hold buffer is empty, then do a timed sleep, which - * ends when the timeout expires or when enough packets - * have arrived to fill the store buffer. - */ - while (d->bd_hbuf == 0) { - if (d->bd_immediate && d->bd_slen != 0) { - /* - * A packet(s) either arrived since the previous - * read or arrived while we were asleep. - * Rotate the buffers and return what's here. - */ - ROTATE_BUFFERS(d); - break; - } - error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf", - d->bd_rtout); - if (error == EINTR || error == ERESTART) { - splx(s); - return (error); - } - if (error == EWOULDBLOCK) { - /* - * On a timeout, return what's in the buffer, - * which may be nothing. If there is something - * in the store buffer, we can rotate the buffers. - */ - if (d->bd_hbuf) - /* - * We filled up the buffer in between - * getting the timeout and arriving - * here, so we don't need to rotate. - */ - break; - - if (d->bd_slen == 0) { - splx(s); - return (0); - } - ROTATE_BUFFERS(d); - break; - } - } - /* - * At this point, we know we have something in the hold slot. - */ - splx(s); - - /* - * Move data from hold buffer into user space. - * We know the entire buffer is transferred since - * we checked above that the read buffer is bpf_bufsize bytes. - */ - error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio); - - s = splimp(); - d->bd_fbuf = d->bd_hbuf; - d->bd_hbuf = 0; - d->bd_hlen = 0; - splx(s); - - return (error); -} - - -/* - * If there are processes sleeping on this descriptor, wake them up. - */ -static __inline void -bpf_wakeup(d) - register struct bpf_d *d; -{ - wakeup((caddr_t)d); - selwakeup(&d->bd_sel); - d->bd_sel.si_thread = 0; -} - -int -bpfwrite(dev, uio) - dev_t dev; - struct uio *uio; -{ - register struct bpf_d *d = &bpf_dtab[minor(dev)]; - struct ifnet *ifp; - struct mbuf *m; - int error, s; - static struct sockaddr dst; - int datlen; - - if (d->bd_bif == 0) - return (ENXIO); - - ifp = d->bd_bif->bif_ifp; - - if (uio->uio_resid == 0) - return (0); - - error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen); - if (error) - return (error); - - if (datlen > ifp->if_mtu) - return (EMSGSIZE); - - s = splnet(); -#if BSD >= 199103 - error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0); -#else - error = (*ifp->if_output)(ifp, m, &dst); -#endif - splx(s); - /* - * The driver frees the mbuf. - */ - return (error); -} - -/* - * Reset a descriptor by flushing its packet buffer and clearing the - * receive and drop counts. Should be called at splimp. - */ -static void -reset_d(d) - struct bpf_d *d; -{ - if (d->bd_hbuf) { - /* Free the hold buffer. */ - d->bd_fbuf = d->bd_hbuf; - d->bd_hbuf = 0; - } - d->bd_slen = 0; - d->bd_hlen = 0; - d->bd_rcount = 0; - d->bd_dcount = 0; -} - -/* - * FIONREAD Check for read packet available. - * SIOCGIFADDR Get interface address - convenient hook to driver. - * BIOCGBLEN Get buffer len [for read()]. - * BIOCSETF Set ethernet read filter. - * BIOCFLUSH Flush read packet buffer. - * BIOCPROMISC Put interface into promiscuous mode. - * BIOCGDLT Get link layer type. - * BIOCGETIF Get interface name. - * BIOCSETIF Set interface. - * BIOCSRTIMEOUT Set read timeout. - * BIOCGRTIMEOUT Get read timeout. - * BIOCGSTATS Get packet stats. - * BIOCIMMEDIATE Set immediate mode. - * BIOCVERSION Get filter language version. - */ -/* ARGSUSED */ -int -bpfioctl(dev, cmd, addr, flag) - dev_t dev; - u_long cmd; - caddr_t addr; - int flag; -{ - register struct bpf_d *d = &bpf_dtab[minor(dev)]; - int s, error = 0; - - switch (cmd) { - - default: - error = EINVAL; - break; - - /* - * Check for read packet available. - */ - case FIONREAD: - { - int n; - - s = splimp(); - n = d->bd_slen; - if (d->bd_hbuf) - n += d->bd_hlen; - splx(s); - - *(int *)addr = n; - break; - } - - case SIOCGIFADDR: - { - struct ifnet *ifp; - - if (d->bd_bif == 0) - error = EINVAL; - else { - ifp = d->bd_bif->bif_ifp; - error = (*ifp->if_ioctl)(ifp, cmd, addr); - } - break; - } - - /* - * Get buffer len [for read()]. - */ - case BIOCGBLEN: - *(u_int *)addr = d->bd_bufsize; - break; - - /* - * Set buffer length. - */ - case BIOCSBLEN: -#if BSD < 199103 - error = EINVAL; -#else - if (d->bd_bif != 0) - error = EINVAL; - else { - register u_int size = *(u_int *)addr; - - if (size > BPF_MAXBUFSIZE) - *(u_int *)addr = size = BPF_MAXBUFSIZE; - else if (size < BPF_MINBUFSIZE) - *(u_int *)addr = size = BPF_MINBUFSIZE; - d->bd_bufsize = size; - } -#endif - break; - - /* - * Set link layer read filter. - */ - case BIOCSETF: - error = bpf_setf(d, (struct bpf_program *)addr); - break; - - /* - * Flush read packet buffer. - */ - case BIOCFLUSH: - s = splimp(); - reset_d(d); - splx(s); - break; - - /* - * Put interface into promiscuous mode. - */ - case BIOCPROMISC: - if (d->bd_bif == 0) { - /* - * No interface attached yet. - */ - error = EINVAL; - break; - } - s = splimp(); - if (d->bd_promisc == 0) { - error = ifpromisc(d->bd_bif->bif_ifp, 1); - if (error == 0) - d->bd_promisc = 1; - } - splx(s); - break; - - /* - * Get device parameters. - */ - case BIOCGDLT: - if (d->bd_bif == 0) - error = EINVAL; - else - *(u_int *)addr = d->bd_bif->bif_dlt; - break; - - /* - * Set interface name. - */ - case BIOCGETIF: - if (d->bd_bif == 0) - error = EINVAL; - else - bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); - break; - - /* - * Set interface. - */ - case BIOCSETIF: - error = bpf_setif(d, (struct ifreq *)addr); - break; - - /* - * Set read timeout. - */ - case BIOCSRTIMEOUT: - { - struct timeval *tv = (struct timeval *)addr; - u_long msec; - - /* Compute number of milliseconds. */ - msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; - /* Scale milliseconds to ticks. Assume hard - clock has millisecond or greater resolution - (i.e. tick >= 1000). For 10ms hardclock, - tick/1000 = 10, so rtout<-msec/10. */ - d->bd_rtout = msec / (tick / 1000); - break; - } - - /* - * Get read timeout. - */ - case BIOCGRTIMEOUT: - { - struct timeval *tv = (struct timeval *)addr; - u_long msec = d->bd_rtout; - - msec *= tick / 1000; - tv->tv_sec = msec / 1000; - tv->tv_usec = msec % 1000; - break; - } - - /* - * Get packet stats. - */ - case BIOCGSTATS: - { - struct bpf_stat *bs = (struct bpf_stat *)addr; - - bs->bs_recv = d->bd_rcount; - bs->bs_drop = d->bd_dcount; - break; - } - - /* - * Set immediate mode. - */ - case BIOCIMMEDIATE: - d->bd_immediate = *(u_int *)addr; - break; - - case BIOCVERSION: - { - struct bpf_version *bv = (struct bpf_version *)addr; - - bv->bv_major = BPF_MAJOR_VERSION; - bv->bv_minor = BPF_MINOR_VERSION; - break; - } - } - return (error); -} - -/* - * Set d's packet filter program to fp. If this file already has a filter, - * free it and replace it. Returns EINVAL for bogus requests. - */ -int -bpf_setf(d, fp) - struct bpf_d *d; - struct bpf_program *fp; -{ - struct bpf_insn *fcode, *old; - u_int flen, size; - int s; - - old = d->bd_filter; - if (fp->bf_insns == 0) { - if (fp->bf_len != 0) - return (EINVAL); - s = splimp(); - d->bd_filter = 0; - reset_d(d); - splx(s); - if (old != 0) - FREE((caddr_t)old, M_DEVBUF); - return (0); - } - flen = fp->bf_len; - if (flen > BPF_MAXINSNS) - return (EINVAL); - - size = flen * sizeof(*fp->bf_insns); - MALLOC(fcode, struct bpf_insn *, size, M_DEVBUF, M_WAITOK); - if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && - bpf_validate(fcode, (int)flen)) { - s = splimp(); - d->bd_filter = fcode; - reset_d(d); - splx(s); - if (old != 0) - FREE((caddr_t)old, M_DEVBUF); - - return (0); - } - FREE((caddr_t)fcode, M_DEVBUF); - return (EINVAL); -} - -/* - * Detach a file from its current interface (if attached at all) and attach - * to the interface indicated by the name stored in ifr. - * Return an errno or 0. - */ -static int -bpf_setif(d, ifr) - struct bpf_d *d; - struct ifreq *ifr; -{ - struct bpf_if *bp; - char *cp; - int unit, s, error; - - /* - * Separate string into name part and unit number. Put a null - * byte at the end of the name part, and compute the number. - * If the a unit number is unspecified, the default is 0, - * as initialized above. XXX This should be common code. - */ - unit = 0; - cp = ifr->ifr_name; - cp[sizeof(ifr->ifr_name) - 1] = '\0'; - while (*cp++) { - if (*cp >= '0' && *cp <= '9') { - unit = *cp - '0'; - *cp++ = '\0'; - while (*cp) - unit = 10 * unit + *cp++ - '0'; - break; - } - } - /* - * Look through attached interfaces for the named one. - */ - for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) { - struct ifnet *ifp = bp->bif_ifp; - - if (ifp == 0 || unit != ifp->if_unit - || strcmp(ifp->if_name, ifr->ifr_name) != 0) - continue; - /* - * We found the requested interface. - * If it's not up, return an error. - * Allocate the packet buffers if we need to. - * If we're already attached to requested interface, - * just flush the buffer. - */ - if ((ifp->if_flags & IFF_UP) == 0) - return (ENETDOWN); - - if (d->bd_sbuf == 0) { - error = bpf_allocbufs(d); - if (error != 0) - return (error); - } - s = splimp(); - if (bp != d->bd_bif) { - if (d->bd_bif) - /* - * Detach if attached to something else. - */ - bpf_detachd(d); - - bpf_attachd(d, bp); - } - reset_d(d); - splx(s); - return (0); - } - /* Not found. */ - return (ENXIO); -} - -/* - * Convert an interface name plus unit number of an ifp to a single - * name which is returned in the ifr. - */ -static void -bpf_ifname(ifp, ifr) - struct ifnet *ifp; - struct ifreq *ifr; -{ - char *s = ifp->if_name; - char *d = ifr->ifr_name; - - while ((*d++ = *s++) != 0) - continue; - /* XXX Assume that unit number is less than 10. */ - *d++ = ifp->if_unit + '0'; - *d = '\0'; -} - -/* - * The new select interface passes down the proc pointer; the old select - * stubs had to grab it out of the user struct. This glue allows either case. - */ -#if BSD < 199103 -int -bpfselect(dev, rw) - register dev_t dev; - int rw; -{ - return (bpf_select(dev, rw, u.u_procp)); -} -#endif - -/* - * Support for select() system call - * - * Return true iff the specific operation will not block indefinitely. - * Otherwise, return false but make a note that a selwakeup() must be done. - */ -int -bpf_select(dev, rw, p) - register dev_t dev; - int rw; - struct proc *p; -{ - register struct bpf_d *d; - register int s; - - if (rw != FREAD) - return (0); - /* - * An imitation of the FIONREAD ioctl code. - */ - d = &bpf_dtab[minor(dev)]; - - s = splimp(); - if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) { - /* - * There is data waiting. - */ - splx(s); - return (1); - } -#if BSD >= 199103 - selrecord(p, &d->bd_sel); -#else - /* - * No data ready. If there's already a select() waiting on this - * minor device then this is a collision. This shouldn't happen - * because minors really should not be shared, but if a process - * forks while one of these is open, it is possible that both - * processes could select on the same descriptor. - */ - if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait) - d->bd_selcoll = 1; - else - d->bd_selproc = p; -#endif - splx(s); - return (0); -} -#endif /* BPFDRV */ - -/* - * Incoming linkage from device drivers. Process the packet pkt, of length - * pktlen, which is stored in a contiguous buffer. The packet is parsed - * by each process' filter, and if accepted, stashed into the corresponding - * buffer. - */ -#ifdef BPFDRV -void -bpf_tap(arg, pkt, pktlen) - struct ifnet *ifp; - register u_char *pkt; - register u_int pktlen; -{ - struct bpf_if *bp; - register struct bpf_d *d; - register u_int slen; - /* - * Note that the ipl does not have to be raised at this point. - * The only problem that could arise here is that if two different - * interfaces shared any data. This is not the case. - */ - bp = (struct bpf_if *)arg; - for (d = bp->bif_dlist; d != 0; d = d->bd_next) { - ++d->bd_rcount; - slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen); - if (slen != 0) - catchpacket(d, pkt, pktlen, slen, bcopy); - } -} - -/* - * Copy data from an mbuf chain into a buffer. This code is derived - * from m_copydata in sys/uipc_mbuf.c. - */ -static void -bpf_mcopy(src_arg, dst_arg, len) - const void *src_arg; - void *dst_arg; - register u_int len; -{ - register const struct mbuf *m; - register u_int count; - u_char *dst; - - m = src_arg; - dst = dst_arg; - while (len > 0) { - if (m == 0) - panic("bpf_mcopy"); - count = min(m->m_len, len); - bcopy(mtod(m, caddr_t), (caddr_t)dst, count); - m = m->m_next; - dst += count; - len -= count; - } -} -#endif /* BPFDRV */ - -#ifdef BPFDRV -/* - * Incoming linkage from device drivers, when packet is in an mbuf chain. - */ -void -bpf_mtap(arg, m) - caddr_t arg; - struct mbuf *m; -{ - struct bpf_if *bp = (struct bpf_if *)arg; - struct bpf_d *d; - u_int pktlen, slen; - struct mbuf *m0; - - pktlen = 0; - for (m0 = m; m0 != 0; m0 = m0->m_next) - pktlen += m0->m_len; - - for (d = bp->bif_dlist; d != 0; d = d->bd_next) { - ++d->bd_rcount; - slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0); - if (slen != 0) - catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy); - } -} -#endif /* BPFDRV */ - -#ifdef BPFDRV -/* - * Move the packet data from interface memory (pkt) into the - * store buffer. Return 1 if it's time to wakeup a listener (buffer full), - * otherwise 0. "copy" is the routine called to do the actual data - * transfer. bcopy is passed in to copy contiguous chunks, while - * bpf_mcopy is passed in to copy mbuf chains. In the latter case, - * pkt is really an mbuf. - */ -static void -catchpacket(d, pkt, pktlen, snaplen, cpfn) - register struct bpf_d *d; - register u_char *pkt; - register u_int pktlen, snaplen; - register void (*cpfn) __P((const void *, void *, u_int)); -{ - register struct bpf_hdr *hp; - register int totlen, curlen; - register int hdrlen = d->bd_bif->bif_hdrlen; - /* - * Figure out how many bytes to move. If the packet is - * greater or equal to the snapshot length, transfer that - * much. Otherwise, transfer the whole packet (unless - * we hit the buffer size limit). - */ - totlen = hdrlen + min(snaplen, pktlen); - if (totlen > d->bd_bufsize) - totlen = d->bd_bufsize; - - /* - * Round up the end of the previous packet to the next longword. - */ - curlen = BPF_WORDALIGN(d->bd_slen); - if (curlen + totlen > d->bd_bufsize) { - /* - * This packet will overflow the storage buffer. - * Rotate the buffers if we can, then wakeup any - * pending reads. - */ - if (d->bd_fbuf == 0) { - /* - * We haven't completed the previous read yet, - * so drop the packet. - */ - ++d->bd_dcount; - return; - } - ROTATE_BUFFERS(d); - bpf_wakeup(d); - curlen = 0; - } - else if (d->bd_immediate) - /* - * Immediate mode is set. A packet arrived so any - * reads should be woken up. - */ - bpf_wakeup(d); - - /* - * Append the bpf header. - */ - hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); -#if BSD >= 199103 - microtime(&hp->bh_tstamp); -#elif defined(sun) - uniqtime(&hp->bh_tstamp); -#else - hp->bh_tstamp = time; -#endif - hp->bh_datalen = pktlen; - hp->bh_hdrlen = hdrlen; - /* - * Copy the packet data into the store buffer and update its length. - */ - (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); - d->bd_slen = curlen + totlen; -} - -/* - * Initialize all nonzero fields of a descriptor. - */ -static int -bpf_allocbufs(d) - register struct bpf_d *d; -{ - MALLOC(d->bd_fbuf, caddr_t, d->bd_bufsize, M_DEVBUF, M_WAITOK); - if (d->bd_fbuf == 0) - return (ENOBUFS); - - MALLOC(d->bd_sbuf, caddr_t, d->bd_bufsize, M_DEVBUF, M_WAITOK); - if (d->bd_sbuf == 0) { - FREE(d->bd_fbuf, M_DEVBUF); - return (ENOBUFS); - } - d->bd_slen = 0; - d->bd_hlen = 0; - return (0); -} - -/* - * Free buffers currently in use by a descriptor. - * Called on close. - */ -static void -bpf_freed(d) - register struct bpf_d *d; -{ - /* - * We don't need to lock out interrupts since this descriptor has - * been detached from its interface and it yet hasn't been marked - * free. - */ - if (d->bd_sbuf != 0) { - FREE(d->bd_sbuf, M_DEVBUF); - if (d->bd_hbuf != 0) - FREE(d->bd_hbuf, M_DEVBUF); - if (d->bd_fbuf != 0) - FREE(d->bd_fbuf, M_DEVBUF); - } - if (d->bd_filter) - FREE((caddr_t)d->bd_filter, M_DEVBUF); - - D_MARKFREE(d); -} -#endif /* BPFDRV */ - -#ifdef BPFDRV -#if BSD >= 199103 -/* XXX This routine belongs in net/if.c. */ -/* - * Set/clear promiscuous mode on interface ifp based on the truth value - * of pswitch. The calls are reference counted so that only the first - * "on" request actually has an effect, as does the final "off" request. - * Results are undefined if the "off" and "on" requests are not matched. - */ -int -ifpromisc(ifp, pswitch) - struct ifnet *ifp; - int pswitch; -{ - struct ifreq ifr; - /* - * If the device is not configured up, we cannot put it in - * promiscuous mode. - */ - if ((ifp->if_flags & IFF_UP) == 0) - return (ENETDOWN); - - if (pswitch) { - if (ifp->if_pcount++ != 0) - return (0); - ifp->if_flags |= IFF_PROMISC; - } else { - if (--ifp->if_pcount > 0) - return (0); - ifp->if_flags &= ~IFF_PROMISC; - } - ifr.ifr_flags = ifp->if_flags; - return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); -} -#endif - -#if BSD < 199103 -/* - * Allocate some memory for bpf. This is temporary SunOS support, and - * is admittedly a hack. - * If resources unavaiable, return 0. - */ -static caddr_t -bpf_alloc(size, canwait) - register int size; - register int canwait; -{ - register struct mbuf *m; - - if ((unsigned)size > (MCLBYTES-8)) - return 0; - - MGET(m, canwait, MT_DATA); - if (m == 0) - return 0; - if ((unsigned)size > (MLEN-8)) { - MCLGET(m); - if (m->m_len != MCLBYTES) { - m_freem(m); - return 0; - } - } - *mtod(m, struct mbuf **) = m; - return mtod(m, caddr_t) + 8; -} -#endif -#endif /* BPFDRV */ diff --git a/iokit/Drivers/network/AppleBPF/bpf_filter.c b/iokit/Drivers/network/AppleBPF/bpf_filter.c deleted file mode 100644 index 09f025c25..000000000 --- a/iokit/Drivers/network/AppleBPF/bpf_filter.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1990, 1991, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93 - */ - -#define BPFDRV - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> - -#if defined(sparc) || defined(hppa) -#define BPF_ALIGN -#endif - -#ifndef BPF_ALIGN -#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) -#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) -#else -#define EXTRACT_SHORT(p)\ - ((u_short)\ - ((u_short)*((u_char *)p+0)<<8|\ - (u_short)*((u_char *)p+1)<<0)) -#define EXTRACT_LONG(p)\ - ((u_int32_t)*((u_char *)p+0)<<24|\ - (u_int32_t)*((u_char *)p+1)<<16|\ - (u_int32_t)*((u_char *)p+2)<<8|\ - (u_int32_t)*((u_char *)p+3)<<0) -#endif - -#ifdef BPFDRV -#ifdef KERNEL -#include <sys/mbuf.h> -#define MINDEX(m, k) \ -{ \ - register int len = m->m_len; \ - \ - while (k >= len) { \ - k -= len; \ - m = m->m_next; \ - if (m == 0) \ - return 0; \ - len = m->m_len; \ - } \ -} - -static int -m_xword(m, k, err) - register struct mbuf *m; - register int k, *err; -{ - register int len; - register u_char *cp, *np; - register struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 4) { - *err = 0; - return EXTRACT_LONG(cp); - } - m0 = m->m_next; - if (m0 == 0 || m0->m_len + len - k < 4) - goto bad; - *err = 0; - np = mtod(m0, u_char *); - switch (len - k) { - - case 1: - return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; - - case 2: - return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | - np[1]; - - default: - return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) | - np[0]; - } - bad: - *err = 1; - return 0; -} - -static int -m_xhalf(m, k, err) - register struct mbuf *m; - register int k, *err; -{ - register int len; - register u_char *cp; - register struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 2) { - *err = 0; - return EXTRACT_SHORT(cp); - } - m0 = m->m_next; - if (m0 == 0) - goto bad; - *err = 0; - return (cp[k] << 8) | mtod(m0, u_char *)[0]; - bad: - *err = 1; - return 0; -} -#endif - -#include <net/bpf.h> - -/* - * Execute the filter program starting at pc on the packet p - * wirelen is the length of the original packet - * buflen is the amount of data present - */ -u_int -bpf_filter(pc, p, wirelen, buflen) - register struct bpf_insn *pc; - register u_char *p; - u_int wirelen; - register u_int buflen; -{ - register u_int32_t A, X; - register int k; - int32_t mem[BPF_MEMWORDS]; - - if (pc == 0) - /* - * No filter means accept all. - */ - return (u_int)-1; -#ifdef lint - A = 0; - X = 0; -#endif - --pc; - while (1) { - ++pc; - switch (pc->code) { - - default: -#ifdef KERNEL - return 0; -#else - abort(); -#endif - case BPF_RET|BPF_K: - return (u_int)pc->k; - - case BPF_RET|BPF_A: - return (u_int)A; - - case BPF_LD|BPF_W|BPF_ABS: - k = pc->k; - if (k + sizeof(int32_t) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } -#ifdef BPF_ALIGN - if (((int)(p + k) & 3) != 0) - A = EXTRACT_LONG(&p[k]); - else -#endif - A = ntohl(*(long *)(p + k)); - continue; - - case BPF_LD|BPF_H|BPF_ABS: - k = pc->k; - if (k + sizeof(short) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xhalf((struct mbuf *)p, k, &merr); - continue; -#else - return 0; -#endif - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, u_char *)[k]; - continue; -#else - return 0; -#endif - } - A = p[k]; - continue; - - case BPF_LD|BPF_W|BPF_LEN: - A = wirelen; - continue; - - case BPF_LDX|BPF_W|BPF_LEN: - X = wirelen; - continue; - - case BPF_LD|BPF_W|BPF_IND: - k = X + pc->k; - if (k + sizeof(int32_t) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } -#ifdef BPF_ALIGN - if (((int)(p + k) & 3) != 0) - A = EXTRACT_LONG(&p[k]); - else -#endif - A = ntohl(*(long *)(p + k)); - continue; - - case BPF_LD|BPF_H|BPF_IND: - k = X + pc->k; - if (k + sizeof(short) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xhalf((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_IND: - k = X + pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, char *)[k]; - continue; -#else - return 0; -#endif - } - A = p[k]; - continue; - - case BPF_LDX|BPF_MSH|BPF_B: - k = pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - X = (mtod(m, char *)[k] & 0xf) << 2; - continue; -#else - return 0; -#endif - } - X = (p[pc->k] & 0xf) << 2; - continue; - - case BPF_LD|BPF_IMM: - A = pc->k; - continue; - - case BPF_LDX|BPF_IMM: - X = pc->k; - continue; - - case BPF_LD|BPF_MEM: - A = mem[pc->k]; - continue; - - case BPF_LDX|BPF_MEM: - X = mem[pc->k]; - continue; - - case BPF_ST: - mem[pc->k] = A; - continue; - - case BPF_STX: - mem[pc->k] = X; - continue; - - case BPF_JMP|BPF_JA: - pc += pc->k; - continue; - - case BPF_JMP|BPF_JGT|BPF_K: - pc += (A > pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_K: - pc += (A >= pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_K: - pc += (A == pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_K: - pc += (A & pc->k) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGT|BPF_X: - pc += (A > X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JGE|BPF_X: - pc += (A >= X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JEQ|BPF_X: - pc += (A == X) ? pc->jt : pc->jf; - continue; - - case BPF_JMP|BPF_JSET|BPF_X: - pc += (A & X) ? pc->jt : pc->jf; - continue; - - case BPF_ALU|BPF_ADD|BPF_X: - A += X; - continue; - - case BPF_ALU|BPF_SUB|BPF_X: - A -= X; - continue; - - case BPF_ALU|BPF_MUL|BPF_X: - A *= X; - continue; - - case BPF_ALU|BPF_DIV|BPF_X: - if (X == 0) - return 0; - A /= X; - continue; - - case BPF_ALU|BPF_AND|BPF_X: - A &= X; - continue; - - case BPF_ALU|BPF_OR|BPF_X: - A |= X; - continue; - - case BPF_ALU|BPF_LSH|BPF_X: - A <<= X; - continue; - - case BPF_ALU|BPF_RSH|BPF_X: - A >>= X; - continue; - - case BPF_ALU|BPF_ADD|BPF_K: - A += pc->k; - continue; - - case BPF_ALU|BPF_SUB|BPF_K: - A -= pc->k; - continue; - - case BPF_ALU|BPF_MUL|BPF_K: - A *= pc->k; - continue; - - case BPF_ALU|BPF_DIV|BPF_K: - A /= pc->k; - continue; - - case BPF_ALU|BPF_AND|BPF_K: - A &= pc->k; - continue; - - case BPF_ALU|BPF_OR|BPF_K: - A |= pc->k; - continue; - - case BPF_ALU|BPF_LSH|BPF_K: - A <<= pc->k; - continue; - - case BPF_ALU|BPF_RSH|BPF_K: - A >>= pc->k; - continue; - - case BPF_ALU|BPF_NEG: - A = -A; - continue; - - case BPF_MISC|BPF_TAX: - X = A; - continue; - - case BPF_MISC|BPF_TXA: - A = X; - continue; - } - } -} - -#ifdef KERNEL -/* - * Return true if the 'fcode' is a valid filter program. - * The constraints are that each jump be forward and to a valid - * code. The code must terminate with either an accept or reject. - * 'valid' is an array for use by the routine (it must be at least - * 'len' bytes long). - * - * The kernel needs to be able to verify an application's filter code. - * Otherwise, a bogus program could easily crash the system. - */ -int -bpf_validate(f, len) - struct bpf_insn *f; - int len; -{ - register int i; - register struct bpf_insn *p; - - for (i = 0; i < len; ++i) { - /* - * Check that that jumps are forward, and within - * the code block. - */ - p = &f[i]; - if (BPF_CLASS(p->code) == BPF_JMP) { - register int from = i + 1; - - if (BPF_OP(p->code) == BPF_JA) { - if (from + p->k >= len) - return 0; - } - else if (from + p->jt >= len || from + p->jf >= len) - return 0; - } - /* - * Check that memory operations use valid addresses. - */ - if ((BPF_CLASS(p->code) == BPF_ST || - (BPF_CLASS(p->code) == BPF_LD && - (p->code & 0xe0) == BPF_MEM)) && - (p->k >= BPF_MEMWORDS || p->k < 0)) - return 0; - /* - * Check for constant division by 0. - */ - if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) - return 0; - } - return BPF_CLASS(f[len - 1].code) == BPF_RET; -} -#endif -#endif /* BPFDRV */ diff --git a/iokit/Drivers/network/drvIntel82557/i82557.cpp b/iokit/Drivers/network/drvIntel82557/i82557.cpp deleted file mode 100644 index 152f1a884..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557.cpp +++ /dev/null @@ -1,820 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. All rights reserved. - * - * i82557.cpp - * - * HISTORY - * - * 22-Jan-96 Dieter Siegmund (dieter) at NeXT - * Created. - * - * 03-May-96 Dieter Siegmund (dieter) at NeXT - * Added a real ISR to improve performance. - * - * 10-June-96 Dieter Siegmund (dieter) at NeXT - * Added support for Splash 3 (10 Base-T only card). - * - * 18-June-96 Dieter Siegmund (dieter) at NeXT - * Keep the transmit queue draining by interrupting every - * N / 2 transmits (where N is the size of the hardware queue). - * - * 15-Dec-97 Joe Liu (jliu) at Apple - * Updated PHY programming to be 82558 aware. - * Misc changes to conform to new 82558 register flags. - * Changed RNR interrupt handler to restart RU instead of a reset. - * Interrupt handler now does a thread_call_func() to do most of its work. - * Interrupts are disabled until the thread callout finishes its work. - * Increased the size of TX/RX rings. - * buffer object removed, we use cluster mbufs to back up the receive ring. - * - * 29-May-98 Joe Liu (jliu) at Apple - * Updated _setupPhy method to take advantage of parallel detection whenever - * possible in order to detect the proper link speed. - * - * 17-Aug-98 Joe Liu (jliu) at Apple - * Re-enabled the setting of txready_sel PHY (PCS) bit for DP83840. - * Simplified interrupt handling, resulting in RCV performance improvements. - * Receive packets are sent upstream via a cached function pointer. - */ - -#include "i82557.h" - -#define ONE_SECOND_TICKS 1000 -#define LOAD_STATISTICS_INTERVAL (4 * ONE_SECOND_TICKS) - -#define super IOEthernetController -OSDefineMetaClassAndStructors( Intel82557, IOEthernetController ) - -//--------------------------------------------------------------------------- -// Function: pciConfigInit -// -// Update PCI command register to enable the memory-mapped range, -// and bus-master interface. - -bool Intel82557::pciConfigInit(IOPCIDevice * provider) -{ - UInt32 reg; - - reg = provider->configRead32( kIOPCIConfigCommand ); - - reg |= ( kIOPCICommandBusMaster | - kIOPCICommandMemorySpace | - kIOPCICommandMemWrInvalidate ); - - reg &= ~kIOPCICommandIOSpace; // disable I/O space - - provider->configWrite32( kIOPCIConfigCommand, reg ); - - return true; -} - -//--------------------------------------------------------------------------- -// Function: initDriver -// -// Create and initialize driver objects before the hardware is -// enabled. -// -// Returns true on sucess, and false if initialization failed. - -bool Intel82557::initDriver(IOService * provider) -{ - currentMediumType = MEDIUM_TYPE_INVALID; - - // This driver will allocate and use an IOGatedOutputQueue. - // - transmitQueue = getOutputQueue(); - if ( transmitQueue == 0 ) return false; - - // Allocate two IOMbufLittleMemoryCursor instances. One for transmit and - // the other for receive. - // - rxMbufCursor = IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE,1); - txMbufCursor = IOMbufLittleMemoryCursor::withSpecification(MAX_BUF_SIZE, - TBDS_PER_TCB); - if (!rxMbufCursor || !txMbufCursor) - return false; - - // Get a handle to our superclass' workloop. - // - IOWorkLoop * myWorkLoop = (IOWorkLoop *) getWorkLoop(); - if (!myWorkLoop) - return false; - - // Create and register an interrupt event source. The provider will - // take care of the low-level interrupt registration stuff. - // - interruptSrc = - IOInterruptEventSource::interruptEventSource(this, - (IOInterruptEventAction) &Intel82557::interruptOccurred, - provider); - - if (!interruptSrc || - (myWorkLoop->addEventSource(interruptSrc) != kIOReturnSuccess)) - return false; - - // Register a timer event source. This is used as a watchdog timer. - // - timerSrc = IOTimerEventSource::timerEventSource( this, - (IOTimerEventSource::Action) &Intel82557::timeoutOccurred ); - if (!timerSrc || - (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) - return false; - - // Create a dictionary to hold IONetworkMedium objects. - // - mediumDict = OSDictionary::withCapacity(5); - if (!mediumDict) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: getDefaultSettings -// -// Get the default driver settings chosen by the user. The properties -// are all stored in our property table (an OSDictionary). - -bool Intel82557::getDefaultSettings() -{ - OSNumber * numObj; - OSBoolean * boolObj; - - // Check for PHY address override. - // - phyAddr = PHY_ADDRESS_DEFAULT; - numObj = OSDynamicCast( OSNumber, getProperty("PHY Address") ); - if ( numObj ) - { - phyAddr = numObj->unsigned32BitValue(); - } - - // Check for Verbose flag. - // - verbose = false; - boolObj = OSDynamicCast( OSBoolean, getProperty("Verbose") ); - if ( boolObj && boolObj->isTrue() ) - { - IOLog("%s: verbose mode enabled\n", getName()); - verbose = true; - } - - // Check for Flow-Control enable flag. - // - flowControl = false; - boolObj = OSDynamicCast( OSBoolean, getProperty("Flow Control") ); - if ( boolObj && boolObj->isTrue() ) - { - IOLog("%s: 802.3x flow control enabled\n", getName()); - flowControl = true; - } - - return true; -} - -//--------------------------------------------------------------------------- -// Function: start <IOService> -// -// Hardware was detected and initialized, start the driver. - -bool Intel82557::start( IOService * provider ) -{ - bool ret = false; - - do { - // Start our superclass first. - - if ( super::start(provider) == false ) - break; - - // Cache our provider to an instance variable. - - pciNub = OSDynamicCast(IOPCIDevice, provider); - if ( pciNub == 0 ) break; - - // Retain provider, released in free(). - - pciNub->retain(); - - // Open our provider. - - if ( pciNub->open(this) == false ) break; - - // Initialize the driver's event sources and other support objects. - - if ( initDriver(provider) == false ) break; - - // Get the virtual address mapping of CSR registers located at - // Base Address Range 0 (0x10). The size of this range is 4K. - - csrMap = pciNub->mapDeviceMemoryWithRegister( kIOPCIConfigBaseAddress0 ); - if ( csrMap == 0 ) break; - - CSR_p = (CSR_t *) csrMap->getVirtualAddress(); - - // Setup our PCI config space. - - if ( pciConfigInit(pciNub) == false ) break; - - // Create the EEPROM object. - - eeprom = i82557eeprom::withAddress(&CSR_p->eepromControl); - if ( eeprom == 0 ) - { - IOLog("%s: couldn't allocate eeprom object", getName()); - break; - } - - // Get default driver settings (stored in property table). - - if ( getDefaultSettings() == false ) break; - - if ( verbose ) eeprom->dumpContents(); - - // Execute one-time initialization code. - - if ( coldInit() == false ) - { - IOLog("%s: coldInit failed\n", getName()); - break; - } - - if ( hwInit() == false ) - { - IOLog("%s: hwInit failed\n", getName()); - break; - } - - // Publish our media capabilities. - - _phyPublishMedia(); - if ( publishMediumDictionary(mediumDict) == false ) - { - IOLog("%s: publishMediumDictionary failed\n", getName()); - break; - } - -#if 0 - // Announce the basic hardware configuration info. - IOLog("%s: Memory 0x%lx irq %d\n", getName(), - csrMap->getPhysicalAddress(), 0); -#endif - - ret = true; - } - while ( false ); - - // Close our provider, it will be re-opened on demand when - // our enable() is called. - - if ( pciNub ) pciNub->close(this); - - do { - if ( ret == false ) break; - - ret = false; - - // Allocate and attach an IOEthernetInterface instance to this driver - // object. - - if ( attachInterface((IONetworkInterface **) &netif, false) == false ) - break; - - // Attach a kernel debugger client. This is not an essential service, - // and the return is not checked. - - attachDebuggerClient(&debugger); - - // Start matching for clients of IONetworkInterface. - - netif->registerService(); - - ret = true; - } - while ( false ); - - return ret; -} - -//--------------------------------------------------------------------------- -// Function: stop <IOService> -// -// Stop all activities and prepare for termination. - -void Intel82557::stop(IOService * provider) -{ - super::stop(provider); -} - -//--------------------------------------------------------------------------- -// Function: createWorkLoop <IONetworkController> -// -// Override IONetworkController::createWorkLoop() method to create a workloop. - -bool Intel82557::createWorkLoop() -{ - workLoop = IOWorkLoop::workLoop(); - - return ( workLoop != 0 ); -} - -//--------------------------------------------------------------------------- -// Function: getWorkLoop <IOService> -// -// Override IOService::getWorkLoop() method to return our workloop. - -IOWorkLoop * Intel82557::getWorkLoop() const -{ - return workLoop; -} - -//--------------------------------------------------------------------------- -// Function: configureInterface <IONetworkController> -// -// Configure a newly instantiated IONetworkInterface object. - -bool Intel82557::configureInterface(IONetworkInterface * netif) -{ - IONetworkData * data; - - if ( super::configureInterface(netif) == false ) - return false; - - // Get the generic network statistics structure. - - data = netif->getParameter(kIONetworkStatsKey); - if (!data || !(netStats = (IONetworkStats *) data->getBuffer())) { - return false; - } - - // Get the Ethernet statistics structure. - - data = netif->getParameter(kIOEthernetStatsKey); - if (!data || !(etherStats = (IOEthernetStats *) data->getBuffer())) { - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// Function: free <IOService> -// -// Deallocate all resources and destroy the instance. - -void Intel82557::free() -{ - if (debugger) { debugger->release(); debugger = 0; } - if (netif) { netif->release(); netif = 0; } - if (interruptSrc) { interruptSrc->release(); interruptSrc = 0; } - if (timerSrc) { timerSrc->release(); timerSrc = 0; } - if (rxMbufCursor) { rxMbufCursor->release(); rxMbufCursor = 0; } - if (txMbufCursor) { txMbufCursor->release(); txMbufCursor = 0; } - if (csrMap) { csrMap->release(); csrMap = 0; } - if (eeprom) { eeprom->release(); eeprom = 0; } - if (mediumDict) { mediumDict->release(); mediumDict = 0; } - if ( pciNub ) { pciNub->release(); pciNub = 0; } - if ( workLoop ) { workLoop->release(); workLoop = 0; } - - _freeMemPage( &shared ); - _freeMemPage( &txRing ); - _freeMemPage( &rxRing ); - - super::free(); // pass it to our superclass -} - -//--------------------------------------------------------------------------- -// Function: enableAdapter -// -// Enables the adapter & driver to the given level of support. - -bool Intel82557::enableAdapter(UInt32 level) -{ - bool ret = false; - -// IOLog("%s::%s enabling level %ld\n", getName(), __FUNCTION__, level); - - switch (level) { - case kActivationLevel1: - - // Open provider. - // - if ( ( pciNub == 0 ) || ( pciNub->open(this) == false ) ) - { - break; - } - - if (!_initRingBuffers()) - break; - - if (!_startReceive()) { - _clearRingBuffers(); - break; - } - - // Set current medium. - // - if (setMedium(getCurrentMedium()) != kIOReturnSuccess) - IOLog("%s: setMedium error\n", getName()); - - // Start the watchdog timer. - // - timerSrc->setTimeoutMS(LOAD_STATISTICS_INTERVAL); - - // Enable interrupt event sources and hardware interrupts. - // - if (getWorkLoop()) - getWorkLoop()->enableAllInterrupts(); - enableAdapterInterrupts(); - - // Force PHY to report link status. - // - _phyReportLinkStatus(true); - - ret = true; - break; - - case kActivationLevel2: - // Issue a dump statistics command. - // - _dumpStatistics(); - - // Start our IOOutputQueue object. - // - transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); - transmitQueue->start(); - - ret = true; - break; - } - - if (!ret) - IOLog("%s::%s error in level %ld\n", getName(), __FUNCTION__, level); - - return ret; -} - -//--------------------------------------------------------------------------- -// Function: disableAdapter -// -// Disables the adapter & driver to the given level of support. - -bool Intel82557::disableAdapter(UInt32 level) -{ - bool ret = false; - -// IOLog("%s::%s disabling level %ld\n", getName(), __FUNCTION__, level); - - switch (level) { - case kActivationLevel1: - // Disable interrupt handling and hardware interrupt sources. - // - disableAdapterInterrupts(); - if (getWorkLoop()) - getWorkLoop()->disableAllInterrupts(); - - // Stop the timer event source, and initialize the watchdog state. - // - timerSrc->cancelTimeout(); - packetsReceived = true; // assume we're getting packets - packetsTransmitted = false; - txCount = 0; - - // Reset the hardware engine. - // - ret = hwInit(); - - // Clear the descriptor rings after the hardware is idle. - // - _clearRingBuffers(); - - // Report link status: unknown. - // - setLinkStatus(0, 0); - - // Flush all packets held in the queue and prevent it - // from accumulating any additional packets. - // - transmitQueue->setCapacity(0); - transmitQueue->flush(); - - // Close provider. - // - if ( pciNub ) - { - pciNub->close(this); - } - - break; - - case kActivationLevel2: - // Stop the transmit queue. outputPacket() will not get called - // after this. - // - transmitQueue->stop(); - - ret = true; - break; - } - - if (!ret) - IOLog("%s::%s error in level %ld\n", getName(), __FUNCTION__, level); - - return ret; -} - -//--------------------------------------------------------------------------- -// Function: setActivationLevel -// -// Sets the adapter's activation level. -// -// kActivationLevel0 - Adapter is disabled. -// kActivationLevel1 - Adapter is brought up just enough to support debugging. -// kActivationLevel2 - Adapter is completely up. - -bool Intel82557::setActivationLevel(UInt32 level) -{ - bool ret = false; - UInt32 nextLevel; - - // IOLog("---> DESIRED LEVEL : %d\n", level); - - if (currentLevel == level) return true; - - for ( ; currentLevel > level; currentLevel--) - { - if ( (ret = disableAdapter(currentLevel)) == false ) - break; - } - - for ( nextLevel = currentLevel + 1; - currentLevel < level; - currentLevel++, nextLevel++ ) - { - if ( (ret = enableAdapter(nextLevel)) == false ) - break; - } - - // IOLog("---> PRESENT LEVEL : %d\n\n", currentLevel); - - return ret; -} - -//--------------------------------------------------------------------------- -// Function: enable <IONetworkController> -// -// A request from our interface client to enable the adapter. - -IOReturn Intel82557::enable(IONetworkInterface * /*netif*/) -{ - if ( enabledForNetif ) return kIOReturnSuccess; - - enabledForNetif = setActivationLevel( kActivationLevel2 ); - - return ( enabledForNetif ? kIOReturnSuccess : kIOReturnIOError ); -} - -//--------------------------------------------------------------------------- -// Function: disable <IONetworkController> -// -// A request from our interface client to disable the adapter. - -IOReturn Intel82557::disable(IONetworkInterface * /*netif*/) -{ - enabledForNetif = false; - - setActivationLevel( enabledForDebugger ? - kActivationLevel1 : kActivationLevel0 ); - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Function: enable <IONetworkController> -// -// A request from our debugger client to enable the adapter. - -IOReturn Intel82557::enable(IOKernelDebugger * /*debugger*/) -{ - if ( enabledForDebugger || enabledForNetif ) - { - enabledForDebugger = true; - return kIOReturnSuccess; - } - - enabledForDebugger = setActivationLevel( kActivationLevel1 ); - - return ( enabledForDebugger ? kIOReturnSuccess : kIOReturnIOError ); -} - -//--------------------------------------------------------------------------- -// Function: disable <IONetworkController> -// -// A request from our debugger client to disable the adapter. - -IOReturn Intel82557::disable(IOKernelDebugger * /*debugger*/) -{ - enabledForDebugger = false; - - if ( enabledForNetif == false ) - setActivationLevel( kActivationLevel0 ); - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Function: timeoutOccurred -// -// Periodic timer that monitors the receiver status, updates error -// and collision statistics, and update the current link status. - -void Intel82557::timeoutOccurred(IOTimerEventSource * /*timer*/) -{ - if ( (packetsReceived == false) && (packetsTransmitted == true) ) - { - /* - * The B-step of the i82557 requires that an mcsetup command be - * issued if the receiver stops receiving. This is a documented - * errata. - */ - mcSetup(0, 0, true); - } - packetsReceived = packetsTransmitted = false; - - _updateStatistics(); - - _phyReportLinkStatus(); - - timerSrc->setTimeoutMS(LOAD_STATISTICS_INTERVAL); -} - -//--------------------------------------------------------------------------- -// Function: setPromiscuousMode <IOEthernetController> - -IOReturn Intel82557::setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - bool rv; - promiscuousEnabled = (mode == kIOEnetPromiscuousModeOff) ? false : true; - reserveDebuggerLock(); - rv = config(); - releaseDebuggerLock(); - return (rv ? kIOReturnSuccess : kIOReturnIOError); -} - -//--------------------------------------------------------------------------- -// Function: setMulticastMode <IOEthernetController> - -IOReturn Intel82557::setMulticastMode(IOEnetMulticastMode mode) -{ - multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Function: setMulticastList <IOEthernetController> - -IOReturn Intel82557::setMulticastList(IOEthernetAddress * addrs, UInt32 count) -{ - IOReturn ret = kIOReturnSuccess; - - if ( mcSetup(addrs, count) == false ) - { - IOLog("%s: set multicast list failed\n", getName()); - ret = kIOReturnIOError; - } - return ret; -} - -//--------------------------------------------------------------------------- -// Function: getPacketBufferConstraints <IONetworkController> -// -// Return our driver's packet alignment requirements. - -void -Intel82557::getPacketBufferConstraints(IOPacketBufferConstraints * constraints) const -{ - constraints->alignStart = kIOPacketBufferAlign2; // even word aligned. - constraints->alignLength = kIOPacketBufferAlign1; // no restriction. -} - -//--------------------------------------------------------------------------- -// Function: getHardwareAddress <IOEthernetController> -// -// Return the adapter's hardware/Ethernet address. - -IOReturn Intel82557::getHardwareAddress(IOEthernetAddress * addrs) -{ - bcopy(&myAddress, addrs, sizeof(*addrs)); - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Function: createOutputQueue <IONetworkController> -// -// Allocate an IOGatedOutputQueue instance. - -IOOutputQueue * Intel82557::createOutputQueue() -{ - return IOGatedOutputQueue::withTarget(this, getWorkLoop()); -} - -//--------------------------------------------------------------------------- -// Function: setMedium <IONetworkController> -// -// Transition the controller/PHY to use a new medium. Note that -// this function can be called my the driver, or by our client. - -IOReturn Intel82557::setMedium(const IONetworkMedium * medium) -{ - bool r; - - if ( OSDynamicCast(IONetworkMedium, medium) == 0 ) - { - // Defaults to Auto. - medium = _phyGetMediumWithType( MEDIUM_TYPE_AUTO ); - if ( medium == 0 ) return kIOReturnError; - } - -#if 0 - IOLog("%s: setMedium -> %s\n", getName(), - medium->getName()->getCStringNoCopy()); -#endif - - // Program PHY to select the desired medium. - // - r = _phySetMedium( (mediumType_t) medium->getIndex() ); - - // Update the current medium property. - // - if ( r && !setCurrentMedium(medium) ) - IOLog("%s: setCurrentMedium error\n", getName()); - - return ( r ? kIOReturnSuccess : kIOReturnIOError ); -} - -//--------------------------------------------------------------------------- -// Function: newVendorString(), newModelString() -// <IONetworkController> -// -// Report human readable hardware information strings. - -const OSString * Intel82557::newVendorString() const -{ - return OSString::withCString("Intel"); -} - -const OSString * Intel82557::newModelString() const -{ - const char * model = 0; - - assert( eeprom && eeprom->getContents() ); - - switch ( eeprom->getContents()->controllerType ) - { - case I82558_CONTROLLER_TYPE: - model = "82558"; - break; - case I82557_CONTROLLER_TYPE: - default: - model = "82557"; - break; - } - return OSString::withCString(model); -} - -//--------------------------------------------------------------------------- -// Kernel debugger entry points. -// -// KDP driven polling routines to send and transmit a frame. -// Remember, no memory allocation! Not even mbufs are safe. - -void Intel82557::sendPacket(void * pkt, UInt32 pkt_len) -{ - _sendPacket(pkt, pkt_len); -} - -void Intel82557::receivePacket(void * pkt, UInt32 * pkt_len, UInt32 timeout) -{ - _receivePacket(pkt, (UInt *) pkt_len, timeout); -} diff --git a/iokit/Drivers/network/drvIntel82557/i82557.h b/iokit/Drivers/network/drvIntel82557/i82557.h deleted file mode 100644 index 398d4b402..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. - * - * i82557.h - * - * HISTORY - * - * 4-Mar-96 Dieter Siegmund (dieter) at NeXT - * Created. - */ - -#ifndef _I82557_H -#define _I82557_H - -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IOGatedOutputQueue.h> -#include <IOKit/network/IOMbufMemoryCursor.h> -#include <IOKit/network/IOPacketQueue.h> -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOFilterInterruptEventSource.h> - -#include "i82557Inline.h" -#include "i82557eeprom.h" -#include "i82557PHY.h" -#include <IOKit/assert.h> - -/* - * Macro: VPRINT - * - * Purpose: - * Dump stuff to console log if the "Verbose" key is present in - * the device description. - */ -#define VPRINT(fmt, args...) \ - if (verbose) \ - IOLog(fmt, ## args); - -#define NUM_RECEIVE_FRAMES 32 -#define NUM_TRANSMIT_FRAMES 32 - -#define TRANSMIT_INT_DELAY 8 -#define TRANSMIT_QUEUE_SIZE 256 - -#define MAX_BUF_SIZE (ETHERMAXPACKET + ETHERCRC) - -#define SPIN_TIMEOUT 50000 -#define SPIN_COUNT 1 - -/* - * Type: tcbQ_t - * - * Purpose: - * Hold transmit hardware queue variables. - */ -typedef struct { - int numTcbs; - tcb_t * activeHead_p; - tcb_t * activeTail_p; - tcb_t * freeHead_p; - int numFree; -} tcbQ_t; - -/* - * Type: overlay_t - * - * Purpose: - * Overlayable memory used during start-up. - */ -typedef union { - cbHeader_t nop; - cb_configure_t configure; - cb_iasetup_t iasetup; - port_selftest_t selftest; -} overlay_t; - -/* - * Type: pageBlock_t - * - * Purpose: - * Track a page sized memory block. - */ -typedef struct { - void * memPtr; - UInt memSize; - void * memAllocPtr; - UInt memAvail; -} pageBlock_t; - -/* - * Adapter activation levels. - */ -enum { - kActivationLevel0 = 0, - kActivationLevel1, - kActivationLevel2 -}; - -class Intel82557 : public IOEthernetController -{ - OSDeclareDefaultStructors(Intel82557) - -public: - IOPhysicalAddress memBasePhysical; - int irq; - IOEthernetAddress myAddress; - IOEthernetInterface * netif; - IOKernelDebugger * debugger; - IOPCIDevice * pciNub; - IOWorkLoop * workLoop; - - IOInterruptEventSource * interruptSrc; - IOOutputQueue * transmitQueue; - IOTimerEventSource * timerSrc; - IONetworkStats * netStats; - IOEthernetStats * etherStats; - IOMemoryMap * csrMap; - OSDictionary * mediumDict; - IONetworkMedium * mediumTable[MEDIUM_TYPE_INVALID]; - - IOMbufLittleMemoryCursor * rxMbufCursor; - IOMbufLittleMemoryCursor * txMbufCursor; - - int txCount; - UInt32 currentLevel; - bool enabledForNetif; - bool enabledForDebugger; - bool promiscuousEnabled; - bool multicastEnabled; - bool allMulticastEnabled; - bool interruptEnabled; - bool packetsReceived; - bool packetsTransmitted; - bool verbose; - bool flowControl; - mediumType_t currentMediumType; - UInt8 phyAddr; - UInt32 phyID; - UInt16 phyStatusPrev; - - /* descriptor and control block data structures */ - pageBlock_t shared; - pageBlock_t rxRing; - pageBlock_t txRing; - - CSR_t * CSR_p; - overlay_t * overlay_p; - IOPhysicalAddress overlay_paddr; - errorCounters_t * errorCounters_p; - IOPhysicalAddress errorCounters_paddr; - i82557eeprom * eeprom; - - /* transmit-related */ - tcbQ_t tcbQ; - tcb_t * tcbList_p; - int prevCUCommand; - - /* kernel debugger */ - tcb_t * KDB_tcb_p; - void * KDB_buf_p; - IOPhysicalAddress KDB_buf_paddr; - - /* receive-related */ - rfd_t * rfdList_p; - rfd_t * headRfd; - rfd_t * tailRfd; - - // -------------------------------------------------- - // IOService (or its superclass) methods. - // -------------------------------------------------- - - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); - virtual void free(); - - // -------------------------------------------------- - // IONetworkController methods. - // -------------------------------------------------- - - virtual IOReturn enable(IONetworkInterface * netif); - virtual IOReturn disable(IONetworkInterface * netif); - - virtual IOReturn enable(IOKernelDebugger * debugger); - virtual IOReturn disable(IOKernelDebugger * debugger); - - virtual void sendPacket(void * pkt, UInt32 pkt_len); - virtual void receivePacket(void * pkt, UInt32 * pkt_len, UInt32 timeout); - - virtual UInt32 outputPacket(struct mbuf * m, void * param); - - virtual void getPacketBufferConstraints( - IOPacketBufferConstraints * constraints) const; - - virtual IOOutputQueue * createOutputQueue(); - - virtual const OSString * newVendorString() const; - virtual const OSString * newModelString() const; - - virtual IOReturn setMedium(const IONetworkMedium * medium); - - virtual bool configureInterface(IONetworkInterface * interface); - - virtual bool createWorkLoop(); - virtual IOWorkLoop * getWorkLoop() const; - - // -------------------------------------------------- - // IOEthernetController methods. - // -------------------------------------------------- - - virtual IOReturn getHardwareAddress(IOEthernetAddress * addr); - virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode); - virtual IOReturn setMulticastMode(IOEnetMulticastMode mode); - virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count); - - // -------------------------------------------------- - // Intel82557 driver specific methods. - // -------------------------------------------------- - - bool pciConfigInit(IOPCIDevice * provider); - bool initDriver(IOService * provider); - bool coldInit(); - bool enableAdapter(UInt32 level); - bool disableAdapter(UInt32 level); - bool setActivationLevel(UInt32 newLevel); - bool config(); - void disableAdapterInterrupts(); - void enableAdapterInterrupts(); - bool hwInit(); - bool iaSetup(); - bool mcSetup(IOEthernetAddress * addrs, UInt count, bool fromData = false); - bool nop(); - void sendPortCommand(port_command_t command, UInt arg); - bool getDefaultSettings(); - void issueReset(); - - bool _selfTest(); - bool _allocateMemPage(pageBlock_t * p); - void _freeMemPage(pageBlock_t * p); - void _updateStatistics(); - bool _dumpStatistics(); - bool _mdiWritePHY(UInt8 phyAddress, UInt8 regAddress, UInt16 data); - bool _mdiReadPHY(UInt8 phyAddress, UInt8 regAddress, UInt16 * data_p); - void * _memAllocFrom(pageBlock_t * p, UInt allocSize, UInt align); - bool _polledCommand(cbHeader_t * hdr_p, IOPhysicalAddress paddr); - bool _abortReceive(); - bool _startReceive(); - void _resetChip(); - - bool _initTcbQ(bool enable = false); - bool _initRfdList(bool enable = false); - bool _resetRfdList(); - bool _initRingBuffers() { - return (_initTcbQ(true) && _initRfdList(true)); } - bool _clearRingBuffers() { - return (_initTcbQ(false) && _initRfdList(false)); } - - bool _sendPacket(void * pkt, UInt len); - bool _receivePacket(void * pkt, UInt * len, UInt timeout); - - bool updateRFDFromMbuf(rfd_t * rfd_p, struct mbuf * m); - struct mbuf * updateTCBForMbuf(tcb_t * tcb_p, struct mbuf * m); - - void interruptOccurred(IOInterruptEventSource * src, int count); - bool receiveInterruptOccurred(); - void transmitInterruptOccurred(); - void timeoutOccurred(IOTimerEventSource * timer); - - // -------------------------------------------------- - // PHY methods. - // -------------------------------------------------- - - bool _phyReset(); - bool _phyWaitAutoNegotiation(); - UInt32 _phyGetID(); - bool _phySetMedium(mediumType_t medium); - bool _phyProbe(); - void _phyPublishMedia(); - bool _phyAddMediumType(UInt32 type, UInt32 speed, UInt32 code); - void _phyReportLinkStatus(bool firstPoll = false); - mediumType_t _phyGetActiveMedium(); - IONetworkMedium * _phyGetMediumWithType(UInt32 type); - mediumType_t _phyGetMediumTypeFromBits(bool rate100, - bool fullDuplex, - bool t4); -}; - -#endif /* !_I82557_H */ diff --git a/iokit/Drivers/network/drvIntel82557/i82557HW.h b/iokit/Drivers/network/drvIntel82557/i82557HW.h deleted file mode 100644 index 5242c223e..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557HW.h +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. All rights reserved. - * - * i82557HW.h - Intel 82557/82558 chip-related definitions - * - * HISTORY - * Jan 22, 1996 Dieter Siegmund at NeXT (dieter@next.com) - * Created. - */ - -#ifndef _I82557HW_H -#define _I82557HW_H - -#include <net/etherdefs.h> - -//------------------------------------------------------------------------- -// Misc definitions. -//------------------------------------------------------------------------- - -#define DWORD_ALIGNMENT 4 -#define WORD_ALIGNMENT 2 -#define PARAGRAPH_ALIGNMENT 16 -#define CACHE_ALIGNMENT 32 - -#define C_NULL (~0) - -#define PCI_CFID_INTEL82557 0x12298086 - -typedef enum { - MEDIUM_TYPE_10_HD = 0, - MEDIUM_TYPE_10_FD, - MEDIUM_TYPE_TX_HD, - MEDIUM_TYPE_TX_FD, - MEDIUM_TYPE_T4, - MEDIUM_TYPE_AUTO, - MEDIUM_TYPE_INVALID, -} mediumType_t; - -//------------------------------------------------------------------------- -// SCB status word. -// Offset 0, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 scb_status_t; -#define SCB_STATUS_CX BIT(15) // command block with 'I' bit set. -#define SCB_STATUS_FR BIT(14) // RU finished receiving a frame. -#define SCB_STATUS_CNA BIT(13) // CU active to suspended/idle. -#define SCB_STATUS_RNR BIT(12) // RU no longer in ready state. -#define SCB_STATUS_MDI BIT(11) // MDI read/write cycle is done. -#define SCB_STATUS_SWI BIT(10) // software interrupt. -#define SCB_STATUS_ER BIT(9) // early receive interrupt. -#define SCB_STATUS_FCP BIT(8) // flow control pause interrupt. -#define SCB_STATUS_INT_MASK 0xff00 // mask for all interrupt bits. - -#define SCB_STATUS_CUS_SHIFT 6 -#define SCB_STATUS_CUS_MASK CSR_MASK(SCB_STATUS_CUS, 0x3) -#define SCB_CUS_IDLE 0 -#define SCB_CUS_SUSPEND 1 -#define SCB_CUS_ACTIVE 2 - -#define SCB_STATUS_RUS_SHIFT 2 -#define SCB_STATUS_RUS_MASK CSR_MASK(SCB_STATUS_RUS, 0xf) -#define SCB_RUS_IDLE 0 -#define SCB_RUS_SUSPEND 1 -#define SCB_RUS_NO_RESOURCES 2 -#define SCB_RUS_READY 4 -#define SCB_RUS_SUSPEND_NO_RBDS 9 -#define SCB_RUS_NO_RBDS 10 -#define SCB_RUS_READY_NO_RBDS 12 - -//------------------------------------------------------------------------- -// SCB interrupt control byte. -// Offset 3, 8-bit, RW. -//------------------------------------------------------------------------- -typedef UInt8 scb_interrupt_t; -#define SCB_INTERRUPT_CX BIT(7) // interrupt masks -#define SCB_INTERRUPT_FR BIT(6) -#define SCB_INTERRUPT_CNA BIT(5) -#define SCB_INTERRUPT_RNR BIT(4) -#define SCB_INTERRUPT_ER BIT(3) -#define SCB_INTERRUPT_FCP BIT(2) -#define SCB_INTERRUPT_SI BIT(1) -#define SCB_INTERRUPT_M BIT(0) - -//------------------------------------------------------------------------- -// SCB command byte. -// Offset 2, 8-bit, RW. -//------------------------------------------------------------------------- -typedef UInt8 scb_command_t; -#define SCB_COMMAND_CUC_SHIFT 4 -#define SCB_COMMAND_CUC_MASK CSR_MASK(SCB_COMMAND_CUC, 0xf) -#define SCB_CUC_NOP 0 -#define SCB_CUC_START 1 -#define SCB_CUC_RESUME 2 -#define SCB_CUC_LOAD_DUMP_ADDR 4 -#define SCB_CUC_DUMP_STAT 5 -#define SCB_CUC_LOAD_BASE 6 -#define SCB_CUC_DUMP_RESET_STAT 7 -#define SCB_CUC_STATIC_RESUME 10 - -#define SCB_COMMAND_RUC_SHIFT 0 -#define SCB_COMMAND_RUC_MASK CSR_MASK(SCB_COMMAND_RUC, 0x7) -#define SCB_RUC_NOP 0 -#define SCB_RUC_START 1 -#define SCB_RUC_RESUME 2 -#define SCB_RUC_DMA_REDIRECT 3 -#define SCB_RUC_ABORT 4 -#define SCB_RUC_LOAD_HDS 5 -#define SCB_RUC_LOAD_BASE 6 -#define SCB_RUC_RBD_RESUME 7 - -//------------------------------------------------------------------------- -// MDI control register. -// Offset 0x10, 32-bit, RW. -//------------------------------------------------------------------------- -typedef UInt32 mdi_control_t; -#define MDI_CONTROL_INT_ENABLE BIT(29) // interrupt enable. -#define MDI_CONTROL_READY BIT(28) // ready bit. -#define MDI_CONTROL_OPCODE_SHIFT 26 -#define MDI_CONTROL_OPCODE_MASK CSR_MASK(MDI_CONTROL_OPCODE, 0x3) -#define MDI_CONTROL_OP_WRITE 1 -#define MDI_CONTROL_OP_READ 2 -#define MDI_CONTROL_PHYADDR_SHIFT 21 -#define MDI_CONTROL_PHYADDR_MASK CSR_MASK(MDI_CONTROL_PHYADDR, 0x1f) -#define MDI_CONTROL_REGADDR_SHIFT 16 -#define MDI_CONTROL_REGADDR_MASK CSR_MASK(MDI_CONTROL_REGADDR, 0x1f) -#define MDI_CONTROL_DATA_SHIFT 0 -#define MDI_CONTROL_DATA_MASK CSR_MASK(MDI_CONTROL_DATA, 0xffff) - -//------------------------------------------------------------------------- -// EEPROM control register. -// Offset 0xE, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 eeprom_control_t; -#define EEPROM_CONTROL_EEDO BIT(3) -#define EEPROM_CONTROL_EEDI BIT(2) -#define EEPROM_CONTROL_EECS BIT(1) -#define EEPROM_CONTROL_EESK BIT(0) - -//------------------------------------------------------------------------- -// Flow control threshold register. -// Offset 0x19, 8-bit, RW. -//------------------------------------------------------------------------- -#define FC_THRESHOLD_SHIFT 0 -#define FC_THRESHOLD_MASK CSR_MASK(FC_THRESHOLD, 0x7) -#define FC_THRESHOLD_512 0 -#define FC_THRESHOLD_1024 1 -#define FC_THRESHOLD_1280 2 -#define FC_THRESHOLD_1536 3 - -//------------------------------------------------------------------------- -// Flow control command register. -// Offset 0x20, 8-bit, RW. -//------------------------------------------------------------------------- -#define FC_XON BIT(0) -#define FC_XOFF BIT(1) -#define FC_FULL BIT(2) -#define FC_PAUSED BIT(3) -#define FC_PAUSED_LOW BIT(4) - -//------------------------------------------------------------------------- -// Generic command block definition. -//------------------------------------------------------------------------- -#define CB_NOP 0 -#define CB_IA_ADDRESS 1 -#define CB_CONFIGURE 2 -#define CB_MULTICAST 3 -#define CB_TRANSMIT 4 -#define CB_LOAD_MICROCODE 5 -#define CB_DUMP 6 -#define CB_DIAGNOSE 7 - -typedef UInt16 cb_status_t; -#define CB_STATUS_C BIT(15) // command complete. -#define CB_STATUS_OK BIT(13) // DMA OK. - -typedef UInt16 cb_command_t; -#define CB_EL BIT(15) // end of list. -#define CB_S BIT(14) // suspend bit. -#define CB_I BIT(13) // interrupt bit. -#define CB_CMD_SHIFT 0 -#define CB_CMD_MASK CSR_MASK(CB_CMD, 0x7) - -#define CB_CMD_NOP 0x0 -#define CB_CMD_IASETUP 0x1 -#define CB_CMD_CONFIGURE 0x2 -#define CB_CMD_MCSETUP 0x3 -#define CB_CMD_TRANSMIT 0x4 - -static __inline__ char * -CUCommandString(int cmd) -{ - char * s[] = { - "nop", - "iasetup", - "configure", - "mcsetup", - "transmit" - }; - return (s[cmd]); -} - -typedef struct { - volatile cb_status_t status; - volatile cb_command_t command; - IOPhysicalAddress link; -} cbHeader_t; - -//------------------------------------------------------------------------- -// Configure command. -//------------------------------------------------------------------------- -#define CB_CONFIG_BYTE_COUNT 22 - -#define CB_CB0_BYTE_COUNT_SHIFT 0 -#define CB_CB0_BYTE_COUNT_MASK CSR_MASK(CB_CB0_BYTE_COUNT, 0x3f) - -#define CB_CB1_TX_FIFO_LIMIT_SHIFT 4 -#define CB_CB1_TX_FIFO_LIMIT_MASK CSR_MASK(CB_CB1_TX_FIFO_LIMIT, 0xf) -#define CB_CB1_RX_FIFO_LIMIT_SHIFT 0 -#define CB_CB1_RX_FIFO_LIMIT_MASK CSR_MASK(CB_CB1_RX_FIFO_LIMIT, 0xf) -#define CB_CB1_TX_FIFO_0 8 // 0 bytes -#define CB_CB1_RX_FIFO_64 8 // 64 bytes - -#define CB_CB2_ADAPTIVE_IFS_SHIFT 0 -#define CB_CB2_ADAPTIVE_IFS_MASK CSR_MASK(CB_CB2_ADAPTIVE_IFS, 0xff) - -#define CB_CB3_TERM_ON_CL BIT(3) -#define CB_CB3_READ_AL_ENABLE BIT(2) -#define CB_CB3_TYPE_ENABLE BIT(1) -#define CB_CB3_MWI_ENABLE BIT(0) - -#define CB_CB4_RX_MIN_SHIFT 0 -#define CB_CB4_RX_MIN_MASK CSR_MASK(CB_CB4_RX_MIN, 0x7f) - -#define CB_CB5_DMBC_EN BIT(7) -#define CB_CB5_TX_MAX_SHIFT 0 -#define CB_CB5_TX_MAX_MASK CSR_MASK(CB_CB4_TX_MAX, 0x7f) - -#define CB_CB6_SAVE_BF BIT(7) -#define CB_CB6_DISC_OVER BIT(6) -#define CB_CB6_STD_STATS BIT(5) -#define CB_CB6_STD_TCB BIT(4) -#define CB_CB6_CI_INT BIT(3) -#define CB_CB6_TNO_INT BIT(2) -#define CB_CB6_NON_DIRECT_DMA BIT(1) -#define CB_CB6_LATE_SCB BIT(0) - -#define CB_CB7_DYNAMIC_TBD BIT(7) -#define CB_CB7_UNDERRUN_RETRY_SHIFT 1 -#define CB_CB7_UNDERRUN_RETRY_MASK CSR_MASK(CB_CB7_UNDERRUN_RETRY, 0x3) -#define CB_CB7_UNDERRUN_RETRY_1 1 -#define CB_CB7_UNDERRUN_RETRY_2 2 -#define CB_CB7_UNDERRUN_RETRY_3 3 -#define CB_CB7_DISC_SHORT_FRAMES BIT(0) - -#define CB_CB8_CSMA_EN BIT(0) - -#define CB_CB10_LOOPBACK_SHIFT 6 -#define CB_CB10_LOOPBACK_MASK CSR_MASK(CB_CB10_LOOPBACK, 0x3) -#define CB_CB10_PREAMBLE_SHIFT 4 -#define CB_CB10_PREAMBLE_MASK CSR_MASK(CB_CB10_PREAMBLE, 0x3) -#define CB_CB10_PREAMBLE_1_BYTE 0 -#define CB_CB10_PREAMBLE_3_BYTES 1 -#define CB_CB10_PREAMBLE_7_BYTES 2 -#define CB_CB10_PREAMBLE_15_BYTES 3 -#define CB_CB10_NSAI BIT(3) - -#define CB_CB11_LIN_PRIORITY_SHIFT 0 -#define CB_CB11_LIN_PRIORITY_MASK CSR_MASK(CB_CB11_PRIORITY, 0x7) - -#define CB_CB12_IFS_SHIFT 4 -#define CB_CB12_IFS_MASK CSR_MASK(CB_CB12_IFS, 0xf) -#define CB_CB12_IFS_96_BIT_TIMES 0x6 -#define CB_CB12_LIN_PRIORITY BIT(0) - -#define CB_CB13_FC_TYPE_LSB_SHIFT 0 -#define CB_CB13_FC_TYPE_LSB_MASK CSR_MASK(CB_CB13_FC_TYPE_LSB, 0xff) -#define CB_CB13_FC_TYPE_LSB_DEF 0 // 82558 compatible - -#define CB_CB14_FC_TYPE_MSB_SHIFT 0 -#define CB_CB14_FC_TYPE_MSB_MASK CSR_MASK(CB_CB14_FC_TYPE_MSB, 0xff) -#define CB_CB14_FC_TYPE_MSB_DEF 0xf2 // 82558 compatible - -#define CB_CB15_CRS_CDT BIT(7) -#define CB_CB15_BROADCAST_DISABLE BIT(1) -#define CB_CB15_PROMISCUOUS BIT(0) - -#define CB_CB16_FC_DELAY_LSB_SHIFT 0 -#define CB_CB16_FC_DELAY_LSB_MASK CSR_MASK(CB_CB16_FC_DELAY_LSB, 0xff) -#define CB_CB16_FC_DELAY_LSB_DEF 0 - -#define CB_CB17_FC_DELAY_MSB_SHIFT 0 -#define CB_CB17_FC_DELAY_MSB_MASK CSR_MASK(CB_CB17_FC_DELAY_MSB, 0xff) -#define CB_CB17_FC_DELAY_MSB_DEF 0x40 - -#define CB_CB18_LONG_RX_OK BIT(3) -#define CB_CB18_CRC_XFER BIT(2) -#define CB_CB18_PADDING BIT(1) -#define CB_CB18_STRIPPING BIT(0) - -#define CB_CB19_AUTO_FDX BIT(7) -#define CB_CB19_FORCE_FDX BIT(6) -#define CB_CB19_REJECT_FC BIT(5) -#define CB_CB19_RX_FC_RESTART BIT(4) -#define CB_CB19_RX_FC_RESTOP BIT(3) -#define CB_CB19_TX_FC BIT(2) -#define CB_CB19_MAGIC_PKT_WAKEUP BIT(1) -#define CB_CB19_ADDRESS_WAKEUP BIT(0) - -#define CB_CB20_MULTI_IA BIT(6) -#define CB_CB20_FC_ADDR_LSB_SHIFT 0 -#define CB_CB20_FC_ADDR_LSB_MASK CSR_MASK(CB_CB20_FC_ADDR_LSB, 0x1f) -#define CB_CB20_FC_ADDR_LSB_DEF 0x0f - -#define CB_CB21_MULTICAST_ALL BIT(3) - -typedef struct cb_configure { - cbHeader_t header; - UInt8 byte[24]; -} cb_configure_t; - -//------------------------------------------------------------------------- -// MC-Setup command. -//------------------------------------------------------------------------- -typedef struct cb_mcsetup { - cbHeader_t header; - UInt16 count; - IOEthernetAddress addrs[0]; -} cb_mcsetup_t; - -//------------------------------------------------------------------------- -// IA-Setup command. -//------------------------------------------------------------------------- -typedef struct cb_iasetup { - cbHeader_t header; - IOEthernetAddress addr; -} cb_iasetup_t; - -//------------------------------------------------------------------------- -// Port Commands. -// Enumerated port command values. -//------------------------------------------------------------------------- -typedef enum { - portReset_e = 0, - portSelfTest_e = 1, - portSelectiveReset_e = 2, - portDump_e = 3, -} port_command_t; - -#define PORT_ADDRESS_SHIFT 4 -#define PORT_ADDRESS_MASK CSR_MASK(PORT_FUNCTION, 0xfffffff) - -#define PORT_FUNCTION_SHIFT 0 -#define PORT_FUNCTION_MASK CSR_MASK(PORT_FUNCTION, 0xf) - -//------------------------------------------------------------------------- -// Port Self-Test -// Definition for self test area. -//------------------------------------------------------------------------- -#define PORT_SELFTEST_GENERAL BIT(12) -#define PORT_SELFTEST_DIAGNOSE BIT(5) -#define PORT_SELFTEST_REGISTER BIT(3) -#define PORT_SELFTEST_ROM BIT(2) - -typedef struct port_selftest_t { - UInt32 signature; - UInt32 results; -} port_selftest_t; - -/* - * Typedef: CSR_t - * - * Purpose: Control Status Registers block - * Communication to the chip occurs via this set of - * memory-mapped (also io-mapped, which we don't use) - * registers. - */ -typedef struct csr { - volatile scb_status_t status; - volatile scb_command_t command; - volatile scb_interrupt_t interrupt; - volatile IOPhysicalAddress pointer; - volatile UInt32 port; - volatile UInt16 flashControl; - volatile eeprom_control_t eepromControl; - volatile mdi_control_t mdiControl; - volatile UInt32 rxDMAByteCount; - volatile UInt8 earlyRxInterrupt; - volatile UInt8 flowControlThreshold; - volatile UInt8 flowControlCommand; - volatile UInt8 powerManagement; -} CSR_t; - -//------------------------------------------------------------------------- -// Structure containing error counters retrieved via: -// Dump Statistics Counters command, or -// Dump and Reset Statistics Counters command. -// -// NOTE: 82558 can return an extended set of statistics counters. -//------------------------------------------------------------------------- -typedef struct { - UInt32 tx_good_frames; - UInt32 tx_maxcol_errors; - UInt32 tx_late_collision_errors; - UInt32 tx_underrun_errors; - UInt32 tx_lost_carrier_sense_errors; - UInt32 tx_deferred; - UInt32 tx_single_collisions; - UInt32 tx_multiple_collisions; - UInt32 tx_total_collisions; - UInt32 rx_good_frames; - UInt32 rx_crc_errors; - UInt32 rx_alignment_errors; - UInt32 rx_resource_errors; - UInt32 rx_overrun_errors; - UInt32 rx_collision_detect_errors; - UInt32 rx_short_frame_errors; - UInt32 _status; -#define DUMP_STATUS 0x0 -#define DUMP_COMPLETE 0xa005 -#define DUMP_AND_RESET_COMPLETE 0xa007 -} errorCounters_t; - -//------------------------------------------------------------------------- -// RBD count dword. -// Offset 0, 32-bit, RW. -//------------------------------------------------------------------------- -typedef UInt32 rbd_count_t; -#define RBD_COUNT_EOF BIT(15) // end-of-frame bit. -#define RBD_COUNT_F BIT(14) // buffer fetch bit. -#define RBD_COUNT_SHIFT 0 -#define RBD_COUNT_MASK CSR_MASK(RBD_COUNT, 0x3fff) - -//------------------------------------------------------------------------- -// RBD size dword. -// Offset 0xC, 32-bit, RW. -//------------------------------------------------------------------------- -typedef UInt32 rbd_size_t; -#define RBD_SIZE_EL BIT(15) // EL bit. -#define RBD_SIZE_SHIFT 0 -#define RBD_SIZE_MASK CSR_MASK(RBD_SIZE, 0x3fff) - -//------------------------------------------------------------------------- -// RBD - receive buffer descriptor definition. -//------------------------------------------------------------------------- -typedef struct rbd { - volatile rbd_count_t count; - volatile IOPhysicalAddress link; - volatile IOPhysicalAddress buffer; - volatile rbd_size_t size; - - /* driver private */ - - struct rbd * _next; - IOPhysicalAddress _paddr; - struct mbuf * _mbuf; - UInt32 _pad; -} rbd_t; - -//------------------------------------------------------------------------- -// RFD status word. -// Offset 0, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 rfd_status_t; -#define RFD_STATUS_C BIT(15) // complete bit. -#define RFD_STATUS_OK BIT(13) // OK bit. -#define RFD_STATUS_CRC_ERROR BIT(11) // CRC error bit. -#define RFD_STATUS_ALIGNMENT_ERROR BIT(10) // alignment error. -#define RFD_STATUS_NO_RESOURCES BIT(9) // no buffer space. -#define RFD_STATUS_DMA_OVERRUN BIT(8) // receive DMA overrun. -#define RFD_STATUS_FRAME_TOO_SHORT BIT(7) // frame too short. -#define RFD_STATUS_TYPE_FRAME BIT(5) // type/length bit. -#define RFD_STATUS_RX_ERROR BIT(4) // RX_ERR pin on PHY was set. -#define RFD_STATUS_NO_ADDR_MATCH BIT(2) // no address match. -#define RFD_STATUS_IA_MATCH BIT(1) // IA address match. -#define RFD_STATUS_COLLISION BIT(0) // receive collision. - -//------------------------------------------------------------------------- -// RFD command word. -// Offset 2, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 rfd_command_t; -#define RFD_COMMAND_EL BIT(15) // EL bit. -#define RFD_COMMAND_S BIT(14) // suspend bit. -#define RFD_COMMAND_H BIT(4) // header RFD bit. -#define RFD_COMMAND_SF BIT(3) // flexible mode bit. - -//------------------------------------------------------------------------- -// RFD misc dword. -// Offset 0xC, 32-bit, RW. -//------------------------------------------------------------------------- -typedef UInt32 rfd_misc_t; -#define RFD_MISC_EOF BIT(15) // end-of-frame bit. -#define RFD_MISC_F BIT(14) // buffer fetch bit. -#define RFD_MISC_ACT_COUNT_SHIFT 0 -#define RFD_MISC_ACT_COUNT_MASK CSR_MASK(RFD_MISC_ACT_COUNT, 0x3fff) -#define RFD_MISC_SIZE_SHIFT 16 -#define RFD_MISC_SIZE_MASK CSR_MASK(RFD_MISC_SIZE, 0x3fff) - -//------------------------------------------------------------------------- -// RFD - receive frame descriptor definition. -//------------------------------------------------------------------------- -typedef struct rfd { - volatile rfd_status_t status; - volatile rfd_command_t command; - volatile IOPhysicalAddress link; - volatile IOPhysicalAddress rbdAddr; - volatile rfd_misc_t misc; // 16 bytes - - UInt32 _pad[2]; // pad it to 64 bytes - - /* driver private */ - - struct rfd * _next; - IOPhysicalAddress _paddr; - rbd_t _rbd; // 32 bytes -} rfd_t; - -//------------------------------------------------------------------------- -// TBD - Transmit Buffer Descriptor. -//------------------------------------------------------------------------- -typedef UInt16 tbd_size_t; -#define TBD_SIZE_EL BIT(15) // end of list -#define TBD_SIZE_SHIFT 0 -#define TBD_SIZE_MASK CSR_MASK(TBD_SIZE, 0x3fff) - -typedef struct tbd { - volatile IOPhysicalAddress addr; - volatile tbd_size_t size; -} tbd_t; - -//------------------------------------------------------------------------- -// TxCB Status Word. -// Offset 0, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 tcb_status_t; -#define TCB_STATUS_C BIT(15) // complete bit -#define TCB_STATUS_OK BIT(13) // error free completion -#define TCB_STATUS_U BIT(12) // underrun bit - -//------------------------------------------------------------------------- -// TxCB Command Word. -// Offset 2, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 tcb_command_t; -#define TCB_COMMAND_EL BIT(15) // end of list -#define TCB_COMMAND_S BIT(14) // suspend bit -#define TCB_COMMAND_I BIT(13) // interrupt bit -#define TCB_COMMAND_NC BIT(4) // CRC/Source Address control -#define TCB_COMMAND_SF BIT(3) // flexible mode bit -#define TCB_COMMAND_SHIFT 0 -#define TCB_COMMAND_MASK CSR_MASK(TCB_COMMAND, 0x7) - -//------------------------------------------------------------------------- -// TxCB Count Word. -// Offset 0xC, 16-bit, RW. -//------------------------------------------------------------------------- -typedef UInt16 tcb_count_t; -#define TCB_COUNT_EOF BIT(15) // whole frame in TCB -#define TCB_COUNT_SHIFT 0 -#define TCB_COUNT_MASK CSR_MASK(TCB_COUNT, 0x3fff) - -//------------------------------------------------------------------------- -// TxCB - Transmit Command Block. -//------------------------------------------------------------------------- -#define TBDS_PER_TCB 12 -#define TCB_TX_THRESHOLD 0xe0 - -typedef struct tcb { - volatile tcb_status_t status; - volatile tcb_command_t command; - volatile IOPhysicalAddress link; - volatile IOPhysicalAddress tbdAddr; - volatile tcb_count_t count; - volatile UInt8 threshold; - volatile UInt8 number; - - /* driver private */ - - tbd_t _tbds[TBDS_PER_TCB]; - struct tcb * _next; - IOPhysicalAddress _paddr; - struct mbuf * _mbuf; - unsigned _pad; -} tcb_t; - -#endif /* !_I82557HW_H */ - diff --git a/iokit/Drivers/network/drvIntel82557/i82557Inline.h b/iokit/Drivers/network/drvIntel82557/i82557Inline.h deleted file mode 100644 index 7fec51241..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557Inline.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _I82557INLINE_H -#define _I82557INLINE_H - -#include <libkern/OSByteOrder.h> -#include <libkern/OSAtomic.h> - -//--------------------------------------------------------------------------- -// CSR macros. - -#define CSR_VALUE(name, x) (((x) & name ## _MASK) >> name ## _SHIFT) -#define CSR_FIELD(name, x) (((x) << name ## _SHIFT) & name ## _MASK) -#define CSR_MASK(name, x) ((x) << name ## _SHIFT) -#define BIT(x) (1 << (x)) - -#define IOSync() OSSynchronizeIO() - -//--------------------------------------------------------------------------- -// CSR read & write. - -static inline -UInt8 -OSReadLE8(volatile void * base) -{ - return *(volatile UInt8 *)base; -} - -static inline -UInt16 -OSReadLE16(volatile void * base) -{ - return OSReadLittleInt16(base, 0); -} - -static inline -UInt32 -OSReadLE32(volatile void * base) -{ - return OSReadLittleInt32(base, 0); -} - -static inline -void -OSWriteLE8(volatile void * base, UInt8 data) -{ - *(volatile UInt8 *)base = data; - IOSync(); -} - -static inline -void -OSWriteLE16(volatile void * base, UInt16 data) -{ - OSWriteLittleInt16(base, 0, data); - IOSync(); -} - -static inline -void -OSWriteLE32(volatile void * base, UInt32 data) -{ - OSWriteLittleInt32(base, 0, data); - IOSync(); -} - -//--------------------------------------------------------------------------- -// Set/clear bit(s) macros. - -#define __SET(n) \ -static inline void \ -OSSetLE##n(volatile void * base, UInt##n bit) \ -{ \ - OSWriteLE##n(base, (OSReadLE##n(base) | (bit))); \ -} - -#define __CLR(n) \ -static inline void \ -OSClearLE##n(volatile void * base, UInt##n bit) \ -{ \ - OSWriteLE##n(base, (OSReadLE##n(base) & ~(bit))); \ -} - -__SET(8) -__SET(16) -__SET(32) - -__CLR(8) -__CLR(16) -__CLR(32) - -#endif /* !_I82557INLINE_H */ diff --git a/iokit/Drivers/network/drvIntel82557/i82557PHY.cpp b/iokit/Drivers/network/drvIntel82557/i82557PHY.cpp deleted file mode 100644 index 3c36d550a..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557PHY.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. All rights reserved. - * - * i82557PHY.cpp - * - */ - -#include "i82557.h" -#include "i82557PHY.h" - -//--------------------------------------------------------------------------- -// Function: _logMDIStatus -// -// Purpose: -// Dump the contents of the MDI status register. - -static inline void -_logMDIStatus(mdi_reg_t reg) -{ - if (reg & MDI_STATUS_T4) - IOLog("PHY: T4 capable\n"); - if (reg & MDI_STATUS_TX_FD) - IOLog("PHY: 100Base-TX full duplex capable\n"); - if (reg & MDI_STATUS_TX_HD) - IOLog("PHY: 100Base-TX half duplex capable\n"); - if (reg & MDI_STATUS_10_FD) - IOLog("PHY: 10Base-T full duplex capable\n"); - if (reg & MDI_STATUS_10_HD) - IOLog("PHY: 10Base-T half duplex capable\n"); - if (reg & MDI_STATUS_EXTENDED_CAPABILITY) - IOLog("PHY: has extended capability registers\n"); - if (reg & MDI_STATUS_JABBER_DETECTED) - IOLog("PHY: jabberDetect set\n"); - if (reg & MDI_STATUS_AUTONEG_CAPABLE) - IOLog("PHY: auto negotiation capable\n"); - IOLog("PHY: link is %s\n", (reg & MDI_STATUS_LINK_STATUS) ? "UP" : "DOWN"); - return; -} - -//--------------------------------------------------------------------------- -// Function: _getModelId -// -// Purpose: -// Read the MDI ID registers and form a single 32-bit id. - -UInt32 Intel82557::_phyGetID() -{ - UInt16 id1, id2; - _mdiReadPHY(phyAddr, MDI_REG_PHYID_WORD_1, &id1); - _mdiReadPHY(phyAddr, MDI_REG_PHYID_WORD_2, &id2); - return ((id2 << 16) | id1); -} - -//--------------------------------------------------------------------------- -// Function: _phySetMedium -// -// Purpose: -// Setup the PHY to the medium type given. -// Returns true on success. - -bool Intel82557::_phySetMedium(mediumType_t medium) -{ - mdi_reg_t status; - mdi_reg_t control; - mediumType_t phyMedium = medium; - UInt32 mediumCapableMask; - - // Reset PHY before changing medium selection. - // - _phyReset(); - - // Get local capability. - // - _mdiReadPHY(phyAddr, MDI_REG_STATUS, &status); - - // Create a medium capable mask. - // - mediumCapableMask = (status >> 11) & 0x1f; - - // Force the PHY's data rate and duplex settings if the medium type - // chosen is not AUTO. - // - if (phyMedium != MEDIUM_TYPE_AUTO) { - if ((MEDIUM_TYPE_TO_MASK(phyMedium) & mediumCapableMask) == 0) { - // Hardware is not capable of selecting the user-selected - // medium. - // - return false; - } - else { - // Medium chosen is valid, go ahead and set PHY. - // - bool speed100 = false; - bool fullDuplex = false; - - if ((medium == MEDIUM_TYPE_TX_HD) || - (medium == MEDIUM_TYPE_TX_FD) || - (medium == MEDIUM_TYPE_T4)) - speed100 = true; - - if ((medium == MEDIUM_TYPE_10_FD) || (medium == MEDIUM_TYPE_TX_FD)) - fullDuplex = true; - - // Disable auto-negotiation function and force speed + duplex. - // - IOSleep(300); - - control = ((speed100 ? MDI_CONTROL_100 : 0) | - (fullDuplex ? MDI_CONTROL_FULL_DUPLEX : 0)); - - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - - VPRINT("%s: user forced %s Mbit/s%s mode\n", getName(), - speed100 ? "100" : "10", - fullDuplex ? " full duplex" : ""); - - IOSleep(50); - } - } - else { - // For MEDIUM_TYPE_AUTO, enable and restart auto-negotiation. - // - control = MDI_CONTROL_AUTONEG_ENABLE; - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - IOSleep(1); - control |= MDI_CONTROL_RESTART_AUTONEG; - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - } - - // Some special bit twiddling for NSC83840. - // - if (phyID == PHY_MODEL_NSC83840) { - /* set-up National Semiconductor 83840 specific registers */ - - mdi_reg_t reg; - - VPRINT("%s: setting NSC83840-specific registers\n", getName()); - _mdiReadPHY(phyAddr, NSC83840_REG_PCR, ®); - - /* - * This bit MUST be set, otherwise the card may not transmit at - * all in 100Mb/s mode. This is specially true for 82557 cards - * with the DP83840 PHY. - * - * In the NSC documentation, bit 10 of PCS register is labeled - * as a reserved bit. What is the real function of this bit? - */ - reg |= (NSC83840_PCR_TXREADY | NSC83840_PCR_CIM_DIS); - - _mdiWritePHY(phyAddr, NSC83840_REG_PCR, reg); - } - - currentMediumType = medium; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _phyAddMediumType -// -// Purpose: -// Add a single medium object to the medium dictionary. -// Also add the medium object to an array for fast lookup. - -bool Intel82557::_phyAddMediumType(UInt32 type, UInt32 speed, UInt32 code) -{ - IONetworkMedium * medium; - bool ret = false; - - medium = IONetworkMedium::medium(type, speed, 0, code); - if (medium) { - ret = IONetworkMedium::addMedium(mediumDict, medium); - if (ret) - mediumTable[code] = medium; - medium->release(); - } - return ret; -} - -//--------------------------------------------------------------------------- -// Function: _phyPublishMedia -// -// Purpose: -// Examine the PHY capabilities and advertise all supported medium types. -// -// FIXME: Non PHY medium types are not probed. - -#define MBPS 1000000 - -void Intel82557::_phyPublishMedia() -{ - mdi_reg_t status; - - // Read the PHY's media capability. - // - _mdiReadPHY(phyAddr, MDI_REG_STATUS, &status); - - _phyAddMediumType(kIOMediumEthernetAuto, - 0, - MEDIUM_TYPE_AUTO); - - if (status & MDI_STATUS_10_HD) - _phyAddMediumType(kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, - 10 * MBPS, - MEDIUM_TYPE_10_HD); - - if (status & MDI_STATUS_10_FD) - _phyAddMediumType(kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, - 10 * MBPS, - MEDIUM_TYPE_10_FD); - - if (status & MDI_STATUS_TX_HD) - _phyAddMediumType( - kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, - 100 * MBPS, - MEDIUM_TYPE_TX_HD); - - if (status & MDI_STATUS_TX_FD) - _phyAddMediumType( - kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, - 100 * MBPS, - MEDIUM_TYPE_TX_FD); - - if (status & MDI_STATUS_T4) - _phyAddMediumType(kIOMediumEthernet100BaseT4, - 100 * MBPS, - MEDIUM_TYPE_T4); -} - -//--------------------------------------------------------------------------- -// Function: _phyReset -// -// Purpose: -// Reset the PHY. - -#define PHY_RESET_TIMEOUT 100 // ms -#define PHY_RESET_DELAY 10 // ms -#define PHY_POST_RESET_DELAY 300 // us - -bool Intel82557::_phyReset() -{ - int i = PHY_RESET_TIMEOUT; - mdi_reg_t control; - - if (!_mdiReadPHY(phyAddr, MDI_REG_CONTROL, &control)) - return false; - - // Set the reset bit in the PHY Control register - // - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control | MDI_CONTROL_RESET); - - // Wait till reset process is complete (MDI_CONTROL_RESET returns to zero) - // - while (i > 0) { - if (!_mdiReadPHY(phyAddr, MDI_REG_CONTROL, &control)) - return false; - if ((control & MDI_CONTROL_RESET) == 0) { - IODelay(PHY_POST_RESET_DELAY); - return true; - } - IOSleep(PHY_RESET_DELAY); - i -= PHY_RESET_DELAY; - } - return false; -} - -//--------------------------------------------------------------------------- -// Function: _phyWaitAutoNegotiation -// -// Purpose: -// Wait until auto-negotiation is complete. - -#define PHY_NWAY_TIMEOUT 5000 // ms -#define PHY_NWAY_DELAY 20 // ms - -bool Intel82557::_phyWaitAutoNegotiation() -{ - int i = PHY_NWAY_TIMEOUT; - mdi_reg_t status; - - while (i > 0) { - if (!_mdiReadPHY(phyAddr, MDI_REG_STATUS, &status)) - return false; - - if (status & MDI_STATUS_AUTONEG_COMPLETE) - return true; - - IOSleep(PHY_NWAY_DELAY); - i -= PHY_NWAY_DELAY; - } - return false; -} - -//--------------------------------------------------------------------------- -// Function: _phyProbe -// -// Purpose: -// Find out which PHY is active. -// -#define AUTONEGOTIATE_TIMEOUT 35 - -bool Intel82557::_phyProbe() -{ - bool foundPhy1 = false; - mdi_reg_t control; - mdi_reg_t status; - - if (phyAddr == PHY_ADDRESS_I82503) { - VPRINT("%s: overriding to use Intel 82503", getName()); - return true; - } - - if (phyAddr > 0 && phyAddr < PHY_ADDRESS_MAX) { - VPRINT("%s: looking for Phy 1 at address %d\n", getName(), phyAddr); - _mdiReadPHY(phyAddr, MDI_REG_CONTROL, &control); - _mdiReadPHY(phyAddr, MDI_REG_STATUS, &status); // do it twice - _mdiReadPHY(phyAddr, MDI_REG_STATUS, &status); - if (control == 0xffff || (status == 0 && control == 0)) - { - VPRINT("%s: Phy 1 at address %d does not exist\n", getName(), - phyAddr); - } - else { - VPRINT("%s: Phy 1 at address %d exists\n", getName(), phyAddr); - foundPhy1 = true; - if (status & MDI_STATUS_LINK_STATUS) { - VPRINT("%s: found Phy 1 at address %d with link\n", - getName(), phyAddr); - return true; // use PHY1 - } - } - } - - // PHY1 does not exist, or it does not have valid link. - // Try PHY0 at address 0. - // - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_CONTROL, &control); - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_STATUS, &status); - - if (control == 0xffff || (status == 0 && control == 0)) { - if (phyAddr == 0) { /* if address forced to 0, then fail */ - IOLog("%s: phy0 not detected\n", getName()); - return false; - } - if (foundPhy1 == true) { - VPRINT("%s: no Phy at address 0, using Phy 1 without link\n", - getName()); - return true; // use PHY1 without a valid link - } - VPRINT("%s: no Phy at address 0, defaulting to 82503\n", getName()); - phyAddr = PHY_ADDRESS_I82503; - return true; - } - - // must isolate PHY1 electrically before using PHY0. - // - if (foundPhy1 == true) { - control = MDI_CONTROL_ISOLATE; - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - IOSleep(1); - } - - // Enable and restart auto-negotiation on PHY0. - // - VPRINT("%s: starting auto-negotiation on Phy 0", getName()); - control = MDI_CONTROL_AUTONEG_ENABLE; - _mdiWritePHY(PHY_ADDRESS_0, MDI_REG_CONTROL, control); - IOSleep(1); - control |= MDI_CONTROL_RESTART_AUTONEG; - _mdiWritePHY(PHY_ADDRESS_0, MDI_REG_CONTROL, control); - - for (int i = 0; i < AUTONEGOTIATE_TIMEOUT; i++) { - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_STATUS, &status); - if (status & MDI_STATUS_AUTONEG_COMPLETE) - break; - IOSleep(100); - } - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_STATUS, &status); - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_STATUS, &status); - _mdiReadPHY(PHY_ADDRESS_0, MDI_REG_STATUS, &status); - if ((status & MDI_STATUS_LINK_STATUS) || foundPhy1 == false) { - VPRINT("%s: using Phy 0 at address 0\n", getName()); - phyAddr = 0; - return true; - } - - // Isolate PHY0. - // - VPRINT("%s: using Phy 1 without link\n", getName()); - control = MDI_CONTROL_ISOLATE; - _mdiWritePHY(PHY_ADDRESS_0, MDI_REG_CONTROL, control); - IOSleep(1); - - // Enable and restart auto-negotiation on PHY1. - // - control = MDI_CONTROL_AUTONEG_ENABLE; - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - IOSleep(1); - control |= MDI_CONTROL_RESTART_AUTONEG; - _mdiWritePHY(phyAddr, MDI_REG_CONTROL, control); - - phyID = _phyGetID(); - VPRINT("%s: PHY model id is 0x%08lx\n", getName(), phyID); - phyID &= PHY_MODEL_MASK; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _phyGetMediumTypeFromBits -// -// Purpose: -// Return the medium type that correspond to the given specifiers. - -mediumType_t Intel82557::_phyGetMediumTypeFromBits(bool rate100, - bool fullDuplex, - bool t4) -{ - mediumType_t mediumType; - - if (t4) { - mediumType = MEDIUM_TYPE_T4; - } - else if (rate100) { - if (fullDuplex) - mediumType = MEDIUM_TYPE_TX_FD; - else - mediumType = MEDIUM_TYPE_TX_HD; - } - else { - if (fullDuplex) - mediumType = MEDIUM_TYPE_10_FD; - else - mediumType = MEDIUM_TYPE_10_HD; - } - - return mediumType; -} - -//--------------------------------------------------------------------------- -// Function: _phyGetMediumWithCode -// -// Purpose: -// Returns the IONetworkMedium object associated with the given type. - -IONetworkMedium * Intel82557::_phyGetMediumWithType(UInt32 type) -{ - if (type < MEDIUM_TYPE_INVALID) - return mediumTable[type]; - else - return 0; -} - -//--------------------------------------------------------------------------- -// Function: _phyReportLinkStatus -// -// Purpose: -// Called periodically to monitor for link changes. When a change -// is detected, determine the current link and report it to the -// upper layers by calling IONetworkController::setLinkStatus(). - -void Intel82557::_phyReportLinkStatus( bool firstPoll = false ) -{ - UInt16 phyStatus; - UInt16 phyStatusChange; - - // Read PHY status register. - - _mdiReadPHY( phyAddr, MDI_REG_STATUS, &phyStatus ); - - // Detect a change in the two link related bits. - // Remember that the link status bit will latch a link fail - // condition (should not miss a link down event). - - phyStatusChange = ( phyStatusPrev ^ phyStatus ) & - ( MDI_STATUS_LINK_STATUS | - MDI_STATUS_AUTONEG_COMPLETE ); - - if ( phyStatusChange || firstPoll ) - { - if ( firstPoll ) - { - // For the initial link status poll, wait a bit, then - // re-read the status register to clear any latched bits. - - _phyWaitAutoNegotiation(); - _mdiReadPHY( phyAddr, MDI_REG_STATUS, &phyStatus ); - _mdiReadPHY( phyAddr, MDI_REG_STATUS, &phyStatus ); - } - - // IOLog("PhyStatus: %04x\n", phyStatus); - - // Determine the link status. - - if ( ( phyStatus & MDI_STATUS_LINK_STATUS ) && - ( phyStatus & MDI_STATUS_AUTONEG_COMPLETE ) ) - { - // Excellent, link is up. - - IONetworkMedium * activeMedium; - - activeMedium = _phyGetMediumWithType( _phyGetActiveMedium() ); - - setLinkStatus( kIONetworkLinkValid | kIONetworkLinkActive, - activeMedium ); - - // IOLog("link is up %lx\n", - // activeMedium ? activeMedium->getType() : 0); - } - else - { - // Link is down. - - setLinkStatus( kIONetworkLinkValid, 0 ); - - // IOLog("link is down\n"); - } - - // Save phyStatus for the next run. - - phyStatusPrev = phyStatus; - } -} - -//--------------------------------------------------------------------------- -// Function: _phyGetActiveMedium -// -// Purpose: -// Once the PHY reports that the link is up, this method can be called -// to return the type of link that was established. - -mediumType_t Intel82557::_phyGetActiveMedium() -{ - mdi_reg_t reg; - mediumType_t medium; - - do { - // For the simple case where the media selection is not - // automatic (e.g. forced to 100BaseTX). - - if ( currentMediumType != MEDIUM_TYPE_AUTO ) - { - medium = currentMediumType; - break; - } - - // i82553 has a special register for determining the speed and - // duplex mode settings. - - if ( ( phyID == PHY_MODEL_I82553_A_B ) || - ( phyID == PHY_MODEL_I82553_C ) ) - { - _mdiReadPHY( phyAddr, I82553_REG_SCR, ® ); - - medium = _phyGetMediumTypeFromBits( reg & I82553_SCR_100, - reg & I82553_SCR_FULL_DUPLEX, - reg & I82553_SCR_T4 ); - break; - } - else if ( phyID == PHY_MODEL_NSC83840 ) - { - // For NSC83840, we use the 83840 specific register to determine - // the link speed and duplex mode setting. Early 83840 devices - // did not seem to report the remote capabilities when the link - // partner does not support NWay. - - mdi_reg_t exp; - - _mdiReadPHY( phyAddr, MDI_REG_ANEX, &exp ); - - if ( ( exp & MDI_ANEX_LP_AUTONEGOTIABLE ) == 0 ) - { - _mdiReadPHY( phyAddr, NSC83840_REG_PAR, ® ); - - medium = _phyGetMediumTypeFromBits( - !(reg & NSC83840_PAR_SPEED_10), - (reg & NSC83840_PAR_DUPLEX_STAT), - 0 ); - break; - } - } - - // For generic PHY, use the standard PHY registers. - // - // Use the local and remote capability words to determine the - // current active medium. - - mdi_reg_t lpa; - mdi_reg_t mya; - - _mdiReadPHY( phyAddr, MDI_REG_ANLP, &lpa ); - _mdiReadPHY( phyAddr, MDI_REG_ANAR, &mya ); - - mya &= lpa; // obtain common capabilities mask. - - // Observe PHY medium precedence. - - if ( mya & MDI_ANAR_TX_FD ) medium = MEDIUM_TYPE_TX_FD; - else if ( mya & MDI_ANAR_T4 ) medium = MEDIUM_TYPE_T4; - else if ( mya & MDI_ANAR_TX_HD ) medium = MEDIUM_TYPE_TX_HD; - else if ( mya & MDI_ANAR_10_FD ) medium = MEDIUM_TYPE_10_FD; - else medium = MEDIUM_TYPE_10_HD; - } - while ( false ); - - return medium; -} diff --git a/iokit/Drivers/network/drvIntel82557/i82557PHY.h b/iokit/Drivers/network/drvIntel82557/i82557PHY.h deleted file mode 100644 index 2391fa3a4..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557PHY.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright 1996 NeXT Software, Inc. - * All rights reserved. - * - * i82557PHY.h - * - contains PHY specific MDI register offsets and definitions - * - * Modification History - * - * 4-Mar-96 Dieter Siegmund (dieter@NeXT.com) - * Created. - */ - -#ifndef _I82557PHY_H -#define _I82557PHY_H - -#define PHY_ADDRESS_0 0 -#define PHY_ADDRESS_DEFAULT 1 -#define PHY_ADDRESS_I82503 32 -#define PHY_ADDRESS_MAX 32 - -#define PHY_MODEL_MASK 0xfff0ffff -#define PHY_MODEL_NSC83840 0x5c002000 -#define PHY_MODEL_I82553_A_B 0x000003e0 -#define PHY_MODEL_I82553_C 0x035002a8 -#define PHY_MODEL_I82555 0x015002a8 // also for internal PHY in i82558 - -#define MEDIUM_TYPE_TO_MASK(m) (1 << (m)) - -//------------------------------------------------------------------------- -// Generic MDI registers: -//------------------------------------------------------------------------- -#define MDI_REG_CONTROL 0x00 -#define MDI_REG_STATUS 0x01 -#define MDI_REG_PHYID_WORD_1 0x02 -#define MDI_REG_PHYID_WORD_2 0x03 -#define MDI_REG_ANAR 0x04 -#define MDI_REG_ANLP 0x05 -#define MDI_REG_ANEX 0x06 -#define MDI_REG_RESERVED_TOP 0x0f - -typedef UInt16 mdi_reg_t; - -//------------------------------------------------------------------------- -// MDI Control Register. -// Address 0, 16-bit, RW. -//------------------------------------------------------------------------- -#define MDI_CONTROL_RESET BIT(15) -#define MDI_CONTROL_LOOPBACK BIT(14) -#define MDI_CONTROL_100 BIT(13) -#define MDI_CONTROL_AUTONEG_ENABLE BIT(12) -#define MDI_CONTROL_POWER_DOWN BIT(11) -#define MDI_CONTROL_ISOLATE BIT(10) -#define MDI_CONTROL_RESTART_AUTONEG BIT(9) -#define MDI_CONTROL_FULL_DUPLEX BIT(8) -#define MDI_CONTROL_CDT_ENABLE BIT(7) - -//------------------------------------------------------------------------- -// MDI Status Register. -// Address 1, 16-bit, RO. -//------------------------------------------------------------------------- -#define MDI_STATUS_T4 BIT(15) -#define MDI_STATUS_TX_FD BIT(14) -#define MDI_STATUS_TX_HD BIT(13) -#define MDI_STATUS_10_FD BIT(12) -#define MDI_STATUS_10_HD BIT(11) -#define MDI_STATUS_AUTONEG_COMPLETE BIT(5) -#define MDI_STATUS_REMOTE_FAULT_DETECT BIT(4) -#define MDI_STATUS_AUTONEG_CAPABLE BIT(3) -#define MDI_STATUS_LINK_STATUS BIT(2) -#define MDI_STATUS_JABBER_DETECTED BIT(1) -#define MDI_STATUS_EXTENDED_CAPABILITY BIT(0) - -//------------------------------------------------------------------------- -// MDI Auto-Negotiation Advertisement Register. -// Address 4, 16-bit, RW. -//------------------------------------------------------------------------- -#define MDI_ANAR_NEXT_PAGE BIT(15) -#define MDI_ANAR_ACKNOWLEDGE BIT(14) -#define MDI_ANAR_REMOTE_FAULT BIT(13) -#define MDI_ANAR_T4 BIT(9) -#define MDI_ANAR_TX_FD BIT(8) -#define MDI_ANAR_TX_HD BIT(7) -#define MDI_ANAR_10_FD BIT(6) -#define MDI_ANAR_10_HD BIT(5) -#define MDI_ANAR_SELECTOR_SHIFT 0 -#define MDI_ANAR_SELECTOR_MASK CSR_MASK(MDI_ANAR_SELECTOR, 0x1f) - -//------------------------------------------------------------------------- -// MDI Auto-Negotiation Link Partner Ability Register. -// Address 5, 16-bit, RO. -//------------------------------------------------------------------------- -#define MDI_ANLP_NEXT_PAGE BIT(15) -#define MDI_ANLP_ACKNOWLEDGE BIT(14) -#define MDI_ANLP_REMOTE_FAULT BIT(13) -#define MDI_ANLP_T4 BIT(9) -#define MDI_ANLP_TX_FD BIT(8) -#define MDI_ANLP_TX_HD BIT(7) -#define MDI_ANLP_10_FD BIT(6) -#define MDI_ANLP_10_HD BIT(5) -#define MDI_ANLP_SELECTOR_SHIFT 0 -#define MDI_ANLP_SELECTOR_MASK CSR_MASK(MDI_ANLP_SELECTOR, 0x1f) - -//------------------------------------------------------------------------- -// MDI Auto-Negotiation Expansion Register. -// Address 6, 16-bit, RO. -//------------------------------------------------------------------------- -#define MDI_ANEX_PARALLEL_DETECT_FAULT BIT(4) -#define MDI_ANEX_LP_NEXT_PAGEABLE BIT(3) -#define MDI_ANEX_NEXT_PAGEABLE BIT(2) -#define MDI_ANEX_PAGE_RECEIVED BIT(1) -#define MDI_ANEX_LP_AUTONEGOTIABLE BIT(0) - -//------------------------------------------------------------------------- -// NSC DP83840-specific MDI registers -//------------------------------------------------------------------------- -#define NSC83840_REG_DCR 0x12 // disconnect counter -#define NSC83840_REG_FCSCR 0x13 // false carrier sense counter -#define NSC83840_REG_RECR 0x15 // receive error counter -#define NSC83840_REG_SRR 0x16 // silicon revision register -#define NSC83840_REG_PCR 0x17 // PCS configuration register -#define NSC83840_REG_LBREMR 0x18 // loopback,bypass,rx err mask -#define NSC83840_REG_PAR 0x19 // PHY address register -#define NSC83840_REG_10BTSR 0x1b // 10Base-T status register -#define NSC83840_REG_10BTCR 0x1c // 10Base-T config register - -//------------------------------------------------------------------------- -// NSC PCS Configuration Register (PCR). -// Address 0x17, 16-bit, RW. -//------------------------------------------------------------------------- -#define NSC83840_PCR_NRZI_EN BIT(15) -#define NSC83840_PCR_DESCR_TO_SEL BIT(14) -#define NSC83840_PCR_DESCR_TO_DIS BIT(13) -#define NSC83840_PCR_REPEATER BIT(12) -#define NSC83840_PCR_ENCSEL BIT(11) -#define NSC83840_PCR_TXREADY BIT(10) -#define NSC83840_PCR_CLK25MDIS BIT(7) -#define NSC83840_PCR_F_LINK_100 BIT(6) -#define NSC83840_PCR_CIM_DIS BIT(5) -#define NSC83840_PCR_TX_OFF BIT(4) -#define NSC83840_PCR_LED1_MODE BIT(2) -#define NSC83840_PCR_LED4_MODE BIT(1) - -//------------------------------------------------------------------------- -// NSC PHY Address Register (PAR). -// Address 0x19, 16-bit, RW. -//------------------------------------------------------------------------- -#define NSC83840_PAR_DIS_CRS_JAB BIT(11) -#define NSC83840_PAR_AN_EN_STAT BIT(10) -#define NSC83840_PAR_FEFI_EN BIT(8) -#define NSC83840_PAR_DUPLEX_STAT BIT(7) -#define NSC83840_PAR_SPEED_10 BIT(6) -#define NSC83840_PAR_CIM_STATUS BIT(5) -#define NSC83840_PAR_PHYADDR_SHIFT 0 -#define NSC83840_PAR_PHYADDR_MASK CSR_MASK(NSC83840_PAR_PHYADDR, 0x1f) - -//------------------------------------------------------------------------- -// Intel 82553-specific MDI registers -//------------------------------------------------------------------------- -#define I82553_REG_SCR 0x10 -#define I82553_REG_100RDCR 0x14 - -//------------------------------------------------------------------------- -// Intel 82553 Status and Control Register (SCR). -// Address 0x10, 16-bit, RW. -//------------------------------------------------------------------------- -#define I82553_SCR_FLOW_CONTROL BIT(15) -#define I82553_SCR_CARRIER_SENSE_DIS BIT(13) -#define I82553_SCR_TX_FLOW_CONTROL BIT(12) -#define I82553_SCR_RX_DESERIAL_IN_SYNC BIT(11) -#define I82553_SCR_100_POWERDOWN BIT(10) -#define I82553_SCR_10_POWERDOWN BIT(9) -#define I82553_SCR_POLARITY BIT(8) -#define I82553_SCR_T4 BIT(2) -#define I82553_SCR_100 BIT(1) -#define I82553_SCR_FULL_DUPLEX BIT(0) - -#endif /* !_I82557PHY_H */ diff --git a/iokit/Drivers/network/drvIntel82557/i82557Private.cpp b/iokit/Drivers/network/drvIntel82557/i82557Private.cpp deleted file mode 100644 index 31ac8842f..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557Private.cpp +++ /dev/null @@ -1,1692 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. All rights reserved. - * - * i82557Private.cpp - * - */ - -#include "i82557.h" - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -#include <string.h> -} - -//--------------------------------------------------------------------------- -// Function: IOPhysicalFromVirtual -// -// Hack, remove ASAP. - -static inline IOReturn -IOPhysicalFromVirtual(vm_address_t vaddr, IOPhysicalAddress * paddr) -{ - *paddr = pmap_extract(kernel_pmap, vaddr); - return (*paddr == 0) ? kIOReturnBadArgument : kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Function: _intrACK -// -// Purpose: -// Acknowledge all of the pending interrupt sources. -// -// Returns: -// Return the interrupt status. -// -// CSR usage: -// Read/Write: SCB status - -static inline scb_status_t _intrACK(CSR_t * CSR_p) -{ - scb_status_t stat_irq = OSReadLE16(&CSR_p->status) & SCB_STATUS_INT_MASK; - if (stat_irq) - OSWriteLE16(&CSR_p->status, stat_irq); // ack pending interrupts. - return (stat_irq); -} - -//--------------------------------------------------------------------------- -// Function: _waitSCBCommandClear -// -// Purpose: -// Wait for the SCB Command field to clear. Ensures that we don't -// overrun the NIC's command unit. -// -// Returns: -// true if the SCB command field was cleared. -// false if the SCB command field was not cleared. -// -// CSR usage: -// Read: SCB command - -static inline bool -_waitSCBCommandClear(CSR_t * CSR_p) -{ - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (!OSReadLE8(&CSR_p->command)) - return true; - IODelay(SPIN_COUNT); - } - return false; // hardware is not responding. -} - -//--------------------------------------------------------------------------- -// Function: _waitCUNonActive -// -// Purpose: -// Waits for the Command Unit to become inactive. -// -// Returns: -// true if the CU has become inactive. -// false if the CU remains active. -// -// CSR usage: -// Read: SCB status - -static inline bool -_waitCUNonActive(CSR_t * CSR_p) -{ - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (CSR_VALUE(SCB_STATUS_CUS, OSReadLE16(&CSR_p->status)) != - SCB_CUS_ACTIVE) - return true; - IODelay(SPIN_COUNT); - } - return false; -} - -//--------------------------------------------------------------------------- -// Function: _polledCommand:WithAddress -// -// Purpose: -// Issue a polled command to the NIC. - -bool Intel82557::_polledCommand(cbHeader_t * hdr_p, IOPhysicalAddress paddr) -{ - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: _polledCommand:(%s): _waitSCBCommandClear failed\n", - CUCommandString(CSR_VALUE(CB_CMD, OSReadLE16(&hdr_p->command))), - getName()); - return false; - } - - if (!_waitCUNonActive(CSR_p)) { - IOLog("%s: _polledCommand:(%s): _waitCUNonActive failed\n", - CUCommandString(CSR_VALUE(CB_CMD, OSReadLE16(&hdr_p->command))), - getName()); - return false; - } - - // Set the physical address of the command block, and issue a - // command unit start. - // - OSWriteLE32(&CSR_p->pointer, paddr); - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_START)); - - prevCUCommand = SCB_CUC_START; - - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (OSReadLE16(&hdr_p->status) & CB_STATUS_C) - return true; - IODelay(SPIN_COUNT); - } - return false; -} - -//--------------------------------------------------------------------------- -// Function: _abortReceive -// -// Purpose: -// Abort the receive unit. - -bool Intel82557::_abortReceive() -{ - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: _abortReceive: _waitSCBCommandClear failed\n", getName()); - return false; - } - - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_ABORT)); - - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)) == - SCB_RUS_IDLE) - return true; - IODelay(SPIN_COUNT); - } - - IOLog("%s: _abortReceive: timeout\n", getName()); - return false; -} - -//--------------------------------------------------------------------------- -// Function: _startReceive -// -// Purpose: -// Start the receive unit - -bool Intel82557::_startReceive() -{ - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: _startReceive: _waitSCBCommandClear failed\n", getName()); - return false; - } - - // Make sure the initial RFD has a link to its RBD - OSWriteLE32(&headRfd->rbdAddr, headRfd->_rbd._paddr); - - OSWriteLE32(&CSR_p->pointer, headRfd->_paddr); - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_START)); - - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)) == - SCB_RUS_READY) - return true; - IODelay(SPIN_COUNT); - } - - IOLog("%s: _startReceive: timeout\n", getName()); - return false; -} - -//--------------------------------------------------------------------------- -// Function: _resetChip -// -// Purpose: -// Issue a selective reset then a full reset. -// This is done to avoid a PCI bus hang if the 82557 is in the midst of -// a PCI bus cycle. The selective reset pauses the transmit and receive -// engines. -// -void Intel82557::_resetChip() -{ - int i = 0; - - sendPortCommand(portSelectiveReset_e, 0); - do { - IOSleep(1); - } while (OSReadLE32(&CSR_p->port) && ++i < 100); - - sendPortCommand(portReset_e, 0); - IOSleep(1); - return; -} - -//--------------------------------------------------------------------------- -// Function: issueReset -// -// Purpose: -// Shut down the chip, and issue a reset. - -void Intel82557::issueReset() -{ - IOLog("%s: resetting adapter\n", getName()); - - etherStats->dot3RxExtraEntry.resets++; - - setActivationLevel(kActivationLevel0); - if (!setActivationLevel(currentLevel)) { - IOLog("%s: Reset attempt unsuccessful\n", getName()); - } -} - -//--------------------------------------------------------------------------- -// Function: updateRFDFromMbuf -// -// Purpose: -// Updated a RFD/RBD in order to attach it to a cluster mbuf. -// XXX - assume cluster will never cross page boundary. - -bool Intel82557::updateRFDFromMbuf(rfd_t * rfd_p, struct mbuf * m) -{ - struct IOPhysicalSegment vector; - UInt count; - - count = rxMbufCursor->getPhysicalSegments(m, &vector, 1); - if (!count) - return false; - - // Start modifying RFD - // - rfd_p->_rbd.buffer = vector.location; // cursor is little-endian -// OSWriteLE32(&rfd_p->_rbd.size, CSR_FIELD(RBD_SIZE, vector.length)); - - rfd_p->_rbd._mbuf = m; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _initTcbQ -// -// Purpose: -// Initialize the transmit control block queue. Create a circularly -// linked list of tcbs. - -bool Intel82557::_initTcbQ(bool enable = false) -{ - int i; - - tcbQ.numFree = tcbQ.numTcbs = NUM_TRANSMIT_FRAMES; - tcbQ.activeHead_p = tcbQ.activeTail_p = tcbQ.freeHead_p = tcbList_p; - - for (i = 0; i < tcbQ.numTcbs; i++) { /* free up buffers */ - if (tcbList_p[i]._mbuf) { - freePacket(tcbList_p[i]._mbuf); - tcbList_p[i]._mbuf = 0; - } - } - bzero(tcbList_p, sizeof(tcb_t) * tcbQ.numTcbs); - - if (!enable) - return true; - - for (i = 0; i < tcbQ.numTcbs; i++) { - IOPhysicalAddress paddr; - - IOReturn result = IOPhysicalFromVirtual((vm_address_t) &tcbList_p[i], - &tcbList_p[i]._paddr); - if (result != kIOReturnSuccess) { - IOLog("i82557(tcbQ): Invalid TCB address\n"); - return false; - } - - result = IOPhysicalFromVirtual((vm_address_t) &tcbList_p[i]._tbds, - &paddr); - if (result != kIOReturnSuccess) { - IOLog("i82557(tcbQ): Invalid TBD address\n"); - return false; - } - OSWriteLE32(&tcbList_p[i].tbdAddr, paddr); - - if (i == (tcbQ.numTcbs - 1)) - tcbList_p[i]._next = &tcbList_p[0]; - else - tcbList_p[i]._next = &tcbList_p[i + 1]; - } - for (i = 0; i < tcbQ.numTcbs; i++) /* make physical links */ - OSWriteLE32(&tcbList_p[i].link, tcbList_p[i]._next->_paddr); - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _setupRfd - -static void _setupRfd(rfd_t * rfdList_p) -{ - for (int i = 0; i < NUM_RECEIVE_FRAMES; i++) { - if (i == (NUM_RECEIVE_FRAMES - 1)) { - /* mark tails and link the lists circularly */ - OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_EL); - rfdList_p[i]._next = &rfdList_p[0]; - OSSetLE32(&rfdList_p[i]._rbd.size, RBD_SIZE_EL); - rfdList_p[i]._rbd._next = &rfdList_p[0]._rbd; - } - else { - rfdList_p[i]._next = &rfdList_p[i + 1]; - rfdList_p[i]._rbd._next = &rfdList_p[i + 1]._rbd; - } - - OSWriteLE32(&rfdList_p[i].link, rfdList_p[i]._next->_paddr); - OSWriteLE32(&rfdList_p[i].rbdAddr, - (i == 0) ? rfdList_p[0]._rbd._paddr : C_NULL); - - OSWriteLE32(&rfdList_p[i]._rbd.link, rfdList_p[i]._rbd._next->_paddr); - OSSetLE32(&rfdList_p[i]._rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE)); - } -} - -//--------------------------------------------------------------------------- -// Function: _initRfdList -// -// Purpose: -// Create a circularly linked list of receive frame descriptors, and -// populate them with receive buffers allocated from our special pool. - -bool Intel82557::_initRfdList(bool enable = false) -{ - int i; - IOReturn result; - - /* free allocated packet buffers */ - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - if (rfdList_p[i]._rbd._mbuf) { - freePacket(rfdList_p[i]._rbd._mbuf); -// rfdList_p[i]._rbd._mbuf = 0; - } - } - - /* zero out the entire structure, and re-create it */ - bzero(rfdList_p, sizeof(rfd_t) * NUM_RECEIVE_FRAMES); - - if (!enable) - return true; - - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_SF); - - result = IOPhysicalFromVirtual((vm_address_t) &rfdList_p[i], - &rfdList_p[i]._paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid RFD address\n", getName()); - return false; - } - result = IOPhysicalFromVirtual((vm_address_t) &rfdList_p[i]._rbd, - &rfdList_p[i]._rbd._paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid RBD address\n", getName()); - return false; - } - } - - _setupRfd(rfdList_p); - - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - // Pre-load the receive ring with max size mbuf packets. - // - struct mbuf * m = allocatePacket(MAX_BUF_SIZE); - if (!m) - return false; - - if (updateRFDFromMbuf(&rfdList_p[i], m) == false) { - IOLog("%s: updateRFDFromMbuf() error\n", getName()); - freePacket(m); - return false; - } - } - - headRfd = rfdList_p; - tailRfd = rfdList_p + NUM_RECEIVE_FRAMES - 1; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _resetRfdList -// -// Purpose: -// Reset the RFD list before the receiver engine is restarted after -// a resource shortage. - -bool Intel82557::_resetRfdList() -{ - int i; - - struct _cache { - IOPhysicalAddress rbd_buffer; - struct mbuf * rbd_mbuf; - IOPhysicalAddress rfd_paddr; - IOPhysicalAddress rbd_paddr; - } * cache_p = (struct _cache *) KDB_buf_p; - - if ((sizeof(struct _cache) * NUM_RECEIVE_FRAMES) > ETHERMAXPACKET) { - IOLog("%s: no space for cache data\n", getName()); - return false; - } - - /* cache allocated packet buffers */ - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - cache_p[i].rbd_mbuf = rfdList_p[i]._rbd._mbuf; - cache_p[i].rbd_buffer = rfdList_p[i]._rbd.buffer; - cache_p[i].rfd_paddr = rfdList_p[i]._paddr; - cache_p[i].rbd_paddr = rfdList_p[i]._rbd._paddr; - } - - /* zero out the entire structure, and re-create it */ - bzero(rfdList_p, sizeof(rfd_t) * NUM_RECEIVE_FRAMES); - - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - OSSetLE16(&rfdList_p[i].command, RFD_COMMAND_SF); - rfdList_p[i]._paddr = cache_p[i].rfd_paddr; - rfdList_p[i]._rbd._paddr = cache_p[i].rbd_paddr; - } - - _setupRfd(rfdList_p); - - for (i = 0; i < NUM_RECEIVE_FRAMES; i++) { - rfdList_p[i]._rbd.buffer = cache_p[i].rbd_buffer; - rfdList_p[i]._rbd._mbuf = cache_p[i].rbd_mbuf; - } - - headRfd = rfdList_p; - tailRfd = rfdList_p + NUM_RECEIVE_FRAMES - 1; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _mdiReadPHY:Register:Data -// -// Purpose: -// Read the specified MDI register and return the results. - -bool -Intel82557::_mdiReadPHY(UInt8 phyAddress, UInt8 regAddress, UInt16 * data_p) -{ - mdi_control_t mdi; - - mdi = CSR_FIELD(MDI_CONTROL_PHYADDR, phyAddress) | - CSR_FIELD(MDI_CONTROL_REGADDR, regAddress) | - CSR_FIELD(MDI_CONTROL_OPCODE, MDI_CONTROL_OP_READ); - - OSWriteLE32(&CSR_p->mdiControl, mdi); - IODelay(20); - - bool ready = false; - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (OSReadLE32(&CSR_p->mdiControl) & MDI_CONTROL_READY) { - ready = true; - break; - } - IODelay(20); - } - if (ready == false) { - IOLog("%s: _mdiReadPHYRegisterSuccess timeout\n", getName()); - return false; - } - - *data_p = CSR_VALUE(MDI_CONTROL_DATA, OSReadLE32(&CSR_p->mdiControl)); - return true; -} - -//--------------------------------------------------------------------------- -// Function: _mdiWritePHY:Register:Data -// -// Purpose: -// Write the specified MDI register with the given data. - -bool Intel82557::_mdiWritePHY(UInt8 phyAddress, UInt8 regAddress, UInt16 data) -{ - mdi_control_t mdi; - - mdi = CSR_FIELD(MDI_CONTROL_PHYADDR, phyAddress) | - CSR_FIELD(MDI_CONTROL_REGADDR, regAddress) | - CSR_FIELD(MDI_CONTROL_OPCODE, MDI_CONTROL_OP_WRITE) | - CSR_FIELD(MDI_CONTROL_DATA, data); - - OSWriteLE32(&CSR_p->mdiControl, mdi); - IODelay(20); - - bool ready = false; - for (int i = 0; i < SPIN_TIMEOUT; i++) { - if (OSReadLE32(&CSR_p->mdiControl) & MDI_CONTROL_READY) { - ready = true; - break; - } - IODelay(20); - } - if (ready == false) { - IOLog("%s: _mdiWritePHYRegisterData timeout\n", getName()); - return false; - } - return true; -} - -//--------------------------------------------------------------------------- -// Function: nop -// -// Purpose: -// Issue a polled NOP command to the NIC. - -bool Intel82557::nop() -{ - cbHeader_t * nop_p = &overlay_p->nop; - - bzero(nop_p, sizeof(*nop_p)); - OSWriteLE16(&nop_p->command, CSR_FIELD(CB_CMD, CB_CMD_NOP) | CB_EL); - OSWriteLE32(&nop_p->link, C_NULL); - - return _polledCommand(nop_p, overlay_paddr); -} - -//--------------------------------------------------------------------------- -// Function: config -// -// Purpose: -// Issue a polled CONFIGURE command to the NIC. - -bool Intel82557::config() -{ - UInt8 * cb_p; - cb_configure_t * cfg_p = &overlay_p->configure; - - /* - * Fill the configure command block - */ - bzero(cfg_p, sizeof(*cfg_p)); - - OSWriteLE16(&cfg_p->header.command, - CSR_FIELD(CB_CMD, CB_CMD_CONFIGURE) | CB_EL); - OSWriteLE32(&cfg_p->header.link, C_NULL); - - cb_p = cfg_p->byte; - cb_p[0] = CSR_FIELD(CB_CB0_BYTE_COUNT, CB_CONFIG_BYTE_COUNT); - - cb_p[1] = CSR_FIELD(CB_CB1_TX_FIFO_LIMIT, CB_CB1_TX_FIFO_0) | - CSR_FIELD(CB_CB1_RX_FIFO_LIMIT, CB_CB1_RX_FIFO_64); - - cb_p[3] = CB_CB3_MWI_ENABLE; // enable PCI-MWI on 82558 devices - - cb_p[4] = 0; // disable PCI transfer limits - cb_p[5] = 0; - - cb_p[6] = CB_CB6_NON_DIRECT_DMA | CB_CB6_STD_TCB | CB_CB6_STD_STATS; - - cb_p[7] = CSR_FIELD(CB_CB7_UNDERRUN_RETRY, CB_CB7_UNDERRUN_RETRY_1) | - CB_CB7_DISC_SHORT_FRAMES; - - if ((eeprom->getContents()->controllerType != I82558_CONTROLLER_TYPE) && - (phyAddr != PHY_ADDRESS_I82503)) - cb_p[8] = CB_CB8_CSMA_EN; - - cb_p[10] = CSR_FIELD(CB_CB10_PREAMBLE, CB_CB10_PREAMBLE_7_BYTES) | - CB_CB10_NSAI; - - cb_p[12] = CSR_FIELD(CB_CB12_IFS, CB_CB12_IFS_96_BIT_TIMES); - - cb_p[13] = CSR_FIELD(CB_CB13_FC_TYPE_LSB, CB_CB13_FC_TYPE_LSB_DEF); - cb_p[14] = CSR_FIELD(CB_CB14_FC_TYPE_MSB, CB_CB14_FC_TYPE_MSB_DEF); - - cb_p[15] = ((cb_p[8] & CB_CB8_CSMA_EN) ? 0 : CB_CB15_CRS_CDT) | - (promiscuousEnabled ? CB_CB15_PROMISCUOUS : 0); - - cb_p[16] = CSR_FIELD(CB_CB16_FC_DELAY_LSB, CB_CB16_FC_DELAY_LSB_DEF); - cb_p[17] = CSR_FIELD(CB_CB17_FC_DELAY_MSB, CB_CB17_FC_DELAY_MSB_DEF); - - cb_p[18] = CB_CB18_PADDING | CB_CB18_STRIPPING; - -#if 0 // XXX - need to fix this - /* - * Force full duplex if there is a user override, or we are using Phy 0 - * and full duplex mode is enabled. The FDX# pin is wired to Phy 1, - * which means that the 82557 can't autodetect the setting correctly. - */ - if (forceFullDuplex || (phyAddr == PHY_ADDRESS_0 && fullDuplexMode)) - cb_p[19] = CB_CB19_FORCE_FDX; -#endif - - cb_p[19] = CB_CB19_AUTO_FDX; - if (flowControl) { - cb_p[19] |= ( CB_CB19_TX_FC | - CB_CB19_RX_FC_RESTOP | - CB_CB19_RX_FC_RESTART | - CB_CB19_REJECT_FC ); - } - - cb_p[20] = CSR_FIELD(CB_CB20_FC_ADDR_LSB, CB_CB20_FC_ADDR_LSB_DEF); - - IOSync(); - - return _polledCommand((cbHeader_t *) cfg_p, overlay_paddr); -} - -//--------------------------------------------------------------------------- -// Function: iaSetup -// -// Purpose: -// Issue a polled IndividualAddressSETUP command to the NIC. -// -bool Intel82557::iaSetup() -{ - cb_iasetup_t * iaSetup_p = &overlay_p->iasetup; - - /* - * Fill the IA-setup command block - */ - bzero(iaSetup_p, sizeof(*iaSetup_p)); - - OSWriteLE16(&iaSetup_p->header.command, CSR_FIELD(CB_CMD, CB_CMD_IASETUP) | - CB_EL); - OSWriteLE32(&iaSetup_p->header.link, C_NULL); - iaSetup_p->addr = myAddress; - - return _polledCommand((cbHeader_t *) iaSetup_p, overlay_paddr); -} - -//--------------------------------------------------------------------------- -// Function: mcSetup -// -// Purpose: -// Issue a polled MultiCastSETUP command to the NIC. If 'fromData' is -// true, then we ignore the addrs/count arguments and instead use the -// multicast address list property in our interface client object. - -bool Intel82557::mcSetup(IOEthernetAddress * addrs, - UInt count, - bool fromData = false) -{ - cb_mcsetup_t * mcSetup_p; - bool cmdResult; - IOReturn result; - IOPhysicalAddress mcSetup_paddr; - - if (fromData) { - // mcSetup() was not called by the setMulticastList() function. - // We should get the multicast list stored in the interface - // object's property table. - // - // mcSetup() is always executed by the default workloop thread, - // thus we don't have to worry about the address list being - // changed while we go through it. - // - addrs = 0; - count = 0; - - if (netif) { - OSData * mcData = OSDynamicCast(OSData, - netif->getProperty(kIOMulticastFilterData)); - if (mcData) { - addrs = (IOEthernetAddress *) mcData->getBytesNoCopy(); - count = mcData->getLength() / sizeof(IOEthernetAddress); - assert(addrs && count); - } - } - } - - mcSetup_p = (cb_mcsetup_t *) IOMallocAligned(PAGE_SIZE, PAGE_SIZE); - if (!mcSetup_p) { - IOLog("%s: mcSetup:IOMallocAligned return NULL\n", getName()); - return false; - } - - reserveDebuggerLock(); - - do { - cmdResult = false; - - OSWriteLE16(&mcSetup_p->header.status, 0); - OSWriteLE16(&mcSetup_p->header.command, - CSR_FIELD(CB_CMD, CB_CMD_MCSETUP) | CB_EL); - OSWriteLE32(&mcSetup_p->header.link, C_NULL); - - /* fill in the addresses (count may be zero) */ - for (UInt i = 0; i < count; i++) - mcSetup_p->addrs[i] = addrs[i]; - - /* Set the number of bytes in the MC list, if the count is zero, - * it is equivalent to disabling the multicast filtering mechanism. - */ - OSWriteLE16(&mcSetup_p->count, count * sizeof(IOEthernetAddress)); - - result = IOPhysicalFromVirtual((vm_address_t) mcSetup_p, - &mcSetup_paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid MC-setup command block address\n", getName()); - break; - } - - if (!_polledCommand((cbHeader_t *) mcSetup_p, mcSetup_paddr)) { - IOLog("%s: MC-setup command failed 0x%x\n", getName(), - OSReadLE16(&mcSetup_p->header.status)); - break; - } - - cmdResult = (OSReadLE16(&mcSetup_p->header.status) & CB_STATUS_OK) ? - true : false; - } while (0); - - releaseDebuggerLock(); - - IOFreeAligned(mcSetup_p, PAGE_SIZE); - - return cmdResult; -} - -//--------------------------------------------------------------------------- -// Function: _selfTest -// -// Purpose: -// Issue a PORT self test command to the NIC and verify the results. - -bool Intel82557::_selfTest() -{ - port_selftest_t * test_p = (port_selftest_t *) overlay_p; - UInt32 results; - - OSWriteLE32(&test_p->signature, 0); - OSWriteLE32(&test_p->results, ~0); - sendPortCommand(portSelfTest_e, overlay_paddr); - IOSleep(20); - if (OSReadLE32(&test_p->signature) == 0) { - IOLog("%s: Self test timed out\n", getName()); - return false; - } - - results = OSReadLE32(&test_p->results); - if (results) { /* report errors from self test */ - if (results & PORT_SELFTEST_ROM) - IOLog("%s: Self test reports invalid ROM contents\n", - getName()); - if (results & PORT_SELFTEST_REGISTER) - IOLog("%s: Self test reports internal register failure\n", - getName()); - if (results & PORT_SELFTEST_DIAGNOSE) - IOLog("%s: Self test reports serial subsystem failure\n", - getName()); - if (results & PORT_SELFTEST_GENERAL) - IOLog("%s: Self test failed\n", getName()); - return false; - } - return true; -} - -//--------------------------------------------------------------------------- -// Function: sendPortCommand -// -// Purpose: -// Issue an 82557 PORT command. -// -void Intel82557::sendPortCommand(port_command_t command, UInt arg) -{ - OSWriteLE32(&CSR_p->port, (arg & PORT_ADDRESS_MASK) | - CSR_FIELD(PORT_FUNCTION, command)); - return; -} - -//--------------------------------------------------------------------------- -// Function: enableAdapterInterrupts, disableAdapterInterrupts -// -// Purpose: -// Turn on/off interrupts at the adapter. - -void Intel82557::enableAdapterInterrupts() -{ - /* - * For 82558, mask (disable) the ER and FCP interrupts. - */ - UInt8 interruptByte; - interruptByte = SCB_INTERRUPT_ER | SCB_INTERRUPT_FCP; - OSWriteLE8(&CSR_p->interrupt, interruptByte); - interruptEnabled = true; - return; -} - -void Intel82557::disableAdapterInterrupts() -{ - UInt8 interruptByte; - interruptByte = SCB_INTERRUPT_M; - OSWriteLE8(&CSR_p->interrupt, interruptByte); - interruptEnabled = false; - return; -} - -//--------------------------------------------------------------------------- -// Function: _logCounters -// -// Purpose: -// If Verbose is defined as yes, log extra information about errors that -// have occurred. - -static inline void -_logCounters(errorCounters_t * errorCounters_p) -{ - if (errorCounters_p->tx_good_frames) - IOLog("tx_good_frames %ld\n", - OSReadLE32(&errorCounters_p->tx_good_frames)); - if (errorCounters_p->tx_maxcol_errors) - IOLog("tx_maxcol_errors %ld\n", - OSReadLE32(&errorCounters_p->tx_maxcol_errors)); - if (errorCounters_p->tx_late_collision_errors) - IOLog("tx_late_collision_errors %ld\n", - OSReadLE32(&errorCounters_p->tx_late_collision_errors)); - if (errorCounters_p->tx_underrun_errors) - IOLog("tx_underrun_errors %ld\n", - OSReadLE32(&errorCounters_p->tx_underrun_errors)); - if (errorCounters_p->tx_lost_carrier_sense_errors) - IOLog("tx_lost_carrier_sense_errors %ld\n", - OSReadLE32(&errorCounters_p->tx_lost_carrier_sense_errors)); - if (errorCounters_p->tx_deferred) - IOLog("tx_deferred %ld\n", OSReadLE32(&errorCounters_p->tx_deferred)); - if (errorCounters_p->tx_single_collisions) - IOLog("tx_single_collisions %ld\n", - OSReadLE32(&errorCounters_p->tx_single_collisions)); - if (errorCounters_p->tx_multiple_collisions) - IOLog("tx_multiple_collisions %ld\n", - OSReadLE32(&errorCounters_p->tx_multiple_collisions)); - if (errorCounters_p->tx_total_collisions) - IOLog("tx_total_collisions %ld\n", - OSReadLE32(&errorCounters_p->tx_total_collisions)); - if (errorCounters_p->rx_good_frames) - IOLog("rx_good_frames %ld\n", - OSReadLE32(&errorCounters_p->rx_good_frames)); - if (errorCounters_p->rx_crc_errors) - IOLog("rx_crc_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_crc_errors)); - if (errorCounters_p->rx_alignment_errors) - IOLog("rx_alignment_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_alignment_errors)); - if (errorCounters_p->rx_resource_errors) - IOLog("rx_resource_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_resource_errors)); - if (errorCounters_p->rx_overrun_errors) - IOLog("rx_overrun_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_overrun_errors)); - if (errorCounters_p->rx_collision_detect_errors) - IOLog("rx_collision_detect_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_collision_detect_errors)); - if (errorCounters_p->rx_short_frame_errors) - IOLog("rx_short_frame_errors %ld\n", - OSReadLE32(&errorCounters_p->rx_short_frame_errors)); - return; -} - -//--------------------------------------------------------------------------- -// Function: _dumpStatistics -// -// Purpose: -// _dumpStatistics issues a new statistics dump command. Every few seconds, -// _updateStatistics is called from timeoutOccurred to check for updated -// statistics. If complete, update our counters, and issue a new dump -// command. - -bool Intel82557::_dumpStatistics() -{ - reserveDebuggerLock(); - - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: _dumpStatistics: _waitSCBCommandClear failed\n", getName()); - return false; - } - - OSWriteLE8(&CSR_p->command, - CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_DUMP_RESET_STAT)); - - prevCUCommand = SCB_CUC_DUMP_RESET_STAT; - - releaseDebuggerLock(); - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _updateStatistics -// -// Purpose: -// Gather statistics information from the adapter at regular intervals. - -void Intel82557::_updateStatistics() -{ - if (OSReadLE32(&errorCounters_p->_status) != DUMP_STATUS) { - if (verbose) - _logCounters(errorCounters_p); - - // Ethernet transmitter stats. - // - etherStats->dot3StatsEntry.singleCollisionFrames += - OSReadLE32(&errorCounters_p->tx_single_collisions); - - etherStats->dot3StatsEntry.multipleCollisionFrames += - OSReadLE32(&errorCounters_p->tx_multiple_collisions); - - etherStats->dot3StatsEntry.lateCollisions += - OSReadLE32(&errorCounters_p->tx_late_collision_errors); - - etherStats->dot3StatsEntry.excessiveCollisions += - OSReadLE32(&errorCounters_p->tx_maxcol_errors); - - etherStats->dot3StatsEntry.deferredTransmissions += - OSReadLE32(&errorCounters_p->tx_deferred); - - etherStats->dot3StatsEntry.carrierSenseErrors += - OSReadLE32(&errorCounters_p->tx_lost_carrier_sense_errors); - - etherStats->dot3TxExtraEntry.underruns += - OSReadLE32(&errorCounters_p->tx_underrun_errors); - - // Ethernet receiver stats. - // - etherStats->dot3StatsEntry.alignmentErrors += - OSReadLE32(&errorCounters_p->rx_alignment_errors); - - etherStats->dot3StatsEntry.fcsErrors += - OSReadLE32(&errorCounters_p->rx_crc_errors); - - etherStats->dot3RxExtraEntry.resourceErrors += - OSReadLE32(&errorCounters_p->rx_resource_errors); - - etherStats->dot3RxExtraEntry.overruns += - OSReadLE32(&errorCounters_p->rx_overrun_errors); - - etherStats->dot3RxExtraEntry.collisionErrors += - OSReadLE32(&errorCounters_p->rx_collision_detect_errors); - - etherStats->dot3RxExtraEntry.frameTooShorts += - OSReadLE32(&errorCounters_p->rx_short_frame_errors); - - // Generic network stats. For the error counters, we assume - // the Ethernet stats will never be cleared. Thus we derive the - // error counters by summing the appropriate Ethernet error fields. - // - netStats->outputErrors = - ( etherStats->dot3StatsEntry.lateCollisions - + etherStats->dot3StatsEntry.excessiveCollisions - + etherStats->dot3StatsEntry.carrierSenseErrors - + etherStats->dot3TxExtraEntry.underruns - + etherStats->dot3TxExtraEntry.resourceErrors); - - netStats->inputErrors = - ( etherStats->dot3StatsEntry.fcsErrors - + etherStats->dot3StatsEntry.alignmentErrors - + etherStats->dot3RxExtraEntry.resourceErrors - + etherStats->dot3RxExtraEntry.overruns - + etherStats->dot3RxExtraEntry.collisionErrors - + etherStats->dot3RxExtraEntry.frameTooShorts); - - netStats->collisions += - OSReadLE32(&errorCounters_p->tx_total_collisions); - - OSWriteLE32(&errorCounters_p->_status, DUMP_STATUS); - _dumpStatistics(); - } -} - -//--------------------------------------------------------------------------- -// Function: _allocateMemPage -// -// Purpose: -// Allocate a page of memory. - -bool Intel82557::_allocateMemPage(pageBlock_t * p) -{ - p->memSize = PAGE_SIZE; - p->memPtr = IOMallocAligned(p->memSize, PAGE_SIZE); - - if (!p->memPtr) - return false; - - bzero(p->memPtr, p->memSize); - p->memAllocPtr = p->memPtr; /* initialize for allocation routine */ - p->memAvail = p->memSize; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _freeMemPage -// -// Purpose: -// Deallocate a page of memory. -// -void Intel82557::_freeMemPage(pageBlock_t * p) -{ - IOFreeAligned(p->memPtr, p->memSize); -} - -//--------------------------------------------------------------------------- -// Function: hwInit -// -// Purpose: -// Reset/configure the chip, detect the PHY. - -bool Intel82557::hwInit() -{ - disableAdapterInterrupts(); - _resetChip(); - disableAdapterInterrupts(); - - /* disable early RX interrupt */ - OSWriteLE8(&CSR_p->earlyRxInterrupt, 0); - - /* load command unit base address */ - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: hwInit: CU _waitSCBCommandClear failed\n", getName()); - return false; - } - OSWriteLE32(&CSR_p->pointer, 0); - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_LOAD_BASE)); - prevCUCommand = SCB_CUC_LOAD_BASE; - - /* load receive unit base address */ - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: hwInit: RU _waitSCBCommandClear failed\n", getName()); - return false; - } - OSWriteLE32(&CSR_p->pointer, 0); - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_RUC, SCB_RUC_LOAD_BASE)); - - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: hwInit: before LOAD_DUMP_COUNTERS_ADDRESS:" - " _waitSCBCommandClear failed\n", getName()); - return false; - } - OSWriteLE32(&errorCounters_p->_status, DUMP_STATUS); - OSWriteLE32(&CSR_p->pointer, errorCounters_paddr); - OSWriteLE8(&CSR_p->command, - CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_LOAD_DUMP_ADDR)); - prevCUCommand = SCB_CUC_LOAD_DUMP_ADDR; - - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: hwInit: before intrACK _waitSCBCommandClear failed\n", - getName()); - return false; - } - - /* Setup flow-control threshold */ - OSWriteLE8(&CSR_p->flowControlThreshold, - CSR_FIELD(FC_THRESHOLD, FC_THRESHOLD_512)); - - _intrACK(CSR_p); /* ack any pending interrupts */ - - _phyProbe(); - - phyID = _phyGetID(); - VPRINT("%s: PHY model id is 0x%08lx\n", getName(), phyID); - phyID &= PHY_MODEL_MASK; - - if (!config()) - return false; - IOSleep(500); - - if (!iaSetup()) - return false; - - _intrACK(CSR_p); /* ack any pending interrupts */ - - return true; -} - -//--------------------------------------------------------------------------- -// Function: _memAlloc -// -// Purpose: -// Return the next aligned chunk of memory in our shared memory page. - -void * Intel82557::_memAllocFrom(pageBlock_t * p, UInt allocSize, UInt align) -{ - void * allocPtr; - UInt sizeReal; - - if (align == 0) - return 0; - - // Advance allocPtr to next aligned boundary. - allocPtr = - (void *)((UInt)((UInt) p->memAllocPtr + (align - 1)) & (~(align - 1))); - - // Actual size of required storage. We need to take the alignment padding - // into account. - sizeReal = allocSize + ((UInt) allocPtr - (UInt) p->memAllocPtr); - - if (sizeReal > p->memAvail) - return 0; - - p->memAllocPtr = (void *)((UInt) p->memAllocPtr + sizeReal); - p->memAvail = p->memSize - ((UInt) p->memAllocPtr - (UInt) p->memPtr); - return allocPtr; -} - -//--------------------------------------------------------------------------- -// Function: coldInit -// -// Purpose: -// One-time initialization code. This is called by start(), before we -// attach any client objects. - -bool Intel82557::coldInit() -{ - IOReturn result; - IOPhysicalAddress paddr; - - disableAdapterInterrupts(); - - /* allocate and initialize shared memory pointers */ - if (!_allocateMemPage(&shared)) { - IOLog("%s: Can't allocate shared memory page\n", getName()); - return false; - } - if (!_allocateMemPage(&txRing)) { - IOLog("%s: Can't allocate memory page for TX ring\n", getName()); - return false; - } - if (!_allocateMemPage(&rxRing)) { - IOLog("%s: Can't allocate memory page for RX ring\n", getName()); - return false; - } - - /* allocate memory for shared data structures - * self test needs to be - * 16 byte aligned - */ - overlay_p = (overlay_t *) _memAllocFrom(&shared, sizeof(overlay_t), - PARAGRAPH_ALIGNMENT); - if (!overlay_p) - return false; - result = IOPhysicalFromVirtual((vm_address_t) overlay_p, &overlay_paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid command block address\n", getName()); - return false; - } - - tcbList_p = (tcb_t *) _memAllocFrom(&txRing, - sizeof(tcb_t) * NUM_TRANSMIT_FRAMES, - CACHE_ALIGNMENT); - if (!tcbList_p) - return false; - - KDB_tcb_p = (tcb_t *) _memAllocFrom(&shared, - sizeof(tcb_t), - CACHE_ALIGNMENT); - if (!KDB_tcb_p) - return false; - result = IOPhysicalFromVirtual((vm_address_t) KDB_tcb_p, - &KDB_tcb_p->_paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid TCB address\n", getName()); - return false; - } - - result = IOPhysicalFromVirtual((vm_address_t) &KDB_tcb_p->_tbds, &paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid TCB->_TBD address\n", getName()); - return false; - } - OSWriteLE32(&KDB_tcb_p->tbdAddr, paddr); - - KDB_buf_p = _memAllocFrom(&shared, ETHERMAXPACKET, DWORD_ALIGNMENT); - if (!KDB_buf_p) - return false; - result = IOPhysicalFromVirtual((vm_address_t) KDB_buf_p, &KDB_buf_paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid address\n", getName()); - return false; - } - - errorCounters_p = (errorCounters_t *) _memAllocFrom(&shared, - sizeof(errorCounters_t), - DWORD_ALIGNMENT); - if (!errorCounters_p) - return false; - result = IOPhysicalFromVirtual((vm_address_t) errorCounters_p, - &errorCounters_paddr); - if (result != kIOReturnSuccess) { - IOLog("%s: Invalid errorCounters address\n", getName()); - return false; - } - - rfdList_p = (rfd_t *) _memAllocFrom(&rxRing, - sizeof(rfd_t) * NUM_RECEIVE_FRAMES, - CACHE_ALIGNMENT); - if (!rfdList_p) - return false; - - if (!_selfTest()) - return false; - - myAddress = eeprom->getContents()->addr; - - return true; -} - -//--------------------------------------------------------------------------- -// Function: receiveInterruptOccurred -// -// Purpose: -// Hand up rceived frames. - -bool Intel82557::receiveInterruptOccurred() -{ - bool packetsQueued = false; - - while (OSReadLE16(&headRfd->status) & RFD_STATUS_C) { - rbd_count_t rbd_count = OSReadLE32(&headRfd->_rbd.count); - - // rxCount does NOT include the Ethernet CRC (FCS). - // - UInt rxCount = CSR_VALUE(RBD_COUNT, rbd_count); - -#if 0 - // When the receive unit runs out of resources, it will - // skip over RFD/RBD, making them as complete, but the RBD will - // have zero bytes and the EOF bit will not be set. - // We just skip over those and allow them to be recycled. - // - // In those cases, the RFD->status word will be 0x8220. - - /* should have exactly 1 rbd per rfd */ - if (!(rbd_count & RBD_COUNT_EOF)) { - IOLog("%s: more than 1 rbd, frame size %d\n", getName(), rxCount); - - IOLog("%s: RFD status: %04x\n", getName(), - OSReadLE16(&headRfd->status)); - - issueReset(); - return; - } -#endif - - if ((!(OSReadLE16(&headRfd->status) & RFD_STATUS_OK)) || - (rxCount < (ETHERMINPACKET - ETHERCRC)) || - !enabledForNetif) { - ; /* bad or unwanted packet */ - } - else { - struct mbuf * m = headRfd->_rbd._mbuf; - struct mbuf * m_in = 0; // packet to pass up to inputPacket() - bool replaced; - - packetsReceived = true; - - m_in = replaceOrCopyPacket(&m, rxCount, &replaced); - if (!m_in) { - etherStats->dot3RxExtraEntry.resourceErrors++; - goto RX_INTR_ABORT; - } - - if (replaced && (updateRFDFromMbuf(headRfd, m) == false)) { - freePacket(m); // free the new replacement mbuf. - m_in = 0; // pass up nothing. - etherStats->dot3RxExtraEntry.resourceErrors++; - IOLog("%s: updateRFDFromMbuf() error\n", getName()); - goto RX_INTR_ABORT; - } - - netif->inputPacket(m_in, rxCount, true); - packetsQueued = true; - netStats->inputPackets++; - } - -RX_INTR_ABORT: - /* clear fields in rfd */ - OSWriteLE16(&headRfd->status, 0); - OSWriteLE16(&headRfd->command, (RFD_COMMAND_SF | RFD_COMMAND_EL)); - OSWriteLE32(&headRfd->rbdAddr, C_NULL); - OSWriteLE32(&headRfd->misc, 0); - - /* clear fields in rbd */ - OSWriteLE32(&headRfd->_rbd.count, 0); - OSWriteLE32(&headRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE) | - RBD_SIZE_EL); - - /* adjust tail markers */ - OSWriteLE32(&tailRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE)); - OSWriteLE16(&tailRfd->command, RFD_COMMAND_SF); - - tailRfd = headRfd; // new tail - headRfd = headRfd->_next; // new head - } /* while */ - - return packetsQueued; -} - -//--------------------------------------------------------------------------- -// Function: transmitInterruptOccurred -// -// Purpose: -// Free up packets associated with any completed TCB's. - -void Intel82557::transmitInterruptOccurred() -{ - tcbQ_t * tcbQ_p = &tcbQ; - tcb_t * head; - - head = tcbQ_p->activeHead_p; - while (tcbQ_p->numFree < tcbQ_p->numTcbs && - (OSReadLE16(&head->status) & TCB_STATUS_C)) - { - OSWriteLE16(&head->status, 0); - if (head->_mbuf) { - freePacket(head->_mbuf); - head->_mbuf = 0; - } - head = tcbQ_p->activeHead_p = head->_next; - tcbQ_p->numFree++; - } - - return; -} - -//--------------------------------------------------------------------------- -// Function: interruptOccurred -// -// Purpose: -// Field an interrupt. - -void Intel82557::interruptOccurred(IOInterruptEventSource * src, int /*count*/) -{ - scb_status_t status; - bool flushInputQ = false; - bool doService = false; - - reserveDebuggerLock(); - - if (interruptEnabled == false) { - _intrACK(CSR_p); - releaseDebuggerLock(); - IOLog("%s: unexpected interrupt\n", getName()); - return; - } - - /* - * Loop until the interrupt line becomes deasserted. - */ - while (1) { - if ((status = _intrACK(CSR_p)) == 0) - break; - - /* - * RX interrupt. - */ - if (status & (SCB_STATUS_FR | SCB_STATUS_RNR)) { - - flushInputQ = receiveInterruptOccurred() || flushInputQ; - - etherStats->dot3RxExtraEntry.interrupts++; - - if (status & SCB_STATUS_RNR) { - etherStats->dot3RxExtraEntry.resets++; - - _abortReceive(); - _resetRfdList(); - - if (!_startReceive()) { - IOLog("%s: Unable to restart receiver\n", getName()); - // issueReset(); /* shouldn't need to do this. */ - } - } - } - - /* - * TX interrupt. - */ - if (status & (SCB_STATUS_CX | SCB_STATUS_CNA)) { - transmitInterruptOccurred(); - etherStats->dot3TxExtraEntry.interrupts++; - doService = true; - } - } - - releaseDebuggerLock(); - - if (enabledForNetif) { - // Flush all packets received and pass them to the network stack. - // - if (flushInputQ) - netif->flushInputQueue(); - - // Call service() without holding the debugger lock to prevent a - // deadlock when service() calls our outputPacket() function. - // - if (doService) - transmitQueue->service(); - } -} - -//--------------------------------------------------------------------------- -// Function: updateTCBForMbuf -// -// Update the TxCB pointed by tcb_p to point to the mbuf chain 'm'. -// Returns the mbuf encoded onto the TxCB. - -struct mbuf * -Intel82557::updateTCBForMbuf(tcb_t * tcb_p, struct mbuf * m) -{ - // Set the invariant TCB fields. - // - OSWriteLE16(&tcb_p->status, 0); - - if (++txCount == TRANSMIT_INT_DELAY) { - OSWriteLE16(&tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) | - TCB_COMMAND_S | - TCB_COMMAND_SF | - TCB_COMMAND_I); - txCount = 0; - } - else - OSWriteLE16(&tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) | - TCB_COMMAND_S | - TCB_COMMAND_SF); - - OSWriteLE8(&tcb_p->threshold, TCB_TX_THRESHOLD); - OSWriteLE16(&tcb_p->count, 0); // all data are in the TBD's, none in TxCB - - // Since the format of a TBD closely matches the structure of an - // 'struct IOPhysicalSegment', we shall have the cursor update the TBD list - // directly. - // - UInt segments = txMbufCursor->getPhysicalSegmentsWithCoalesce(m, - (struct IOPhysicalSegment *) &tcb_p->_tbds[0], - TBDS_PER_TCB); - - if (!segments) { - IOLog("%s: getPhysicalSegments error, pkt len = %d\n", - getName(), m->m_pkthdr.len); - return 0; - } - - // Update the TBD array size count. - // - OSWriteLE8(&tcb_p->number, segments); - - return m; -} - -//--------------------------------------------------------------------------- -// Function: outputPacket <IONetworkController> -// -// Purpose: -// Transmit the packet handed by our IOOutputQueue. -// TCBs have the suspend bit set, so that the CU goes into the suspend -// state when done. We use the CU_RESUME optimization that allows us to -// issue CU_RESUMES without waiting for SCB command to clear. -// -UInt32 Intel82557::outputPacket(struct mbuf * m, void * param) -{ - tcb_t * tcb_p; - - if (!enabledForNetif) { // drop the packet. - freePacket(m); - return kIOReturnOutputDropped; - } - - reserveDebuggerLock(); - - if (tcbQ.numFree == 0) { // retry when more space is available. - releaseDebuggerLock(); - return kIOReturnOutputStall; - } - - packetsTransmitted = true; - netStats->outputPackets++; - - tcb_p = tcbQ.freeHead_p; - - tcb_p->_mbuf = updateTCBForMbuf(tcb_p, m); - if (tcb_p->_mbuf == 0) { - etherStats->dot3TxExtraEntry.resourceErrors++; - goto fail; - } - - /* update the queue */ - tcbQ.numFree--; - tcbQ.freeHead_p = tcbQ.freeHead_p->_next; - - /* The TCB is already setup and the suspend bit set. Now clear the - * suspend bit of the previous TCB. - */ - if (tcbQ.activeTail_p != tcb_p) - OSClearLE16(&tcbQ.activeTail_p->command, TCB_COMMAND_S); - tcbQ.activeTail_p = tcb_p; - - /* - * CUC_RESUME is optimized such that it is unnecessary to wait - * for the CU to clear the SCB command word if the previous command - * was a resume and the CU state is not idle. - */ - if (CSR_VALUE(SCB_STATUS_CUS, OSReadLE16(&CSR_p->status)) == SCB_CUS_IDLE) - { - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: outputPacket: _waitSCBCommandClear error\n", getName()); - etherStats->dot3TxExtraEntry.timeouts++; - goto fail; - } - OSWriteLE32(&CSR_p->pointer, tcb_p->_paddr); - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC, SCB_CUC_START)); - prevCUCommand = SCB_CUC_START; - } - else { - if (prevCUCommand != SCB_CUC_RESUME) { - if (!_waitSCBCommandClear(CSR_p)) { - IOLog("%s: outputPacket: _waitSCBCommandClear error\n", - getName()); - etherStats->dot3TxExtraEntry.timeouts++; - goto fail; - } - } - OSWriteLE8(&CSR_p->command, CSR_FIELD(SCB_COMMAND_CUC,SCB_CUC_RESUME)); - prevCUCommand = SCB_CUC_RESUME; - } - releaseDebuggerLock(); - return kIOReturnOutputSuccess; - -fail: - freePacket(m); - tcb_p->_mbuf = 0; - releaseDebuggerLock(); - return kIOReturnOutputDropped; -} - -//--------------------------------------------------------------------------- -// Function: _receivePacket -// -// Purpose: -// Part of kerneldebugger protocol. -// Returns true if a packet was received successfully. -// -bool Intel82557::_receivePacket(void * pkt, UInt * len, UInt timeout) -{ - bool processPacket = true; - bool ret = false; - scb_status_t status; - - timeout *= 1000; - - while ((OSReadLE16(&headRfd->status) & RFD_STATUS_C) == 0) { - if ((int) timeout <= 0) { - processPacket = false; - break; - } - IODelay(50); - timeout -= 50; - } - - if (processPacket) { - if ((OSReadLE16(&headRfd->status) & RFD_STATUS_OK) && - (OSReadLE32(&headRfd->_rbd.count) & RBD_COUNT_EOF)) - { - // Pass up good frames. - // - *len = CSR_VALUE(RBD_COUNT, OSReadLE32(&headRfd->_rbd.count)); - *len = MIN(*len, ETHERMAXPACKET); - bcopy(mtod(headRfd->_rbd._mbuf, void *), pkt, *len); - ret = true; - } - - /* the head becomes the new tail */ - /* clear fields in rfd */ - OSWriteLE16(&headRfd->status, 0); - OSWriteLE16(&headRfd->command, (RFD_COMMAND_SF | RFD_COMMAND_EL)); - OSWriteLE32(&headRfd->rbdAddr, C_NULL); - OSWriteLE32(&headRfd->misc, 0); - - /* clear fields in rbd */ - OSWriteLE32(&headRfd->_rbd.count, 0); - OSWriteLE32(&headRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE) | - RBD_SIZE_EL); - - /* adjust tail markers */ - OSWriteLE32(&tailRfd->_rbd.size, CSR_FIELD(RBD_SIZE, MAX_BUF_SIZE)); - OSWriteLE16(&tailRfd->command, RFD_COMMAND_SF); - - tailRfd = headRfd; // new tail - headRfd = headRfd->_next; // new head - } - - status = OSReadLE16(&CSR_p->status) & SCB_STATUS_RNR; - if (status) { - OSWriteLE16(&CSR_p->status, status); // ack RNR interrupt - - IOLog("Intel82557::%s restarting receiver\n", __FUNCTION__); - - IOLog("%s::%s RUS:0x%x Index:%d\n", getName(), __FUNCTION__, - CSR_VALUE(SCB_STATUS_RUS, OSReadLE16(&CSR_p->status)), - tailRfd - rfdList_p); - - _abortReceive(); - -#if 0 // Display RFD/RBD fields - for (int i = 0; i < NUM_RECEIVE_FRAMES; i++) { - IOLog(" %02d: %04x %04x - %08x %08x\n", i, - OSReadLE16(&rfdList_p[i].command), - OSReadLE16(&rfdList_p[i].status), - OSReadLE32(&rfdList_p[i]._rbd.size), - OSReadLE32(&rfdList_p[i].misc)); - } -#endif - - _resetRfdList(); - _startReceive(); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Function: _sendPacket -// -// Purpose: -// Part of kerneldebugger protocol. -// Returns true if the packet was sent successfully. - -bool Intel82557::_sendPacket(void * pkt, UInt len) -{ - tbd_t * tbd_p; - - // Set up the TCB and issue the command - // - OSWriteLE16(&KDB_tcb_p->status, 0); - OSWriteLE32(&KDB_tcb_p->link, C_NULL); - OSWriteLE8(&KDB_tcb_p->threshold, TCB_TX_THRESHOLD); - OSWriteLE16(&KDB_tcb_p->command, CSR_FIELD(TCB_COMMAND, CB_CMD_TRANSMIT) | - TCB_COMMAND_EL | - TCB_COMMAND_SF ); - OSWriteLE16(&KDB_tcb_p->count, 0); // all data are in the TBD's. - OSWriteLE8(&KDB_tcb_p->number, 1); // 1 TBD only. - - // Copy the debugger packet to the pre-allocated buffer area. - // - len = MIN(len, ETHERMAXPACKET); - len = MAX(len, ETHERMINPACKET); - bcopy(pkt, KDB_buf_p, len); - - // Update the TBD. - // - tbd_p = &KDB_tcb_p->_tbds[0]; - OSWriteLE32(&tbd_p->addr, KDB_buf_paddr); - OSWriteLE32(&tbd_p->size, CSR_FIELD(TBD_SIZE, len)); - - // Start up the command unit to send the packet. - // - return _polledCommand((cbHeader_t *) KDB_tcb_p, KDB_tcb_p->_paddr); -} diff --git a/iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp b/iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp deleted file mode 100644 index a0a479cee..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. - * - * i82557eeprom.m - * - Intel 82557 eeprom access object - * - * HISTORY - * - * 6-Mar-96 Dieter Siegmund (dieter) at NeXT - * Created. - */ - -#include <IOKit/network/IOEthernetController.h> -#include "i82557eeprom.h" - -#define super OSObject -OSDefineMetaClassAndStructors( i82557eeprom, OSObject ) - -static __inline__ void -_logAddr(unsigned char * addr) -{ - int i; - for (i = 0; i < NUM_EN_ADDR_BYTES; i++) { - IOLog("%s%02x", i > 0 ? ":" : "", addr[i]); - } - return; -} - -void i82557eeprom::dumpContents() -{ - EEPROM_t * eeprom_p = &image.fields; - - IOLog("The EEPROM contains the following information:\n"); - - IOLog("ethernet address: "); - _logAddr((unsigned char *) &eeprom_p->addr); - IOLog("\n"); - - if (eeprom_p->compatibility_0 & EEPROM_C0_MC_10) - IOLog("compatibility: MCSETUP workaround required for 10 Mbits\n"); - if (eeprom_p->compatibility_0 & EEPROM_C0_MC_100) - IOLog("compatibility: MCSETUP workaround required for 100 Mbits\n"); - - IOLog("connectors: %s %s %s %s\n", - eeprom_p->connectors & EEPROM_CON_RJ45 ? "RJ-45" : "", - eeprom_p->connectors & EEPROM_CON_BNC ? "BNC" : "", - eeprom_p->connectors & EEPROM_CON_AUI ? "AUI" : "", - eeprom_p->connectors & EEPROM_CON_MII ? "MII" : ""); - - IOLog("controller type: %d\n", eeprom_p->controllerType); - - for (int i = 0; i < NUM_PHYS; i++) { - char * s = (i == PRIMARY_PHY) ? "primary" : "secondary"; - UInt16 phy = OSReadLE16(&eeprom_p->phys[i]); - - IOLog("%s PHY: %s\n", s, - PHYDeviceNames(CSR_VALUE(EEPROM_PHY_DEVICE, phy))); - if (CSR_VALUE(EEPROM_PHY_DEVICE, phy) != PHYDevice_None_e) { - if (phy & EEPROM_PHY_VSCR) - IOLog("%s PHY: vendor specific code required\n", s); - if (phy & EEPROM_PHY_10) - IOLog("%s PHY: 10 Mbits only, requires 503 interface\n", s); - IOLog("%s PHY address: 0x%x\n", s, - CSR_VALUE(EEPROM_PHY_ADDRESS, phy)); - } - } - - IOLog("PWA Number: %d %d %d-0%d\n", eeprom_p->PWANumber[1], - eeprom_p->PWANumber[0], eeprom_p->PWANumber[3], - eeprom_p->PWANumber[2]); - - IOLog("Checksum: 0x%x\n", OSReadLE16(&eeprom_p->checkSum)); -#if 0 - if (eeprom_p->checkSum != image.words[NUM_EEPROM_WORDS - 1]) - IOLog("the checksum in the struct doesn't match that in the array\n"); -#endif - return; -} - -i82557eeprom * i82557eeprom::withAddress(volatile eeprom_control_t * p) -{ - i82557eeprom * eeprom = new i82557eeprom; - - if (eeprom && !eeprom->initWithAddress(p)) { - eeprom->release(); - return 0; - } - return eeprom; -} - -bool i82557eeprom::initWithAddress(volatile eeprom_control_t * p) -{ - int i; - UInt16 sum; - - if (!super::init()) - return false; - - ee_p = p; - - /* - * Find out the number of bits in the address by issuing a read to address - * 0 ie. keep feeding eeprom address bits with value 0, until the eeprom - * says that the address is complete. It tells us by setting EEDO to 0 - * after a write cycle. - */ - EEPROMEnable(ee_p); - EEPROMWriteBit(ee_p, 1); /* read */ - EEPROMWriteBit(ee_p, 1); - EEPROMWriteBit(ee_p, 0); - nbits = 1; - - do { - EEPROMWriteBit(ee_p, 0); - if ((OSReadLE16(ee_p) & EEPROM_CONTROL_EEDO) == 0) - break; - nbits++; - } while (nbits <= 32); - - // IOLog("nbits: %d\n", nbits); - - EEPROMDisable(ee_p); - for (sum = 0, i = 0; i < NUM_EEPROM_WORDS; i++) { - UInt16 w = readWord(i); - sum += w; - OSWriteLE16(&image.words[i], w); - } - if (sum != EEPROM_CHECKSUM_VALUE) { - IOLog("i82557eeprom: checksum %x incorrect\n", sum); - return false; - } - - return true; -} - -/* READ command bit sequence: 1 1 0 a5a4a3a2a1a0 */ -UInt16 i82557eeprom::readWord(int offset) -{ - int i; - UInt16 value; - - EEPROMEnable(ee_p); - EEPROMWriteBit(ee_p, 1); - EEPROMWriteBit(ee_p, 1); - EEPROMWriteBit(ee_p, 0); - for (i = (nbits - 1); i >= 0; i--) { - EEPROMWriteBit(ee_p, (offset >> i) & 1); - } - value = 0; - for (i = BITS_IN_SHORT - 1; i >= 0; i--) { - value |= (EEPROMReadBit(ee_p) << i); - } - EEPROMDisable(ee_p); - return (value); -} - -EEPROM_t * i82557eeprom::getContents() -{ - return (&image.fields); -} - diff --git a/iokit/Drivers/network/drvIntel82557/i82557eeprom.h b/iokit/Drivers/network/drvIntel82557/i82557eeprom.h deleted file mode 100644 index a1e7c2539..000000000 --- a/iokit/Drivers/network/drvIntel82557/i82557eeprom.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1996 NeXT Software, Inc. - * - * i82557eeprom.h - * - Intel 82557 eeprom access object - * - * HISTORY - * - * 6-Mar-96 Dieter Siegmund (dieter) at NeXT - * Created. - */ - -#ifndef _I82557EEPROM_H -#define _I82557EEPROM_H - -#include "i82557Inline.h" -#include "i82557HW.h" - -#define BITS_IN_SHORT 16 -#define MIN_SK_HIGH 20 -#define MIN_SK_LOW 20 -#define NUM_EEPROM_WORDS 0x40 -#define EEPROM_CHECKSUM_VALUE 0xbaba - -//------------------------------------------------------------------------- -// Compatibility Byte 0 -// 8-bit, word 0x3, low byte -//------------------------------------------------------------------------- -#define EEPROM_C0_MC_100 BIT(1) -#define EEPROM_C0_MC_10 BIT(0) - -//------------------------------------------------------------------------- -// Compatibility Byte 1 -// 8-bit, word 0x3, high byte -//------------------------------------------------------------------------- -#define EEPROM_C1_OEM BIT(0) - -//------------------------------------------------------------------------- -// Controller Type -// 8-bit, word 0x5, high byte -//------------------------------------------------------------------------- -#define EEPROM_TYPE_82558 2 -#define EEPROM_TYPE_82557 1 - -//------------------------------------------------------------------------- -// Connectors -// 8-bit, word 0x5, low byte -//------------------------------------------------------------------------- -#define EEPROM_CON_MII BIT(3) -#define EEPROM_CON_AUI BIT(2) -#define EEPROM_CON_BNC BIT(1) -#define EEPROM_CON_RJ45 BIT(0) - -//------------------------------------------------------------------------- -// PHY Device Record. -// 16-bit, Primary word 0x6, Secondary word 0x7. -//------------------------------------------------------------------------- -#define EEPROM_PHY_10 BIT(15) -#define EEPROM_PHY_VSCR BIT(14) -#define EEPROM_PHY_DEVICE_SHIFT 8 -#define EEPROM_PHY_DEVICE_MASK CSR_MASK(EEPROM_PHY_DEVICE, 0x3f) -#define EEPROM_PHY_ADDRESS_SHIFT 0 -#define EEPROM_PHY_ADDRESS_MASK CSR_MASK(EEPROM_PHY_ADDRESS, 0xff) - -typedef enum { - PHYDevice_None_e = 0, - PHYDevice_Intel82553_A_B_step_e, - PHYDevice_Intel82553_C_step_e, - PHYDevice_Intel82503_e, - PHYDevice_NationalDP83840_TX_C_step_e, - PHYDevice_Seeq80C240_T4_e, - PHYDevice_Seeq80C24_e, - PHYDevice_Intel82555_e, - PHYDevice_MicroLinear_e, - PHYDevice_Level_One_e, - PHYDevice_NationalDP82840A_e, - PHYDevice_ICS1890_e, - PHYDevice_Last_e -} PHYDevice_t; - -static inline char * -PHYDeviceNames(unsigned int i) -{ - char * devices[] = { - "No PHY device installed", - "Intel 82553 (PHY 100) A or B step", - "Intel 82553 (PHY 100) C step", - "Intel 82503 10Mps", - "National DP83840 C step 100Base-TX", - "Seeq 80C240 100Base-T4", - "Seeq 80C24 10 Mps", - "Intel 82555 10/100Base-TX PHY", - "MicroLinear 10Mbps", - "Level One 10Mbps", - "National DP83840A", - "ICS 1890", - "PHY device unknown" - }; - if (i > PHYDevice_Last_e) - i = PHYDevice_Last_e; - return (devices[i]); -}; - -#define NUM_PHYS 2 -#define PRIMARY_PHY 0 -#define SECONDARY_PHY 1 -#define NPWA_BYTES 4 - -typedef struct { - IOEthernetAddress addr; - UInt8 compatibility_0; - UInt8 compatibility_1; - UInt16 zero0; - UInt8 connectors; - UInt8 controllerType; -#define I82557_CONTROLLER_TYPE 1 -#define I82558_CONTROLLER_TYPE 2 - UInt16 phys[NUM_PHYS]; - UInt8 PWANumber[NPWA_BYTES]; - UInt16 zero1[38]; - UInt16 rplConfig[2]; - UInt16 zero5[13]; - UInt16 checkSum; -} EEPROM_t; - -static inline -void EEPROMWriteBit(volatile eeprom_control_t * ee_p, bool bit) -{ - if (bit) - OSSetLE16(ee_p, EEPROM_CONTROL_EEDI); - else - OSClearLE16(ee_p, EEPROM_CONTROL_EEDI); - - OSSetLE16(ee_p, EEPROM_CONTROL_EESK); - IODelay(MIN_SK_HIGH); - OSClearLE16(ee_p, EEPROM_CONTROL_EESK); - IODelay(MIN_SK_LOW); -} - -static inline -bool EEPROMReadBit(volatile eeprom_control_t * ee_p) -{ - bool bit; - - OSSetLE16(ee_p, EEPROM_CONTROL_EESK); - IODelay(MIN_SK_HIGH); - bit = (OSReadLE16(ee_p) & EEPROM_CONTROL_EEDO) ? 1 : 0; - OSClearLE16(ee_p, EEPROM_CONTROL_EESK); - IODelay(MIN_SK_LOW); - return (bit); -} - -static inline -void EEPROMEnable(volatile eeprom_control_t * ee_p) -{ - OSSetLE16(ee_p, EEPROM_CONTROL_EECS); - return; -} - -static inline -void EEPROMDisable(volatile eeprom_control_t * ee_p) -{ - OSClearLE16(ee_p, EEPROM_CONTROL_EECS); - return; -} - -class i82557eeprom : public OSObject -{ - OSDeclareDefaultStructors(i82557eeprom) - -public: - volatile eeprom_control_t * ee_p; - int nbits; - union { - UInt16 words[NUM_EEPROM_WORDS]; - EEPROM_t fields; - } image; - - static i82557eeprom * withAddress(volatile eeprom_control_t * p); - - bool initWithAddress(volatile eeprom_control_t * p); - - UInt16 readWord(int offset); - - EEPROM_t * getContents(); - - void dumpContents(); -}; - -#endif /* !_I82557EEPROM_H */ diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnet.cpp b/iokit/Drivers/network/drvMaceEnet/MaceEnet.cpp deleted file mode 100644 index 778daebe2..000000000 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnet.cpp +++ /dev/null @@ -1,918 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Hardware independent (relatively) code for the Mace Ethernet Controller - * - * HISTORY - * - * dd-mmm-yy - * Created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/platform/AppleMacIODevice.h> -#include "MaceEnetPrivate.h" - -//------------------------------------------------------------------------ - -#define super IOEthernetController - -OSDefineMetaClassAndStructors( MaceEnet, IOEthernetController ) - -//------------------------------------------------------------------------ - -#define PROVIDER_DEV 0 -#define PROVIDER_DMA_TX 1 -#define PROVIDER_DMA_RX 2 - -/* - * Public Instance Methods - */ - -bool MaceEnet::init(OSDictionary * properties) -{ - if (!super::init(properties)) - return false; - - isPromiscuous = false; - multicastEnabled = false; - ready = false; - debugClient = false; - debugTxPoll = false; - netifClient = false; - - return true; -} - -MaceEnet * MaceEnet::probe(IOService * /*provider*/, - unsigned int * /*score*/, - unsigned int * /*specificity*/) -{ -#ifdef OLD_CODE - extern int kdp_flag; - - /* - * If bootargs: kdp bit 0 using in-kernel mace driver for early debugging, - * Don't probe this driver. - */ - if( kdp_flag & 1) - { - return 0; - } -#endif - - return this; -} - -bool MaceEnet::start(IOService * provider) -{ - AppleMacIODevice *nub = OSDynamicCast(AppleMacIODevice, provider); - - if (!nub || !super::start(provider)) - return false; - - transmitQueue = OSDynamicCast(IOGatedOutputQueue, getOutputQueue()); - if (!transmitQueue) - { - IOLog("Mace: output queue initialization failed\n"); - return false; - } - transmitQueue->retain(); - - // Allocate debug queue. This stores packets retired from the TX ring - // by the polling routine. We cannot call freePacket() or m_free() within - // the debugger context. - // - // The capacity of the queue is set at maximum to prevent the queue from - // calling m_free() due to over-capacity. But we don't expect the size - // of the queue to grow too large. - // - debugQueue = IOPacketQueue::withCapacity((UInt) -1); - if (!debugQueue) - return false; - - // Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum - // number of segments is set to 2. The maximum length for each segment - // is set to the maximum ethernet frame size (plus padding). - - mbufCursor = IOMbufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 2); - if (!mbufCursor) - { - IOLog("Mace: IOMbufMemoryCursor allocation failed\n"); - return false; - } - - // - // Our provider is the nub representing the MaceEnet hardware - // controller. We will query it for our resource information. - // - - for (int i = 0; i < MEMORY_MAP_COUNT; i++) { - IOMemoryMap * map; - - map = provider->mapDeviceMemoryWithIndex(i); - if (!map) - return false; - -#ifdef DEBUG_XXX - IOLog("map %d: Phys:%08x Virt:%08x len:%d\n", - i, - (UInt) map->getPhysicalAddress(), - (UInt) map->getVirtualAddress(), - (UInt) map->getLength()); -#endif - - switch (i) { - case MEMORY_MAP_ENET_INDEX: - ioBaseEnet = (IOPPCAddress) map->getVirtualAddress(); - ioBaseEnetROM = (IOPPCAddress) ((map->getPhysicalAddress() & - ~0xffff) | kControllerROMOffset); - break; - - case MEMORY_MAP_TXDMA_INDEX: - ioBaseEnetTxDMA = (IODBDMAChannelRegisters *) - map->getVirtualAddress(); - break; - - case MEMORY_MAP_RXDMA_INDEX: - ioBaseEnetRxDMA = (IODBDMAChannelRegisters *) - map->getVirtualAddress(); - break; - } - - maps[i] = map; - } - - // Manually create an IODeviceMemory for the ROM memory - // range. - // - IODeviceMemory * romMemory = IODeviceMemory::withRange( - (UInt) ioBaseEnetROM, 0x1000); - if (!romMemory) { - IOLog("Mace: can't create ROM memory object\n"); - return false; - } - - romMap = romMemory->map(); - romMemory->release(); - - if (!romMap) - return false; - - ioBaseEnetROM = (IOPPCAddress) romMap->getVirtualAddress(); - -#ifdef DEBUG_XXX - IOLog("Mace: ioBaseEnet : %08x\n", (UInt) ioBaseEnet); - IOLog("Mace: ioBaseEnetTxDMA : %08x\n", (UInt) ioBaseEnetTxDMA); - IOLog("Mace: ioBaseEnetRxDMA : %08x\n", (UInt) ioBaseEnetRxDMA); - IOLog("Mace: ioBaseEnetROM : %08x\n", (UInt) ioBaseEnetROM); -#endif - - // - // Get a reference to the IOWorkLoop in our superclass. - // - IOWorkLoop * myWorkLoop = (IOWorkLoop *) getWorkLoop(); - assert(myWorkLoop); - - // - // Allocate two IOInterruptEventSources. - // - txIntSrc = IOInterruptEventSource::interruptEventSource - (this, - (IOInterruptEventAction) &MaceEnet::interruptOccurredForSource, - provider, PROVIDER_DMA_TX); - if (!txIntSrc - || (myWorkLoop->addEventSource(txIntSrc) != kIOReturnSuccess)) { - IOLog("Mace: txIntSrc init failure\n"); - return false; - } - - rxIntSrc = IOInterruptEventSource::interruptEventSource - (this, - (IOInterruptEventAction) &MaceEnet::interruptOccurredForSource, - provider, PROVIDER_DMA_RX); - if (!rxIntSrc - || (myWorkLoop->addEventSource(rxIntSrc) != kIOReturnSuccess)) { - IOLog("Mace: rxIntSrc init failure\n"); - return false; - } - - timerSrc = IOTimerEventSource::timerEventSource - (this, (IOTimerEventSource::Action) &MaceEnet::timeoutOccurred); - if (!timerSrc - || (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) { - IOLog("Mace: timerSrc init failure\n"); - return false; - } - - MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA); - if (!txDebuggerPkt) - { - IOLog("Mace: Can't allocate KDB buffer\n"); - return false; - } - -#if 0 - // Do not enable interrupt sources until the hardware - // is enabled. - - // Enable the interrupt event sources. - myWorkLoop->enableAllInterrupts(); -#endif - -#if 0 - // Do not reset the hardware until we are ready to use it. - // Otherwise, we would have messed up kdp_mace driver's - // state. And we won't be able to break into the debugger - // until we attach our debugger client. - - // - // Perform a hardware reset. - // - if ( !resetAndEnable(false) ) - { - return false; - } -#endif - - // Cache my MAC address. - // - getHardwareAddress(&myAddress); - - // - // Allocate memory for ring buffers. - // - if (_allocateMemory() == false) - { - return false; - } - - // - // Attach a kernel debugger client. - // - attachDebuggerClient(&debugger); - - // - // Allocate and initialize an IONetworkInterface object. - // - if (!attachInterface((IONetworkInterface **) &networkInterface)) - return false; - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::free() -{ - UInt i; - - timerSrc->cancelTimeout(); - - _resetChip(); - - if (debugger) - debugger->release(); - - if (timerSrc) - timerSrc->release(); - - if (rxIntSrc) - rxIntSrc->release(); - - if (txIntSrc) - txIntSrc->release(); - - if (transmitQueue) - transmitQueue->release(); - - if (debugQueue) - debugQueue->release(); - - if (networkInterface) - networkInterface->release(); - - if (mbufCursor) - mbufCursor->release(); - - if (txDebuggerPkt) - freePacket(txDebuggerPkt); - - for (i = 0; i < rxMaxCommand; i++) - if (rxMbuf[i]) freePacket(rxMbuf[i]); - - for (i = 0; i < txMaxCommand; i++) - if (txMbuf[i]) freePacket(txMbuf[i]); - - if (romMap) romMap->release(); - - for (i = 0; i < MEMORY_MAP_COUNT; i++) - if (maps[i]) maps[i]->release(); - - if (dmaMemory.ptr) - { - IOFree(dmaMemory.ptrReal, dmaMemory.sizeReal); - dmaMemory.ptr = 0; - } - - if ( workLoop ) - { - workLoop->release(); - workLoop = 0; - } - - super::free(); -} - -/*------------------------------------------------------------------------- - * Override IONetworkController::createWorkLoop() method and create - * a workloop. - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::createWorkLoop() -{ - workLoop = IOWorkLoop::workLoop(); - - return ( workLoop != 0 ); -} - -/*------------------------------------------------------------------------- - * Override IOService::getWorkLoop() method to return our workloop. - * - * - *-------------------------------------------------------------------------*/ - -IOWorkLoop * MaceEnet::getWorkLoop() const -{ - return workLoop; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::interruptOccurredForSource(IOInterruptEventSource *src, - int /*count*/) -{ - bool doFlushQueue = false; - bool doService = false; - - // IOLog("Mace: interrupt %08x %d\n", (UInt) src, count); - - if (!ready) { - // IOLog("Mace: unexpected interrupt\n"); - return; - } - - reserveDebuggerLock(); - - if (src == txIntSrc) { - txWDInterrupts++; - KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doService = _transmitInterruptOccurred(); - KERNEL_DEBUG(DBG_MACE_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - } - else { - KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doFlushQueue = _receiveInterruptOccurred(); - KERNEL_DEBUG(DBG_MACE_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - } - - releaseDebuggerLock(); - - /* - * Submit all received packets queued up by _receiveInterruptOccurred() - * to the network stack. The up call is performed without holding the - * debugger lock. - */ - if (doFlushQueue) - networkInterface->flushInputQueue(); - - /* - * Make sure the output queue is not stalled. - */ - if (doService && netifClient) - transmitQueue->service(); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -UInt32 MaceEnet::outputPacket(struct mbuf *pkt, void *param) -{ - u_int32_t i; - u_int8_t regValue; - UInt32 ret = kIOReturnOutputSuccess; - - // IOLog("Mace: outputPacket %d\n", pkt->m_pkthdr.len); - - KERNEL_DEBUG(DBG_MACE_TXQUEUE | DBG_FUNC_NONE, (int) pkt, - (int) pkt->m_pkthdr.len, 0, 0, 0 ); - - /* - * Hold the debugger lock so the debugger can't interrupt us - */ - reserveDebuggerLock(); - - do - { - /* - * Someone is turning off the receiver before the first transmit. - * Dont know who yet! - */ - regValue = ReadMaceRegister( ioBaseEnet, kMacCC ); - regValue |= kMacCCEnRcv; - WriteMaceRegister( ioBaseEnet, kMacCC, regValue ); - - /* - * Preliminary sanity checks - */ - assert(pkt && netifClient); - - /* - * Remove any completed packets from the Tx ring - */ - _transmitInterruptOccurred(); - - i = txCommandTail + 1; - if ( i >= txMaxCommand ) i = 0; - if ( i == txCommandHead ) - { - ret = kIOReturnOutputStall; - continue; - } - - /* - * If there is space on the Tx ring, add the packet directly to the - * ring - */ - _transmitPacket(pkt); - } - while ( 0 ); - - releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to enable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::enable(IONetworkInterface * netif) -{ - IONetworkParameter * param; - - // If an interface client has previously enabled us, - // and we know there can only be one interface client - // for this driver, then simply return true. - // - if (netifClient) { - IOLog("Mace: already enabled\n"); - return kIOReturnSuccess; - } - - param = netif->getParameter(kIONetworkStatsKey); - if (!param || !(netStats = (IONetworkStats *) param->getBuffer())) - { - IOLog("Mace: invalid network statistics\n"); - return kIOReturnError; - } - - if ((ready == false) && !resetAndEnable(true)) - return kIOReturnIOError; - - // Record the interface as an active client. - // - netifClient = true; - - // Start our IOOutputQueue object. - // - transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); - transmitQueue->start(); - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to disable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::disable(IONetworkInterface * /*netif*/) -{ - // If we have no active clients, then disable the controller. - // - if (debugClient == false) - resetAndEnable(false); - - // Disable our IOOutputQueue object. - // - transmitQueue->stop(); - - // Flush all packets currently in the output queue. - // - transmitQueue->setCapacity(0); - transmitQueue->flush(); - - netifClient = false; - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to bring up the controller - * just before the controller is registered as the debugger device. The - * debugger client is attached in response to the attachDebuggerClient() - * call. - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::enable(IOKernelDebugger * /*debugger*/) -{ - // Enable hardware and make it ready to support the debugger client. - // - if ((ready == false) && !resetAndEnable(true)) - return kIOReturnIOError; - - // Record the debugger as an active client of ours. - // - debugClient = true; - - // Returning true will allow the kdp registration to continue. - // If we return false, then we will not be registered as the - // debugger device, and the attachDebuggerClient() call will - // return NULL. - // - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to stop the controller. - * The debugger will call this method when we issue a detachDebuggerClient(). - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::disable(IOKernelDebugger * /*debugger*/) -{ - debugClient = false; - - // If we have no active clients, then disable the controller. - // - if (netifClient == false) - resetAndEnable(false); - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::resetAndEnable(bool enable) -{ - bool ret = true; - - if (timerSrc) - timerSrc->cancelTimeout(); - - _disableAdapterInterrupts(); - if (getWorkLoop()) getWorkLoop()->disableAllInterrupts(); - - reserveDebuggerLock(); - - ready = false; - - _resetChip(); - - do { - if (!enable) break; - - if ( !_initRxRing() || !_initTxRing() || !_initChip() ) - { - ret = false; - break; - } - - _startChip(); - - ready = true; - - releaseDebuggerLock(); - - timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); - - if (getWorkLoop()) getWorkLoop()->enableAllInterrupts(); - _enableAdapterInterrupts(); - - return true; - } - while (0); - - releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_sendTestPacket() -{ -// IOOutputPacketStatus ret; - unsigned char * buf; - const unsigned int size = 64; - - struct mbuf * m = allocatePacket(size); - if (!m) { - IOLog("Mace: _sendTestpacket: allocatePacket() failed\n"); - return; - } - - buf = mtod(m, unsigned char *); - - bcopy(&myAddress, buf, NUM_EN_ADDR_BYTES); - buf += NUM_EN_ADDR_BYTES; - bcopy(&myAddress, buf, NUM_EN_ADDR_BYTES); - buf += NUM_EN_ADDR_BYTES; - *buf++ = 0; - *buf++ = 0; - - outputPacket(m, 0); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::timeoutOccurred(IOTimerEventSource * /*timer*/) -{ - u_int32_t dmaStatus; - bool doFlushQueue = false; - bool doService = false; - - reserveDebuggerLock(); - - /* - * Check for DMA shutdown on receive channel - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); - if ( !(dmaStatus & kdbdmaActive) ) - { -#if 0 - IOLog("Mace: Timeout check - RxHead = %d RxTail = %d\n", - rxCommandHead, rxCommandTail); -#endif - -#if 0 - IOLog( "Mace: Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) ); - [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)]; -#endif - - doFlushQueue = _receiveInterruptOccurred(); - } - - /* - * If there are pending entries on the Tx ring - */ - if ( txCommandHead != txCommandTail ) - { - /* - * If we did not service the Tx ring during the last timeout interval, - * then force servicing of the Tx ring. - * If we have more than one timeout interval without any transmit - * interrupts, then force the transmitter to reset. - */ - if ( txWDInterrupts == 0 ) - { - if ( ++txWDTimeouts > 1 ) txWDForceReset = true; - -#if 0 - IOLog( "Mace: Checking for timeout - TxHead = %d TxTail = %d\n", - txCommandHead, txCommandTail); -#endif - doService = _transmitInterruptOccurred(); - } - else - { - txWDTimeouts = 0; - txWDInterrupts = 0; - } - } - else - { - txWDTimeouts = 0; - txWDInterrupts = 0; - } - - // Clean-up after the debugger if the debugger was active. - // - if (debugTxPoll) - { - debugQueue->flush(); - debugTxPoll = false; - releaseDebuggerLock(); - doService = true; - } - else - { - releaseDebuggerLock(); - } - - /* - * Submit all received packets queued up by _receiveInterruptOccurred() - * to the network stack. The up call is performed without holding the - * debugger lock. - */ - if (doFlushQueue) - { - networkInterface->flushInputQueue(); - } - - /* - * Make sure the output queue is not stalled. - */ - if (doService && netifClient) - { - transmitQueue->service(); - } - - /* - * Restart the watchdog timer - */ - timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -const OSString * MaceEnet::newVendorString() const -{ - return OSString::withCString("Apple"); -} - -const OSString * MaceEnet::newModelString() const -{ - return OSString::withCString("Mace"); -} - -const OSString * MaceEnet::newRevisionString() const -{ - return OSString::withCString(""); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::_setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - u_int8_t regVal; - - regVal = ReadMaceRegister( ioBaseEnet, kMacCC ); - WriteMaceRegister( ioBaseEnet, kMacCC, regVal & ~kMacCCEnRcv ); - if (mode == kIOEnetPromiscuousModeOff) { - regVal &= ~kMacCCProm; - isPromiscuous = false; - } - else { - regVal |= kMacCCProm; - isPromiscuous = true; - } - WriteMaceRegister( ioBaseEnet, kMacCC, regVal ); - - return kIOReturnSuccess; - -} - -IOReturn MaceEnet::setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - IOReturn ret; - - reserveDebuggerLock(); - ret = _setPromiscuousMode(mode); - releaseDebuggerLock(); - - return ret; -} - -IOReturn MaceEnet::setMulticastMode(IOEnetMulticastMode mode) -{ - multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; - return kIOReturnSuccess; -} - -IOReturn MaceEnet::setMulticastList(IOEthernetAddress *addrs, UInt32 count) -{ - reserveDebuggerLock(); - _resetHashTableMask(); - for (UInt32 i = 0; i < count; i++) { - _addToHashTableMask(addrs->bytes); - addrs++; - } - _updateHashTableMask(); - releaseDebuggerLock(); - return kIOReturnSuccess; -} - -/* - * Allocate an IOOutputQueue object. - */ -IOOutputQueue * MaceEnet::createOutputQueue() -{ - return IOGatedOutputQueue::withTarget( this, getWorkLoop() ); -} - -/* - * Kernel Debugger Support - */ -void MaceEnet::sendPacket(void *pkt, UInt32 pkt_len) -{ - _sendPacket(pkt, pkt_len); -} - -void MaceEnet::receivePacket(void *pkt, UInt32 *pkt_len, UInt32 timeout) -{ - _receivePacket(pkt, (UInt *) pkt_len, timeout); -} - -#if 0 // no power management stuff in IOKit yet. -/* - * Power management methods. - */ -- (IOReturn)getPowerState:(PMPowerState *)state_p -{ - return kIOReturnUnsupported; -} - -- (IOReturn)setPowerState:(PMPowerState)state -{ - if (state == PM_OFF) { - resetAndEnabled = NO; - [self _resetChip]; - return kIOReturnSuccess; - } - return kIOReturnUnsupported; -} - -- (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p -{ - return kIOReturnUnsupported; -} - -- (IOReturn)setPowerManagement:(PMPowerManagementState)state -{ - return kIOReturnUnsupported; -} -#endif /* 0 */ diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnet.h b/iokit/Drivers/network/drvMaceEnet/MaceEnet.h deleted file mode 100644 index c01aef76d..000000000 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnet.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Interface definition for the Mace Ethernet chip - * - * HISTORY - * - * 16-Sept-97 - * Created. - */ - -#ifndef _MACEENET_H -#define _MACEENET_H - -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IOGatedOutputQueue.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/network/IOMbufMemoryCursor.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/ppc/IODBDMA.h> -#include <string.h> /* bcopy */ - -#if 0 -#include <kern/kdebug.h> /* Performance tracepoints */ -#else -#define KERNEL_DEBUG(x,a,b,c,d,e) -#endif - -#include "MaceEnetRegisters.h" - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -} - -#if 0 -#define IOLog kprintf -#endif - -typedef void * IOPPCAddress; - -typedef struct enet_dma_cmd_t -{ - IODBDMADescriptor desc_seg[2]; -} enet_dma_cmd_t; - -typedef struct enet_txdma_cmd_t -{ - IODBDMADescriptor desc_seg[4]; -} enet_txdma_cmd_t; - -class MaceEnet : public IOEthernetController -{ - OSDeclareDefaultStructors(MaceEnet) - -private: - volatile IOPPCAddress ioBaseEnet; - volatile IOPPCAddress ioBaseEnetROM; - volatile IODBDMAChannelRegisters *ioBaseEnetRxDMA; - volatile IODBDMAChannelRegisters *ioBaseEnetTxDMA; - - u_int16_t chipId; - - IOEthernetAddress myAddress; - IOEthernetInterface * networkInterface; - IOGatedOutputQueue * transmitQueue; - IOPacketQueue * debugQueue; - IOKernelDebugger * debugger; - bool isPromiscuous; - bool multicastEnabled; - bool ready; - bool netifClient; - bool debugClient; - bool debugTxPoll; - - IOWorkLoop * workLoop; - IOInterruptEventSource *rxIntSrc; - IOInterruptEventSource *txIntSrc; - IOMemoryMap * maps[MEMORY_MAP_COUNT]; - IOMemoryMap * romMap; - IONetworkStats * netStats; - IOTimerEventSource * timerSrc; - IOMbufBigMemoryCursor * mbufCursor; - - struct mbuf * txMbuf[TX_RING_LENGTH]; - struct mbuf * rxMbuf[RX_RING_LENGTH]; - struct mbuf * txDebuggerPkt; - - unsigned int txCommandHead; /* Transmit ring descriptor index */ - unsigned int txCommandTail; - unsigned int txMaxCommand; - unsigned int rxCommandHead; /* Receive ring descriptor index */ - unsigned int rxCommandTail; - unsigned int rxMaxCommand; - - struct { - void *ptr; - u_int size; - void *ptrReal; - u_int sizeReal; - } dmaMemory; - - unsigned char * dmaCommands; - enet_txdma_cmd_t * txDMACommands; /* TX descriptor ring ptr */ - unsigned int txDMACommandsPhys; - - enet_dma_cmd_t * rxDMACommands; /* RX descriptor ring ptr */ - unsigned int rxDMACommandsPhys; - - u_int32_t txWDInterrupts; - u_int32_t txWDTimeouts; - bool txWDForceReset; - - void * debuggerPkt; - u_int32_t debuggerPktSize; - - u_int16_t hashTableUseCount[64]; - u_int8_t hashTableMask[8]; - - bool _allocateMemory(); - bool _initTxRing(); - bool _initRxRing(); - bool _initChip(); - void _resetChip(); - void _disableAdapterInterrupts(); - void _enableAdapterInterrupts(); - void _startChip(); - void _restartChip(); - void _stopReceiveDMA(); - void _stopTransmitDMA(); - bool _transmitPacket(struct mbuf * packet); - bool _transmitInterruptOccurred(bool fDebugger = false); - bool _receiveInterruptOccurred(); - bool _receivePackets(bool fDebugger); - void _packetToDebugger(struct mbuf * packet, u_int size); - bool _updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, - bool isReceive); - void _resetHashTableMask(); - void _addToHashTableMask(u_int8_t *addr); - void _removeFromHashTableMask(u_int8_t *addr); - void _updateHashTableMask(); -#ifdef DEBUG - void _dumpRegisters(); - void _dumpDesc(void * addr, u_int32_t size); -#endif - IOReturn _setPromiscuousMode(IOEnetPromiscuousMode mode); - void MaceEnet::_sendTestPacket(); - - /* - * Kernel Debugger - */ - void _sendPacket(void *pkt, unsigned int pkt_len); - void _receivePacket(void *pkt, unsigned int *pkt_len, unsigned int - timeout); - - bool resetAndEnable(bool enable); - void interruptOccurredForSource(IOInterruptEventSource *src, int count); - void timeoutOccurred(IOTimerEventSource *timer); - -public: - virtual MaceEnet * MaceEnet::probe(IOService * provider, - unsigned int * score, - unsigned int * specificity); - virtual bool init(OSDictionary * properties = 0); - virtual bool start(IOService * provider); - virtual void free(); - - virtual bool createWorkLoop(); - virtual IOWorkLoop * getWorkLoop() const; - - virtual IOReturn enable(IONetworkInterface * netif); - virtual IOReturn disable(IONetworkInterface * netif); - - virtual IOReturn enable(IOKernelDebugger * debugger); - virtual IOReturn disable(IOKernelDebugger * debugger); - - virtual IOReturn getHardwareAddress(IOEthernetAddress *addr); - - virtual IOReturn setMulticastMode(IOEnetMulticastMode mode); - virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count); - - virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode); - - virtual IOOutputQueue * createOutputQueue(); - - virtual UInt32 outputPacket(struct mbuf * m, void * param); - - virtual void sendPacket(void *pkt, UInt32 pkt_len); - virtual void receivePacket(void *pkt, UInt32 *pkt_len, UInt32 timeout); - - virtual const OSString * newVendorString() const; - virtual const OSString * newModelString() const; - virtual const OSString * newRevisionString() const; -}; - -#if 0 // no power management stuff in IOKit yet. -/* - * Power management methods. - */ -- (IOReturn)getPowerState:(PMPowerState *)state_p; -- (IOReturn)setPowerState:(PMPowerState)state; -- (IOReturn)getPowerManagement:(PMPowerManagementState *)state_p; -- (IOReturn)setPowerManagement:(PMPowerManagementState)state; -#endif - -/* - * Performance tracepoints - * - * DBG_MACE_RXIRQ - Receive ISR run time - * DBG_MACE_TXIRQ - Transmit ISR run time - * DBG_MACE_TXQUEUE - Transmit packet passed from network stack - * DBG_MACE_TXCOMPLETE - Transmit packet sent - * DBG_MACE_RXCOMPLETE - Receive packet passed to network stack - */ -#define DBG_MACE_ENET 0x0800 -#define DBG_MACE_RXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_MACE_ENET+1)) -#define DBG_MACE_TXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_MACE_ENET+2)) -#define DBG_MACE_TXQUEUE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_MACE_ENET+3)) -#define DBG_MACE_TXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_MACE_ENET+4)) -#define DBG_MACE_RXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_MACE_ENET+5)) - -#endif /* !_MACEENET_H */ diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.cpp b/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.cpp deleted file mode 100644 index c1af0e36a..000000000 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.cpp +++ /dev/null @@ -1,1793 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Implementation for hardware dependent (relatively) code - * for the Mace Ethernet controller. - * - * HISTORY - * - * 10-Sept-97 - * Created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/system.h> -#include <IOKit/IOLib.h> -#include "MaceEnetPrivate.h" - - -/***************************************************************************** - * - * Hacks. - */ - -typedef unsigned long long ns_time_t; /* nanoseconds! */ - -#define NSEC_PER_SEC 1000000000 - -static void -_IOGetTimestamp(ns_time_t *nsp) -{ - mach_timespec_t now; - - IOGetTime(&now); - *nsp = ((ns_time_t)now.tv_sec * NSEC_PER_SEC) + now.tv_nsec; -} - -/* - * Find a physical address (if any) for the specified virtual address. - * - * Note: what about vm_offset_t kvtophys(vm_offset_t va) - */ -static IOReturn _IOPhysicalFromVirtual( - vm_address_t virtualAddress, - unsigned *physicalAddress) -{ - *physicalAddress = pmap_extract(kernel_pmap, virtualAddress); - if(*physicalAddress == 0) { - return kIOReturnBadArgument; - } - else { - return kIOReturnSuccess; - } -} - -// From osfmk/ppc/pmap.h -// -extern "C" { -extern void invalidate_dcache(vm_offset_t va, unsigned length, boolean_t phys); -extern void flush_dcache(vm_offset_t va, unsigned length, boolean_t phys); -} - -static inline void -invalidate_cache_v(vm_offset_t va, unsigned length) -{ - invalidate_dcache(va, length, 0); -} - -static inline void -flush_cache_v(vm_offset_t va, unsigned length) -{ - flush_dcache(va, length, 0); -} - -/****************************************************************************/ - -static IODBDMADescriptor dbdmaCmd_Nop; -static IODBDMADescriptor dbdmaCmd_NopWInt; -static IODBDMADescriptor dbdmaCmd_LoadXFS; -static IODBDMADescriptor dbdmaCmd_LoadIntwInt; -static IODBDMADescriptor dbdmaCmd_Stop; -static IODBDMADescriptor dbdmaCmd_Branch; - - -static u_int8_t reverseBitOrder(u_int8_t data ) -{ - u_int8_t val = 0; - int i; - - for ( i=0; i < 8; i++ ) - { - val <<= 1; - if (data & 1) val |= 1; - data >>= 1; - } - return( val ); -} - -/* - * Function: IOMallocPage - * - * Purpose: - * Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE - * - * Return: - * Actual pointer and size of block returned in actual_ptr and actual_size. - * Use these as arguments to kfree: kfree(*actual_ptr, *actual_size); - */ -static void * -IOMallocPage(int request_size, void ** actual_ptr, u_int * actual_size) -{ - void * mem_ptr; - - *actual_size = round_page(request_size) + PAGE_SIZE; - mem_ptr = IOMalloc(*actual_size); - if (mem_ptr == NULL) - return NULL; - *actual_ptr = mem_ptr; - return ((void *)round_page(mem_ptr)); -} - -/* - * Private functions - */ -bool MaceEnet::_allocateMemory() -{ - u_int32_t i, n; - unsigned char * virtAddr; - u_int32_t physBase; - u_int32_t physAddr; - u_int32_t dbdmaSize; - - /* - * Calculate total space for DMA channel commands - */ - dbdmaSize = round_page( - RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + - TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + - 2 * sizeof(IODBDMADescriptor) ); - - /* - * Allocate required memory - */ - dmaMemory.size = dbdmaSize; - dmaMemory.ptr = (void *)IOMallocPage( - dmaMemory.size, - &dmaMemory.ptrReal, - &dmaMemory.sizeReal - ); - - dmaCommands = (unsigned char *) dmaMemory.ptr; - if (!dmaCommands) { - IOLog( "Mace: Cant allocate channel DBDMA commands\n\r" ); - return false; - } - - /* - * If we needed more than one page, then make sure we received - * contiguous memory. - */ - n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE; - _IOPhysicalFromVirtual((vm_address_t) dmaCommands, &physBase ); - - virtAddr = (unsigned char *) dmaCommands; - for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) - { - _IOPhysicalFromVirtual( (vm_address_t) virtAddr, &physAddr ); - if (physAddr != (physBase + i * PAGE_SIZE) ) - { - IOLog("Mace: Cannot allocate contiguous memory for DBDMA " - "commands\n"); - return false; - } - } - - /* - * Setup the receive ring pointers - */ - rxDMACommands = (enet_dma_cmd_t *)dmaCommands; - rxMaxCommand = RX_RING_LENGTH; - - /* - * Setup the transmit ring pointers - */ - txDMACommands = (enet_txdma_cmd_t *)( - dmaCommands + - RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + - sizeof(IODBDMADescriptor)); - - txMaxCommand = TX_RING_LENGTH; - - /* - * Setup pre-initialized DBDMA commands - */ - IOMakeDBDMADescriptor( (&dbdmaCmd_Nop), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0 ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntAlways, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0 ); - - UInt32 ioBaseEnetPhys = maps[MEMORY_MAP_ENET_INDEX]->getPhysicalAddress(); - - IOMakeDBDMADescriptor( (&dbdmaCmd_LoadXFS), - kdbdmaLoadQuad, - kdbdmaKeySystem, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 1, - ((int)ioBaseEnetPhys + kXmtFS) ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntwInt), - kdbdmaLoadQuad, - kdbdmaKeySystem, - kdbdmaIntAlways, - kdbdmaBranchNever, - kdbdmaWaitNever, - 1, - ((int)ioBaseEnetPhys + kIntReg) ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_Stop), - kdbdmaStop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0 ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_Branch), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchAlways, - kdbdmaWaitNever, - 0, - 0 ); - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Transmit Ring - * ----------------------- - * Each transmit ring entry consists of two words to transmit data from buffer - * segments (possibly) spanning a page boundary. This is followed by two DMA - * commands which read transmit frame status and interrupt status from the Mace - * chip. The last DMA command in each transmit ring entry generates a host - * interrupt. The last entry in the ring is followed by a DMA branch to the - * first entry. - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_initTxRing() -{ - bool kr; - u_int32_t i; - - /* - * Clear the transmit DMA command memory - */ - bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand); - txCommandHead = 0; - txCommandTail = 0; - - /* - * DMA Channel commands 2,3 are the same for all DBDMA entries on transmit. - * Initialize them now. - */ - for( i=0; i < txMaxCommand; i++ ) - { - txDMACommands[i].desc_seg[2] = dbdmaCmd_LoadXFS; - txDMACommands[i].desc_seg[3] = dbdmaCmd_LoadIntwInt; - } - - /* - * Put a DMA Branch command after the last entry in the transmit ring. - * Set the branch address to the physical address of the start of the - * transmit ring. - */ - txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch; - - kr = _IOPhysicalFromVirtual( (vm_address_t) txDMACommands, - (u_int32_t *)&txDMACommandsPhys ); - if ( kr != kIOReturnSuccess ) - { - IOLog("Mace: Bad Tx DBDMA command buf - %08x\n\r", - (u_int32_t)txDMACommands ); - } - IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0], - txDMACommandsPhys ); - - /* - * Set the Transmit DMA Channel pointer to the first entry in the - * transmit ring. - */ - IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys ); - - /* - * Push the DMA channel words into physical memory. - */ - flush_cache_v( (vm_offset_t)txDMACommands, - txMaxCommand*sizeof(enet_txdma_cmd_t) + sizeof(IODBDMADescriptor)); - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Receive ring - * ---------------------- - * Each receive ring entry consists of two DMA commands to receive data - * into a network buffer (possibly) spanning a page boundary. The second - * DMA command in each entry generates a host interrupt. - * The last entry in the ring is followed by a DMA branch to the first - * entry. - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_initRxRing() -{ - u_int32_t i; - bool status; - IOReturn kr; - - /* - * Clear the receive DMA command memory - */ - bzero( (void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand); - - kr = _IOPhysicalFromVirtual( (vm_address_t) rxDMACommands, - (u_int32_t *)&rxDMACommandsPhys ); - if ( kr != kIOReturnSuccess ) - { - IOLog("Mace: Bad Rx DBDMA command buf - %08x\n\r", - (u_int32_t)rxDMACommands ); - return false; - } - - /* - * Allocate a receive buffer for each entry in the Receive ring - */ - for (i = 0; i < rxMaxCommand-1; i++) - { - if (rxMbuf[i] == 0) - { - rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE); - - if (!rxMbuf[i]) - { - IOLog("Mace: allocatePacket failed in _initRxRing()\n\r"); - return false; - } - } - - /* - * Set the DMA commands for the ring entry to transfer data to the - * mbuf. - */ - status = _updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); - if (status == false) - { - IOLog("Mace: Cant map mbuf to physical memory in _initRxRing\n\r"); - return false; - } - } - - /* - * Set the receive queue head to point to the first entry in the ring. - * Set the receive queue tail to point to a DMA Stop command after the - * last ring entry - */ - rxCommandHead = 0; - rxCommandTail = i; - - rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; - rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; - - /* - * Setup a DMA branch command after the stop command - */ - i++; - rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch; - - IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys ); - - /* - * Set DMA command pointer to first receive entry - */ - IOSetDBDMACommandPtr( ioBaseEnetRxDMA, rxDMACommandsPhys ); - - /* - * Push DMA commands to physical memory - */ - flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], - 2 * sizeof(enet_dma_cmd_t) ); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_startChip() -{ - WriteMaceRegister( ioBaseEnet, kMacCC, kMacCCEnXmt | kMacCCEnRcv ); - - // enable rx dma channel - IODBDMAContinue( ioBaseEnetRxDMA ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_resetChip() -{ - u_int8_t regValue; - - /* - * Mace errata - chip reset does not clear pending interrupts - */ - ReadMaceRegister( ioBaseEnet, kIntReg ); - - IODBDMAReset( ioBaseEnetRxDMA ); - IODBDMAReset( ioBaseEnetTxDMA ); - - IOSetDBDMAWaitSelect( ioBaseEnetTxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS5 ) ); - - IOSetDBDMABranchSelect( ioBaseEnetRxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); - - IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); - - WriteMaceRegister( ioBaseEnet, kBIUCC, kBIUCCSWRst ); - do - { - regValue = ReadMaceRegister( ioBaseEnet, kBIUCC ); - } - while( regValue & kBIUCCSWRst ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_initChip() -{ - volatile u_int16_t regValue; - u_int32_t i; - - _disableAdapterInterrupts(); - - chipId = ReadMaceRegister( ioBaseEnet, kMaceChipId0 ); - chipId |= ReadMaceRegister( ioBaseEnet, kMaceChipId1 ) << 8; - - /* - * Turn off ethernet header stripping - */ - regValue = ReadMaceRegister( ioBaseEnet, kRcvFC ); - regValue &= ~kRcvFCAStrpRcv; - WriteMaceRegister( ioBaseEnet, kRcvFC, regValue ); - - /* - * Set Mace destination address. - */ - if ( chipId != kMaceRevisionA2 ) - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACPhyAddr ); - do - { - regValue = ReadMaceRegister( ioBaseEnet, kIAC ); - } - while( regValue & kIACAddrChg ); - } - else - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACPhyAddr ); - } - - for (i=0; i < sizeof(IOEthernetAddress); i++ ) - { - WriteMaceRegister( ioBaseEnet, kPADR, - reverseBitOrder(((unsigned char *)ioBaseEnetROM)[i<<4]) ); - } - - /* - * Clear logical address (multicast) filter - */ - if ( chipId != kMaceRevisionA2 ) - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr ); - do - { - regValue = ReadMaceRegister( ioBaseEnet, kIAC ); - } - while( regValue & kIACAddrChg ); - } - else - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr ); - } - - for (i = 0; i < 8; i++ ) - { - WriteMaceRegister( ioBaseEnet, kLADRF, 0 ); - } - - /* - * Enable ethernet transceiver - */ - WriteMaceRegister( ioBaseEnet, kPLSCC, kPLSCCPortSelGPSI | kPLSCCEnSts ); - - return true; -} - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_restartChip() -{ - /* - * Shutdown DMA channels - */ - _stopReceiveDMA(); - _stopTransmitDMA(); - - /* - * Get the silicon's attention - */ - _resetChip(); - _initChip(); - - /* - * Restore multicast settings - */ - _updateHashTableMask(); - - if ( isPromiscuous ) - { - _setPromiscuousMode(kIOEnetPromiscuousModeOn); - } - - /* - * Enable receiver and transmitter - */ - _startChip(); - _enableAdapterInterrupts(); - - /* - * Restart transmit DMA - */ - IODBDMAContinue( ioBaseEnetTxDMA ); -} - -/*------------------------------------------------------------------------- - * - * Orderly stop of receive DMA. - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_stopReceiveDMA() -{ - u_int32_t dmaStatus; - u_int32_t dmaCmdPtr; - u_int32_t dmaIndex; - u_int8_t tmpBuf[16]; - u_int8_t *p = 0; - u_int8_t MacCCReg; - - /* - * Stop the receiver and allow any frame receive in progress to complete - */ - MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC ); - WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnRcv ); - IODelay( RECEIVE_QUIESCE_uS ); - - /* - * Capture channel status and pause the dma channel. - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); - IODBDMAPause( ioBaseEnetRxDMA ); - - /* - * Read the command pointer and convert it to a byte offset into the - * DMA program. - */ - dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetRxDMA ); - dmaIndex = (dmaCmdPtr - rxDMACommandsPhys); - - /* - * If the channel status is DEAD, the DMA pointer is pointing to the - * next command - */ - if ( dmaStatus & kdbdmaDead ) - { - dmaIndex -= sizeof(IODBDMADescriptor); - } - - /* - * Convert channel program offset to command index - */ - dmaIndex = dmaIndex / sizeof(enet_dma_cmd_t); - if ( dmaIndex >= rxMaxCommand ) dmaIndex = 0; - - /* - * The DMA controller doesnt like being stopped before transferring any - * data. - * - * When we do so it pollutes up to 16-bytes aligned to the nearest (lower) - * 16-byte boundary. This corruption can be outside the data transfer area - * of the mbuf, so we capture and then restore these bytes after stopping - * the channel. - * - */ - if ( rxMbuf[dmaIndex] ) - { - p = mtod(rxMbuf[dmaIndex], u_int8_t *); - } - - (u_int32_t)p &= ~0x0f; - - if ( p ) - { - bcopy( p, tmpBuf, 16 ); - } - - IODBDMAReset( ioBaseEnetRxDMA ); - - if ( p ) - { - bcopy( tmpBuf, p, 16 ); - } - - /* - * Reset the dma channel pointer to the nearest command index - */ - dmaCmdPtr = rxDMACommandsPhys + sizeof(enet_dma_cmd_t) * dmaIndex; - IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_stopTransmitDMA() -{ - u_int32_t dmaStatus; - u_int32_t dmaCmdPtr; - u_int32_t dmaIndex; - u_int8_t MacCCReg; - - /* - * Stop the transmitter and allow any frame transmit in progress to abort - */ - MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC ); - WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnXmt ); - IODelay( TRANSMIT_QUIESCE_uS ); - - /* - * Capture channel status and pause the dma channel. - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); - IODBDMAPause( ioBaseEnetTxDMA ); - - /* - * Read the command pointer and convert it to a byte offset into the - * DMA program. - */ - dmaCmdPtr = IOGetDBDMACommandPtr( ioBaseEnetTxDMA ); - dmaIndex = (dmaCmdPtr - txDMACommandsPhys); - - /* - * If the channel status is DEAD, the DMA pointer is pointing to the - * next command - */ - if ( dmaStatus & kdbdmaDead ) - { - dmaIndex -= sizeof(IODBDMADescriptor); - } - - /* - * Convert channel program offset to command index - */ - dmaIndex = dmaIndex / sizeof(enet_txdma_cmd_t); - if ( dmaIndex >= txMaxCommand ) dmaIndex = 0; - - IODBDMAReset( ioBaseEnetTxDMA ); - - /* - * Reset the dma channel pointer to the nearest command index - */ - dmaCmdPtr = txDMACommandsPhys + sizeof(enet_txdma_cmd_t) * dmaIndex; - IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_disableAdapterInterrupts() -{ - WriteMaceRegister( ioBaseEnet, kIntMask, 0xFF ); -} - -/*------------------------------------------------------------------------- - * - * _enableAdapterInterrupts - * - * It appears to make the Mace chip work properly with the DBDMA channel - * we need to leave the transmit interrupt unmasked at the chip. This - * is weird, but that's what happens when you try to glue a chip that - * wasn't intended to work with a DMA engine on to a DMA. - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_enableAdapterInterrupts() -{ - u_int8_t regValue; - - regValue = ReadMaceRegister( ioBaseEnet, kIntMask ); - regValue &= ~kIntMaskXmtInt; - WriteMaceRegister( ioBaseEnet, kIntMask, regValue ); - IODelay(500); - ReadMaceRegister( ioBaseEnet, kXmtFS ); - ReadMaceRegister( ioBaseEnet, kIntReg ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_transmitPacket(struct mbuf * packet) -{ - enet_dma_cmd_t tmpCommand; - u_int32_t i; - - /* - * Check for room on the transmit ring. There should always be space - * since it is the responsibility of the caller to verify this before - * calling _transmitPacket. - * - * Get a copy of the DMA transfer commands in a temporary buffer. - * The new DMA command is written into the channel program so that the - * command word for the old Stop command is overwritten last. This prevents - * the DMA engine from executing a partially written channel command. - */ - i = txCommandTail + 1; - if ( i >= txMaxCommand ) i = 0; - - if ( (i == txCommandHead) || - !_updateDescriptorFromMbuf(packet, &tmpCommand, false)) - { - IOLog("Mace: Freeing transmit packet eh?\n\r"); - if (packet != txDebuggerPkt) - freePacket(packet); - return false; - } - - /* - * txCommandTail points to the current DMA Stop command for the channel. - * We are now creating a new DMA Stop command in the next slot in the - * transmit ring. The previous DMA Stop command will be overwritten with - * the DMA commands to transfer the new mbuf. - */ - txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; - txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; - - flush_cache_v( (vm_offset_t)&txDMACommands[i], sizeof(enet_dma_cmd_t) ); - - bcopy( ((u_int32_t *)&tmpCommand)+1, - ((u_int32_t *)&txDMACommands[txCommandTail])+1, - sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); - - flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], - sizeof(enet_dma_cmd_t) ); - - txMbuf[txCommandTail] = packet; - txDMACommands[txCommandTail].desc_seg[0].operation = - tmpCommand.desc_seg[0].operation; - - flush_cache_v( (vm_offset_t)&txDMACommands[txCommandTail], - sizeof(enet_dma_cmd_t) ); - - /* - * Set the transmit tail to the new stop command. - */ - txCommandTail = i; - - /* - * Tap the DMA channel to wake it up - */ - IODBDMAContinue( ioBaseEnetTxDMA ); - - return true; -} - -/*------------------------------------------------------------------------- - * _receivePacket - * -------------- - * This routine runs the receiver in polled-mode (yuk!) for the kernel - * debugger. - * - * The _receivePackets allocate mbufs and pass them up the stack. The kernel - * debugger interface passes a buffer into us. To reconcile the two interfaces, - * we allow the receive routine to continue to allocate its own buffers and - * transfer any received data to the passed-in buffer. This is handled by - * _receivePacket calling _packetToDebugger. - *-------------------------------------------------------------------------*/ - -void MaceEnet::_receivePacket(void *pkt, unsigned int *pkt_len, - unsigned int timeout) -{ - ns_time_t startTime; - ns_time_t currentTime; - u_int32_t elapsedTimeMS; - - if (!ready || !pkt || !pkt_len) - return; - - *pkt_len = 0; - - debuggerPkt = pkt; - debuggerPktSize = 0; - - _IOGetTimestamp(&startTime); - do - { - _receivePackets(true); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); - - *pkt_len = debuggerPktSize; - - return; -} - -/*------------------------------------------------------------------------- - * _packetToDebugger - * ----------------- - * This is called by _receivePackets when we are polling for kernel debugger - * packets. It copies the mbuf contents to the buffer passed by the debugger. - * It also sets the var debuggerPktSize which will break the polling loop. - *-------------------------------------------------------------------------*/ - -void MaceEnet::_packetToDebugger(struct mbuf * packet, u_int size) -{ - debuggerPktSize = size; - bcopy( mtod(packet, char *), debuggerPkt, size ); -} - -/*------------------------------------------------------------------------- - * _sendPacket - * ----------- - * - * This routine runs the transmitter in polled-mode (yuk!) for the - * kernel debugger. - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_sendPacket(void *pkt, unsigned int pkt_len) -{ - ns_time_t startTime; - ns_time_t currentTime; - u_int32_t elapsedTimeMS; - - if ( !ready || !pkt || (pkt_len > ETHERMAXPACKET)) - return; - - /* - * Wait for the transmit ring to empty - */ - _IOGetTimestamp(&startTime); - do - { - _transmitInterruptOccurred(true); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && - (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog( "Mace: Polled tranmit timeout - 1\n\r"); - return; - } - - txDebuggerPkt->m_next = 0; - txDebuggerPkt->m_data = (caddr_t) pkt; - txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len; - - /* - * Send the debugger packet. txDebuggerPkt must not be freed by - * the transmit routine. - */ - _transmitPacket(txDebuggerPkt); - - /* - * Poll waiting for the transmit ring to empty again - */ - do - { - _transmitInterruptOccurred(true); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && - (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog("Mace: Polled transmit timeout - 2\n\r"); - } - - return; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_receiveInterruptOccurred() -{ - return _receivePackets(false); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_receivePackets(bool fDebugger) -{ - enet_dma_cmd_t tmpCommand; - struct mbuf * packet; - u_int32_t i,j,last; - u_int32_t dmaChnlStatus; - int receivedFrameSize = 0; - u_int32_t dmaCount[2], dmaResid[2], dmaStatus[2]; - bool reusePkt; - bool status; - bool useNetif = !fDebugger && netifClient; - bool packetsQueued = false; - u_int8_t *rxFS = NULL; - u_int32_t nextDesc; - static const u_int32_t lastResetValue = (u_int32_t)(-1); - - last = lastResetValue; - i = rxCommandHead; - - while ( 1 ) - { - reusePkt = false; - - /* - * Purge cache references for the DBDMA entry we are about to look at. - */ - invalidate_cache_v((vm_offset_t)&rxDMACommands[i], - sizeof(enet_dma_cmd_t)); - - /* - * Collect the DMA residual counts/status for the two buffer segments. - */ - for ( j = 0; j < 2; j++ ) - { - dmaResid[j] = IOGetCCResult( &rxDMACommands[i].desc_seg[j] ); - dmaStatus[j] = dmaResid[j] >> 16; - dmaResid[j] &= 0x0000ffff; - dmaCount[j] = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] ) & - kdbdmaReqCountMask; - } - -#if 0 - IOLog("Ethernet(Mace): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r", - i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] ); -#endif - - /* - * If the current entry has not been written, then stop at this entry - */ - if ( !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) ) - { - break; - } - - /* - * The Mace Ethernet controller appends four bytes to each receive - * buffer containing the buffer size and receive frame status. - * We locate these bytes by using the DMA residual counts. - */ - receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] - - ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]); - - if ( ( receivedFrameSize >= 4 ) && - ( receivedFrameSize <= NETWORK_BUFSIZE ) ) - { - /* - * Get the receive frame size as reported by the Mace controller - */ - - rxFS = mtod(rxMbuf[i], u_int8_t *) + receivedFrameSize - 4; - - receivedFrameSize = (u_int16_t) rxFS[0] | - (rxFS[1] & kRcvFS1RcvCnt) << 8; - } - - /* - * Reject packets that are runts or that have other mutations. - */ - if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || - receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || - (rxFS[1] & (kRcvFS1OFlo | kRcvFS1Clsn | kRcvFS1Fram | kRcvFS1FCS)) - ) - { - if (useNetif) netStats->inputErrors++; - reusePkt = true; - } - else if ( useNetif == false ) - { - /* - * Always reuse packets in debugger mode. - */ - reusePkt = true; - if (fDebugger) - _packetToDebugger(rxMbuf[i], receivedFrameSize); - } - - /* - * Before we pass this packet up the networking stack. Make sure we - * can get a replacement. Otherwise, hold on to the current packet and - * increment the input error count. - * Thanks Justin! - */ - - packet = 0; - - if ( reusePkt == false ) - { - bool replaced; - - packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, - &replaced); - - reusePkt = true; - - if (packet && replaced) - { - status = _updateDescriptorFromMbuf(rxMbuf[i], - &rxDMACommands[i], true); - - if (status) - { - reusePkt = false; - } - else - { - // Assume descriptor has not been corrupted. - freePacket(rxMbuf[i]); // release new packet. - rxMbuf[i] = packet; // get the old packet back. - packet = 0; // pass up nothing. - IOLog("Mace: _updateDescriptorFromMbuf error\n"); - } - } - - if (packet == 0) - netStats->inputErrors++; - } - - /* - * If we are reusing the existing mbuf, then refurbish the existing - * DMA command \ descriptors by clearing the status/residual count - * fields. - */ - - if ( reusePkt == true ) - { - for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor); - j++ ) - { - IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 ); - } - flush_cache_v( (vm_offset_t)&rxDMACommands[i], - sizeof(enet_dma_cmd_t) ); - } - - /* - * Keep track of the last receive descriptor processed - */ - last = i; - - /* - * Implement ring wrap-around - */ - if (++i >= rxMaxCommand) i = 0; - - /* - * Early exit in debugger mode. - */ - if (fDebugger) - { - break; - } - - /* - * Transfer received to network stack. - */ - if (packet) - { - KERNEL_DEBUG(DBG_MACE_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, - (int)receivedFrameSize, 0, 0, 0 ); - - /* - * The KDB lock must be held before calling this function. - */ - networkInterface->inputPacket(packet, receivedFrameSize, true); - netStats->inputPackets++; - packetsQueued = true; - } - } - - /* - * OK...this is a little messy - * - * We just processed a bunch of DMA receive descriptors. We are going to - * exchange the current DMA stop command (rxCommandTail) with the last - * receive descriptor we processed (last). This will make these list of - * descriptors we just processed available. If we processed no receive - * descriptors on this call then skip this exchange. - */ - -#if 0 - IOLog("Mace: Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", - rxCommandHead, rxCommandTail, last ); -#endif - - if ( last != lastResetValue ) - { - /* - * Save the contents of the last receive descriptor processed. - */ - packet = rxMbuf[last]; - tmpCommand = rxDMACommands[last]; - - /* - * Write a DMA stop command into this descriptor slot - */ - rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop; - rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop; - rxMbuf[last] = 0; - - flush_cache_v( (vm_offset_t)&rxDMACommands[last], - sizeof(enet_dma_cmd_t) ); - - /* - * Replace the previous DMA stop command with the last receive - * descriptor processed. - * - * The new DMA command is written into the channel program so that the - * command word for the old Stop command is overwritten last. This - * prevents the DMA engine from executing a partially written channel - * command. - * - * Note: When relocating the descriptor, we must update its branch - * field to reflect its new location. - */ - nextDesc = rxDMACommandsPhys + (int)&rxDMACommands[rxCommandTail+1] - - (int)rxDMACommands; - IOSetCCCmdDep( &tmpCommand.desc_seg[0], nextDesc ); - - bcopy( (u_int32_t *)&tmpCommand+1, - (u_int32_t *)&rxDMACommands[rxCommandTail]+1, - sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); - - flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], - sizeof(enet_dma_cmd_t) ); - - rxMbuf[rxCommandTail] = packet; - - rxDMACommands[rxCommandTail].desc_seg[0].operation = - tmpCommand.desc_seg[0].operation; - - flush_cache_v( (vm_offset_t)&rxDMACommands[rxCommandTail], - sizeof(IODBDMADescriptor) ); - - /* - * Update rxCommmandTail to point to the new Stop command. Update - * rxCommandHead to point to the next slot in the ring past the Stop - * command - */ - rxCommandTail = last; - rxCommandHead = i; - } - - /* - * The DMA channel has a nasty habit of shutting down when there is a - * non-recoverable error on receive. We get no interrupt for this since - * the channel shuts down before the descriptor that causes the host - * interrupt is executed. - * - * We check if the channel is DEAD by checking the channel status reg. - * Also, the watchdog timer can force receiver interrupt servicing based - * on detecting that the receive DMA is DEAD. - */ - dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); - if ( dmaChnlStatus & kdbdmaDead ) - { - /* - * Read log error - */ - if (useNetif) netStats->inputErrors++; - IOLog( "Mace: Rx DMA Error - Status = %04x\n", dmaChnlStatus ); - - /* - * Reset and reinitialize chip - */ - _restartChip(); // This must not block in debugger mode. - } - else - { - /* - * Tap the DMA to wake it up - */ - IODBDMAContinue( ioBaseEnetRxDMA ); - } - -#if 0 - IOLog( "Mace: New - Rx Head = %2d Rx Tail = %2d\n\r", - rxCommandHead, rxCommandTail ); -#endif - - return packetsQueued; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool MaceEnet::_transmitInterruptOccurred(bool fDebugger = false) -{ - u_int32_t dmaStatus; - u_int32_t xmtFS; - bool fServiced = false; - bool useNetif = !fDebugger && netifClient; - - // Set the debugTxPoll flag to indicate the debugger was active - // and some cleanup may be needed when the driver returns to - // normal operation. - // - if (fDebugger) - debugTxPoll = true; - - while ( 1 ) - { - /* - * Purge cache references for the DBDMA entry we are about to look at. - */ - invalidate_cache_v((vm_offset_t)&txDMACommands[txCommandHead], - sizeof(enet_txdma_cmd_t)); - - /* - * Check the status of the last descriptor in this entry to see if - * the DMA engine completed this entry. - */ - dmaStatus = IOGetCCResult( - &txDMACommands[txCommandHead].desc_seg[3] ) >> 16; - - if ( !(dmaStatus & kdbdmaActive) ) - { - break; - } - - fServiced = true; - - /* - * Reset the status word for the entry we are about to process - */ - IOSetCCResult( &txDMACommands[txCommandHead].desc_seg[3], 0 ); - - flush_cache_v( (vm_offset_t) &txDMACommands[txCommandHead].desc_seg[3], - sizeof(IODBDMADescriptor) ); - - /* - * This DMA descriptor read the transmit frame status. See what it has - * to tell us. - */ - xmtFS = IOGetCCCmdDep( &txDMACommands[txCommandHead].desc_seg[2] ); - if ( useNetif && (xmtFS & kXmtFSXmtSV) ) - { - if (xmtFS & (kXmtFSUFlo | kXmtFSLCol | kXmtFSRtry | kXmtFSLCar) ) - { - netStats->outputErrors++; - } - else - { - netStats->outputPackets++; - } - - if (xmtFS & (kXmtFSOne | kXmtFSMore) ) - { - netStats->collisions++; - } - } - - /* - * Free the mbuf we just transmitted. - */ - KERNEL_DEBUG(DBG_MACE_TXCOMPLETE | DBG_FUNC_NONE, - (int) txMbuf[txCommandHead], - (int) txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 ); - - if (txMbuf[txCommandHead] != txDebuggerPkt) - { - if ( fDebugger ) - { - // - // While in debugger mode, do not touch the mbuf pool. - // Queue any used mbufs to a local queue. This queue - // will get flushed after we exit from debugger mode. - // - // During continuous debugger transmission and - // interrupt polling, we expect only the txDebuggerPkt - // to show up on the transmit mbuf ring. - // - debugQueue->enqueue( txMbuf[txCommandHead] ); - } - else - { - freePacket( txMbuf[txCommandHead] ); - } - } - - txMbuf[txCommandHead] = 0; - - if ( ++txCommandHead >= txMaxCommand ) txCommandHead = 0; - } - - /* - * The DMA channel has a nasty habit of shutting down when there is - * non-recoverable error on transmit. We get no interrupt for this since - * the channel shuts down before the descriptor that causes the host - * interrupt is executed. - * - * We check if the channel is DEAD by checking the channel status reg. - * Also, the watchdog timer can force a transmitter reset if it sees no - * interrupt activity for to consecutive timeout intervals. - */ - - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); - if ( (dmaStatus & kdbdmaDead) || (txWDForceReset == true) ) - { - /* - * Read the transmit frame status and log error - */ - xmtFS = ReadMaceRegister( ioBaseEnet, kXmtFS ); - if (useNetif) netStats->outputErrors++; - IOLog( "Mace: Tx DMA Error - Status = %04x FS = %02x\n\r", - dmaStatus, xmtFS); - - /* - * Reset and reinitialize chip - */ - _restartChip(); - - txWDForceReset = false; - fServiced = true; - } - - return fServiced; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -/* - * Breaks up an ethernet data buffer into two physical chunks. We know that - * the buffer can't straddle more than two pages. If the content of paddr2 is - * zero this means that all of the buffer lies in one physical page. Note - * that we use the fact that tx and rx descriptors have the same size and - * same layout of relevent fields (data address and count). - */ -bool -MaceEnet::_updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, - bool isReceive) -{ - u_int32_t nextDesc = 0; - int segments; - struct IOPhysicalSegment segVector[2]; - - /* - * Although coalescing is always enabled, it cannot occur - * while the driver is in debugger mode. - */ - segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector); - - if ((!segments) || (segments > 2)) { - IOLog("Mace: _updateDescriptorFromMbuf error, %d segments\n", - segments); - return false; - } - - if ( segments == 1 ) - { - IOMakeDBDMADescriptor( (&desc->desc_seg[0]), - ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), - (kdbdmaKeyStream0), - (kdbdmaIntNever), - (kdbdmaBranchNever), - ((isReceive) ? kdbdmaWaitNever : - kdbdmaWaitIfFalse), - (segVector[0].length), - (segVector[0].location) ); - - desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop; - } - else - { - if ( isReceive ) - { - nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands + - sizeof(enet_dma_cmd_t); - } - - IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]), - ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore), - (kdbdmaKeyStream0), - ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever), - ((isReceive) ? kdbdmaBranchIfTrue : - kdbdmaBranchNever), - (kdbdmaWaitNever), - (segVector[0].length), - (segVector[0].location), - nextDesc ); - - IOMakeDBDMADescriptor( (&desc->desc_seg[1]), - ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), - (kdbdmaKeyStream0), - ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever), - (kdbdmaBranchNever), - ((isReceive) ? kdbdmaWaitNever : - kdbdmaWaitIfFalse), - (segVector[1].length), - (segVector[1].location) ); - } - - flush_cache_v( (vm_offset_t)desc, sizeof(enet_dma_cmd_t) ); - - return true; -} - - -#ifdef DEBUG -/* - * Useful for testing. - */ - -void MaceEnet::_dumpDesc(void * addr, u_int32_t size) -{ - u_int32_t i; - unsigned long *p; - vm_offset_t paddr; - - _IOPhysicalFromVirtual( (vm_offset_t) addr, (vm_offset_t *)&paddr ); - - p = (unsigned long *)addr; - - for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4, - paddr+=sizeof(IODBDMADescriptor) ) - { - IOLog("Ethernet(Mace): %08x(v) %08x(p): %08x %08x %08x %08x\n", - (int)p, - (int)paddr, - (int)OSReadSwapInt32(p, 0), (int)OSReadSwapInt32(p, 4), - (int)OSReadSwapInt32(p, 8), (int)OSReadSwapInt32(p, 12) ); - } - IOLog("\n"); -} - -void MaceEnet::_dumpRegisters() -{ - u_int8_t dataValue; - - IOLog("\nEthernet(Mace): IO Address = %08x", (int)ioBaseEnet ); - - dataValue = ReadMaceRegister(ioBaseEnet, kXmtFC); - IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Control = %02x", kXmtFC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kXmtFS); - IOLog("\nEthernet(Mace): Read Register %04x Transmit Frame Status = %02x", kXmtFS, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kXmtRC); - IOLog("\nEthernet(Mace): Read Register %04x Transmit Retry Count = %02x", kXmtRC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kRcvFC); - IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Control = %02x", kRcvFC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS0); - IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 0 = %02x", kRcvFS0, dataValue ); - dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS1); - IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 1 = %02x", kRcvFS1, dataValue ); - dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS2); - IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 2 = %02x", kRcvFS2, dataValue ); - dataValue = ReadMaceRegister(ioBaseEnet, kRcvFS3); - IOLog("\nEthernet(Mace): Read Register %04x Receive Frame Status 3 = %02x", kRcvFS3, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kFifoFC); - IOLog("\nEthernet(Mace): Read Register %04x FIFO Frame Count = %02x", kFifoFC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kIntReg); - IOLog("\nEthernet(Mace): Read Register %04x Interrupt Register = %02x", kIntReg, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kIntMask); - IOLog("\nEthernet(Mace): Read Register %04x Interrupt Mask Register = %02x", kIntMask, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kPollReg); - IOLog("\nEthernet(Mace): Read Register %04x Poll Register = %02x", kPollReg, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kBIUCC); - IOLog("\nEthernet(Mace): Read Register %04x BUI Configuration Control = %02x", kBIUCC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kFifoCC); - IOLog("\nEthernet(Mace): Read Register %04x FIFO Configuration Control = %02x", kFifoCC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kMacCC); - IOLog("\nEthernet(Mace): Read Register %04x MAC Configuration Control = %02x", kMacCC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kPLSCC); - IOLog("\nEthernet(Mace): Read Register %04x PLS Configuration Contro = %02x", kPLSCC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kPHYCC); - IOLog("\nEthernet(Mace): Read Register %04x PHY Configuration Control = %02x", kPHYCC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId0); - IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 7:0 = %02x", kMaceChipId0, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kMaceChipId1); - IOLog("\nEthernet(Mace): Read Register %04x MACE ChipID Register 15:8 = %02x", kMaceChipId1, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kMPC); - IOLog("\nEthernet(Mace): Read Register %04x Missed Packet Count = %02x", kMPC, dataValue ); - - dataValue = ReadMaceRegister(ioBaseEnet, kUTR); - IOLog("\nEthernet(Mace): Read Register %04x User Test Register = %02x", kUTR, dataValue ); - IOLog("\nEthernet(Mace): -------------------------------------------------------\n" ); -} -#endif DEBUG - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn MaceEnet::getHardwareAddress(IOEthernetAddress *ea) -{ - unsigned char data; - - for (UInt i = 0; i < sizeof(*ea); i++) - { - data = ((unsigned char *)ioBaseEnetROM)[i << 4]; - ea->bytes[i] = reverseBitOrder(data); - } - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -#define ENET_CRCPOLY 0x04c11db7 - -/* Real fast bit-reversal algorithm, 6-bit values */ -static int reverse6[] = -{ 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38, - 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c, - 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a, - 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e, - 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39, - 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d, - 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b, - 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f -}; - -static u_int32_t crc416(unsigned int current, unsigned short nxtval ) -{ - register unsigned int counter; - register int highCRCBitSet, lowDataBitSet; - - /* Swap bytes */ - nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); - - /* Compute bit-by-bit */ - for (counter = 0; counter != 16; ++counter) - { /* is high CRC bit set? */ - if ((current & 0x80000000) == 0) - highCRCBitSet = 0; - else - highCRCBitSet = 1; - - current = current << 1; - - if ((nxtval & 0x0001) == 0) - lowDataBitSet = 0; - else - lowDataBitSet = 1; - - nxtval = nxtval >> 1; - - /* do the XOR */ - if (highCRCBitSet ^ lowDataBitSet) - current = current ^ ENET_CRCPOLY; - } - return current; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -static u_int32_t mace_crc(unsigned short *address) -{ - register u_int32_t newcrc; - - newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ - newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ - newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ - - return (newcrc); -} - -/* - * Clear the hash table filter. - * - */ -void MaceEnet::_resetHashTableMask() -{ - bzero(hashTableUseCount, sizeof(hashTableUseCount)); - bzero(hashTableMask, sizeof(hashTableMask)); -} - -/* - * Add requested mcast addr to Mace's hash table filter. - * - */ -void MaceEnet::_addToHashTableMask(u_int8_t *addr) -{ - u_int32_t crc; - u_int8_t mask; - - crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ - crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ - if (hashTableUseCount[crc]++) - return; /* This bit is already set */ - mask = crc % 8; - mask = (unsigned char) 1 << mask; - hashTableMask[crc/8] |= mask; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void MaceEnet::_removeFromHashTableMask(u_int8_t *addr) -{ - unsigned int crc; - unsigned char mask; - - /* Now, delete the address from the filter copy, as indicated */ - crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ - crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ - if (hashTableUseCount[crc] == 0) - return; /* That bit wasn't in use! */ - - if (--hashTableUseCount[crc]) - return; /* That bit is still in use */ - - mask = crc % 8; - mask = ((unsigned char)1 << mask) ^ 0xffff; /* To turn off bit */ - hashTableMask[crc/8] &= mask; -} - -/* - * Sync the adapter with the software copy of the multicast mask - * (logical address filter). - */ -void MaceEnet::_updateHashTableMask() -{ - u_int8_t status; - u_int32_t i; - u_int8_t *p; - u_int8_t MacCCReg; - - // Stop the receiver before changing the filter. - // - MacCCReg = ReadMaceRegister( ioBaseEnet, kMacCC ); - WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg & ~kMacCCEnRcv ); - IODelay( RECEIVE_QUIESCE_uS ); - - if ( chipId != kMaceRevisionA2 ) - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACAddrChg | kIACLogAddr ); - do - { - status = ReadMaceRegister( ioBaseEnet, kIAC ); - } - while( status & kIACAddrChg ); - } - else - { - WriteMaceRegister( ioBaseEnet, kIAC, kIACLogAddr ); - } - - p = (u_int8_t *) hashTableMask; - for (i = 0; i < 8; i++, p++ ) - { - WriteMaceRegister( ioBaseEnet, kLADRF, *p ); - } - - // Restore the engine's state. - // - WriteMaceRegister( ioBaseEnet, kMacCC, MacCCReg ); -} diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.h b/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.h deleted file mode 100644 index 849e3a96e..000000000 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Interface for hardware dependent (relatively) code - * for the Mace Ethernet chip - * - * HISTORY - * - * 11/22/97 R. Berkoff - * Created. - */ - -#ifndef _MACEENETPRIVATE_H -#define _MACEENETPRIVATE_H - -#include "MaceEnet.h" - -void WriteMaceRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset, u_int8_t data); - -volatile u_int8_t ReadMaceRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset); - -#endif /* !_MACEENETPRIVATE_H */ diff --git a/iokit/Drivers/network/drvMaceEnet/MaceEnetRegisters.h b/iokit/Drivers/network/drvMaceEnet/MaceEnetRegisters.h deleted file mode 100644 index 64e05bc24..000000000 --- a/iokit/Drivers/network/drvMaceEnet/MaceEnetRegisters.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1995-1996 NeXT Software, Inc. - * - * Interface definition for the Mace Ethernet controller. - * - * HISTORY - * - * 04-Nov-97 - * Created. - */ - -#ifndef _MACEENETREGISTERS_H -#define _MACEENETREGISTERS_H - -// --------------------------------------------------------------------------------------------- -// Mace and GC I/O Addresses -// --------------------------------------------------------------------------------------------- -#define kTxDMABaseOffset 0x08200 // offset from I/O Space Base address -#define kRxDMABaseOffset 0x08300 -#define kControllerBaseOffset 0x11000 -#define kControllerROMOffset 0x19000 - - -// --------------------------------------------------------------------------------------------- -// Mace Register Numbers & Bit Assignments -// --------------------------------------------------------------------------------------------- -/* - * Chip Revisions.. - */ - -#define kMaceRevisionB0 0x0940 -#define kMaceRevisionA2 0x0941 - -/* xmtfc */ -#define kXmtFC 0x0020 /* Transmit Frame Control */ -#define kXmtFCDRtry 0X80 /* - Disable Retry */ -#define kXmtFCDXmtFCS 0x08 /* - Disable Transmit FCS */ -#define kXmtFCAPadXmt 0x01 /* - Auto PAD Transmit */ - -/* xmtfs */ -#define kXmtFS 0x0030 /* Transmit Frame Status */ -#define kXmtFSXmtSV 0x80 /* - Transmit Status Valid */ -#define kXmtFSUFlo 0x40 /* - Transmit Underflow */ -#define kXmtFSLCol 0x20 /* - Transmit late collision */ -#define kXmtFSMore 0x10 /* - Transmit < 1 retry */ -#define kXmtFSOne 0x08 /* - Transmit single retry */ -#define kXmtFSDefer 0x04 /* - Transmit deferred */ -#define kXmtFSLCar 0x02 /* - Transmit lost carrier */ -#define kXmtFSRtry 0x01 /* - Transmit Unsuccessful */ - -/* xmtrc */ -#define kXmtRC 0x0040 /* Transmit Retry Count */ -#define kXmtRCExDef 0x80 /* - ? */ -#define kXmtRCXmrRC 0x0F /* - Transmit retry count */ - -/* rcvfc */ -#define kRcvFC 0x0050 /* Receive Frame Control */ -#define kRcvFCLLRcv 0x08 /* - ? */ -#define kRcvFCMR 0x04 /* - Match/Reject (not implemented) */ -#define kRcvFCAStrpRcv 0x01 /* - Auto Strip Receive Enable */ - -/* rcvfs */ -#define kRcvFS0 0x0060 /* Receive Frame Status - Byte 0 */ -#define kRcvFS0RcvCnt 0xFF /* - Receive Msg Byte Count (7:0) */ - -#define kRcvFS1 0x0060 /* Receive Frame Status - Byte 1 */ -#define kRcvFS1OFlo 0x80 /* - Receive Overflow */ -#define kRcvFS1Clsn 0x40 /* - Receive Collision */ -#define kRcvFS1Fram 0x20 /* - Receive Framming Error */ -#define kRcvFS1FCS 0x10 /* - Receive Frame Check Error */ -#define kRcvFS1RcvCnt 0x0f /* - Receive Msg Byte Count (11:8) */ - - -#define kRcvFS2 0x0060 /* Receive Frame Status - Byte 2 */ -#define kRcvFS2RntPC 0xFF /* - Runt Packet Count */ - -#define kRcvFS3 0x0060 /* Receive Frame Status - Byte 3 */ -#define kRcvFS3RcvCC 0xFF /* Receive Collision Count */ - -/* fifofc */ -#define kFifoFC 0x0070 /* FIFO Frame Count */ -#define kFifoFCXFW 0xc0 /* - ? */ -#define kFifoFCXFW8 0x00 /* - ? */ -#define kFifoFCXFW16 0x40 /* - ? */ -#define kFifoFCXFW32 0x80 /* - ? */ - -#define kFifoFCRFW 0x30 /* - ? */ -#define kFifoFCRFW16 0x00 /* - ? */ -#define kFifoFCRFW32 0x10 /* - ? */ -#define kFifoFCRFW64 0x20 /* - ? */ -#define kFifoFCXFWU 0x08 /* - ? */ -#define kFifoFCRFWU 0x04 /* - ? */ -#define kFifoFCXBRst 0x02 /* - ? */ -#define kFifoFCRBRst 0x01 /* - ? */ - - -/* ir */ -#define kIntReg 0x0080 /* Interrupt Register */ -#define kIntRegJab 0x80 /* - Jabber Error */ -#define kIntRegBabl 0x40 /* - Babble Error */ -#define kIntRegCErr 0x20 /* - Collision Error */ -#define kIntRegRcvCCO 0x10 /* - Receive Collision Count Overflow */ -#define kIntRegRntPCO 0x08 /* - Runt Packet Count Overflow */ -#define kIntRegMPCO 0x04 /* - Missed Packet Count Overflow */ -#define kIntRegRcvInt 0x02 /* - Receive Interrupt */ -#define kIntRegXmtInt 0x01 /* - Transmit Interrupt */ - -/* imr */ -#define kIntMask 0x0090 /* Interrupt Mask Register */ -#define kIntMaskJab 0x80 /* - Mask Jabber Error Int */ -#define kIntMaskBabl 0x40 /* - Mask Babble Error Int */ -#define kIntMaskCErr 0x20 /* - Mask Collision Error Int */ -#define kIntMaskRcvCCO 0x10 /* - Mask Rcv Coll Ctr Overflow Int */ -#define kIntMaskRntPCO 0x08 /* - Mask Runt Packet Ctr Overflow Int */ -#define kIntMaskMPCO 0x04 /* - Mask Missed Pkt Ctr Overflow Int */ -#define kIntMaskRcvInt 0x02 /* - Mask Receive Int */ -#define kIntMaskXmtInt 0x01 /* - Mask Transmit Int */ - -/* pr */ -#define kPollReg 0x00A0 /* Poll Register */ -#define kPollRegXmtSV 0x80 /* - Transmit Status Valid */ -#define kPollRegTDTReq 0x40 /* - Transmit Data Transfer Request */ -#define kPollRegRDTReq 0x20 /* - Receive Data Transfer Request */ - -/* biucc */ -#define kBIUCC 0x00B0 /* BUI Configuration Control */ -#define kBIUCCBSwp 0x40 /* - Byte Swap Enable */ -#define kBIUCCXmtSP 0x30 /* - Transmit Start Point: */ -#define kBIUCCXmtSP04 0x00 /* - 00b = 4 Bytes */ -#define kBIUCCXmtSP16 0x10 /* - 01b = 16 Bytes */ -#define kBIUCCXmtSP64 0x20 /* - 10b = 64 Bytes */ -#define kBIUCCXmtSP112 0x30 /* - 11b = 112 Bytes */ -#define kBIUCCSWRst 0x01 /* Software Reset */ - -/* fifocc */ -#define kFifoCC 0x00C0 /* FIFO Configuration Control */ -#define kFifoCCXmtFW 0xC0 /* - Transmit FIFO Watermark: */ -#define kFifoCCXmtFW08 0x00 /* - 00b = 8 Write Cycles */ -#define kFifoCCXmtFW16 0x40 /* - 01b = 16 Write Cycles */ -#define kFifoCCXmtFW32 0x80 /* - 10b = 32 Write Cycles */ - -#define kFifoCCRcvFW 0x30 /* - Receive FIFO Watermark: */ -#define kFifoCCRcvFW16 0x00 /* - 00b = 16 Bytes */ -#define kFifoCCRcvFW32 0x10 /* - 01b = 32 Bytes */ -#define kFifoCCRcvFW64 0x20 /* - 10b = 64 Bytes */ - -#define kFifoCCXmtFWRst 0x08 /* - Transmit FIFO Watermark Reset */ -#define kFifoCCRcvFWRst 0x04 /* - Receive FIFO Watermark Reset */ -#define kFifoCCXmtBRst 0x02 /* - Transmit Burst Enable */ -#define kFifoCCRcvBRst 0x01 /* - Receive Burst Enable */ - -/* maccc */ -#define kMacCC 0x00D0 /* MAC Configuration Control */ -#define kMacCCProm 0x80 /* - Promiscuous Mode Enable */ -#define kMacCCDXmt2PD 0x40 /* - Disable Transmit Two Part Deferral */ -#define kMacCCEMBA 0x20 /* - Enable Modified Backoff Algorithm */ -#define kMacCCDRcvPA 0x08 /* - ? */ -#define kMacCCDRcvBC 0x04 /* - ? */ -#define kMacCCEnXmt 0x02 /* - Transmit Enable */ -#define kMacCCEnRcv 0x01 /* - Receive Enable */ - -/* plscc */ -#define kPLSCC 0x00E0 /* PLS Configuration Control */ -#define kPLSCCXmtSel 0x08 /* - Transmit Mode Select */ -#define kPLSCCPortSel 0x06 /* - Port Select: */ -#define kPLSCCPortSelAUI 0x00 /* - 00b = AUI */ -#define kPLSCCPortSelTenBase 0x02 /* - 01b = 10BaseT */ -#define kPLSCCPortSelDAI 0x04 /* - 10b = DAI */ -#define kPLSCCPortSelGPSI 0x06 /* - 11b = GPSI */ -#define kPLSCCEnSts 0x01 /* - Enable Status */ - -/* phycc */ -#define kPHYCC 0x00F0 /* PHY Configuration Control */ -#define kPHYCCLnkFL 0x80 /* - ? */ -#define kPHYCCDLnkTst 0x40 /* - ? */ -#define kPHYCCRcvPol 0x20 /* - ? */ -#define kPHYCCDAPC 0x10 /* - ? */ -#define kPHYCCLRT 0x08 /* - ? */ -#define kPHYCCASel 0x04 /* - ? */ -#define kPHYCCRWake 0x02 /* - ? */ -#define kPHYCCAWake 0x01 /* - ? */ - -#define kMaceChipId0 0x0100 /* MACE Chip ID Register (7:0) */ -#define kMaceChipId1 0x0110 /* MACE Chip ID Register (15:8) */ - -/* iac */ -#define kIAC 0x0120 /* Internal Address Configuration */ -#define kIACAddrChg 0x80 /* - ? */ -#define kIACPhyAddr 0x04 /* - Physical Address Reset */ -#define kIACLogAddr 0x02 /* - Logical Address Reset */ - - -/* ladrf */ -#define kLADRF 0x0140 /* Logical Address Filter - 8 Bytes */ - -/* padr */ -#define kPADR 0x0150 /* Physical Address Filter - 6 Bytes */ - -/* kMPC */ -#define kMPC 0x0180 /* Missed Packet Count */ - -/* utr */ -#define kUTR 0x01D0 /* User Test Register */ -#define kUTRRTRE 0x80 /* - Reserved Test Register Enable */ -#define kUTRRTRD 0x40 /* - Reserved Test Register Disable */ -#define kUTRRPA 0x20 /* - Runt Packet Accept */ -#define kUTRFColl 0x10 /* - Force Collision */ -#define kUTRRcvFCS 0x08 /* - Receive FCS Enable */ - -#define kUTRLoop 0x06 /* - Loopback Control: */ -#define kUTRLoopNone 0x00 /* - 00b = None */ -#define kUTRLoopExt 0x02 /* - 01b = External */ -#define kUTRLoopInt 0x04 /* - 10b = Internal (excludes MENDEC) */ -#define kUTRLoopIntM 0x06 /* - 11b = Internal (includes MENDEC) */ - - -#define TX_RING_LENGTH (32+1) -#define RX_RING_LENGTH (32+1) - -#define NETWORK_BUFSIZE (ETHERMAXPACKET + ETHERCRC + 8) -#define TRANSMIT_QUEUE_SIZE 128 - -#define WATCHDOG_TIMER_MS 500 -#define TX_KDB_TIMEOUT 1000 - -#define TRANSMIT_QUIESCE_uS 200 -#define RECEIVE_QUIESCE_uS 1500 - -enum -{ - kIRQEnetDev = 0, - kIRQEnetTxDMA = 1, - kIRQEnetRxDMA = 2 -}; - -enum -{ - MEMORY_MAP_ENET_INDEX = 0, - MEMORY_MAP_TXDMA_INDEX = 1, - MEMORY_MAP_RXDMA_INDEX = 2, - MEMORY_MAP_COUNT = 3 -}; - -#endif /* !_MACEENETREGISTERS_H */ diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp b/iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp deleted file mode 100644 index c164a2ebd..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp +++ /dev/null @@ -1,1199 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Hardware independent (relatively) code for the BMac Ethernet Controller - * - * HISTORY - * - * dd-mmm-yy - * Created. - * - * Dec 10, 1998 jliu - * Converted to IOKit/C++. - */ - -#include "BMacEnet.h" -#include "BMacEnetPrivate.h" - -#include <IOKit/IORegistryEntry.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/platform/AppleMacIODevice.h> -#include <IOKit/assert.h> - -// #define DEBUG_JOE 1 - -//------------------------------------------------------------------------ - -#define super IOEthernetController - -OSDefineMetaClassAndStructors( BMacEnet, IOEthernetController ) - -//------------------------------------------------------------------------ - -#define PROVIDER_DEV 0 -#define PROVIDER_DMA_TX 1 -#define PROVIDER_DMA_RX 2 - -/* - * Public Instance Methods - */ - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::init(OSDictionary * properties = 0) -{ - if ( super::init(properties) == false ) - return false; - - /* - * Initialize my ivars. - */ - phyId = 0xff; - phyMIIDelay = MII_DEFAULT_DELAY; - sromAddressBits = 6; - enetAddressOffset = 20; - phyStatusPrev = 0; - - return true; -} - -bool BMacEnet::start(IOService * provider) -{ - AppleMacIODevice *nub = OSDynamicCast(AppleMacIODevice, provider); - IOInterruptEventSource *intES; - - if (!nub || !super::start(provider)) - return false; - - transmitQueue = OSDynamicCast(IOGatedOutputQueue, getOutputQueue()); - if (!transmitQueue) { - IOLog("BMac: output queue initialization failed\n"); - return false; - } - transmitQueue->retain(); - - // Allocate debug queue. This stores packets retired from the TX ring - // by the polling routine. We cannot call freePacket() or m_free() within - // the debugger context. - // - // The capacity of the queue is set at maximum to prevent the queue from - // calling m_free() due to over-capacity. But we don't expect the size - // of the queue to grow too large. - // - debugQueue = IOPacketQueue::withCapacity((UInt) -1); - if (!debugQueue) - return false; - - // Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum - // number of segments is set to 2. The maximum length for each segment - // is set to the maximum ethernet frame size (plus padding). - - mbufCursor = IOMbufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 2); - if (!mbufCursor) { - IOLog("Ethernet(BMac): IOMbufBigMemoryCursor allocation failure\n"); - return false; - } - - // - // Our provider is the nub representing the BMacEnet hardware - // controller. We will query it for our resource information. - // - - for (int i = 0; i < MEMORY_MAP_HEATHROW_INDEX; i++) { - IOMemoryMap * map; - - map = provider->mapDeviceMemoryWithIndex(i); - if (!map) - return false; -#ifdef DEBUG_JOE - IOLog("map %d: Phys:%08x Virt:%08x len:%d\n", - i, - (unsigned) map->getPhysicalAddress(), - (unsigned) map->getVirtualAddress(), - (unsigned) map->getLength()); -#endif DEBUG_JOE - - switch (i) { - case MEMORY_MAP_ENET_INDEX: - ioBaseEnet = (IOPPCAddress) map->getVirtualAddress(); - break; - - case MEMORY_MAP_TXDMA_INDEX: - ioBaseEnetTxDMA = (IODBDMAChannelRegisters *) - map->getVirtualAddress(); - break; - - case MEMORY_MAP_RXDMA_INDEX: - ioBaseEnetRxDMA = (IODBDMAChannelRegisters *) - map->getVirtualAddress(); - break; - } - - maps[i] = map; - } - -#ifdef DEBUG_JOE - IOLog("ioBaseEnet: 0x%08x\n", ioBaseEnet); - IOLog("ioBaseEnetTxDMA: 0x%08x\n", ioBaseEnetTxDMA); - IOLog("ioBaseEnetRxDMA: 0x%08x\n", ioBaseEnetRxDMA); -#endif DEBUG_JOE - - // - // We need to get the I/O address for the Heathrow controller. - // We ask the provider (bmac) for its device tree parent. - // - IOService *heathrow; - if (!(heathrow = OSDynamicCast(IOService, - provider->getParentEntry( gIODTPlane )))) - return false; - - // Check whether the hardware is susceptible to the broken unicast - // filter problem. - // - OSData * devIDData; - devIDData = OSDynamicCast(OSData, heathrow->getProperty("device-id")); - - if (devIDData) { - useUnicastFilter = ( *((UInt32 *) devIDData->getBytesNoCopy()) == - 0x10 ); - if (useUnicastFilter) - IOLog("%s: Enabling workaround for broken unicast filter\n", - getName()); - } - - IOMemoryMap * map = heathrow->mapDeviceMemoryWithIndex(0); - if (map) - { -#ifdef DEBUG_JOE - IOLog("Heathrow: Phys:%08x Virt:%08x len:%d\n", - (unsigned) map->getPhysicalAddress(), - (unsigned) map->getVirtualAddress(), - (unsigned) map->getLength()); -#endif DEBUG_JOE - ioBaseHeathrow = (IOPPCAddress) map->getVirtualAddress(); - - maps[MEMORY_MAP_HEATHROW_INDEX] = map; - } - else { - return false; - } - - // - // Get a reference to the IOWorkLoop in our superclass. - // - IOWorkLoop * myWorkLoop = getWorkLoop(); - assert(myWorkLoop); - - // - // Allocate three IOInterruptEventSources. - // - rxIntSrc = IOInterruptEventSource::interruptEventSource - (this, - (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource, - provider, PROVIDER_DMA_RX); - if (!rxIntSrc - || (myWorkLoop->addEventSource(rxIntSrc) != kIOReturnSuccess)) { - IOLog("Ethernet(BMac): rxIntSrc init failure\n"); - return false; - } - - intES = IOInterruptEventSource::interruptEventSource - (this, - (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource, - provider, PROVIDER_DMA_TX); - if (intES) { - bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess); - intES->release(); - if (res) { - IOLog("Ethernet(BMac): PROVIDER_DMA_TX add failure\n"); - return false; - } - } - else { - IOLog("Mace: PROVIDER_DMA_TX init failure\n"); - return false; - } - - intES = IOInterruptEventSource::interruptEventSource - (this, - (IOInterruptEventAction) &BMacEnet::interruptOccurredForSource, - provider, PROVIDER_DEV); - if (intES) { - bool res = (myWorkLoop->addEventSource(intES) != kIOReturnSuccess); - intES->release(); - if (res) { - IOLog("Ethernet(BMac): PROVIDER_DEV add failure\n"); - return false; - } - } - else { - IOLog("Ethernet(BMac): PROVIDER_DEV init failure\n"); - return false; - } - - timerSrc = IOTimerEventSource::timerEventSource - (this, (IOTimerEventSource::Action) &BMacEnet::timeoutOccurred); - if (!timerSrc - || (myWorkLoop->addEventSource(timerSrc) != kIOReturnSuccess)) { - IOLog("Ethernet(BMac): timerSrc init failure\n"); - return false; - } - - MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA); - if (!txDebuggerPkt) { - IOLog("Ethernet(BMac): Couldn't allocate KDB buffer\n"); - return false; - } - -#if 0 - // Enable the interrupt event sources. The hardware interrupts - // sources remain disabled until _resetAndEnable(true) is called. - // - // myWorkLoop->enableAllInterrupts(); -#endif - - // Perform a hardware reset. - // - if ( !_resetAndEnable(false) ) - { - return false; - } - - // Cache my MAC address. - // - getHardwareAddress(&myAddress); - - // Allocate memory for ring buffers. - // - if (_allocateMemory() == false) - { - return false; - } - - // Create a table of supported media types. - // - if ( !createMediumTables() ) - return false; - - // Attach an IOEthernetInterface client. - // - if ( !attachInterface((IONetworkInterface **) &networkInterface, false) ) - return false; - - // Attach a kernel debugger client. - // - attachDebuggerClient(&debugger); - - // Ready to service interface requests. - // - networkInterface->registerService(); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::free() -{ - UInt i; - - _resetAndEnable(false); - - if (debugger) - debugger->release(); - - if (getWorkLoop()) - getWorkLoop()->disableAllEventSources(); - - if (timerSrc) - timerSrc->release(); - - if (rxIntSrc) - rxIntSrc->release(); - - if (txDebuggerPkt) - freePacket(txDebuggerPkt); - - if (transmitQueue) - transmitQueue->release(); - - if (debugQueue) - debugQueue->release(); - - if (networkInterface) - networkInterface->release(); - - if (mbufCursor) - mbufCursor->release(); - - if ( mediumDict ) - mediumDict->release(); - - for (i = 0; i < rxMaxCommand; i++) - if (rxMbuf[i]) freePacket(rxMbuf[i]); - - for (i = 0; i < txMaxCommand; i++) - if (txMbuf[i]) freePacket(txMbuf[i]); - - for (i = 0; i < MEMORY_MAP_COUNT; i++) - if (maps[i]) maps[i]->release(); - - if (dmaMemory.ptr) - { - IOFree(dmaMemory.ptrReal, dmaMemory.sizeReal); - dmaMemory.ptr = 0; - } - - if ( workLoop ) - { - workLoop->release(); - workLoop = 0; - } - - super::free(); -} - -/*------------------------------------------------------------------------- - * Override IONetworkController::createWorkLoop() method and create - * a workloop. - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::createWorkLoop() -{ - workLoop = IOWorkLoop::workLoop(); - - return ( workLoop != 0 ); -} - -/*------------------------------------------------------------------------- - * Override IOService::getWorkLoop() method to return our workloop. - * - * - *-------------------------------------------------------------------------*/ - -IOWorkLoop * BMacEnet::getWorkLoop() const -{ - return workLoop; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::interruptOccurredForSource(IOInterruptEventSource *src, - int /*count*/) -{ - bool doFlushQueue = false; - bool doService = false; - - reserveDebuggerLock(); - - statReg = ReadBigMacRegister( ioBaseEnet, kSTAT ); - - if (src == rxIntSrc) { - KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doFlushQueue = _receiveInterruptOccurred(); - KERNEL_DEBUG(DBG_BMAC_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - } - else { - /* - * On the transmit side, we use the chipset interrupt. Using the - * transmit DMA interrupt (or having multiple transmit DMA entries) - * would allows us to send the next frame to the chipset prior the - * transmit fifo going empty. - * However, this aggrevates a BMac chipset bug where the next frame going - * out gets corrupted (first two bytes lost) if the chipset had to retry - * the previous frame. - */ - txWDInterrupts++; - KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doService = _transmitInterruptOccurred(); - KERNEL_DEBUG(DBG_BMAC_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - } - - releaseDebuggerLock(); - - /* - * Submit all received packets queued up by _receiveInterruptOccurred() - * to the network stack. The up call is performed without holding the - * debugger lock. - */ - if ( doFlushQueue ) - networkInterface->flushInputQueue(); - - /* - * Unstall the output queue if some space was made available. - */ - if ( doService && netifEnabled ) - transmitQueue->service(); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -UInt32 BMacEnet::outputPacket(struct mbuf * pkt, void * param) -{ - u_int32_t i; - UInt32 ret = kIOReturnOutputSuccess; - - KERNEL_DEBUG(DBG_BMAC_TXQUEUE | DBG_FUNC_NONE, (int) pkt, - (int) pkt->m_pkthdr.len, 0, 0, 0 ); - - /* - * Hold the debugger lock so the debugger can't interrupt us - */ - reserveDebuggerLock(); - - do - { - /* - * Preliminary sanity checks - */ - assert( pkt && netifEnabled ); - -#if 0 - /* - * Remove any completed packets from the Tx ring - */ - if ( chipId >= kCHIPID_PaddingtonXmitStreaming ) - { - _transmitInterruptOccurred(); - } -#endif - - i = txCommandTail + 1; - if ( i >= txMaxCommand ) i = 0; - if ( i == txCommandHead ) - { - /* - * Ring buffer is full. Disable the dequeueing process. - * We reenable it when an entry is made available by the - * transmit interrupt handler, or if a timeout occurs. - */ - ret = kIOReturnOutputStall; - continue; - } - - /* - * If there is space on the Tx ring, add the packet directly to the - * ring. - */ - _transmitPacket(pkt); - } - while ( 0 ); - - releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_resetAndEnable(bool enable) -{ - bool ret = true; - -// reserveDebuggerLock(); - - ready = false; - - if (timerSrc) timerSrc->cancelTimeout(); - - _disableAdapterInterrupts(); - if (getWorkLoop()) getWorkLoop()->disableAllInterrupts(); - - if (enable) - { - phyId = 0xff; - } - - _resetChip(); - - // Initialize the link status. - - phyStatusPrev = 0; - setLinkStatus( 0, 0 ); - - while (enable) - { - if (!_initRxRing() || !_initTxRing()) - { - ret = false; - break; - } - - if ( phyId != 0xff ) - { - miiInitializePHY(phyId); - } - - if (_initChip() == false) - { - ret = false; - break; - } - - _startChip(); - - timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); - - if (getWorkLoop()) getWorkLoop()->enableAllInterrupts(); - _enableAdapterInterrupts(); - - ready = true; - - _sendDummyPacket(); - - monitorLinkStatus( true ); - - break; - } - -// releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * Grab a pointer to the statistics counters. - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::configureInterface( IONetworkInterface * netif ) -{ - IONetworkData * nd; - - if ( super::configureInterface( netif ) == false ) - return false; - - /* - * Grab a pointer to the statistics structure in the interface. - */ - nd = netif->getNetworkData( kIONetworkStatsKey ); - - if ( !nd || !(netStats = (IONetworkStats *) nd->getBuffer()) ) - { - IOLog("EtherNet(BMac): invalid network statistics\n"); - return false; - } - - return true; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to enable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::enable(IONetworkInterface * netif) -{ - // If an interface client has previously enabled us, - // and we know there can only be one interface client - // for this driver, then simply return true. - // - if ( netifEnabled ) - { - IOLog("EtherNet(BMac): already enabled\n"); - return kIOReturnSuccess; - } - - if ( (ready == false) && !_resetAndEnable(true) ) - return kIOReturnIOError; - - // Record the interface as an active client. - // - netifEnabled = true; - - // Start our IOOutputQueue object. - // - transmitQueue->setCapacity(TRANSMIT_QUEUE_SIZE); - transmitQueue->start(); - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to disable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::disable(IONetworkInterface * /*netif*/) -{ - // Disable our IOOutputQueue object. This will prevent the - // outputPacket() method from being called. - // - transmitQueue->stop(); - - // Flush all packets currently in the output queue. - // - transmitQueue->setCapacity(0); - transmitQueue->flush(); - - // If we have no active clients, then disable the controller. - // - if ( debugEnabled == false ) - { - _resetAndEnable(false); - } - - netifEnabled = false; - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to bring up the controller - * just before the controller is registered as the debugger device. The - * debugger client is attached in response to the attachDebuggerClient() - * call. - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::enable(IOKernelDebugger *debugger) -{ - // Enable hardware and make it ready to support the debugger client. - // - if ( (ready == false) && !_resetAndEnable(true) ) - { - return kIOReturnIOError; - } - - // Record the debugger as an active client of ours. - // - debugEnabled = true; - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to stop the controller. - * The debugger will call this method when we issue a detachDebuggerClient(). - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::disable(IOKernelDebugger * /*debugger*/) -{ - debugEnabled = false; - - // If we have no active clients, then disable the controller. - // - if ( netifEnabled == false ) - { - _resetAndEnable(false); - } - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::timeoutOccurred(IOTimerEventSource * /*timer*/) -{ - u_int32_t dmaStatus; - bool doFlushQueue = false; - bool doService = false; - - if ( ready == false ) - { - return; - } - - // IOLog("Ethernet(BMac): watchdog timer\n"); - - reserveDebuggerLock(); - - /* - * Check for DMA shutdown on receive channel - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); - if ( !(dmaStatus & kdbdmaActive) ) - { -#if 0 - IOLog( "Ethernet(BMac): Timeout check - RxHead = %d RxTail = %d\n", - rxCommandHead, rxCommandTail); - - IOLog( "Ethernet(BMac): Rx Commands = %08x(p) Rx DMA Ptr = %08x(p)\n\r", rxDMACommandsPhys, IOGetDBDMACommandPtr(ioBaseEnetRxDMA) ); - [self _dumpDesc:(void *)rxDMACommands Size:rxMaxCommand * sizeof(enet_dma_cmd_t)]; -#endif - - doFlushQueue = _receiveInterruptOccurred(); - } - - /* - * If there are pending entries on the Tx ring - */ - if ( txCommandHead != txCommandTail ) - { - /* - * If we did not service the Tx ring during the last timeout interval, - * then force servicing of the Tx ring - */ - if ( txWDInterrupts == 0 ) - { - if ( txWDCount++ > 0 ) - { - if (_transmitInterruptOccurred() == false) - { -#if 0 - IOLog( "Ethernet(BMac): Timeout check - TxHead = %d TxTail = %d\n", - txCommandHead, txCommandTail); -#endif - _restartTransmitter(); - } - doService = true; - } - } - else - { - txWDInterrupts = 0; - txWDCount = 0; - } - } - else - { - txWDInterrupts = 0; - txWDCount = 0; - } - - // Poll link status periodically. - - monitorLinkStatus(); - - // Clean-up after the debugger if the debugger was active. - // - if ( debugTxPoll ) - { - debugQueue->flush(); - debugTxPoll = false; - doService = true; - } - - releaseDebuggerLock(); - - /* - * Submit all received packets queued up by _receiveInterruptOccurred() - * to the network stack. This call is performed without holding the - * debugger lock. - */ - if ( doFlushQueue ) - { - networkInterface->flushInputQueue(); - } - - /* - * Make sure the output queue is not stalled. - */ - if ( doService && netifEnabled ) - { - transmitQueue->service(); - } - - /* - * Restart the watchdog timer - */ - timerSrc->setTimeoutMS(WATCHDOG_TIMER_MS); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::monitorLinkStatus( bool firstPoll ) -{ - u_int16_t phyStatus; - u_int16_t phyReg; - u_int16_t phyStatusChange; - bool fullDuplex; - bool reportLinkStatus = false; - UInt32 linkSpeed; - UInt32 linkStatus; - - if ( phyId == 0xff ) - { - // For implementations without a PHY, query the link status bit from - // the transceiver control register (kXCVRIF). - - phyStatus = ReadBigMacRegister(ioBaseEnet, kXCVRIF); - - if ( ( ( phyStatus ^ phyStatusPrev ) & kLinkStatus ) || firstPoll ) - { - linkStatus = kIONetworkLinkValid; - linkSpeed = 0; - fullDuplex = false; - reportLinkStatus = true; - - if ( ( phyStatus & kLinkStatus ) == 0 ) - { - linkSpeed = 10; - linkStatus |= kIONetworkLinkActive; - } - - phyStatusPrev = phyStatus; - } - } - else if ( miiReadWord(&phyStatus, MII_STATUS, phyId) == true ) - { - phyStatusChange = ( phyStatusPrev ^ phyStatus ) & - ( MII_STATUS_LINK_STATUS | - MII_STATUS_NEGOTIATION_COMPLETE); - - if ( phyStatusChange || firstPoll ) - { - if ( firstPoll ) - { - // For the initial link status poll, wait a bit, then - // re-read the status register to clear any latched bits. - // Why wait? Well, the debugger can kick in shortly after - // this function returns, and we want the duplex setting - // on the MAC to match the PHY. - - miiWaitForAutoNegotiation( phyId ); - miiReadWord(&phyStatus, MII_STATUS, phyId); - miiReadWord(&phyStatus, MII_STATUS, phyId); - } - - if ( (phyStatus & MII_STATUS_LINK_STATUS) && - (firstPoll || (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE)) ) - { - if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID ) - { - miiReadWord(&phyReg, MII_ST10040_CHIPST, phyId); - linkSpeed = (phyReg & MII_ST10040_CHIPST_SPEED) ? - 100 : 10; - fullDuplex = (phyReg & MII_ST10040_CHIPST_DUPLEX) ? - true : false; - } - else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID ) - { - miiReadWord(&phyReg, MII_DP83843_PHYSTS, phyId); - linkSpeed = (phyReg & MII_DP83843_PHYSTS_SPEED10) ? - 10 : 100; - fullDuplex = (phyReg & MII_DP83843_PHYSTS_DUPLEX) ? - true : false; - } - else - { - linkSpeed = 0; - fullDuplex = false; - } - - if ( fullDuplex != isFullDuplex ) - { - _setDuplexMode(fullDuplex); - } - - linkStatus = kIONetworkLinkActive | kIONetworkLinkValid; - } - else - { - linkStatus = kIONetworkLinkValid; - linkSpeed = 0; - fullDuplex = false; - } - - reportLinkStatus = true; - phyStatusPrev = phyStatus; - } - } - - if ( reportLinkStatus ) - { - IONetworkMedium * medium; - IOMediumType mediumType; - - switch ( linkSpeed ) - { - case 10: - mediumType = kIOMediumEthernet10BaseT; - mediumType |= (fullDuplex == true) ? - kIOMediumOptionFullDuplex : - kIOMediumOptionHalfDuplex; - break; - case 100: - mediumType = kIOMediumEthernet100BaseTX; - mediumType |= (fullDuplex == true) ? - kIOMediumOptionFullDuplex : - kIOMediumOptionHalfDuplex; - break; - default: - mediumType = kIOMediumEthernetNone; - break; - } - - medium = IONetworkMedium::getMediumWithType(mediumDict, mediumType); - - setLinkStatus( linkStatus, medium, linkSpeed * 1000000 ); - - if ( linkStatus & kIONetworkLinkActive ) - IOLog( "Ethernet(BMac): Link up at %ld Mbps - %s Duplex\n", - linkSpeed, (fullDuplex) ? "Full" : "Half" ); - else - IOLog( "Ethernet(BMac): Link down\n" ); - } -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -const OSString * BMacEnet::newVendorString() const -{ - return OSString::withCString("Apple"); -} - -const OSString * BMacEnet::newModelString() const -{ - return OSString::withCString("BMac"); -} - -const OSString * BMacEnet::newRevisionString() const -{ - return OSString::withCString(""); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - u_int16_t rxCFGVal; - - reserveDebuggerLock(); - - /* - * Turn off the receiver and wait for the chipset to acknowledge - */ - rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG); - WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable ); - while( ReadBigMacRegister(ioBaseEnet, kRXCFG) & kRxMACEnable ) - ; - - /* - * Set or reset promiscuous mode and restore receiver state - */ - if (mode == kIOEnetPromiscuousModeOff) { - rxCFGVal &= ~kRxPromiscEnable; - isPromiscuous = false; - } - else { - rxCFGVal |= kRxPromiscEnable; - isPromiscuous = true; - } - - WriteBigMacRegister( ioBaseEnet, kRXCFG, rxCFGVal ); - - releaseDebuggerLock(); - - return kIOReturnSuccess; -} - -IOReturn BMacEnet::setMulticastMode(IOEnetMulticastMode mode) -{ - multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; - - return kIOReturnSuccess; -} - -IOReturn BMacEnet::setMulticastList(IOEthernetAddress *addrs, UInt32 count) -{ - reserveDebuggerLock(); - _resetHashTableMask(); - for (UInt32 i = 0; i < count; i++) { - _addToHashTableMask(addrs->bytes); - addrs++; - } - _updateBMacHashTableMask(); - releaseDebuggerLock(); - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -static struct MediumTable -{ - UInt32 type; - UInt32 speed; -} -mediumTable[] = -{ - { kIOMediumEthernetNone , 0 }, - { kIOMediumEthernetAuto , 0 }, - { kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10 }, - { kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10 }, - { kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100 }, - { kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100 }, -}; - - -bool BMacEnet::createMediumTables() -{ - IONetworkMedium *medium; - UInt32 i; - - mediumDict = OSDictionary::withCapacity( sizeof(mediumTable)/sizeof(mediumTable[0]) ); - if ( mediumDict == 0 ) return false; - - for ( i=0; i < sizeof(mediumTable)/sizeof(mediumTable[0]); i++ ) - { - medium = IONetworkMedium::medium( mediumTable[i].type, mediumTable[i].speed ); - if ( medium != 0 ) - { - IONetworkMedium::addMedium( mediumDict, medium ); - medium->release(); - } - } - - if ( publishMediumDictionary( mediumDict ) != true ) - { - return false; - } - - medium = IONetworkMedium::getMediumWithType( mediumDict, - kIOMediumEthernetAuto ); - - setCurrentMedium( medium ); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -/* - * Kernel Debugger Support - */ -void BMacEnet::sendPacket( void * pkt, UInt32 pkt_len ) -{ - _sendPacket(pkt, pkt_len); -} - -void BMacEnet::receivePacket( void * pkt, - UInt32 * pkt_len, - UInt32 timeout ) -{ - _receivePacket(pkt, (UInt *) pkt_len, timeout); -} - -/* - * Create a WorkLoop serialized output queue object. - */ -IOOutputQueue * BMacEnet::createOutputQueue() -{ - return IOGatedOutputQueue::withTarget( this, - getWorkLoop(), - TRANSMIT_QUEUE_SIZE ); -} - -/* - * Power management methods. - */ - -IOReturn BMacEnet::registerWithPolicyMaker(IOService * policyMaker) -{ -#define number_of_power_states 2 - - static IOPMPowerState ourPowerStates[number_of_power_states] = { - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable,IOPMPowerOn,IOPMPowerOn,0,0,0,0,0,0,0,0} - }; - - currentPowerState = 1; - - return policyMaker->registerPowerDriver( this, - ourPowerStates, - number_of_power_states ); -} - -IOReturn BMacEnet::setPowerState( unsigned long powerStateOrdinal, - IOService * whatDevice ) -{ - IOReturn ret = IOPMAckImplied; - - // kprintf("Ethernet(BMac): setPowerState %d\n", powerStateOrdinal); - - if ( currentPowerState == powerStateOrdinal ) - return IOPMAckImplied; - - switch ( powerStateOrdinal ) - { - case 0: - kprintf("Ethernet(BMac): powering off\n"); - currentPowerState = powerStateOrdinal; - break; - - case 1: - kprintf("Ethernet(BMac): powering on\n"); - currentPowerState = powerStateOrdinal; - break; - - default: - ret = IOPMNoSuchState; - break; - } - - return ret; -} diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnet.h b/iokit/Drivers/network/drvPPCBMac/BMacEnet.h deleted file mode 100644 index d1cda0c95..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnet.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Interface definition for the BMac Ethernet Controller - * - * HISTORY - * - * Dec 10, 1998 jliu - * Converted to IOKit/C++. - */ - -#ifndef _BMACENET_H -#define _BMACENET_H - -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IOGatedOutputQueue.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/network/IOMbufMemoryCursor.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/ppc/IODBDMA.h> -#include <string.h> /* bcopy */ -#include "BMacEnetRegisters.h" - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -} - -// No kernel tracing support at this time. -// -#define KERNEL_DEBUG(x,a,b,c,d,e) - -// #define IOLog kprintf - -typedef void * IOPPCAddress; - -typedef struct enet_dma_cmd_t -{ - IODBDMADescriptor desc_seg[2]; -} enet_dma_cmd_t; - -typedef struct enet_txdma_cmd_t -{ - IODBDMADescriptor desc_seg[3]; -} enet_txdma_cmd_t; - -class BMacEnet : public IOEthernetController -{ - OSDeclareDefaultStructors( BMacEnet ) - -private: - volatile IOPPCAddress ioBaseEnet; - volatile IOPPCAddress ioBaseHeathrow; - volatile IODBDMAChannelRegisters * ioBaseEnetRxDMA; - volatile IODBDMAChannelRegisters * ioBaseEnetTxDMA; - - IOEthernetAddress myAddress; - IOEthernetInterface * networkInterface; - IOGatedOutputQueue * transmitQueue; - IOPacketQueue * debugQueue; - IOKernelDebugger * debugger; - bool isPromiscuous; - bool multicastEnabled; - bool isFullDuplex; - - IOWorkLoop * workLoop; - IOInterruptEventSource * rxIntSrc; - IOMemoryMap * maps[MEMORY_MAP_COUNT]; - IONetworkStats * netStats; - IOTimerEventSource * timerSrc; - IOMbufBigMemoryCursor * mbufCursor; - - bool ready; - bool netifEnabled; - bool debugEnabled; - bool debugTxPoll; - bool useUnicastFilter; - unsigned int enetAddressOffset; - - unsigned long chipId; - - unsigned long phyType; - unsigned long phyMIIDelay; - - unsigned char phyId; - unsigned char sromAddressBits; - - unsigned short phyStatusPrev; - - OSDictionary * mediumDict; - - struct mbuf * txMbuf[TX_RING_LENGTH]; - struct mbuf * rxMbuf[RX_RING_LENGTH]; - struct mbuf * txDebuggerPkt; - - unsigned int txCommandHead; // TX ring descriptor index - unsigned int txCommandTail; - unsigned int txMaxCommand; - unsigned int rxCommandHead; // RX ring descriptor index - unsigned int rxCommandTail; - unsigned int rxMaxCommand; - - struct { - void * ptr; - u_int size; - void * ptrReal; - u_int sizeReal; - } dmaMemory; - - unsigned char * dmaCommands; - enet_txdma_cmd_t * txDMACommands; // TX descriptor ring ptr - unsigned int txDMACommandsPhys; - - enet_dma_cmd_t * rxDMACommands; // RX descriptor ring ptr - unsigned int rxDMACommandsPhys; - - u_int32_t txWDInterrupts; - u_int32_t txWDCount; - - void * debuggerPkt; - u_int32_t debuggerPktSize; - - u_int16_t statReg; // Current STAT register contents - - u_int16_t hashTableUseCount[64]; - u_int16_t hashTableMask[4]; - - unsigned long currentPowerState; - - bool _allocateMemory(); - bool _initTxRing(); - bool _initRxRing(); - bool _initChip(); - void _resetChip(); - void _disableAdapterInterrupts(); - void _enableAdapterInterrupts(); - void _setDuplexMode(bool duplexMode); - void _startChip(); - bool _updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t * desc, - bool isReceive); - void _restartTransmitter(); - void _stopTransmitDMA(); - bool _transmitPacket(struct mbuf * packet); - bool _transmitInterruptOccurred(); - bool _debugTransmitInterruptOccurred(); - bool _receiveInterruptOccurred(); - bool _rejectBadUnicastPacket(ether_header_t * etherHeader); - bool _receivePackets(bool fDebugger); - void _packetToDebugger(struct mbuf * packet, u_int size); - void _restartReceiver(); - void _stopReceiveDMA(); - bool _resetAndEnable(bool enable); - void _sendDummyPacket(); - void _resetHashTableMask(); - void _addToHashTableMask(u_int8_t * addr); - void _removeFromHashTableMask(u_int8_t * addr); - void _updateBMacHashTableMask(); - bool createMediumTables(); - -#ifdef DEBUG - void _dumpRegisters(); - void _dumpDesc(void * addr, u_int32_t size); - void _dump_srom(); -#endif DEBUG - - void _sendPacket(void * pkt, unsigned int pkt_len); - void _receivePacket(void * pkt, unsigned int * pkt_len, - unsigned int timeout); - - void sendPacket(void * pkt, UInt32 pkt_len); - void receivePacket(void * pkt, UInt32 * pkt_len, - UInt32 timeout); - - bool miiReadWord(unsigned short * dataPtr, unsigned short reg, - unsigned char phy); - bool miiWriteWord(unsigned short data, unsigned short reg, - unsigned char phy); - void miiWrite(unsigned int miiData, unsigned int dataSize); - int miiReadBit(); - bool miiCheckZeroBit(); - void miiOutThreeState(); - bool miiResetPHY(unsigned char phy); - bool miiWaitForLink(unsigned char phy); - bool miiWaitForAutoNegotiation(unsigned char phy); - void miiRestartAutoNegotiation(unsigned char phy); - bool miiFindPHY(unsigned char * phy_num); - bool miiInitializePHY(unsigned char phy); - - UInt32 outputPacket(struct mbuf * m, void * param); - - void interruptOccurredForSource(IOInterruptEventSource * src, int count); - - void timeoutOccurred(IOTimerEventSource * timer); - - void monitorLinkStatus( bool firstPoll = false ); - -public: - virtual bool init(OSDictionary * properties = 0); - virtual bool start(IOService * provider); - virtual void free(); - - virtual bool createWorkLoop(); - virtual IOWorkLoop * getWorkLoop() const; - - virtual IOReturn enable(IONetworkInterface * netif); - virtual IOReturn disable(IONetworkInterface * netif); - - virtual IOReturn getHardwareAddress(IOEthernetAddress * addr); - - virtual IOReturn setMulticastMode(IOEnetMulticastMode mode); - virtual IOReturn setMulticastList(IOEthernetAddress * addrs, UInt32 count); - - virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode); - - virtual IOOutputQueue * createOutputQueue(); - - virtual const OSString * newVendorString() const; - virtual const OSString * newModelString() const; - virtual const OSString * newRevisionString() const; - - virtual IOReturn enable(IOKernelDebugger * debugger); - virtual IOReturn disable(IOKernelDebugger * debugger); - - virtual bool configureInterface(IONetworkInterface * netif); - - // Simple power managment support: - virtual IOReturn setPowerState( UInt32 powerStateOrdinal, - IOService * whatDevice ); - - virtual IOReturn registerWithPolicyMaker(IOService * policyMaker); -}; - -/* - * Performance tracepoints - * - * DBG_BMAC_RXIRQ - Receive ISR run time - * DBG_BMAC_TXIRQ - Transmit ISR run time - * DBG_BMAC_TXQUEUE - Transmit packet passed from network stack - * DBG_BMAC_TXCOMPLETE - Transmit packet sent - * DBG_BMAC_RXCOMPLETE - Receive packet passed to network stack - */ -#define DBG_BMAC_ENET 0x0900 -#define DBG_BMAC_RXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_BMAC_ENET+1)) -#define DBG_BMAC_TXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_BMAC_ENET+2)) -#define DBG_BMAC_TXQUEUE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_BMAC_ENET+3)) -#define DBG_BMAC_TXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_BMAC_ENET+4)) -#define DBG_BMAC_RXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_BMAC_ENET+5)) - -#endif /* !_BMACENET_H */ diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetHW.cpp b/iokit/Drivers/network/drvPPCBMac/BMacEnetHW.cpp deleted file mode 100644 index a64bd544f..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetHW.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Miscellaneous definitions for the BMac Ethernet controller. - * - * HISTORY - * - */ - -#include "BMacEnetRegisters.h" -#include "BMacEnetPrivate.h" -#include <libkern/OSByteOrder.h> - -void WriteBigMacRegister( IOPPCAddress ioBaseEnet, u_int32_t reg_offset, u_int16_t data ) -{ - OSWriteSwapInt16( ioBaseEnet, reg_offset, data ); - eieio(); -} - - -volatile u_int16_t ReadBigMacRegister( IOPPCAddress ioBaseEnet, u_int32_t reg_offset ) -{ - return OSReadSwapInt16( ioBaseEnet, reg_offset ); -} - -/* - * Procedure for reading EEPROM - */ -#define kSROMAddressLength 5 -#define kDataInOn 0x0008 -#define kDataInOff 0x0000 -#define kClk 0x0002 -#define kChipSelect 0x0001 -#define kSDIShiftCount 3 -#define kSD0ShiftCount 2 -#define kDelayValue 1000 // number of microseconds - -#define kSROMStartOffset 10 // this is in words -#define kSROMReadCount 3 // number of words to read from SROM - -static unsigned char clock_out_bit(IOPPCAddress base) -{ - u_int16_t data; - u_int16_t val; - - WriteBigMacRegister(base, kSROMCSR, kChipSelect | kClk); - IODelay(kDelayValue); - - data = ReadBigMacRegister(base, kSROMCSR); - IODelay(kDelayValue); - val = (data >> kSD0ShiftCount) & 1; - - WriteBigMacRegister(base, kSROMCSR, kChipSelect); - IODelay(kDelayValue); - - return val; -} - -static void clock_in_bit(IOPPCAddress base, unsigned int val) -{ - u_int16_t data; - - if (val != 0 && val != 1) - { - IOLog("bogus data in clock_in_bit\n"); - return; - } - - data = (val << kSDIShiftCount); - WriteBigMacRegister(base, kSROMCSR, data | kChipSelect ); - IODelay(kDelayValue); - - WriteBigMacRegister(base, kSROMCSR, data | kChipSelect | kClk ); - IODelay(kDelayValue); - - WriteBigMacRegister(base, kSROMCSR, data | kChipSelect); - IODelay(kDelayValue); -} - -void reset_and_select_srom(IOPPCAddress base) -{ - /* first reset */ - WriteBigMacRegister(base, kSROMCSR, 0); - IODelay(kDelayValue); - - /* send it the read command (110) */ - clock_in_bit(base, 1); - clock_in_bit(base, 1); - clock_in_bit(base, 0); -} - -unsigned short read_srom(IOPPCAddress base, unsigned int addr, - unsigned int addr_len) -{ - unsigned short data, val; - unsigned int i; - - /* send out the address we want to read from */ - for (i = 0; i < addr_len; i++) { - val = addr >> (addr_len-i-1); - clock_in_bit(base, val & 1); - } - - /* Now read in the 16-bit data */ - data = 0; - for (i = 0; i < 16; i++) { - val = clock_out_bit(base); - data <<= 1; - data |= val; - } - WriteBigMacRegister(base, kSROMCSR, 0); - - return data; -} diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp b/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp deleted file mode 100644 index 4f9816368..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * MII/PHY (National Semiconductor DP83840/DP83840A) support methods. - * It is general enough to work with most MII/PHYs. - * - * HISTORY - * - */ - -#include "BMacEnet.h" -#include "BMacEnetPrivate.h" - -/* - * Read from MII/PHY registers. - */ -bool BMacEnet::miiReadWord(unsigned short *dataPtr, unsigned short reg, - unsigned char phy) -{ - int i; - miiFrameUnion frame; - unsigned short phyreg; - bool ret = true; - - do - { - // Write preamble - // - miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE); - - if ( miiCheckZeroBit() == true ) - { -// IOLog("Ethernet(BMac): MII not floating before read\n\r"); - ret = false; - break; - } - - // Prepare command frame - // - frame.data = MII_FRAME_READ; - frame.bit.regad = reg; - frame.bit.phyad = phy; - - // write ST, OP, PHYAD, REGAD in the MII command frame - // - miiWrite(frame.data, 14); - - // Hi-Z state - // Make sure the PHY generated a zero bit after the 2nd Hi-Z bit - // - - miiOutThreeState(); - - if (miiCheckZeroBit() == false) - { -// IOLog("Ethernet(BMac): MII not driven after turnaround\n\r"); - ret = false; - break; - } - - // read 16-bit data - // - phyreg = 0; - for (i = 0; i < 16; i++) - { - phyreg = miiReadBit() | (phyreg << 1); - } - if (dataPtr) - *dataPtr = phyreg; - - // Hi-Z state - miiOutThreeState(); - - if (miiCheckZeroBit() == true) - { -// IOLog("Ethernet(BMac): MII not floating after read\n\r"); - ret = false; - break; - } - } - while ( 0 ); - - return ret; -} - -/* - * Write to MII/PHY registers. - */ -bool BMacEnet::miiWriteWord(unsigned short data, unsigned short reg, - unsigned char phy) -{ - miiFrameUnion frame; - bool ret = true; - - do - { - // Write preamble - // - miiWrite(MII_FRAME_PREAMBLE, MII_FRAME_SIZE); - - if (miiCheckZeroBit() == true) - { - ret = false; - break; - } - - // Prepare command frame - // - frame.data = MII_FRAME_WRITE; - frame.bit.regad = reg; - frame.bit.phyad = phy; - frame.bit.data = data; - - // Write command frame - // - miiWrite(frame.data, MII_FRAME_SIZE); - - // Hi-Z state - miiOutThreeState(); - - if (miiCheckZeroBit() == true) - { - ret = false; - break; - } - } - while ( 0 ); - - return ret; -} - -/* - * Write 'dataSize' number of bits to the MII management interface, - * starting with the most significant bit of 'miiData'. - * - */ -void BMacEnet::miiWrite(unsigned int miiData, unsigned int dataSize) -{ - int i; - u_int16_t regValue; - - regValue = kMIFCSR_DataOutEnable; - - for (i = dataSize; i > 0; i--) - { - int bit = ((miiData & 0x80000000) ? kMIFCSR_DataOut : 0); - - regValue &= ~(kMIFCSR_Clock | kMIFCSR_DataOut) ; - regValue |= bit; - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); - IODelay(phyMIIDelay); - - regValue |= kMIFCSR_Clock; - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue ); - IODelay(phyMIIDelay); - - miiData = miiData << 1; - } -} - -/* - * Read one bit from the MII management interface. - */ -int BMacEnet::miiReadBit() -{ - u_int16_t regValue; - u_int16_t regValueRead; - - regValue = 0; - - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); - IODelay(phyMIIDelay); - - regValue |= kMIFCSR_Clock; - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); - IODelay(phyMIIDelay); - - regValueRead = ReadBigMacRegister(ioBaseEnet, kMIFCSR); - IODelay(phyMIIDelay); // delay next invocation of this routine - - return ( (regValueRead & kMIFCSR_DataIn) ? 1 : 0 ); -} - -/* - * Read the zero bit on the second clock of the turn-around (TA) - * when reading a PHY register. - */ -bool BMacEnet::miiCheckZeroBit() -{ - u_int16_t regValue; - - regValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR); - - return (((regValue & kMIFCSR_DataIn) == 0) ? true : false ); -} - -/* - * Tri-state the STA's MDIO pin. - */ -void BMacEnet::miiOutThreeState() -{ - u_int16_t regValue; - - regValue = 0; - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); - IODelay(phyMIIDelay); - - regValue |= kMIFCSR_Clock; - WriteBigMacRegister(ioBaseEnet, kMIFCSR, regValue); - IODelay(phyMIIDelay); -} - -bool BMacEnet::miiResetPHY(unsigned char phy) -{ - int i = MII_RESET_TIMEOUT; - unsigned short mii_control; - - // Set the reset bit - // - miiWriteWord(MII_CONTROL_RESET, MII_CONTROL, phy); - - IOSleep(MII_RESET_DELAY); - - // Wait till reset process is complete (MII_CONTROL_RESET returns to zero) - // - while (i > 0) - { - if (miiReadWord(&mii_control, MII_CONTROL, phy) == false) - return false; - - if (!(mii_control & MII_CONTROL_RESET)) - { - miiReadWord(&mii_control, MII_CONTROL, phy); - mii_control &= ~MII_CONTROL_ISOLATE; - miiWriteWord(mii_control, MII_CONTROL, phy); - return true; - } - - IOSleep(MII_RESET_DELAY); - i -= MII_RESET_DELAY; - } - return false; -} - -bool BMacEnet::miiWaitForLink(unsigned char phy) -{ - int i = MII_LINK_TIMEOUT; - unsigned short mii_status; - - while (i > 0) - { - if (miiReadWord(&mii_status, MII_STATUS, phy) == false) - return false; - - if (mii_status & MII_STATUS_LINK_STATUS) - return true; - - IOSleep(MII_LINK_DELAY); - i -= MII_LINK_DELAY; - } - return false; -} - -bool BMacEnet::miiWaitForAutoNegotiation(unsigned char phy) -{ - int i = MII_LINK_TIMEOUT; - unsigned short mii_status; - - while (i > 0) - { - if (miiReadWord(&mii_status, MII_STATUS, phy) == false) - return false; - - if (mii_status & MII_STATUS_NEGOTIATION_COMPLETE) - return true; - - IOSleep(MII_LINK_DELAY); - i -= MII_LINK_DELAY; - } - return false; -} - -void BMacEnet::miiRestartAutoNegotiation(unsigned char phy) -{ - unsigned short mii_control; - - miiReadWord(&mii_control, MII_CONTROL, phy); - mii_control |= MII_CONTROL_RESTART_NEGOTIATION; - miiWriteWord(mii_control, MII_CONTROL, phy); - - /* - * If the system is not connected to the network, then auto-negotiation - * never completes and we hang in this loop! - */ -#if 0 - while (1) - { - miiReadWord(&mii_control, MII_CONTROL, phy); - if ((mii_control & MII_CONTROL_RESTART_NEGOTIATION) == 0) - break; - } -#endif -} - -/* - * Find the first PHY device on the MII interface. - * - * Return - * true PHY found - * false PHY not found - */ -bool BMacEnet::miiFindPHY(unsigned char *phy) -{ - int i; - - *phy = 0xff; - - // The first two PHY registers are required. - // - for (i = 0; i < MII_MAX_PHY; i++) - { - if (miiReadWord(NULL, MII_STATUS, i) && - miiReadWord(NULL, MII_CONTROL, i)) - break; - } - - if (i >= MII_MAX_PHY) - return false; - - *phy = i; - - return true; -} - -/* - * - * - */ -bool BMacEnet::miiInitializePHY(unsigned char phy) -{ - u_int16_t phyWord; - - // Clear then set the enable auto-negotiation bit - // - miiReadWord(&phyWord, MII_CONTROL, phy); - phyWord &= ~MII_CONTROL_AUTONEGOTIATION; - miiWriteWord(phyWord, MII_CONTROL, phy); - - // Advertise 10/100 Half/Full duplex capable to link partner - // - miiReadWord(&phyWord, MII_ADVERTISEMENT, phy); - phyWord |= (MII_ANAR_100BASETX_FD | MII_ANAR_100BASETX | - MII_ANAR_10BASET_FD | MII_ANAR_10BASET ); - miiWriteWord(phyWord, MII_ADVERTISEMENT, phy); - - // Set enable auto-negotiation bit - // - miiReadWord(&phyWord, MII_CONTROL, phy); - phyWord |= MII_CONTROL_AUTONEGOTIATION; - miiWriteWord(phyWord, MII_CONTROL, phy); - - miiRestartAutoNegotiation(phy); - - return true; -} diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.h b/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.h deleted file mode 100644 index 411876fc2..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetMII.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * MII protocol and PHY register definitions. - * - * HISTORY - * - */ - -#ifndef _BMACENETMII_H -#define _BMACENETMII_H - -/* - * MII command frame (32-bits) as documented in IEEE 802.3u - */ - -// _BIG_ENDIAN is already defined for PPC -// -#if 0 -#ifdef __PPC__ -#define _BIG_ENDIAN -#endif -#endif /* 0 */ - -typedef union { - unsigned int data; -#ifdef _BIG_ENDIAN - struct { - unsigned int - st:2, // start of frame -#define MII_ST 0x01 - op:2, // operation code -#define MII_OP_READ 0x02 -#define MII_OP_WRITE 0x01 - phyad:5, // PHY address - regad:5, // register address - ta:2, // turnaround - data:16; // 16-bit data field - } bit; -#else _BIG_ENDIAN - struct { - unsigned int - data:16, // 16-bit data field - ta:2, // turnaround - regad:5, // register address - phyad:5, // PHY address - op:2, // operation code - st:2; // start of frame - } bit; -#endif _BIG_ENDIAN -} miiFrameUnion; - -#define MII_FRAME_PREAMBLE 0xFFFFFFFF -#define MII_FRAME_SIZE 32 -#define MII_FRAME_READ 0x60000000 -#define MII_FRAME_WRITE 0x50020000 - -#define MII_MAX_PHY 32 - -/* MII Registers */ -#define MII_CONTROL 0 -#define MII_STATUS 1 -#define MII_ID0 2 -#define MII_ID1 3 -#define MII_ADVERTISEMENT 4 -#define MII_LINKPARTNER 5 -#define MII_EXPANSION 6 -#define MII_NEXTPAGE 7 - -/* MII Control register bits */ -#define MII_CONTROL_RESET 0x8000 -#define MII_CONTROL_LOOPBACK 0x4000 -#define MII_CONTROL_SPEED_SELECTION 0x2000 -#define MII_CONTROL_AUTONEGOTIATION 0x1000 -#define MII_CONTROL_POWERDOWN 0x800 -#define MII_CONTROL_ISOLATE 0x400 -#define MII_CONTROL_RESTART_NEGOTIATION 0x200 -#define MII_CONTROL_FULLDUPLEX 0x100 -#define MII_CONTROL_COLLISION_TEST 0x80 - -/* MII Status register bits */ -#define MII_STATUS_100BASET4 0x8000 -#define MII_STATUS_100BASETX_FD 0x4000 -#define MII_STATUS_100BASETX 0x2000 -#define MII_STATUS_10BASET_FD 0x1000 -#define MII_STATUS_10BASET 0x800 -#define MII_STATUS_NEGOTIATION_COMPLETE 0x20 -#define MII_STATUS_REMOTE_FAULT 0x10 -#define MII_STATUS_NEGOTIATION_ABILITY 0x8 -#define MII_STATUS_LINK_STATUS 0x4 -#define MII_STATUS_JABBER_DETECT 0x2 -#define MII_STATUS_EXTENDED_CAPABILITY 0x1 - -/* MII ANAR register bits */ -#define MII_ANAR_100BASET4 0x200 -#define MII_ANAR_100BASETX_FD 0x100 -#define MII_ANAR_100BASETX 0x80 -#define MII_ANAR_10BASET_FD 0x40 -#define MII_ANAR_10BASET 0x20 - -/* MII ST10040 Specific */ - -/* MII ST10040 ID */ -#define MII_ST10040_OUI 0x1e0400 -#define MII_ST10040_MODEL 0x00 -#define MII_ST10040_REV 0x01 -#define MII_ST10040_ID ((MII_ST10040_OUI << 10) | \ - (MII_ST10040_MODEL << 4)) -#define MII_ST10040_MASK 0xfffffff0 - -#define MII_ST10040_DELAY 1 - -/* MII ST10040 Regs */ -#define MII_ST10040_CHIPST 0x14 - -/* MII ST10040 CHIPST register bits */ -#define MII_ST10040_CHIPST_LINK 0x2000 -#define MII_ST10040_CHIPST_DUPLEX 0x1000 -#define MII_ST10040_CHIPST_SPEED 0x0800 -#define MII_ST10040_CHIPST_NEGOTIATION 0x0020 - -/* MII DP83843 Specific */ - -/* MII DP83843 ID */ -#define MII_DP83843_OUI 0x080017 -#define MII_DP83843_MODEL 0x01 -#define MII_DP83843_REV 0x00 -#define MII_DP83843_ID ((MII_DP83843_OUI << 10) | \ - (MII_DP83843_MODEL << 4)) -#define MII_DP83843_MASK 0xfffffff0 - -#define MII_DP83843_DELAY 20 - -/* MII DP83843 PHYSTS register bits */ -#define MII_DP83843_PHYSTS 0x10 -#define MII_DP83843_PHYSTS_LINK 0x0001 -#define MII_DP83843_PHYSTS_SPEED10 0x0002 -#define MII_DP83843_PHYSTS_DUPLEX 0x0004 -#define MII_DP83843_PHYSTS_NEGOTIATION 0x0020 - - -/* MII timeout */ -#define MII_DEFAULT_DELAY 20 -#define MII_RESET_TIMEOUT 100 -#define MII_RESET_DELAY 10 - -#define MII_LINK_TIMEOUT 2500 -#define MII_LINK_DELAY 20 - -#endif /* _BMACENETMII_H */ diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.cpp b/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.cpp deleted file mode 100644 index ba5a2eabc..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.cpp +++ /dev/null @@ -1,1958 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Implementation for hardware dependent (relatively) code - * for the BMac Ethernet controller. - * - * HISTORY - * - */ - -#include <IOKit/assert.h> -#include <IOKit/system.h> - -#include "BMacEnetPrivate.h" -#include <IOKit/IOLib.h> - -/***************************************************************************** - * - * Hacks. - */ - -typedef unsigned long long ns_time_t; /* nanoseconds! */ - -#define NSEC_PER_SEC 1000000000 - -static void -_IOGetTimestamp(ns_time_t *nsp) -{ - mach_timespec_t now; - - IOGetTime(&now); - *nsp = ((ns_time_t)now.tv_sec * NSEC_PER_SEC) + now.tv_nsec; -} - -/* - * Find a physical address (if any) for the specified virtual address. - * - * Note: what about vm_offset_t kvtophys(vm_offset_t va) - */ -static IOReturn _IOPhysicalFromVirtual( - vm_address_t virtualAddress, - unsigned *physicalAddress) -{ - *physicalAddress = pmap_extract(kernel_pmap, virtualAddress); - if(*physicalAddress == 0) { - return kIOReturnBadArgument; - } - else { - return kIOReturnSuccess; - } -} - -/****************************************************************************/ - - -extern kern_return_t kmem_alloc_wired(); - -static IODBDMADescriptor dbdmaCmd_Nop; -static IODBDMADescriptor dbdmaCmd_NopWInt; -static IODBDMADescriptor dbdmaCmd_LoadInt; -static IODBDMADescriptor dbdmaCmd_LoadIntWInt; -static IODBDMADescriptor dbdmaCmd_Stop; -static IODBDMADescriptor dbdmaCmd_Branch; - -static u_int8_t reverseBitOrder(u_int8_t data ) -{ - u_int8_t val = 0; - int i; - - for ( i=0; i < 8; i++ ) - { - val <<= 1; - if (data & 1) val |= 1; - data >>= 1; - } - return( val ); -} - -/* - * Function: IOMallocPage - * - * Purpose: - * Returns a pointer to a page-aligned memory block of size >= PAGE_SIZE - * - * Return: - * Actual pointer and size of block returned in actual_ptr and actual_size. - * Use these as arguments to kfree: kfree(*actual_ptr, *actual_size); - */ -static void * -IOMallocPage(int request_size, void ** actual_ptr, u_int * actual_size) -{ - void * mem_ptr; - - *actual_size = round_page(request_size) + PAGE_SIZE; - mem_ptr = IOMalloc(*actual_size); - if (mem_ptr == NULL) - return NULL; - *actual_ptr = mem_ptr; - return ((void *)round_page(mem_ptr)); -} - -/* - * Private functions - */ -bool BMacEnet::_allocateMemory() -{ - u_int32_t i, n; - unsigned char * virtAddr; - u_int32_t physBase; - u_int32_t physAddr; - u_int32_t dbdmaSize; - - /* - * Calculate total space for DMA channel commands - */ - dbdmaSize = round_page( - RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + - TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + - 2 * sizeof(IODBDMADescriptor) ); - - /* - * Allocate required memory - */ - dmaMemory.size = dbdmaSize; - dmaMemory.ptr = (void *)IOMallocPage( - dmaMemory.size, - &dmaMemory.ptrReal, - &dmaMemory.sizeReal - ); - - dmaCommands = (unsigned char *) dmaMemory.ptr; - if (dmaCommands == NULL) { - IOLog( "Ethernet(BMac): Cant allocate channel DBDMA commands\n\r" ); - return false; - } - - /* - * If we needed more than one page, then make sure we received - * contiguous memory. - */ - n = (dbdmaSize - PAGE_SIZE) / PAGE_SIZE; - _IOPhysicalFromVirtual( (vm_address_t) dmaCommands, &physBase ); - - virtAddr = (unsigned char *) dmaCommands; - for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) - { - _IOPhysicalFromVirtual( (vm_address_t) virtAddr, &physAddr ); - if (physAddr != (physBase + i * PAGE_SIZE) ) - { - IOLog( "Ethernet(BMac): Cannot allocate contiguous memory" - " for DBDMA commands\n\r" ); - return false; - } - } - - /* - * Setup the receive ring pointers - */ - rxDMACommands = (enet_dma_cmd_t *)dmaCommands; - rxMaxCommand = RX_RING_LENGTH; - - /* - * Setup the transmit ring pointers - */ - txDMACommands = (enet_txdma_cmd_t *)(dmaCommands + - RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + sizeof(IODBDMADescriptor)); - txMaxCommand = TX_RING_LENGTH; - - /* - * Setup pre-initialized DBDMA commands - */ - IOMakeDBDMADescriptor( (&dbdmaCmd_Nop), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0); - - IOMakeDBDMADescriptor( (&dbdmaCmd_NopWInt), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntAlways, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0); - - UInt32 ioBaseEnetPhys = maps[MEMORY_MAP_ENET_INDEX]->getPhysicalAddress(); - - IOMakeDBDMADescriptor( (&dbdmaCmd_LoadInt), - kdbdmaLoadQuad, - kdbdmaKeySystem, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 2, - ((int)ioBaseEnetPhys + kSTAT) ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_LoadIntWInt), - kdbdmaLoadQuad, - kdbdmaKeySystem, - kdbdmaIntAlways, - kdbdmaBranchNever, - kdbdmaWaitNever, - 2, - ((int)ioBaseEnetPhys + kSTAT) ); - - IOMakeDBDMADescriptor( (&dbdmaCmd_Stop), - kdbdmaStop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchNever, - kdbdmaWaitNever, - 0, - 0); - - IOMakeDBDMADescriptor( (&dbdmaCmd_Branch), - kdbdmaNop, - kdbdmaKeyStream0, - kdbdmaIntNever, - kdbdmaBranchAlways, - kdbdmaWaitNever, - 0, - 0); - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Transmit Ring - * ----------------------- - * Each transmit ring entry consists of two words to transmit data from buffer - * segments (possibly) spanning a page boundary. This is followed by two DMA - * commands which read transmit frame status and interrupt status from the Bmac - * chip. The last DMA command in each transmit ring entry generates a host - * interrupt. The last entry in the ring is followed by a DMA branch to the - * first entry. - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_initTxRing() -{ - bool kr; - u_int32_t i; - IODBDMADescriptor dbdmaCmd, dbdmaCmdInt; - - /* - * Clear mbufs from TX ring. - */ - for ( i = 0; i < txMaxCommand; i++ ) - { - if ( txMbuf[i] ) - { - freePacket( txMbuf[i] ); - txMbuf[i] = 0; - } - } - - /* - * Clear the transmit DMA command memory - */ - bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * txMaxCommand); - txCommandHead = 0; - txCommandTail = 0; - - /* - * DMA Channel commands 2 are the same for all DBDMA entries on transmit. - * Initialize them now. - */ - - dbdmaCmd = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_Nop : dbdmaCmd_LoadInt; - dbdmaCmdInt = ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? dbdmaCmd_NopWInt : dbdmaCmd_LoadIntWInt; - - for( i=0; i < txMaxCommand; i++ ) - { - txDMACommands[i].desc_seg[2] = ( (i+1) % TX_PKTS_PER_INT ) ? dbdmaCmd : dbdmaCmdInt; - } - - /* - * Put a DMA Branch command after the last entry in the transmit ring. - * Set the branch address to the physical address of the start of the - * transmit ring. - */ - txDMACommands[txMaxCommand].desc_seg[0] = dbdmaCmd_Branch; - - kr = _IOPhysicalFromVirtual( (vm_address_t) txDMACommands, - (u_int32_t *)&txDMACommandsPhys ); - if ( kr != kIOReturnSuccess ) - { - IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r", - (u_int32_t)txDMACommands ); - } - IOSetCCCmdDep( &txDMACommands[txMaxCommand].desc_seg[0], - txDMACommandsPhys ); - - /* - * Set the Transmit DMA Channel pointer to the first entry in the - * transmit ring. - */ - IOSetDBDMACommandPtr( ioBaseEnetTxDMA, txDMACommandsPhys ); - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Receive ring - * ---------------------- - * Each receive ring entry consists of two DMA commands to receive data - * into a network buffer (possibly) spanning a page boundary. The second - * DMA command in each entry generates a host interrupt. - * The last entry in the ring is followed by a DMA branch to the first - * entry. - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_initRxRing() -{ - u_int32_t i; - bool status; - IOReturn kr; - - /* - * Clear the receive DMA command memory - */ - bzero((void *)rxDMACommands, sizeof(enet_dma_cmd_t) * rxMaxCommand); - - kr = _IOPhysicalFromVirtual( (vm_address_t) rxDMACommands, - (u_int32_t *)&rxDMACommandsPhys ); - if ( kr != kIOReturnSuccess ) - { - IOLog( "Ethernet(BMac): Bad DBDMA command buf - %08x\n\r", - (u_int32_t)rxDMACommands ); - return false; - } - - /* - * Allocate a receive buffer for each entry in the Receive ring - */ - for (i = 0; i < rxMaxCommand-1; i++) - { - if (rxMbuf[i] == NULL) - { - rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE); - if (!rxMbuf[i]) - { - IOLog("Ethernet(BMac): allocatePacket failed\n"); - return false; - } - } - - /* - * Set the DMA commands for the ring entry to transfer data to the - * mbuf. - */ - status = _updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); - if (status == false) - { - IOLog("Ethernet(BMac): cannot map mbuf to physical memory in" - " _initRxRing\n\r"); - return false; - } - } - - /* - * Set the receive queue head to point to the first entry in the ring. - * Set the receive queue tail to point to a DMA Stop command after the - * last ring entry - */ - rxCommandHead = 0; - rxCommandTail = i; - - rxDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; - rxDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; - - /* - * Setup a DMA branch command after the stop command - */ - i++; - rxDMACommands[i].desc_seg[0] = dbdmaCmd_Branch; - - IOSetCCCmdDep( &rxDMACommands[i].desc_seg[0], rxDMACommandsPhys ); - - /* - * Set DMA command pointer to first receive entry - */ - IOSetDBDMACommandPtr (ioBaseEnetRxDMA, rxDMACommandsPhys); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_startChip() -{ - u_int16_t oldConfig; - - IODBDMAContinue( ioBaseEnetRxDMA ); - - // turn on rx plus any other bits already on (promiscuous possibly) - oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG); - WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable ); - - oldConfig = ReadBigMacRegister(ioBaseEnet, kTXCFG); - WriteBigMacRegister(ioBaseEnet, kTXCFG, oldConfig | kTxMACEnable ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_resetChip() -{ - volatile u_int32_t *heathrowFCR; - u_int32_t fcrValue; - u_int16_t *pPhyType; - - IODBDMAReset( ioBaseEnetRxDMA ); - IODBDMAReset( ioBaseEnetTxDMA ); - - IOSetDBDMAWaitSelect( ioBaseEnetTxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS5 ) ); - - IOSetDBDMABranchSelect( ioBaseEnetRxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); - - IOSetDBDMAInterruptSelect( ioBaseEnetRxDMA, - IOSetDBDMAChannelControlBits( kdbdmaS6 ) ); - - heathrowFCR = (u_int32_t *)((u_int8_t *)ioBaseHeathrow + kHeathrowFCR); - - fcrValue = *heathrowFCR; - eieio(); - - fcrValue = OSReadSwapInt32( &fcrValue, 0 ); - - /* - * Enable the ethernet transceiver/clocks - */ - fcrValue |= kEnetEnabledBits; - fcrValue &= ~kResetEnetCell; - - *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 ); - eieio(); - IOSleep( 100 ); - - /* - * Determine if PHY chip is configured. Reset and enable it (if present). - */ - if ( phyId == 0xff ) - { - phyMIIDelay = 20; - if ( miiFindPHY(&phyId) == true ) - { - miiResetPHY(phyId); - - pPhyType = (u_int16_t *)&phyType; - miiReadWord(pPhyType, MII_ID0, phyId); - miiReadWord(pPhyType+1, MII_ID1, phyId); - - if ( (phyType & MII_ST10040_MASK) == MII_ST10040_ID ) - { - phyMIIDelay = MII_ST10040_DELAY; - } - else if ( (phyType & MII_DP83843_MASK) == MII_DP83843_ID ) - { - phyMIIDelay = MII_DP83843_DELAY; - } - - kprintf("Ethernet(BMac): PHY id = %d\n", phyId); - } - } - - /* - * Reset the reset the ethernet cell - */ - fcrValue |= kResetEnetCell; - *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 ); - eieio(); - IOSleep( 10 ); - - fcrValue &= ~kResetEnetCell; - *heathrowFCR = OSReadSwapInt32( &fcrValue, 0 ); - eieio(); - IOSleep( 10 ); - - chipId = ReadBigMacRegister(ioBaseEnet, kCHIPID) & 0xFF; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_initChip() -{ - volatile u_int16_t regValue; - ns_time_t timeStamp; - u_int16_t *pWord16; - - WriteBigMacRegister(ioBaseEnet, kTXRST, kTxResetBit); - - do - { - // wait for reset to clear..acknowledge - regValue = ReadBigMacRegister(ioBaseEnet, kTXRST); - } - while( regValue & kTxResetBit ); - - WriteBigMacRegister(ioBaseEnet, kRXRST, kRxResetValue); - - if ( phyId == 0xff ) - { - WriteBigMacRegister(ioBaseEnet, kXCVRIF, - kClkBit | kSerialMode | kCOLActiveLow); - } - - _IOGetTimestamp(&timeStamp); - WriteBigMacRegister(ioBaseEnet, kRSEED, (u_int16_t) timeStamp ); - - regValue = ReadBigMacRegister(ioBaseEnet, kXIFC); - regValue |= kTxOutputEnable; - WriteBigMacRegister(ioBaseEnet, kXIFC, regValue); - - ReadBigMacRegister(ioBaseEnet, kPAREG); - - // set collision counters to 0 - WriteBigMacRegister(ioBaseEnet, kNCCNT, 0); - WriteBigMacRegister(ioBaseEnet, kNTCNT, 0); - WriteBigMacRegister(ioBaseEnet, kEXCNT, 0); - WriteBigMacRegister(ioBaseEnet, kLTCNT, 0); - - // set rx counters to 0 - WriteBigMacRegister(ioBaseEnet, kFRCNT, 0); - WriteBigMacRegister(ioBaseEnet, kLECNT, 0); - WriteBigMacRegister(ioBaseEnet, kAECNT, 0); - WriteBigMacRegister(ioBaseEnet, kFECNT, 0); - WriteBigMacRegister(ioBaseEnet, kRXCV, 0); - - // set tx fifo information - // 255 octets before tx starts - WriteBigMacRegister(ioBaseEnet, kTXTH, 0xff); - - // first disable txFIFO - WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, 0); - WriteBigMacRegister(ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable ); - - // set rx fifo information - // first disable rxFIFO - WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, 0); - WriteBigMacRegister(ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable ); - - // kTxNeverGiveUp maybe later - //WriteBigMacRegister(ioBaseEnet, kTXCFG, kTxMACEnable); - ReadBigMacRegister(ioBaseEnet, kSTAT); // read it just to clear it - - // zero out the chip Hash Filter registers - WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[0]); // bits 15 - 0 - WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[1]); // bits 31 - 16 - WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[2]); // bits 47 - 32 - WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[3]); // bits 63 - 48 - - pWord16 = (u_int16_t *)&myAddress.bytes[0]; - WriteBigMacRegister(ioBaseEnet, kMADD0, *pWord16++); - WriteBigMacRegister(ioBaseEnet, kMADD1, *pWord16++); - WriteBigMacRegister(ioBaseEnet, kMADD2, *pWord16); - - WriteBigMacRegister(ioBaseEnet, kRXCFG, - kRxCRCEnable | kRxHashFilterEnable | kRxRejectOwnPackets); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_disableAdapterInterrupts() -{ - WriteBigMacRegister( ioBaseEnet, kINTDISABLE, kNoEventsMask ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_enableAdapterInterrupts() -{ - WriteBigMacRegister( ioBaseEnet, - kINTDISABLE, - ( chipId >= kCHIPID_PaddingtonXmitStreaming ) ? - kNoEventsMask: kNormalIntEvents ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_setDuplexMode(bool duplexMode) -{ - u_int16_t txCFGVal; - - isFullDuplex = duplexMode; - - txCFGVal = ReadBigMacRegister( ioBaseEnet, kTXCFG); - - WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable ); - while( ReadBigMacRegister(ioBaseEnet, kTXCFG) & kTxMACEnable ) - ; - - if ( isFullDuplex ) - { - txCFGVal |= (kTxIgnoreCollision | kTxFullDuplex); - } - else - { - txCFGVal &= ~(kTxIgnoreCollision | kTxFullDuplex); - } - - WriteBigMacRegister( ioBaseEnet, kTXCFG, txCFGVal ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_restartTransmitter() -{ - u_int16_t regValue; - - /* - * Shutdown DMA channel - */ - _stopTransmitDMA(); - - /* - * Get the silicon's attention - */ - WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, 0 ); - WriteBigMacRegister( ioBaseEnet, kTXFIFOCSR, kTxFIFOEnable); - - ReadBigMacRegister( ioBaseEnet, kSTAT ); - - regValue = ReadBigMacRegister(ioBaseEnet, kTXCFG); - WriteBigMacRegister(ioBaseEnet, kTXCFG, regValue | kTxMACEnable ); - - /* - * Restart transmit DMA - */ - IODBDMAContinue( ioBaseEnetTxDMA ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_restartReceiver() -{ - u_int16_t oldConfig; - - /* - * Shutdown DMA channel - */ - _stopReceiveDMA(); - - /* - * Get the silicon's attention - */ - WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, 0 ); - WriteBigMacRegister( ioBaseEnet, kRXFIFOCSR, kRxFIFOEnable); - - oldConfig = ReadBigMacRegister(ioBaseEnet, kRXCFG); - WriteBigMacRegister(ioBaseEnet, kRXCFG, oldConfig | kRxMACEnable ); - - /* - * Restart receive DMA - */ - IODBDMAContinue( ioBaseEnetRxDMA ); -} - -/*------------------------------------------------------------------------- - * - * Orderly stop of receive DMA. - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_stopReceiveDMA() -{ - u_int32_t dmaCmdPtr; - u_int8_t rxCFGVal; - - /* - * Stop the receiver and allow any frame receive in progress to complete. - */ - rxCFGVal = ReadBigMacRegister(ioBaseEnet, kRXCFG); - WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGVal & ~kRxMACEnable ); - IODelay( RECEIVE_QUIESCE_uS ); - - IODBDMAReset( ioBaseEnetRxDMA ); - - dmaCmdPtr = rxDMACommandsPhys + rxCommandHead * sizeof(enet_dma_cmd_t); - IOSetDBDMACommandPtr( ioBaseEnetRxDMA, dmaCmdPtr ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_stopTransmitDMA() -{ - u_int32_t dmaCmdPtr; - u_int8_t txCFGVal; - - /* - * Stop the transmitter and allow any frame transmit in progress to abort - */ - txCFGVal = ReadBigMacRegister(ioBaseEnet, kTXCFG); - WriteBigMacRegister(ioBaseEnet, kTXCFG, txCFGVal & ~kTxMACEnable ); - - IODelay( TRANSMIT_QUIESCE_uS ); - - IODBDMAReset( ioBaseEnetTxDMA ); - - dmaCmdPtr = txDMACommandsPhys + txCommandHead * sizeof(enet_txdma_cmd_t); - IOSetDBDMACommandPtr( ioBaseEnetTxDMA, dmaCmdPtr ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_transmitPacket(struct mbuf *packet) -{ - enet_dma_cmd_t tmpCommand; - u_int32_t i; - - /* - * Check for room on the transmit ring. There should always be space - * since it is the responsibility of the caller to verify this before - * calling _transmitPacket. - * - * Get a copy of the DMA transfer commands in a temporary buffer. - * The new DMA command is written into the channel program so that the - * command word for the old Stop command is overwritten last. This prevents - * the DMA engine from executing a partially written channel command. - */ - i = txCommandTail + 1; - if ( i >= txMaxCommand ) i = 0; - - if ( (i == txCommandHead) || - !_updateDescriptorFromMbuf(packet, &tmpCommand, false) ) - { - IOLog("Ethernet(BMac): Freeing transmit packet eh?\n\r"); - if (packet != txDebuggerPkt) - freePacket(packet); - return false; - } - - /* - * txCommandTail points to the current DMA Stop command for the channel. - * We are now creating a new DMA Stop command in the next slot in the - * transmit ring. The previous DMA Stop command will be overwritten with - * the DMA commands to transfer the new mbuf. - */ - txDMACommands[i].desc_seg[0] = dbdmaCmd_Stop; - txDMACommands[i].desc_seg[1] = dbdmaCmd_Nop; - - bcopy( ((u_int32_t *)&tmpCommand)+1, - ((u_int32_t *)&txDMACommands[txCommandTail])+1, - sizeof(enet_dma_cmd_t)-sizeof(u_int32_t) ); - - txMbuf[txCommandTail] = packet; - txDMACommands[txCommandTail].desc_seg[0].operation = - tmpCommand.desc_seg[0].operation; - - /* - * Set the transmit tail to the new stop command. - */ - txCommandTail = i; - - /* - * Tap the DMA channel to wake it up - */ - IODBDMAContinue( ioBaseEnetTxDMA ); - - return true; -} - -/*------------------------------------------------------------------------- - * _receivePacket - * -------------- - * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger. - * - * The _receivePackets allocate NetBufs and pass them up the stack. The kernel - * debugger interface passes a buffer into us. To reconsile the two interfaces, - * we allow the receive routine to continue to allocate its own buffers and - * transfer any received data to the passed-in buffer. This is handled by - * _receivePacket calling _packetToDebugger. - *-------------------------------------------------------------------------*/ - -void BMacEnet::_receivePacket(void *pkt, unsigned int *pkt_len, - unsigned int timeout) -{ - ns_time_t startTime; - ns_time_t currentTime; - u_int32_t elapsedTimeMS; - - if (!ready || !pkt || !pkt_len) - return; - - *pkt_len = 0; - - debuggerPkt = pkt; - debuggerPktSize = 0; - - _IOGetTimestamp(&startTime); - do - { - _receivePackets(true); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); - - *pkt_len = debuggerPktSize; -} - -/*------------------------------------------------------------------------- - * _packetToDebugger - * ----------------- - * This is called by _receivePackets when we are polling for kernel debugger - * packets. It copies the NetBuf contents to the buffer passed by the debugger. - * It also sets the var debuggerPktSize which will break the polling loop. - *-------------------------------------------------------------------------*/ - -void BMacEnet::_packetToDebugger(struct mbuf * packet, u_int size) -{ - debuggerPktSize = size; - bcopy( mtod(packet, char *), debuggerPkt, size ); -} - -/*------------------------------------------------------------------------- - * _sendPacket - * ----------- - * - * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger. - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_sendPacket(void *pkt, unsigned int pkt_len) -{ - ns_time_t startTime; - ns_time_t currentTime; - u_int32_t elapsedTimeMS; - - if (!ready || !pkt || (pkt_len > ETHERMAXPACKET)) - return; - - /* - * Wait for the transmit ring to empty - */ - _IOGetTimestamp(&startTime); - do - { - _debugTransmitInterruptOccurred(); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && - (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog( "Ethernet(BMac): Polled tranmit timeout - 1\n\r"); - return; - } - - /* - * Allocate a NetBuf and copy the debugger transmit data into it. - * - * jliu - no allocation, just recycle the same buffer dedicated to - * KDB transmit. - */ - txDebuggerPkt->m_next = 0; - txDebuggerPkt->m_data = (caddr_t) pkt; - txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len; - - /* - * Send the debugger packet. txDebuggerPkt must not be freed by - * the transmit routine. - */ - _transmitPacket(txDebuggerPkt); - - /* - * Poll waiting for the transmit ring to empty again - */ - do - { - _debugTransmitInterruptOccurred(); - _IOGetTimestamp(¤tTime); - elapsedTimeMS = (currentTime - startTime) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && - (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog( "Ethernet(BMac): Polled tranmit timeout - 2\n\r"); - } - - return; -} - -/*------------------------------------------------------------------------- - * _sendDummyPacket - * ---------------- - * The BMac receiver seems to be locked until we send our first packet. - * - *-------------------------------------------------------------------------*/ -void BMacEnet::_sendDummyPacket() -{ - union - { - u_int8_t bytes[64]; - IOEthernetAddress enet_addr[2]; - } dummyPacket; - - bzero( &dummyPacket, sizeof(dummyPacket) ); - dummyPacket.enet_addr[0] = myAddress; - dummyPacket.enet_addr[1] = myAddress; - _sendPacket((void *)dummyPacket.bytes, sizeof(dummyPacket)); - IOSleep(50); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_receiveInterruptOccurred() -{ - return _receivePackets(false); -} - -/*------------------------------------------------------------------------- - * Work around a hardware bug where the controller will receive - * unicast packets not directed to the station. The hardware is - * erroneously using the hash table to qualify the unicast address. - * This routine will check that the packet is unicast, and if so, - * makes sure that the unicast address matches the station's address. - * Thus function returns true if the packet should be rejected. - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_rejectBadUnicastPacket(ether_header_t * etherHeader) -{ - bool rejectPacket = false; - - if ( useUnicastFilter && (isPromiscuous == false) && - (etherHeader->ether_dhost[EA_GROUP_BYTE] & EA_GROUP_BIT) == 0) { - // - // Destination Ethernet address is not multicast nor broadcast. - // Then it must be addresses to the station MAC address, - // otherwise reject the packet. - // - if (bcmp(etherHeader->ether_dhost, &myAddress, NUM_EN_ADDR_BYTES) != 0) - rejectPacket = true; - } - - return rejectPacket; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_receivePackets(bool fDebugger) -{ - enet_dma_cmd_t tmpCommand; - struct mbuf * packet; - u_int32_t i, j, last; - int receivedFrameSize = 0; - u_int32_t dmaCount[2], dmaResid[2], dmaStatus[2]; - u_int32_t dmaChnlStatus; - u_int16_t rxPktStatus = 0; - u_int32_t badFrameCount; - bool reusePkt; - bool status; - bool useNetif = !fDebugger && netifEnabled; - bool doFlushQueue = false; - u_int32_t nextDesc; - static const u_int32_t lastResetValue = (u_int32_t)(-1); - - last = lastResetValue; - i = rxCommandHead; - - while ( 1 ) - { - reusePkt = false; - - /* - * Collect the DMA residual counts/status for the two - * buffer segments. - */ - for ( j = 0; j < 2; j++ ) - { - dmaResid[j] = IOGetCCResult( &rxDMACommands[i].desc_seg[j] ); - dmaStatus[j] = dmaResid[j] >> 16; - dmaResid[j] &= 0x0000ffff; - dmaCount[j] = IOGetCCOperation( &rxDMACommands[i].desc_seg[j] ) - & kdbdmaReqCountMask; - } - -#if 0 - IOLog("Ethernet(BMac): Rx NetBuf[%2d] = %08x Resid[0] = %04x Status[0] = %04x Resid[1] = %04x Status[1] = %04x\n\r", - i, (int)nb_map(rxNetbuf[i]), dmaResid[0], dmaStatus[0], dmaResid[1], dmaStatus[1] ); -#endif - - /* - * If the current entry has not been written, then stop at this entry - */ - if ( !((dmaStatus[0] & kdbdmaBt) || (dmaStatus[1] & kdbdmaActive)) ) - { - break; - } - - /* - * The BMac Ethernet controller appends two bytes to each receive - * buffer containing the buffer - * size and receive frame status. - * We locate these bytes by using the DMA residual counts. - */ - receivedFrameSize = dmaCount[0] - dmaResid[0] + dmaCount[1] - - ((dmaStatus[0] & kdbdmaBt) ? dmaCount[1] : dmaResid[1]); - - if ( ( receivedFrameSize >= 2 ) && - ( receivedFrameSize <= NETWORK_BUFSIZE ) ) - { - /* - * Get the receive frame size as reported by the BMac controller - */ - rxPktStatus = *(u_int16_t *)(mtod(rxMbuf[i], u_int32_t) + - receivedFrameSize - 2); - receivedFrameSize = rxPktStatus & kRxLengthMask; - } - - /* - * Reject packets that are runts or that have other mutations. - */ - if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || - receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || - rxPktStatus & kRxAbortBit || - _rejectBadUnicastPacket(mtod(rxMbuf[i], ether_header_t *)) - ) - { - if (useNetif) netStats->inputErrors++; - reusePkt = true; - } - else if ( useNetif == false ) - { - /* - * Always reuse packets in debugger mode. We also refuse to - * pass anything up the stack unless the driver is open. The - * hardware is enabled before the stack has opened us, to - * allow earlier debug interface registration. But we must - * not pass any packets up. - */ - reusePkt = true; - if (fDebugger) - _packetToDebugger(rxMbuf[i], receivedFrameSize); - } - - /* - * Before we pass this packet up the networking stack. Make sure we - * can get a replacement. Otherwise, hold on to the current packet and - * increment the input error count. - * Thanks Justin! - */ - - packet = 0; - - if ( reusePkt == false ) - { - bool replaced; - - packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, - &replaced); - - reusePkt = true; - - if (packet && replaced) - { - status = _updateDescriptorFromMbuf(rxMbuf[i], - &rxDMACommands[i], true); - - if (status) - { - reusePkt = false; - } - else - { - // Assume descriptor has not been corrupted. - freePacket(rxMbuf[i]); // release new packet. - rxMbuf[i] = packet; // get the old packet back. - packet = 0; // pass up nothing. - IOLog("Ethernet(BMac): _updateDescriptorFromMbuf error\n"); - } - } - - if (packet == 0) - netStats->inputErrors++; - } - - /* - * If we are reusing the existing mbuf, then refurbish the existing - * DMA command \ descriptors by clearing the status/residual count - * fields. - */ - if ( reusePkt ) - { - for ( j=0; j < sizeof(enet_dma_cmd_t)/sizeof(IODBDMADescriptor); - j++ ) - { - IOSetCCResult( &rxDMACommands[i].desc_seg[j], 0 ); - } - } - - /* - * Keep track of the last receive descriptor processed - */ - last = i; - - /* - * Implement ring wrap-around - */ - if (++i >= rxMaxCommand) i = 0; - - if (fDebugger) - { - break; - } - - /* - * Transfer received packet to network - */ - if (packet) - { - KERNEL_DEBUG(DBG_BMAC_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, - (int)receivedFrameSize, 0, 0, 0 ); - - networkInterface->inputPacket(packet, receivedFrameSize, true); - doFlushQueue = true; - netStats->inputPackets++; - } - } - - /* - * OK...this is a little messy - * - * We just processed a bunch of DMA receive descriptors. We are going to - * exchange the current DMA stop command (rxCommandTail) with the last - * receive descriptor we processed (last). This will make these list of - * descriptors we just processed available. If we processed no receive - * descriptors on this call then skip this exchange. - */ - -#if 0 - IOLog( "Ethernet(BMac): Prev - Rx Head = %2d Rx Tail = %2d Rx Last = %2d\n\r", rxCommandHead, rxCommandTail, last ); -#endif - - if ( last != lastResetValue ) - { - /* - * Save the contents of the last receive descriptor processed. - */ - packet = rxMbuf[last]; - tmpCommand = rxDMACommands[last]; - - /* - * Write a DMA stop command into this descriptor slot - */ - rxDMACommands[last].desc_seg[0] = dbdmaCmd_Stop; - rxDMACommands[last].desc_seg[1] = dbdmaCmd_Nop; - rxMbuf[last] = 0; - - /* - * Replace the previous DMA stop command with the last receive - * descriptor processed. - * - * The new DMA command is written into the channel program so that the - * command word for the old Stop command is overwritten last. This - * prevents the DMA engine from executing a partially written channel - * command. - * - * Note: When relocating the descriptor, we must update its branch - * field to reflect its new location. - */ - nextDesc = rxDMACommandsPhys + - (int) &rxDMACommands[rxCommandTail + 1] - (int)rxDMACommands; - IOSetCCCmdDep( &tmpCommand.desc_seg[0], nextDesc ); - - bcopy( (u_int32_t *) &tmpCommand + 1, - (u_int32_t *) &rxDMACommands[rxCommandTail] + 1, - sizeof(enet_dma_cmd_t) - sizeof(u_int32_t) ); - - rxMbuf[rxCommandTail] = packet; - - rxDMACommands[rxCommandTail].desc_seg[0].operation = - tmpCommand.desc_seg[0].operation; - - /* - * Update rxCommmandTail to point to the new Stop command. Update - * rxCommandHead to point to the next slot in the ring past the Stop - * command - */ - rxCommandTail = last; - rxCommandHead = i; - } - - /* - * Update receive error statistics - */ - badFrameCount = ReadBigMacRegister(ioBaseEnet, kFECNT) - + ReadBigMacRegister(ioBaseEnet, kAECNT) - + ReadBigMacRegister(ioBaseEnet, kLECNT); - - /* - * Clear Hardware counters - */ - WriteBigMacRegister(ioBaseEnet, kFECNT, 0); - WriteBigMacRegister(ioBaseEnet, kAECNT, 0); - WriteBigMacRegister(ioBaseEnet, kLECNT, 0); - - if (badFrameCount && useNetif) - netStats->inputErrors += badFrameCount; - - /* - * Check for error conditions that may cause the receiver to stall - */ - dmaChnlStatus = IOGetDBDMAChannelStatus( ioBaseEnetRxDMA ); - - if ( dmaChnlStatus & kdbdmaDead ) - { - if (useNetif) netStats->inputErrors++; - IOLog( "Ethernet(BMac): Rx DMA Error - Status = %04x\n\r", - dmaChnlStatus ); - _restartReceiver(); - } - else - { - /* - * Tap the DMA to wake it up - */ - IODBDMAContinue( ioBaseEnetRxDMA ); - } - -#if 0 - IOLog( "Ethernet(BMac): New - Rx Head = %2d Rx Tail = %2d\n\r", rxCommandHead, rxCommandTail ); -#endif - - return doFlushQueue; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_transmitInterruptOccurred() -{ - u_int32_t dmaStatus; - u_int32_t collisionCount; - u_int32_t badFrameCount; - bool fServiced = false; - - while ( 1 ) - { - /* - * Check the status of the last descriptor in this entry to see if - * the DMA engine completed this entry. - */ - dmaStatus = IOGetCCResult( - &(txDMACommands[txCommandHead].desc_seg[1])) >> 16; - - if ( !(dmaStatus & kdbdmaActive) ) - { - break; - } - - if (netifEnabled) netStats->outputPackets++; - - fServiced = true; - - KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE | DBG_FUNC_NONE, - (int)txMbuf[txCommandHead], - (int)txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 ); - - /* - * Free the mbuf we just transmitted. - * - * If it is the debugger packet, just remove it from the ring. - * and reuse the same packet for the next sendPacket() request. - */ - if (txMbuf[txCommandHead] != txDebuggerPkt) - { - freePacket( txMbuf[txCommandHead] ); - } - txMbuf[txCommandHead] = NULL; - - if ( ++(txCommandHead) >= txMaxCommand ) - txCommandHead = 0; - } - - /* - * Increment transmit error statistics - */ - collisionCount = ReadBigMacRegister(ioBaseEnet, kNCCNT ); - - WriteBigMacRegister( ioBaseEnet, kNCCNT, 0 ); - - badFrameCount = ReadBigMacRegister(ioBaseEnet, kEXCNT ) - + ReadBigMacRegister(ioBaseEnet, kLTCNT ); - - WriteBigMacRegister( ioBaseEnet, kEXCNT, 0 ); - WriteBigMacRegister( ioBaseEnet, kLTCNT, 0 ); - - if (netifEnabled) { - netStats->collisions += collisionCount; - netStats->outputErrors += badFrameCount; - } - - /* - * Check for error conditions that may cause the transmitter to stall - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); - - if ( dmaStatus & kdbdmaDead ) - { - if (netifEnabled) netStats->outputErrors++; - IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus ); - _restartTransmitter(); - fServiced = true; - } - - return fServiced; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool BMacEnet::_debugTransmitInterruptOccurred() -{ - u_int32_t dmaStatus; - u_int32_t badFrameCount; - bool fServiced = false; - - // Set the debugTxPoll flag to indicate the debugger was active - // and some cleanup may be needed when the driver returns to - // normal operation. - // - debugTxPoll = true; - - while ( 1 ) - { - /* - * Check the status of the last descriptor in this entry to see if - * the DMA engine completed this entry. - */ - dmaStatus = IOGetCCResult( - &(txDMACommands[txCommandHead].desc_seg[1])) >> 16; - - if ( !(dmaStatus & kdbdmaActive) ) - { - break; - } - - fServiced = true; - - KERNEL_DEBUG(DBG_BMAC_TXCOMPLETE | DBG_FUNC_NONE, - (int)txMbuf[txCommandHead], - (int)txMbuf[txCommandHead]->m_pkthdr.len, 0, 0, 0 ); - - /* - * Free the mbuf we just transmitted. - * - * If it is the debugger packet, just remove it from the ring. - * and reuse the same packet for the next sendPacket() request. - */ - if (txMbuf[txCommandHead] != txDebuggerPkt) { - // - // While in debugger mode, do not touch the mbuf pool. - // Queue any used mbufs to a local queue. This queue - // will get flushed after we exit from debugger mode. - // - // During continuous debugger transmission and - // interrupt polling, we expect only the txDebuggerPkt - // to show up on the transmit mbuf ring. - // - debugQueue->enqueue( txMbuf[txCommandHead] ); - } - txMbuf[txCommandHead] = NULL; - - if ( ++(txCommandHead) >= txMaxCommand ) - txCommandHead = 0; - } - - /* - * Clear transmit error statistics - */ - badFrameCount = ReadBigMacRegister(ioBaseEnet, kNCCNT ); - WriteBigMacRegister( ioBaseEnet, kNCCNT, 0 ); - - badFrameCount = ReadBigMacRegister(ioBaseEnet, kEXCNT ) - + ReadBigMacRegister(ioBaseEnet, kLTCNT ); - WriteBigMacRegister( ioBaseEnet, kEXCNT, 0 ); - WriteBigMacRegister( ioBaseEnet, kLTCNT, 0 ); - - /* - * Check for error conditions that may cause the transmitter to stall - */ - dmaStatus = IOGetDBDMAChannelStatus( ioBaseEnetTxDMA ); - - if ( dmaStatus & kdbdmaDead ) - { - IOLog( "Ethernet(BMac): Tx DMA Error - Status = %04x\n\r", dmaStatus ); - _restartTransmitter(); - fServiced = true; - } - - return fServiced; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool -BMacEnet::_updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, - bool isReceive) -{ - u_int32_t nextDesc = 0; - u_int32_t waitMask = 0; - int segments; - struct IOPhysicalSegment segVector[2]; - - segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector); - - if ((!segments) || (segments > 2)) { - IOLog("BMac: _updateDescriptorFromMbuf error, %d segments\n", - segments); - return false; - } - - // IOLog("segments: %d\n", segments); - - if ( isReceive || chipId >= kCHIPID_PaddingtonXmitStreaming ) - { - waitMask = kdbdmaWaitNever; - } - else - { - waitMask = kdbdmaWaitIfFalse; - } - - if ( segments == 1 ) - { - IOMakeDBDMADescriptor( (&desc->desc_seg[0]), - ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), - (kdbdmaKeyStream0), - (kdbdmaIntNever), - (kdbdmaBranchNever), - (waitMask), - (segVector[0].length), - (segVector[0].location) ); - - desc->desc_seg[1] = (isReceive) ? dbdmaCmd_NopWInt : dbdmaCmd_Nop; - } - else - { - if ( isReceive ) - { - nextDesc = rxDMACommandsPhys + (int)desc - (int)rxDMACommands + - sizeof(enet_dma_cmd_t); - } - - IOMakeDBDMADescriptorDep( (&desc->desc_seg[0]), - ((isReceive) ? kdbdmaInputMore : kdbdmaOutputMore), - (kdbdmaKeyStream0), - ((isReceive) ? kdbdmaIntIfTrue : kdbdmaIntNever), - ((isReceive) ? kdbdmaBranchIfTrue : - kdbdmaBranchNever), - (kdbdmaWaitNever), - (segVector[0].length), - (segVector[0].location), - nextDesc ); - - IOMakeDBDMADescriptor( (&desc->desc_seg[1]), - ((isReceive) ? kdbdmaInputLast : kdbdmaOutputLast), - (kdbdmaKeyStream0), - ((isReceive) ? kdbdmaIntAlways : kdbdmaIntNever), - (kdbdmaBranchNever), - (waitMask), - (segVector[1].length), - (segVector[1].location) ); - } - - return true; -} - -#ifdef DEBUG -/* - * Useful for testing. - */ -void BMacEnet::_dump_srom() -{ - unsigned short data; - int i; - - for (i = 0; i < 128; i++) - { - reset_and_select_srom(ioBaseEnet); - data = read_srom(ioBaseEnet, i, sromAddressBits); - IOLog("Ethernet(BMac): %x = %x ", i, data); - if (i % 10 == 0) IOLog("\n"); - } -} - -void BMacEnet::_dumpDesc(void * addr, u_int32_t size) -{ - u_int32_t i; - unsigned long *p; - vm_offset_t paddr; - - _IOPhysicalFromVirtual( (vm_offset_t) addr, (vm_offset_t *)&paddr ); - - p = (unsigned long *)addr; - - for ( i=0; i < size/sizeof(IODBDMADescriptor); i++, p+=4, - paddr+=sizeof(IODBDMADescriptor) ) - { - IOLog("Ethernet(BMac): %08x(v) %08x(p): %08x %08x %08x %08x\n\r", - (int)p, - (int)paddr, - (int)OSReadSwapInt32(p, 0), (int)OSReadSwapInt32(p, 4), - (int)OSReadSwapInt32(p, 8), (int)OSReadSwapInt32(p, 12) ); - } -} - -void BMacEnet::_dumpRegisters() -{ - u_int16_t dataValue; - - IOLog("\nEthernet(BMac): IO Address = %08x", (int)ioBaseEnet ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kXIFC); - IOLog("\nEthernet(BMac): Read Register %04x Transceiver I/F = %04x", kXIFC, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kSTAT); - IOLog("\nEthernet(BMac): Read Register %04x Int Events = %04x", kSTAT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kINTDISABLE); - IOLog("\nEthernet(BMac): Read Register %04x Int Disable = %04x", kINTDISABLE, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXRST); - IOLog("\nEthernet(BMac): Read Register %04x Tx Reset = %04x", kTXRST, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXCFG); - IOLog("\nEthernet(BMac): Read Register %04x Tx Config = %04x", kTXCFG, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kIPG1); - IOLog("\nEthernet(BMac): Read Register %04x IPG1 = %04x", kIPG1, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kIPG2); - IOLog("\nEthernet(BMac): Read Register %04x IPG2 = %04x", kIPG2, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kALIMIT); - IOLog("\nEthernet(BMac): Read Register %04x Attempt Limit = %04x", kALIMIT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kSLOT); - IOLog("\nEthernet(BMac): Read Register %04x Slot Time = %04x", kSLOT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kPALEN); - IOLog("\nEthernet(BMac): Read Register %04x Preamble Length = %04x", kPALEN, dataValue ); - - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - dataValue = ReadBigMacRegister(ioBaseEnet, kPAPAT); - IOLog("\nEthernet(BMac): Read Register %04x Preamble Pattern = %04x", kPAPAT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXSFD); - IOLog("\nEthernet(BMac): Read Register %04x Tx Start Frame Delimeter = %04x", kTXSFD, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kJAM); - IOLog("\nEthernet(BMac): Read Register %04x Jam Size = %04x", kJAM, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXMAX); - IOLog("\nEthernet(BMac): Read Register %04x Tx Max Size = %04x", kTXMAX, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXMIN); - IOLog("\nEthernet(BMac): Read Register %04x Tx Min Size = %04x", kTXMIN, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kPAREG); - IOLog("\nEthernet(BMac): Read Register %04x Peak Attempts = %04x", kPAREG, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kDCNT); - IOLog("\nEthernet(BMac): Read Register %04x Defer Timer = %04x", kDCNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kNCCNT); - IOLog("\nEthernet(BMac): Read Register %04x Normal Collision Count = %04x", kNCCNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kNTCNT); - IOLog("\nEthernet(BMac): Read Register %04x Network Collision Count = %04x", kNTCNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kEXCNT); - IOLog("\nEthernet(BMac): Read Register %04x Excessive Coll Count = %04x", kEXCNT, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kLTCNT); - IOLog("\nEthernet(BMac): Read Register %04x Late Collision Count = %04x", kLTCNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRSEED); - IOLog("\nEthernet(BMac): Read Register %04x Random Seed = %04x", kRSEED, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXSM); - IOLog("\nEthernet(BMac): Read Register %04x Tx State Machine = %04x", kTXSM, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXRST); - IOLog("\nEthernet(BMac): Read Register %04x Rx Reset = %04x", kRXRST, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXCFG); - IOLog("\nEthernet(BMac): Read Register %04x Rx Config = %04x", kRXCFG, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXMAX); - IOLog("\nEthernet(BMac): Read Register %04x Rx Max Size = %04x", kRXMAX, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXMIN); - IOLog("\nEthernet(BMac): Read Register %04x Rx Min Size = %04x", kRXMIN, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMADD2); - IOLog("\nEthernet(BMac): Read Register %04x Mac Address 2 = %04x", kMADD2, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMADD1); - IOLog("\nEthernet(BMac): Read Register %04x Mac Address 1 = %04x", kMADD1, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMADD0); - IOLog("\nEthernet(BMac): Read Register %04x Mac Address 0 = %04x", kMADD0, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kFRCNT); - IOLog("\nEthernet(BMac): Read Register %04x Rx Frame Counter = %04x", kFRCNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kLECNT); - IOLog("\nEthernet(BMac): Read Register %04x Rx Length Error Cnt = %04x", kLECNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kAECNT); - IOLog("\nEthernet(BMac): Read Register %04x Alignment Error Cnt = %04x", kAECNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kFECNT); - IOLog("\nEthernet(BMac): Read Register %04x FCS Error Cnt = %04x", kFECNT, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXSM); - IOLog("\nEthernet(BMac): Read Register %04x Rx State Machine = %04x", kRXSM, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXCV); - IOLog("\nEthernet(BMac): Read Register %04x Rx Code Violation = %04x", kRXCV, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kHASH3); - IOLog("\nEthernet(BMac): Read Register %04x Hash 3 = %04x", kHASH3, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kHASH2); - IOLog("\nEthernet(BMac): Read Register %04x Hash 2 = %04x", kHASH2, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kHASH1); - IOLog("\nEthernet(BMac): Read Register %04x Hash 1 = %04x", kHASH1, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kHASH0); - IOLog("\nEthernet(BMac): Read Register %04x Hash 0 = %04x", kHASH0, dataValue ); - IOLog("\n-------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kAFR2); - IOLog("\nEthernet(BMac): Read Register %04x Address Filter 2 = %04x", kAFR2, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kAFR1); - IOLog("\nEthernet(BMac): Read Register %04x Address Filter 1 = %04x", kAFR1, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kAFR0); - IOLog("\nEthernet(BMac): Read Register %04x Address Filter 0 = %04x", kAFR0, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kAFCR); - IOLog("\nEthernet(BMac): Read Register %04x Adress Filter Mask = %04x", kAFCR, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXFIFOCSR); - IOLog("\nEthernet(BMac): Read Register %04x Tx FIFO CSR = %04x", kTXFIFOCSR, dataValue ); - IOLog("\n-------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXTH); - IOLog("\nEthernet(BMac): Read Register %04x Tx Threshold = %04x", kTXTH, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXFIFOCSR); - IOLog("\nEthernet(BMac): Read Register %04x Rx FIFO CSR = %04x", kRXFIFOCSR, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMEMADD); - IOLog("\nEthernet(BMac): Read Register %04x Mem Addr = %04x", kMEMADD, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATAHI); - IOLog("\nEthernet(BMac): Read Register %04x Mem Data High = %04x", kMEMDATAHI, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMEMDATALO); - IOLog("\nEthernet(BMac): Read Register %04x Mem Data Low = %04x", kMEMDATALO, dataValue ); - IOLog("\n-------------------------------------------------------" ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kXCVRIF); - IOLog("\nEthernet(BMac): Read Register %04x Transceiver IF Control = %04x", kXCVRIF, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kCHIPID); - IOLog("\nEthernet(BMac): Read Register %04x Chip ID = %04x", kCHIPID, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kMIFCSR); - IOLog("\nEthernet(BMac): Read Register %04x MII CSR = %04x", kMIFCSR, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kSROMCSR); - IOLog("\nEthernet(BMac): Read Register %04x SROM CSR = %04x", kSROMCSR, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kTXPNTR); - IOLog("\nEthernet(BMac): Read Register %04x Tx Pointer = %04x", kTXPNTR, dataValue ); - - dataValue = ReadBigMacRegister(ioBaseEnet, kRXPNTR); - IOLog("\nEthernet(BMac): Read Register %04x Rx Pointer = %04x", kRXPNTR, dataValue ); - IOLog("\nEthernet(BMac): -------------------------------------------------------\n" ); -} -#endif DEBUG - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn BMacEnet::getHardwareAddress(IOEthernetAddress *ea) -{ - int i; - unsigned short data; - - for (i = 0; i < (unsigned short)sizeof(*ea)/2; i++) - { - reset_and_select_srom(ioBaseEnet); - data = read_srom(ioBaseEnet, i + enetAddressOffset/2, sromAddressBits); - ea->bytes[2*i] = reverseBitOrder(data & 0x0ff); - ea->bytes[2*i+1] = reverseBitOrder((data >> 8) & 0x0ff); - } - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -#define ENET_CRCPOLY 0x04c11db7 - -/* Real fast bit-reversal algorithm, 6-bit values */ -static int reverse6[] = -{ 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38, - 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c, - 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a, - 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e, - 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39, - 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d, - 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b, - 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f -}; - -static u_int32_t crc416(unsigned int current, unsigned short nxtval ) -{ - register unsigned int counter; - register int highCRCBitSet, lowDataBitSet; - - /* Swap bytes */ - nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); - - /* Compute bit-by-bit */ - for (counter = 0; counter != 16; ++counter) - { /* is high CRC bit set? */ - if ((current & 0x80000000) == 0) - highCRCBitSet = 0; - else - highCRCBitSet = 1; - - current = current << 1; - - if ((nxtval & 0x0001) == 0) - lowDataBitSet = 0; - else - lowDataBitSet = 1; - - nxtval = nxtval >> 1; - - /* do the XOR */ - if (highCRCBitSet ^ lowDataBitSet) - current = current ^ ENET_CRCPOLY; - } - - return current; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -static u_int32_t mace_crc(unsigned short *address) -{ - register u_int32_t newcrc; - - newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ - newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ - newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ - - return(newcrc); -} - -/* - * Clear the hash table filter. - * - */ -void BMacEnet::_resetHashTableMask() -{ - bzero(hashTableUseCount, sizeof(hashTableUseCount)); - bzero(hashTableMask, sizeof(hashTableMask)); -} - -/* - * Add requested mcast addr to BMac's hash table filter. - * - */ -void BMacEnet::_addToHashTableMask(u_int8_t *addr) -{ - u_int32_t crc; - u_int16_t mask; - - crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ - crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ - if (hashTableUseCount[crc]++) - return; /* This bit is already set */ - mask = crc % 16; - mask = (unsigned short)1 << mask; - hashTableMask[crc/16] |= mask; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void BMacEnet::_removeFromHashTableMask(u_int8_t *addr) -{ - unsigned int crc; - u_int16_t mask; - - /* Now, delete the address from the filter copy, as indicated */ - crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ - crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ - if (hashTableUseCount[crc] == 0) - return; /* That bit wasn't in use! */ - - if (--hashTableUseCount[crc]) - return; /* That bit is still in use */ - - mask = crc % 16; - mask = (u_int16_t)1 << mask; /* To turn off bit */ - hashTableMask[crc/16] &= ~mask; -} - -/* - * Sync the adapter with the software copy of the multicast mask - * (logical address filter). - */ -void BMacEnet::_updateBMacHashTableMask() -{ - u_int16_t rxCFGReg; - - rxCFGReg = ReadBigMacRegister(ioBaseEnet, kRXCFG); - WriteBigMacRegister(ioBaseEnet, kRXCFG, - rxCFGReg & ~(kRxMACEnable | kRxHashFilterEnable) ); - - while ( ReadBigMacRegister(ioBaseEnet, kRXCFG) & - (kRxMACEnable | kRxHashFilterEnable) ) - ; - - WriteBigMacRegister(ioBaseEnet, kHASH0, hashTableMask[0]); // bits 15 - 0 - WriteBigMacRegister(ioBaseEnet, kHASH1, hashTableMask[1]); // bits 31 - 16 - WriteBigMacRegister(ioBaseEnet, kHASH2, hashTableMask[2]); // bits 47 - 32 - WriteBigMacRegister(ioBaseEnet, kHASH3, hashTableMask[3]); // bits 63 - 48 - - rxCFGReg |= kRxHashFilterEnable; - WriteBigMacRegister(ioBaseEnet, kRXCFG, rxCFGReg ); -} diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.h b/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.h deleted file mode 100644 index 2250fe75a..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Interface for hardware dependent (relatively) code - * for the BMac Ethernet chip - * - * HISTORY - * - */ - -#ifndef _BMACENETPRIVATE_H -#define _BMACENETPRIVATE_H - -#include "BMacEnet.h" -#include "BMacEnetMII.h" - -void WriteBigMacRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset, - u_int16_t data); - -volatile u_int16_t ReadBigMacRegister( IOPPCAddress ioEnetBase, - u_int32_t reg_offset); - -void reset_and_select_srom(IOPPCAddress base); - -u_int16_t read_srom(IOPPCAddress base, unsigned int addr, - unsigned int addr_len); - -#endif /* !_BMACENETPRIVATE_H */ diff --git a/iokit/Drivers/network/drvPPCBMac/BMacEnetRegisters.h b/iokit/Drivers/network/drvPPCBMac/BMacEnetRegisters.h deleted file mode 100644 index ca433076d..000000000 --- a/iokit/Drivers/network/drvPPCBMac/BMacEnetRegisters.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * Interface definition for the BigMac Ethernet controller. - * - * HISTORY - * - */ - -#ifndef _BMACENETREGISTERS_H -#define _BMACENETREGISTERS_H - -// --------------------------------------------------------------------------------------------- -// Heathrow (F)eature (C)ontrol (R)egister Addresses -// --------------------------------------------------------------------------------------------- -#define kHeathrowFCR 0x0038 // FCR offset from Heathrow Base Address -#define kEnetEnabledBits 0x60000000 // mask to enable Enet Xcvr/Controller -#define kResetEnetCell 0x80000000 // mask used to reset Enet cell -#define kClearResetEnetCell 0x7fffffff // mask used to clear reset Enet cell -#define kDisableEnet 0x1fffffff // mask to disable Enet Xcvr/Controller - - -// --------------------------------------------------------------------------------------------- -// BMAC & Heathrow I/O Addresses -// --------------------------------------------------------------------------------------------- -#define kTxDMABaseOffset 0x08200 // offset from Heathrow Base address -#define kRxDMABaseOffset 0x08300 -#define kControllerBaseOffset 0x11000 - - -// --------------------------------------------------------------------------------------------- -// BigMac Register Numbers & Bit Assignments -// --------------------------------------------------------------------------------------------- -#define kXIFC 0x0000 -#define kTxOutputEnable 0x0001 -#define kMIILoopbackBits 0x0006 -#define kMIIBufferEnable 0x0008 -#define kSQETestEnable 0x0010 -#define kSTAT 0x0200 -#define kINTDISABLE 0x0210 -#define kIntFrameReceived 0x0001 -#define kIntRxFrameCntExp 0x0002 -#define kIntRxAlignCntExp 0x0004 -#define kIntRxCRCCntExp 0x0008 -#define kIntRxLenCntExp 0x0010 -#define kIntRxOverFlow 0x0020 -#define kIntRxCodeViolation 0x0040 -#define kIntSQETestError 0x0080 -#define kIntFrameSent 0x0100 -#define kIntTxUnderrun 0x0200 -#define kIntTxMaxSizeError 0x0400 -#define kIntTxNormalCollExp 0x0800 -#define kIntTxExcessCollExp 0x1000 -#define kIntTxLateCollExp 0x2000 -#define kIntTxNetworkCollExp 0x4000 -#define kIntTxDeferTimerExp 0x8000 -#define kNormalIntEvents ~(0xFFFF & ( kIntFrameSent | kIntTxUnderrun) ) -#if EXTRA_INTERRUPTS - #define kXtraInterrupts ~(0xFFFF & (kIntFrameReceived | kIntRxFrameCntExp \ - | kIntFrameSent | kIntTxUnderrun | kIntFrameSent) ) -#endif -#define kNoEventsMask 0xFFFF -#define kTXRST 0x0420 -#define kTxResetBit 0x0001 -#define kTXCFG 0x0430 -#define kTxMACEnable 0x0001 -#define kTxThreshold 0x0004 -#define kTxSlowDown 0x0020 -#define kTxIgnoreCollision 0x0040 -#define kTxDisableFCS 0x0080 -#define kTxNoBackoff 0x0100 -#define kTxFullDuplex 0x0200 -#define kTxNeverGiveUp 0x0400 -#define kIPG1 0x0440 -#define kIPG2 0x0450 -#define kALIMIT 0x0460 -#define kSLOT 0x0470 -#define kPALEN 0x0480 -#define kPAPAT 0x0490 -#define kTXSFD 0x04A0 -#define kJAM 0x04B0 -#define kTXMAX 0x04C0 -#define kTXMIN 0x04D0 -#define kPAREG 0x04E0 -#define kDCNT 0x04F0 -#define kNCCNT 0x0500 -#define kNTCNT 0x0510 -#define kEXCNT 0x0520 -#define kLTCNT 0x0530 -#define kRSEED 0x0540 -#define kTXSM 0x0550 -#define kRXRST 0x0620 -#define kRxResetValue 0x0000 -#define kRXCFG 0x0630 -#define kRxMACEnable 0x0001 -#define kReservedValue 0x0004 -#define kRxPromiscEnable 0x0040 -#define kRxCRCEnable 0x0100 -#define kRxRejectOwnPackets 0x0200 -#define kRxHashFilterEnable 0x0800 -#define kRxAddrFilterEnable 0x1000 -#define kRXMAX 0x0640 -#define kRXMIN 0x0650 -#define kMADD2 0x0660 -#define kMADD1 0x0670 -#define kMADD0 0x0680 -#define kFRCNT 0x0690 -#define kLECNT 0x06A0 -#define kAECNT 0x06B0 -#define kFECNT 0x06C0 -#define kRXSM 0x06D0 -#define kRXCV 0x06E0 -#define kHASH3 0x0700 -#define kHASH2 0x0710 -#define kHASH1 0x0720 -#define kHASH0 0x0730 -#define kAFR2 0x0740 -#define kAFR1 0x0750 -#define kAFR0 0x0760 -#define kAFCR 0x0770 -#define kEnableAllCompares 0x0fff -#define kTXFIFOCSR 0x0100 -#define kTxFIFOEnable 0x0001 -#define kTxFIFO128 0x0000 -#define kTxFIFO2048 0x001e -#define kTXTH 0x0110 -#define kRXFIFOCSR 0x0120 -#define kRxFIFOEnable kTxFIFOEnable -#define kRxFIFO128 kTxFIFO128 -#define kRxFIFO2048 kTxFIFO2048 -#define kMEMADD 0x0130 -#define kMEMDATAHI 0x0140 -#define kMEMDATALO 0x0150 -#define kXCVRIF 0x0160 -#define kCOLActiveLow 0x0002 -#define kSerialMode 0x0004 -#define kClkBit 0x0008 -#define kLinkStatus 0x0100 -#define kCHIPID 0x0170 -#define kCHIPID_Heathrow 0xB0 -#define kCHIPID_Paddington 0xC0 -#define kCHIPID_PaddingtonXmitStreaming 0xC4 - -#define kMIFCSR 0x0180 -#define kMIFCSR_Clock 0x0001 -#define kMIFCSR_DataOut 0x0002 -#define kMIFCSR_DataOutEnable 0x0004 -#define kMIFCSR_DataIn 0x0008 -#define kSROMCSR 0x0190 -#define kTXPNTR 0x01A0 -#define kRXPNTR 0x01B0 - -// --------------------------------------------------------------------------------------------- -// Misc. Bit definitions for BMac Status word -// --------------------------------------------------------------------------------------------- -#define kRxAbortBit 0x8000 // status bit in BMac status for rx packets -#define kRxLengthMask 0x3FFF // bits that determine length of rx packets - - -#define TX_RING_LENGTH 33 -#define RX_RING_LENGTH 33 - -#define TX_PKTS_PER_INT 10 - -#define NETWORK_BUFSIZE (ETHERMAXPACKET + ETHERCRC + 2) -#define TRANSMIT_QUEUE_SIZE 1024 - -#define WATCHDOG_TIMER_MS 500 -#define TX_KDB_TIMEOUT 1000 - -#define TRANSMIT_QUIESCE_uS 200 -#define RECEIVE_QUIESCE_uS 1500 - - -enum -{ - kIRQEnetDev = 0, - kIRQEnetTxDMA = 1, - kIRQEnetRxDMA = 2 -}; - -enum -{ - MEMORY_MAP_ENET_INDEX = 0, - MEMORY_MAP_TXDMA_INDEX = 1, - MEMORY_MAP_RXDMA_INDEX = 2, - MEMORY_MAP_HEATHROW_INDEX = 3, - MEMORY_MAP_COUNT = 4 -}; - -#endif /* !_BMACENETREGISTERS_H */ diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp b/iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp deleted file mode 100644 index 958fbb6b4..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnet.cpp +++ /dev/null @@ -1,1071 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Computer - * - * Hardware independent (relatively) code for the Sun GEM Ethernet Controller - * - * HISTORY - * - * dd-mmm-yy - * Created. - * - */ - -//void call_kdp(void); - -#include "UniNEnetPrivate.h" - -#define super IOEthernetController - -OSDefineMetaClassAndStructors( UniNEnet, IOEthernetController ) - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::init(OSDictionary * properties) -{ - if ( super::init(properties) == false ) - return false; - - /* - * Initialize my ivars. - */ - phyId = 0xff; - linkStatusPrev = kLinkStatusUnknown; - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::start(IOService * provider) -{ - OSString *matchEntry; - - keyLargo_resetUniNEthernetPhy = OSSymbol::withCString("keyLargo_resetUniNEthernetPhy"); - - // Wait for KeyLargo to show up. - keyLargo = waitForService(serviceMatching("KeyLargo")); - if (keyLargo == 0) return false; - - nub = OSDynamicCast(IOPCIDevice, provider); - - if (!nub || !super::start(provider)) - { - return false; - } - - // Create spinlock to protect TxElementQueue. - - txQueueLock = IOSimpleLockAlloc(); - if ( txQueueLock == 0 ) return false; - IOSimpleLockInit(txQueueLock); - - transmitQueue = (IOGatedOutputQueue *) getOutputQueue(); - if (!transmitQueue) - { - IOLog("Ethernet(UniN): Output queue initialization failed\n"); - return false; - } - transmitQueue->retain(); - - /* - * Allocate debug queue. This stores packets retired from the TX ring - * by the polling routine. We cannot call freePacket() or m_free() within - * the debugger context. - * - * The capacity of the queue is set at maximum to prevent the queue from - * calling m_free() due to over-capacity. But we don't expect the size - * of the queue to grow too large. - */ - debugQueue = IOPacketQueue::withCapacity((UInt) -1); - if (!debugQueue) - { - return false; - } - - /* - * Allocate a IOMbufBigMemoryCursor instance. Currently, the maximum - * number of segments is set to 1. The maximum length for each segment - * is set to the maximum ethernet frame size (plus padding). - */ - mbufCursor = IOMbufBigMemoryCursor::withSpecification(NETWORK_BUFSIZE, 1); - if (!mbufCursor) - { - IOLog("Ethernet(UniN): IOMbufBigMemoryCursor allocation failure\n"); - return false; - } - - matchEntry = OSDynamicCast( OSString, getProperty( gIONameMatchedKey ) ); - if ( matchEntry == 0 ) - { - IOLog("Ethernet(UniN): Cannot obtain matching property.\n"); - return false; - } - - if ( matchEntry->isEqualTo( "gmac" ) == true ) - { - callPlatformFunction("EnableUniNEthernetClock", true, - (void *)true, 0, 0, 0); - } - - /* - * BUS MASTER, MEM I/O Space, MEM WR & INV - */ - nub->configWrite32( 0x04, 0x16 ); - - /* - * set Latency to Max , cache 32 - */ - nub->configWrite32( 0x0C, ((2 + (kGEMBurstSize * (0+1)))<< 8) | (CACHE_LINE_SIZE >> 2) ); - - ioMapEnet = nub->mapDeviceMemoryWithRegister( 0x10 ); - if ( ioMapEnet == NULL ) - { - return false; - } - ioBaseEnet = (volatile IOPPCAddress)ioMapEnet->getVirtualAddress(); - fpRegs = (GMAC_Registers*) ioBaseEnet; - phyId = (UInt8) -1; - - /* - * Get a reference to the IOWorkLoop in our superclass. - */ - IOWorkLoop * myWorkLoop = getWorkLoop(); - - /* - * Allocate three IOInterruptEventSources. - */ - interruptSource = IOInterruptEventSource::interruptEventSource( - (OSObject *) this, - (IOInterruptEventAction) &UniNEnet::interruptOccurred, - (IOService *) provider, - (int) 0 ); - - if ( interruptSource == NULL ) - { - IOLog("Ethernet(UniN): Couldn't allocate Interrupt event source\n"); - return false; - } - - if ( myWorkLoop->addEventSource( interruptSource ) != kIOReturnSuccess ) - { - IOLog("Ethernet(UniN): Couldn't add Interrupt event source\n"); - return false; - } - - - timerSource = IOTimerEventSource::timerEventSource - (this, (IOTimerEventSource::Action) &UniNEnet::timeoutOccurred); - if ( timerSource == NULL ) - { - IOLog("Ethernet(UniN): Couldn't allocate timer event source\n"); - return false; - } - - if ( myWorkLoop->addEventSource( timerSource ) != kIOReturnSuccess ) - { - IOLog("Ethernet(UniN): Couldn't add timer event source\n"); - return false; - } - - MGETHDR(txDebuggerPkt, M_DONTWAIT, MT_DATA); - - if (!txDebuggerPkt) - { - IOLog("Ethernet(UniN): Couldn't allocate KDB buffer\n"); - return false; - } - - /* - * Perform a hardware reset. - */ - if ( resetAndEnable(false) == false ) - { - IOLog("Ethernet(UniN): resetAndEnable() failed\n"); - return false; - } - - /* - * Cache my MAC address. - */ - if ( getHardwareAddress(&myAddress) != kIOReturnSuccess ) - { - IOLog("Ethernet(UniN): getHardwareAddress() failed\n"); - return false; - } - - /* - * Allocate memory for ring buffers. - */ - if ( allocateMemory() == false) - { - IOLog("Ethernet(UniN): allocateMemory() failed\n"); - return false; - } - - if ( createMediumTables() == false ) - { - IOLog("Ethernet(UniN): createMediumTables() failed\n"); - return false; - } - - /* - * Attach an IOEthernetInterface client. But don't registers it just yet. - */ - if ( !attachInterface((IONetworkInterface **) &networkInterface, false) ) - { - IOLog("Ethernet(UniN): attachInterface() failed\n"); - return false; - } - - /* - * Attach a kernel debugger client. - */ - attachDebuggerClient(&debugger); - - /* - * Ready to service interface requests. - */ - networkInterface->registerService(); - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::configureInterface(IONetworkInterface * netif) -{ - IONetworkData * nd; - - if ( super::configureInterface( netif ) == false ) - return false; - - /* - * Grab a pointer to the statistics structure in the interface. - */ - nd = netif->getNetworkData( kIONetworkStatsKey ); - if (!nd || !(fpNetStats = (IONetworkStats *) nd->getBuffer())) - { - IOLog("EtherNet(UniN): invalid network statistics\n"); - return false; - } - - // Get the Ethernet statistics structure: - nd = netif->getParameter( kIOEthernetStatsKey ); - if ( !nd || !(fpEtherStats = (IOEthernetStats*)nd->getBuffer()) ) - { - IOLog("EtherNet(UniN): invalid ethernet statistics\n"); - return false; - } - - /* - * Set the driver/stack reentrancy flag. This is meant to reduce - * context switches. May become irrelevant in the future. - */ - return true; -}/* end configureInterface */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::free() -{ - TxQueueElement * txElement; - - resetAndEnable(false); - - if (debugger) - debugger->release(); - - if (getWorkLoop()) - { - getWorkLoop()->disableAllEventSources(); - } - - if (timerSource) - { - timerSource->release(); - timerSource = 0; - } - - if (interruptSource) - { - interruptSource->release(); - } - - if (txDebuggerPkt) - { - freePacket(txDebuggerPkt); - } - - if (transmitQueue) - { - transmitQueue->release(); - } - - if (debugQueue) - { - debugQueue->release(); - } - - if (networkInterface) - { - networkInterface->release(); - } - - if (mbufCursor) - { - mbufCursor->release(); - } - - if ( mediumDict ) - { - mediumDict->release(); - } - - while ( ( txElement = getTxElement() ) ) - { - IOFree( txElement, sizeof(TxQueueElement) ); - } - - if ( ioMapEnet ) - { - ioMapEnet->release(); - } - - if ( dmaCommands != 0 ) - { - IOFreeContiguous( (void *)dmaCommands, dmaCommandsSize ); - } - - if ( workLoop ) - { - workLoop->release(); - workLoop = 0; - } - - if ( txQueueLock ) - { - IOSimpleLockFree( txQueueLock ); - txQueueLock = 0; - } - - super::free(); -} - -/*------------------------------------------------------------------------- - * Override IONetworkController::createWorkLoop() method and create - * a workloop. - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::createWorkLoop() -{ - workLoop = IOWorkLoop::workLoop(); - - return ( workLoop != 0 ); -} - -/*------------------------------------------------------------------------- - * Override IOService::getWorkLoop() method to return our workloop. - * - * - *-------------------------------------------------------------------------*/ - -IOWorkLoop * UniNEnet::getWorkLoop() const -{ - return workLoop; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::interruptOccurred(IOInterruptEventSource * src, int /*count*/) -{ - IODebuggerLockState lockState; - UInt32 interruptStatus; - bool doFlushQueue; - bool doService; - - - if ( ready == false ) return; - - do - { - lockState = IODebuggerLock( this ); - - interruptStatus = READ_REGISTER( Status ) - & ( kStatus_TX_INT_ME | kStatus_RX_DONE ); - - doService = false; - - if ( interruptStatus & kStatus_TX_INT_ME ) - { - txWDInterrupts++; - KERNEL_DEBUG(DBG_GEM_TXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doService = transmitInterruptOccurred(); - KERNEL_DEBUG(DBG_GEM_TXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - ETHERNET_STAT_ADD( dot3TxExtraEntry.interrupts ); - } - - doFlushQueue = false; - - if ( interruptStatus & kStatus_RX_DONE ) - { - rxWDInterrupts++; - KERNEL_DEBUG(DBG_GEM_RXIRQ | DBG_FUNC_START, 0, 0, 0, 0, 0 ); - doFlushQueue = receiveInterruptOccurred(); - KERNEL_DEBUG(DBG_GEM_RXIRQ | DBG_FUNC_END, 0, 0, 0, 0, 0 ); - ETHERNET_STAT_ADD( dot3RxExtraEntry.interrupts ); - } - - IODebuggerUnlock( lockState ); - - /* - * Submit all received packets queued up by _receiveInterruptOccurred() - * to the network stack. The up call is performed without holding the - * debugger lock. - */ - if (doFlushQueue) - { - networkInterface->flushInputQueue(); - } - - /* - * Make sure the output queue is not stalled. - */ - if (doService && netifEnabled) - { - transmitQueue->service(); - } - } - while ( interruptStatus ); - -// interruptSource->enable(); - return; -}/* end interruptOccurred */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -UInt32 UniNEnet::outputPacket(struct mbuf * pkt, void * param) -{ - UInt32 ret = kIOReturnOutputSuccess; - - KERNEL_DEBUG( DBG_GEM_TXQUEUE | DBG_FUNC_NONE, - (int) pkt, (int) pkt->m_pkthdr.len, 0, 0, 0 ); - - /* - * Hold the debugger lock so the debugger can't interrupt us - */ - reserveDebuggerLock(); - - if ( linkStatusPrev != kLinkStatusUp ) - { - freePacket( pkt ); - } - else if ( transmitPacket(pkt) == false ) - { - ret = kIOReturnOutputStall; - } - - releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::resetAndEnable(bool enable) -{ - bool ret = true; - - reserveDebuggerLock(); - - ready = false; - - if (timerSource) - { - timerSource->cancelTimeout(); - } - - disableAdapterInterrupts(); - if (getWorkLoop()) - { - getWorkLoop()->disableAllInterrupts(); - } - - if (enable) - { - phyId = 0xff; - } - - if ( resetChip() == false ) - { - ret = false; - goto resetAndEnable_exit; - } - - // Initialize the link status. - - setLinkStatus( 0, 0 ); - - // Flush all mbufs from RX and TX rings. - - flushRings(); - - while (enable) - { - if (!initRxRing() || !initTxRing()) - { - ret = false; - break; - } - - if ( phyId != 0xff ) - { - miiInitializePHY(phyId); - } - - if (initChip() == false) - { - ret = false; - break; - } - -// startChip(); - - timerSource->setTimeoutMS(WATCHDOG_TIMER_MS); - - if (getWorkLoop()) - { - getWorkLoop()->enableAllInterrupts(); - } - enableAdapterInterrupts(); - - ready = true; - - monitorLinkStatus( true ); - - break; - } - -resetAndEnable_exit: ; - - releaseDebuggerLock(); - - return ret; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to enable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::enable(IONetworkInterface * netif) -{ - /* - * If an interface client has previously enabled us, - * and we know there can only be one interface client - * for this driver, then simply return true. - */ - if ( netifEnabled ) - { - IOLog("EtherNet(UniN): already enabled\n"); - return kIOReturnSuccess; - } - - if ( (ready == false) && !resetAndEnable(true) ) - return kIOReturnIOError; - - /* - * Mark the controller as enabled by the interface. - */ - netifEnabled = true; - - /* - * Start our IOOutputQueue object. - */ - transmitQueue->setCapacity( TRANSMIT_QUEUE_SIZE ); - transmitQueue->start(); - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * Called by IOEthernetInterface client to disable the controller. - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::disable(IONetworkInterface * /*netif*/) -{ - /* - * Disable our IOOutputQueue object. This will prevent the - * outputPacket() method from being called. - */ - transmitQueue->stop(); - - /* - * Flush all packets currently in the output queue. - */ - transmitQueue->setCapacity(0); - transmitQueue->flush(); - - /* - * If we have no active clients, then disable the controller. - */ - if ( debugEnabled == false ) - { - resetAndEnable(false); - } - - netifEnabled = false; - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to bring up the controller - * just before the controller is registered as the debugger device. The - * debugger client is attached in response to the attachDebuggerClient() - * call. - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::enable(IOKernelDebugger * /*debugger*/) -{ - /* - * Enable hardware and make it ready to support the debugger client. - */ - if ( (ready == false) && !resetAndEnable(true) ) - { - return kIOReturnIOError; - } - - /* - * Mark the controller as enabled by the debugger. - */ - debugEnabled = true; - - /* - * Returning true will allow the kdp registration to continue. - * If we return false, then we will not be registered as the - * debugger device, and the attachDebuggerClient() call will - * return NULL. - */ - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * This method is called by our debugger client to stop the controller. - * The debugger will call this method when we issue a detachDebuggerClient(). - * - * This method is always called while running on the default workloop - * thread. - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::disable(IOKernelDebugger * /*debugger*/) -{ - debugEnabled = false; - - /* - * If we have no active clients, then disable the controller. - */ - if ( netifEnabled == false ) - { - resetAndEnable(false); - } - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::timeoutOccurred(IOTimerEventSource * /*timer*/) -{ - IODebuggerLockState lockState; - bool doService = false; - UInt32 txRingIndex; - UInt32 x; - - - if ( ready == false ) - { - // IOLog("EtherNet(UniN): Spurious timeout event!!\n"); - return; - } - - - /* Update statistics from the GMAC statistics registers: */ - - x = READ_REGISTER( LengthErrorCounter ); - writeRegister( &fpRegs->LengthErrorCounter, 0 ); - fpEtherStats->dot3StatsEntry.frameTooLongs += x; - - x = READ_REGISTER( AlignmentErrorCounter ); - writeRegister( &fpRegs->AlignmentErrorCounter, 0 ); - fpEtherStats->dot3StatsEntry.alignmentErrors += x; - - x = READ_REGISTER( FCSErrorCounter ); - writeRegister( &fpRegs->FCSErrorCounter, 0 ); - fpEtherStats->dot3StatsEntry.fcsErrors += x; - - x = READ_REGISTER( RxCodeViolationErrorCounter ); - writeRegister( &fpRegs->RxCodeViolationErrorCounter, 0 ); - fpEtherStats->dot3StatsEntry.internalMacTransmitErrors += x; - - x = READ_REGISTER( FirstAttemptSuccessfulCollisionCounter ); - writeRegister( &fpRegs->FirstAttemptSuccessfulCollisionCounter, 0 ); - fpEtherStats->dot3StatsEntry.singleCollisionFrames += x; - - x = READ_REGISTER( ExcessiveCollisionCounter ); - writeRegister( &fpRegs->ExcessiveCollisionCounter, 0 ); - fpEtherStats->dot3StatsEntry.excessiveCollisions += x; - - x = READ_REGISTER( LateCollisionCounter ); - writeRegister( &fpRegs->LateCollisionCounter, 0 ); - fpEtherStats->dot3StatsEntry.lateCollisions += x; - - lockState = IODebuggerLock( this ); - - monitorLinkStatus(); - - /* - * If there are pending entries on the Tx ring - */ - if ( txCommandHead != txCommandTail ) - { - /* - * If the hardware tx pointer did not move since the last - * check, increment the txWDCount. - */ - txRingIndex = READ_REGISTER( TxCompletion ); - if ( txRingIndex == txRingIndexLast ) - { - txWDCount++; - } - else - { - txWDCount = 0; - txRingIndexLast = txRingIndex; - } - - if ( txWDCount > 2 ) - { - /* - * We only take interrupts every 64 tx completions, so we may be here just - * to do normal clean-up of tx packets. We check if the hardware tx pointer - * points to the next available tx slot. This indicates that we transmitted all - * packets that were scheduled vs rather than the hardware tx being stalled. - */ - if ( txRingIndex != txCommandTail ) - { - UInt32 interruptStatus, compReg, kickReg; - - interruptStatus = READ_REGISTER( Status ); - compReg = READ_REGISTER( TxCompletion ); - kickReg = READ_REGISTER( TxKick ); - - IOLog( "Tx Int Timeout - Comp = %04x Kick = %04x Int = %08x\n\r", (int)compReg, (int)kickReg, (int)interruptStatus ); - } - -// dumpRegisters(); - - transmitInterruptOccurred(); - - doService = true; - - txRingIndexLast = txRingIndex; - txWDCount = 0; - } - } - else - { - txWDCount = 0; - } - - // Monitor receiver's health. - - if ( rxWDInterrupts == 0 ) - { - UInt32 rxMACStatus; - - switch ( rxWDCount ) - { - case 0: - case 1: - rxWDCount++; // Extend timeout - break; - - default: - // We could be less conservative here and restart the - // receiver unconditionally. - - rxMACStatus = READ_REGISTER( RxMACStatus ); - - if ( rxMACStatus & kRX_MAC_Status_Rx_Overflow ) - { - // Bad news, the receiver may be deaf as a result of this - // condition, and if so, a RX MAC reset is needed. Note - // that reading this register will clear all bits. - - restartReceiver(); - - NETWORK_STAT_ADD( inputErrors ); - ETHERNET_STAT_ADD( dot3RxExtraEntry.watchdogTimeouts ); - } - rxWDCount = 0; - break; - } - } - else - { - // Reset watchdog - - rxWDCount = 0; - rxWDInterrupts = 0; - } - - /* Clean-up after the debugger if the debugger was active: */ - - if ( debugTxPoll ) - { - debugQueue->flush(); - debugTxPoll = false; - doService = true; - } - IODebuggerUnlock( lockState ); - - /* - * Make sure the queue is not stalled. - */ - if (doService && netifEnabled) - { - transmitQueue->service(); - } - - /* - * Restart the watchdog timer - */ - timerSource->setTimeoutMS(WATCHDOG_TIMER_MS); - return; -}/* end timeoutOccurred */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -const OSString * UniNEnet::newVendorString() const -{ - return OSString::withCString("Apple"); -} - -const OSString * UniNEnet::newModelString() const -{ - return OSString::withCString("gmac+"); -} - -const OSString * UniNEnet::newRevisionString() const -{ - return OSString::withCString(""); -} - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::setPromiscuousMode(IOEnetPromiscuousMode mode) -{ - reserveDebuggerLock(); - - rxMacConfigReg = READ_REGISTER( RxMACConfiguration ); - if (mode == kIOEnetPromiscuousModeOff) - { - rxMacConfigReg &= ~(kRxMACConfiguration_Promiscuous); - isPromiscuous = false; - - } - else - { - rxMacConfigReg |= kRxMACConfiguration_Promiscuous; - isPromiscuous = true; - - } - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); - - releaseDebuggerLock(); - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::setMulticastMode(IOEnetMulticastMode mode) -{ - multicastEnabled = (mode == kIOEnetMulticastModeOff) ? false : true; - - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::setMulticastList(IOEthernetAddress *addrs, UInt32 count) -{ - reserveDebuggerLock(); - - resetHashTableMask(); - for (UInt32 i = 0; i < count; i++) - { - addToHashTableMask(addrs->bytes); - addrs++; - } - updateHashTableMask(); - - releaseDebuggerLock(); - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOOutputQueue* UniNEnet::createOutputQueue() -{ - return IOBasicOutputQueue::withTarget( this, TRANSMIT_QUEUE_SIZE ); -}/* end createOutputQueue */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -static struct MediumTable -{ - UInt32 type; - UInt32 speed; -} -mediumTable[] = -{ - { kIOMediumEthernetNone , 0 }, - { kIOMediumEthernetAuto , 0 }, - { kIOMediumEthernet10BaseT | kIOMediumOptionHalfDuplex, 10 }, - { kIOMediumEthernet10BaseT | kIOMediumOptionFullDuplex, 10 }, - { kIOMediumEthernet100BaseTX | kIOMediumOptionHalfDuplex, 100 }, - { kIOMediumEthernet100BaseTX | kIOMediumOptionFullDuplex, 100 }, - { kIOMediumEthernet1000BaseSX | kIOMediumOptionFullDuplex, 1000 }, - { kIOMediumEthernet1000BaseTX | kIOMediumOptionFullDuplex, 1000 } -}; - - -bool UniNEnet::createMediumTables() -{ - IONetworkMedium *medium; - UInt32 i; - - mediumDict = OSDictionary::withCapacity( sizeof(mediumTable)/sizeof(mediumTable[0]) ); - if ( mediumDict == 0 ) return false; - - for ( i=0; i < sizeof(mediumTable)/sizeof(mediumTable[0]); i++ ) - { - medium = IONetworkMedium::medium( mediumTable[i].type, mediumTable[i].speed ); - if ( medium != 0 ) - { - IONetworkMedium::addMedium( mediumDict, medium ); - medium->release(); - } - } - - if ( publishMediumDictionary( mediumDict ) != true ) - { - return false; - } - - medium = IONetworkMedium::getMediumWithType( mediumDict, - kIOMediumEthernetAuto ); - - setCurrentMedium( medium ); - - return true; -} - - -void UniNEnet::writeRegister( UInt32 *pReg, UInt32 data ) -{ -/// ELG( data, (UInt32)pReg - (UInt32)fpRegs, 'wReg', "writeRegister" ); - - OSWriteLittleInt32( pReg, 0, data ); - return; -}/* end writeRegister */ diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnet.h b/iokit/Drivers/network/drvPPCUniN/UniNEnet.h deleted file mode 100644 index 235ff2b14..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnet.h +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Software, Inc. - * - * Interface definition for the UniN Ethernet Controller - * - * HISTORY - * - */ - -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IOGatedOutputQueue.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/network/IOMbufMemoryCursor.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/IOLib.h> /* bcopy */ - -extern "C" -{ - #include <sys/param.h> - #include <sys/mbuf.h> -} - -//#define IOLog kprintf - -// No kernel tracing support at this time. -// -#define KERNEL_DEBUG(x,a,b,c,d,e) - -#include "UniNEnetRegisters.h" - - - -#define NETWORK_STAT_ADD( x ) (fpNetStats->x++) -#define ETHERNET_STAT_ADD( x ) (fpEtherStats->x++) - -#define READ_REGISTER( REG ) OSReadLittleInt32( (void*)&fpRegs->REG, 0 ) -#define DBG_WRITE 0 -#if DBG_WRITE -#define WRITE_REGISTER( REG, VAL ) writeRegister( &fpRegs->REG, VAL ) -#else -#define WRITE_REGISTER( REG, VAL ) OSWriteLittleInt32( (void*)&fpRegs->REG, 0, VAL ) -#endif // DBG_WRITE - - -typedef void * IOPPCAddress; - -#define NUM_RX_DESC 1 -typedef struct enet_dma_cmd_t -{ - GEMRxDescriptor desc_seg[NUM_RX_DESC]; -} enet_dma_cmd_t; - -#define NUM_TX_DESC 1 -typedef struct enet_txdma_cmd_t -{ - GEMTxDescriptor desc_seg[NUM_TX_DESC]; -} enet_txdma_cmd_t; - - -typedef struct TxQueueElement -{ - queue_chain_t next; - queue_head_t * list; - - struct mbuf * mbuf; - UInt32 slot; - UInt32 count; -} TxQueueElement; - -enum LinkStatus -{ - kLinkStatusUnknown, - kLinkStatusDown, - kLinkStatusUp, -}; - -#define kMaxUniNEnetPowerState 1 -#define kUniNsettle_time 500 //guess 500 microseconds for settling - - -class UniNEnet: public IOEthernetController -{ - OSDeclareDefaultStructors( UniNEnet ) - -private: - volatile GMAC_Registers *fpRegs; - IOPCIDevice * nub; - IOMemoryMap * ioMapEnet; - volatile IOPPCAddress ioBaseEnet; - - IOEthernetInterface * networkInterface; - IOBasicOutputQueue * transmitQueue; - IOPacketQueue * debugQueue; - IOKernelDebugger * debugger; - - IOWorkLoop * workLoop; - IOInterruptEventSource * interruptSource; - IONetworkStats * fpNetStats; - IOEthernetStats * fpEtherStats; - IOTimerEventSource * timerSource; - IOMbufBigMemoryCursor * mbufCursor; - IOSimpleLock * txQueueLock; - - bool ready; - bool netifEnabled; - bool debugEnabled; - bool debugTxPoll; - - IOEthernetAddress myAddress; - bool isPromiscuous; - bool multicastEnabled; - bool isFullDuplex; - - UInt32 phyType; - UInt8 phyId; - - UInt16 phyStatusPrev; - UInt32 linkStatusPrev; - - UInt16 phyBCMType; // 5400 or 5201 for PM - - OSDictionary * mediumDict; - - queue_head_t txActiveQueue; - queue_head_t txFreeQueue; - - TxQueueElement * txElementPtrs[TX_RING_LENGTH]; - struct mbuf * rxMbuf[RX_RING_LENGTH]; - struct mbuf * txDebuggerPkt; - - void * debuggerPkt; - u_int32_t debuggerPktSize; - - UInt32 txCommandHead; // TX ring descriptor index - UInt32 txCommandTail; - UInt32 rxCommandHead; // RX ring descriptor index - UInt32 rxCommandTail; - - UInt32 dmaCommandsSize; - UInt8 * dmaCommands; - enet_txdma_cmd_t * txDMACommands; // TX descriptor ring ptr - UInt32 txDMACommandsPhys; - UInt32 txCommandsAvail; - - enet_dma_cmd_t * rxDMACommands; // RX descriptor ring ptr - UInt32 rxDMACommandsPhys; - - UInt32 txIntCnt; - UInt32 txRingIndexLast; - UInt32 txWDInterrupts; - UInt32 txWDCount; - - UInt32 rxWDInterrupts; - UInt32 rxWDCount; - UInt32 rxMacConfigReg; - - UInt16 hashTableUseCount[256]; - UInt16 hashTableMask[16]; - - unsigned long currentPowerState; /* must be 0 or 1 */ - - bool allocateMemory(); - bool initTxRing(); - bool initRxRing(); - void flushRings(); - bool initChip(); - bool resetChip(); - void disableAdapterInterrupts(); - void enableAdapterInterrupts(); - void setDuplexMode(bool duplexMode); - void startChip(); - void stopChip(); - bool updateDescriptorFromMbuf(struct mbuf * m, - enet_dma_cmd_t * desc, - bool isReceive); - void monitorLinkStatus( bool firstPoll = false ); - void restartTransmitter(); - void stopTransmitDMA(); - bool transmitPacket(struct mbuf * packet); - bool transmitInterruptOccurred(); - bool debugTransmitInterruptOccurred(); - void debugTransmitCleanup(); - bool receiveInterruptOccurred(); - bool receivePackets(bool fDebugger); - void packetToDebugger(struct mbuf * packet, u_int size); - void restartReceiver(); - void stopReceiveDMA(); - bool resetAndEnable(bool enable); - void sendDummyPacket(); - void resetHashTableMask(); - void addToHashTableMask(u_int8_t *addr); - void removeFromHashTableMask(u_int8_t *addr); - void updateHashTableMask(); - - - TxQueueElement * getTxElement(); - void releaseTxElement(TxQueueElement * txElement); - -#ifdef DEBUG - void dumpRegisters(); -#endif DEBUG - - void sendPacket(void * pkt, UInt32 pkt_len); - void receivePacket(void * pkt, UInt32 * pkt_len, - UInt32 timeout); - - bool miiReadWord(unsigned short * dataPtr, - unsigned short reg, UInt8 phy); - bool miiWriteWord(unsigned short data, - unsigned short reg, UInt8 phy); - void miiWrite(UInt32 miiData, UInt32 dataSize); - bool miiResetPHY(UInt8 phy); - bool miiWaitForLink(UInt8 phy); - bool miiWaitForAutoNegotiation(UInt8 phy); - void miiRestartAutoNegotiation(UInt8 phy); - bool miiFindPHY(UInt8 * phy_num); - bool miiInitializePHY(UInt8 phy); - - UInt32 outputPacket(struct mbuf * m, void * param); - - void interruptOccurred(IOInterruptEventSource * src, - int count); - void timeoutOccurred(IOTimerEventSource * timer); - bool createMediumTables(); - - void writeRegister( UInt32 *pReg, UInt32 data ); - - void stopPHYChip(bool setupWOL); - void startPHYChip(); - bool resetPHYChip(); - - // callPlatformFunction symbols - const OSSymbol *keyLargo_resetUniNEthernetPhy; - - IOService *keyLargo; - -public: - virtual bool init(OSDictionary * properties = 0); - virtual bool start(IOService * provider); - virtual void free(); - - virtual bool createWorkLoop(); - virtual IOWorkLoop * getWorkLoop() const; - - virtual IOReturn enable(IONetworkInterface * netif); - virtual IOReturn disable(IONetworkInterface * netif); - - virtual IOReturn getHardwareAddress(IOEthernetAddress *addr); - - virtual IOReturn setMulticastMode(IOEnetMulticastMode mode); - virtual IOReturn setMulticastList(IOEthernetAddress *addrs, UInt32 count); - - virtual IOReturn setPromiscuousMode(IOEnetPromiscuousMode mode); - - virtual IOOutputQueue * createOutputQueue(); - - virtual const OSString * newVendorString() const; - virtual const OSString * newModelString() const; - virtual const OSString * newRevisionString() const; - - virtual IOReturn enable(IOKernelDebugger * debugger); - virtual IOReturn disable(IOKernelDebugger * debugger); - - virtual bool configureInterface(IONetworkInterface * netif); - - // Power management methods: - virtual IOReturn registerWithPolicyMaker(IOService * policyMaker); - virtual UInt32 maxCapabilityForDomainState(IOPMPowerFlags state); - virtual UInt32 initialPowerStateForDomainState(IOPMPowerFlags state); - virtual UInt32 powerStateForDomainState(IOPMPowerFlags state); - virtual IOReturn setPowerState(UInt32 powerStateOrdinal, - IOService * whatDevice); -}; - - -/* - * Performance tracepoints - * - * DBG_UniN_RXIRQ - Receive ISR run time - * DBG_UniN_TXIRQ - Transmit ISR run time - * DBG_UniN_TXQUEUE - Transmit packet passed from network stack - * DBG_UniN_TXCOMPLETE - Transmit packet sent - * DBG_UniN_RXCOMPLETE - Receive packet passed to network stack - */ -#define DBG_UniN_ENET 0x0900 -#define DBG_UniN_RXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_UniN_ENET+1)) -#define DBG_UniN_TXIRQ DRVDBG_CODE(DBG_DRVNETWORK,(DBG_UniN_ENET+2)) -#define DBG_UniN_TXQUEUE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_UniN_ENET+3)) -#define DBG_UniN_TXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_UniN_ENET+4)) -#define DBG_UniN_RXCOMPLETE DRVDBG_CODE(DBG_DRVNETWORK,(DBG_UniN_ENET+5)) diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetHW.cpp b/iokit/Drivers/network/drvPPCUniN/UniNEnetHW.cpp deleted file mode 100644 index c6c2b8db2..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetHW.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Software, Inc. - * - * Miscellaneous definitions for the Sun GEM Ethernet controller. - * - * HISTORY - * - */ - -#include "UniNEnetPrivate.h" - - -void xWriteUniNRegister( IOPPCAddress ioBaseEnet, u_int32_t reg_offset, u_int32_t data ) -{ - switch ( reg_offset >> 16 ) - { - case 1: - ((u_int8_t *) ioBaseEnet)[reg_offset & 0xffff] = data; - break; - case 2: - ((u_int16_t *)ioBaseEnet)[(reg_offset & 0xFFFF) >> 1] = OSSwapInt16( data ); - break; - case 4: - ((u_int32_t *)ioBaseEnet)[(reg_offset & 0xFFFF) >> 2] = OSSwapInt32( data ); - break; - } - eieio(); -} - - -volatile u_int32_t xReadUniNRegister( IOPPCAddress ioBaseEnet, u_int32_t reg_offset ) -{ - switch ( reg_offset >> 16 ) - { - case 1: - return ((u_int8_t *) ioBaseEnet)[reg_offset & 0xffff]; - - case 2: - return OSSwapInt16( ((u_int16_t *)ioBaseEnet)[(reg_offset & 0xFFFF) >> 1] ); - - case 4: - return OSSwapInt32( ((u_int32_t *)ioBaseEnet)[(reg_offset & 0xFFFF) >> 2] ); - } - - return 0; -} - - -/* - * Procedure for reading EEPROM - */ diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.cpp b/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.cpp deleted file mode 100644 index af9004a62..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * MII/PHY (National Semiconductor DP83840/DP83840A) support methods. - * It is general enough to work with most MII/PHYs. - * - * HISTORY - * - */ -#include "UniNEnetPrivate.h" - - -/* - * Read from MII/PHY registers. - */ -bool UniNEnet::miiReadWord( UInt16 *dataPtr, UInt16 reg, UInt8 phy ) -{ - UInt32 i; - UInt32 miiReg; - - WRITE_REGISTER( MIFBitBangFrame_Output, - kMIFBitBangFrame_Output_ST_default - | kMIFBitBangFrame_Output_OP_read - | phy << kMIFBitBangFrame_Output_PHYAD_shift - | reg << kMIFBitBangFrame_Output_REGAD_shift - | kMIFBitBangFrame_Output_TA_MSB ); - - for (i=0; i < 20; i++ ) - { - miiReg = READ_REGISTER( MIFBitBangFrame_Output ); - - if ( miiReg & kMIFBitBangFrame_Output_TA_LSB ) - { -// IOLog("Phy = %d Reg = %d miiReg = %08x\n\r", phy, reg, miiReg ); - *dataPtr = (UInt16) miiReg; - return true; - } - IODelay(10); - } - - return false; -} - -/* - * Write to MII/PHY registers. - */ -bool UniNEnet::miiWriteWord( UInt16 data, UInt16 reg, UInt8 phy ) -{ - UInt32 i; - UInt32 miiReg; - - - WRITE_REGISTER( MIFBitBangFrame_Output, - kMIFBitBangFrame_Output_ST_default - | kMIFBitBangFrame_Output_OP_write - | phy << kMIFBitBangFrame_Output_PHYAD_shift - | reg << kMIFBitBangFrame_Output_REGAD_shift - | kMIFBitBangFrame_Output_TA_MSB - | data ); - - for ( i=0; i < 20; i++ ) - { - miiReg = READ_REGISTER( MIFBitBangFrame_Output ); - - if ( miiReg & kMIFBitBangFrame_Output_TA_LSB ) - { - return true; - } - IODelay(10); - } - - return false; -} - - -bool UniNEnet::miiResetPHY( UInt8 phy ) -{ - int i = MII_RESET_TIMEOUT; - UInt16 mii_control; - - // Set the reset bit - // - miiWriteWord( MII_CONTROL_RESET, MII_CONTROL, phy ); - - IOSleep(MII_RESET_DELAY); - - // Wait till reset process is complete (MII_CONTROL_RESET returns to zero) - // - while ( i > 0 ) - { - if ( miiReadWord( &mii_control, MII_CONTROL, phy) == false ) - return false; - - if (!(mii_control & MII_CONTROL_RESET)) - { - miiReadWord( &mii_control, MII_CONTROL, phy); - mii_control &= ~MII_CONTROL_ISOLATE; - miiWriteWord( mii_control, MII_CONTROL, phy ); - return true; - } - - IOSleep(MII_RESET_DELAY); - i -= MII_RESET_DELAY; - } - return false; -} - -bool UniNEnet::miiWaitForLink( UInt8 phy ) -{ - int i = MII_LINK_TIMEOUT; - unsigned short mii_status; - - while (i > 0) - { - if ( miiReadWord( &mii_status, MII_STATUS, phy ) == false) - return false; - - if (mii_status & MII_STATUS_LINK_STATUS) - return true; - - IOSleep(MII_LINK_DELAY); - i -= MII_LINK_DELAY; - } - return false; -} - -bool UniNEnet::miiWaitForAutoNegotiation( UInt8 phy ) -{ - int i = MII_LINK_TIMEOUT; - unsigned short mii_status; - - while (i > 0) - { - if ( miiReadWord( &mii_status, MII_STATUS, phy ) == false) - return false; - - if (mii_status & MII_STATUS_NEGOTIATION_COMPLETE) - return true; - - IOSleep(MII_LINK_DELAY); - i -= MII_LINK_DELAY; - } - return false; -} - -void UniNEnet::miiRestartAutoNegotiation( UInt8 phy ) -{ - unsigned short mii_control; - - miiReadWord( &mii_control, MII_CONTROL, phy); - mii_control |= MII_CONTROL_RESTART_NEGOTIATION; - miiWriteWord( mii_control, MII_CONTROL, phy); - - /* - * If the system is not connected to the network, then auto-negotiation - * never completes and we hang in this loop! - */ -#if 0 - while (1) - { - miiReadWord( &mii_control, MII_CONTROL, phy ); - if ((mii_control & MII_CONTROL_RESTART_NEGOTIATION) == 0) - break; - } -#endif -} - -/* - * Find the first PHY device on the MII interface. - * - * Return - * true PHY found - * false PHY not found - */ -bool UniNEnet::miiFindPHY( UInt8 *phy ) -{ - int i; - UInt16 phyWord[2]; - - *phy = 0xff; - - // The first two PHY registers are required. - // - for (i = 0; i < MII_MAX_PHY; i++) - { - if ( miiReadWord( &phyWord[0], MII_STATUS, i ) == false ) - { - continue; - } - if ( miiReadWord( &phyWord[1], MII_CONTROL, i ) == false ) - { - continue; - } - if ( phyWord[0] == 0xffff && phyWord[1] == 0xffff ) - { - continue; - } - - if ( *phy == 0xff ) *phy = i; - } - - return (*phy == 0xff) ? false : true; -} - -/* - * - * - */ -bool UniNEnet::miiInitializePHY( UInt8 phy ) -{ - UInt16 phyWord; - - // Clear enable auto-negotiation bit - // - miiReadWord( &phyWord, MII_CONTROL, phy ); - phyWord &= ~MII_CONTROL_AUTONEGOTIATION; - miiWriteWord( phyWord, MII_CONTROL, phy ); - - // Advertise 10/100 Half/Full duplex capable to link partner - // - miiReadWord( &phyWord, MII_ADVERTISEMENT, phy ); - phyWord |= (MII_ANAR_100BASETX_FD | MII_ANAR_100BASETX | - MII_ANAR_10BASET_FD | MII_ANAR_10BASET ); - miiWriteWord( phyWord, MII_ADVERTISEMENT, phy ); - - // Set enable auto-negotiation bit - // - miiReadWord( &phyWord, MII_CONTROL, phy ); - phyWord |= MII_CONTROL_AUTONEGOTIATION; - miiWriteWord( phyWord, MII_CONTROL, phy ); - - miiRestartAutoNegotiation( phy ); - - return true; -} - - diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.h b/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.h deleted file mode 100644 index 9588e2b85..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetMII.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * Copyright (c) 1998-1999 by Apple Computer, Inc., All rights reserved. - * - * MII protocol and PHY register definitions. - * - * HISTORY - * - */ - -/* - * MII command frame (32-bits) as documented in IEEE 802.3u - */ -#define MII_OP_READ 0x02 -#define MII_OP_WRITE 0x01 - -#define MII_MAX_PHY 32 - -/* MII Registers */ -#define MII_CONTROL 0 -#define MII_STATUS 1 -#define MII_ID0 2 -#define MII_ID1 3 -#define MII_ADVERTISEMENT 4 -#define MII_LINKPARTNER 5 -#define MII_EXPANSION 6 -#define MII_NEXTPAGE 7 - -/* MII Control register bits */ -#define MII_CONTROL_RESET 0x8000 -#define MII_CONTROL_LOOPBACK 0x4000 -#define MII_CONTROL_SPEED_SELECTION 0x2000 -#define MII_CONTROL_AUTONEGOTIATION 0x1000 -#define MII_CONTROL_POWERDOWN 0x800 -#define MII_CONTROL_ISOLATE 0x400 -#define MII_CONTROL_RESTART_NEGOTIATION 0x200 -#define MII_CONTROL_FULLDUPLEX 0x100 -#define MII_CONTROL_COLLISION_TEST 0x80 - -/* MII Status register bits */ -#define MII_STATUS_100BASET4 0x8000 -#define MII_STATUS_100BASETX_FD 0x4000 -#define MII_STATUS_100BASETX 0x2000 -#define MII_STATUS_10BASET_FD 0x1000 -#define MII_STATUS_10BASET 0x800 -#define MII_STATUS_NEGOTIATION_COMPLETE 0x20 -#define MII_STATUS_REMOTE_FAULT 0x10 -#define MII_STATUS_NEGOTIATION_ABILITY 0x8 -#define MII_STATUS_LINK_STATUS 0x4 -#define MII_STATUS_JABBER_DETECT 0x2 -#define MII_STATUS_EXTENDED_CAPABILITY 0x1 - -/* MII ANAR register bits */ -#define MII_ANAR_ASYM_PAUSE 0x800 -#define MII_ANAR_PAUSE 0x400 -#define MII_ANAR_100BASET4 0x200 -#define MII_ANAR_100BASETX_FD 0x100 -#define MII_ANAR_100BASETX 0x80 -#define MII_ANAR_10BASET_FD 0x40 -#define MII_ANAR_10BASET 0x20 - -/* MII ANLPAR register bits */ -#define MII_LPAR_NEXT_PAGE 0x8000 -#define MII_LPAR_ACKNOWLEDGE 0x4000 -#define MII_LPAR_REMOTE_FAULT 0x2000 -#define MII_LPAR_ASYM_PAUSE 0x0800 -#define MII_LPAR_PAUSE 0x0400 -#define MII_LPAR_100BASET4 0x200 -#define MII_LPAR_100BASETX_FD 0x100 -#define MII_LPAR_100BASETX 0x80 -#define MII_LPAR_10BASET_FD 0x40 -#define MII_LPAR_10BASET 0x20 - - -/* MII BCM5201 Specific */ - -/* MII BCM5201 ID */ -#define MII_BCM5201_OUI 0x001018 -#define MII_BCM5201_MODEL 0x21 -#define MII_BCM5201_REV 0x01 -#define MII_BCM5201_ID ((MII_BCM5201_OUI << 10) | (MII_BCM5201_MODEL << 4)) -#define MII_BCM5201_MASK 0xfffffff0 - -#define MII_BCM5201_DELAY 1 - -/* MII BCM5201 Regs */ -#define MII_BCM5201_AUXSTATUS 0x18 - -/* MII BCM5201 AUXSTATUS register bits */ -#define MII_BCM5201_AUXSTATUS_DUPLEX 0x0001 -#define MII_BCM5201_AUXSTATUS_SPEED 0x0002 - -/* MII BCM5201 MULTIPHY interrupt register. - * Added 4/20/2000 by A.W. for power management */ -#define MII_BCM5201_INTERRUPT 0x1A -#define MII_BCM5201_INTERRUPT_INTENABLE 0x4000 - -#define MII_BCM5201_AUXMODE2 0x1B -#define MII_BCM5201_AUXMODE2_LOWPOWER 0x0008 - -#define MII_BCM5201_MULTIPHY 0x1E - -/* MII BCM5201 MULTIPHY register bits */ -#define MII_BCM5201_MULTIPHY_SERIALMODE 0x0002 -#define MII_BCM5201_MULTIPHY_SUPERISOLATE 0x0008 - - -/* MII LXT971 (Level One) Specific */ - -/* MII LXT971 ID */ -#define MII_LXT971_OUI 0x0004de -#define MII_LXT971_MODEL 0x0e -#define MII_LXT971_REV 0x01 -#define MII_LXT971_ID ((MII_LXT971_OUI << 10) | (MII_LXT971_MODEL << 4)) -#define MII_LXT971_MASK 0xfffffff0 - -#define MII_LXT971_DELAY 1 - -/* MII LXT971 Regs */ -#define MII_LXT971_STATUS_2 0x11 - -/* MII LXT971 Status #2 register bits */ -#define MII_LXT971_STATUS_2_DUPLEX 0x0200 -#define MII_LXT971_STATUS_2_SPEED 0x4000 - -/* MII BCM5400 Specific */ - -/* MII BCM5400 ID */ -#define MII_BCM5400_OUI 0x000818 -#define MII_BCM5400_MODEL 0x04 -#define MII_BCM5401_MODEL 0x05 -#define MII_BCM5400_REV 0x01 -#define MII_BCM5400_ID ((MII_BCM5400_OUI << 10) | (MII_BCM5400_MODEL << 4)) -#define MII_BCM5401_ID ((MII_BCM5400_OUI << 10) | (MII_BCM5401_MODEL << 4)) -#define MII_BCM5400_MASK 0xfffffff0 - -#define MII_BCM5400_DELAY 1 - -/* MII BCM5400 Regs */ - -#define MII_BCM5400_1000BASETCONTROL 0x09 -/* MII BCM5400 1000-BASET Control register bits */ - -#define MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 - -#define MII_BCM5400_AUXCONTROL 0x18 - -/* MII BCM5400 AUXCONTROL register bits */ -#define MII_BCM5400_AUXCONTROL_PWR10BASET 0x0004 - -#define MII_BCM5400_AUXSTATUS 0x19 - -/* MII BCM5400 AUXSTATUS register bits */ -#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700 -#define MII_BCM5400_AUXSTATUS_LINKMODE_BIT 0x0100 - - -/* MII ST10040 Specific */ - -/* MII ST10040 ID */ -#define MII_ST10040_OUI 0x1e0400 -#define MII_ST10040_MODEL 0x00 -#define MII_ST10040_REV 0x01 -#define MII_ST10040_ID ((MII_ST10040_OUI << 10) | (MII_ST10040_MODEL << 4)) -#define MII_ST10040_MASK 0xfffffff0 - -#define MII_ST10040_DELAY 1 - -/* MII ST10040 Regs */ -#define MII_ST10040_CHIPST 0x14 - -/* MII ST10040 CHIPST register bits */ -#define MII_ST10040_CHIPST_LINK 0x2000 -#define MII_ST10040_CHIPST_DUPLEX 0x1000 -#define MII_ST10040_CHIPST_SPEED 0x0800 -#define MII_ST10040_CHIPST_NEGOTIATION 0x0020 - - -/* MII DP83843 Specific */ - -/* MII DP83843 ID */ -#define MII_DP83843_OUI 0x080017 -#define MII_DP83843_MODEL 0x01 -#define MII_DP83843_REV 0x00 -#define MII_DP83843_ID ((MII_DP83843_OUI << 10) | (MII_DP83843_MODEL << 4)) -#define MII_DP83843_MASK 0xfffffff0 - -#define MII_DP83843_DELAY 20 - -/* MII DP83843 PHYSTS register bits */ -#define MII_DP83843_PHYSTS 0x10 -#define MII_DP83843_PHYSTS_LINK 0x0001 -#define MII_DP83843_PHYSTS_SPEED10 0x0002 -#define MII_DP83843_PHYSTS_DUPLEX 0x0004 -#define MII_DP83843_PHYSTS_NEGOTIATION 0x0020 - - -/* MII timeout */ -#define MII_DEFAULT_DELAY 20 -#define MII_RESET_TIMEOUT 100 -#define MII_RESET_DELAY 10 - -#define MII_LINK_TIMEOUT 2500 -#define MII_LINK_DELAY 20 - -/* A few constants needed for miiWriteWord() */ -enum { - kPHYAddr0 = 0x00000000, //PHY addr is 0 - kPHYAddr1F = 0x0000001F -}; diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.cpp b/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.cpp deleted file mode 100644 index 11f30da29..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.cpp +++ /dev/null @@ -1,1701 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Computer - * - * Implementation for hardware dependent (relatively) code - * for the Sun GEM Ethernet controller. - * - * HISTORY - * - * 10-Sept-97 - * Created. - * - */ -#include "UniNEnetPrivate.h" - -extern void *kernel_pmap; - -/* - * Private functions - */ -bool UniNEnet::allocateMemory() -{ - UInt32 rxRingSize, txRingSize; - UInt32 i, n; - UInt8 *virtAddr; - UInt32 physBase; - UInt32 physAddr; - TxQueueElement *txElement; - - /* - * Calculate total space for DMA channel commands - */ - txRingSize = (TX_RING_LENGTH * sizeof(enet_txdma_cmd_t) + 2048 - 1) & ~(2048-1); - rxRingSize = (RX_RING_LENGTH * sizeof(enet_dma_cmd_t) + 2048 - 1) & ~(2048-1); - - dmaCommandsSize = round_page( txRingSize + rxRingSize ); - /* - * Allocate required memory - */ - if ( !dmaCommands ) - { - dmaCommands = (UInt8 *)IOMallocContiguous( dmaCommandsSize, PAGE_SIZE, 0 ); - - if ( dmaCommands == 0 ) - { - IOLog( "Ethernet(UniN): Cant allocate channel dma commands\n\r" ); - return false; - } - } - - /* - * If we needed more than one page, then make sure we received contiguous memory. - */ - n = (dmaCommandsSize - PAGE_SIZE) / PAGE_SIZE; - physBase = pmap_extract(kernel_pmap, (vm_address_t) dmaCommands); - - virtAddr = (UInt8 *) dmaCommands; - for( i=0; i < n; i++, virtAddr += PAGE_SIZE ) - { - physAddr = pmap_extract(kernel_pmap, (vm_address_t) virtAddr); - if (physAddr != (physBase + i * PAGE_SIZE) ) - { - IOLog( "Ethernet(UniN): Cant allocate contiguous memory for dma commands\n\r" ); - return false; - } - } - - /* Setup the receive ring pointer */ - rxDMACommands = (enet_dma_cmd_t*)dmaCommands; - - /* Setup the transmit ring pointer */ - txDMACommands = (enet_txdma_cmd_t*)(dmaCommands + rxRingSize); - - - queue_init( &txActiveQueue ); - queue_init( &txFreeQueue ); - - for ( i = 0; i < TX_MAX_MBUFS; i++ ) - { - txElement = (TxQueueElement *)IOMalloc( sizeof(TxQueueElement) ); - if ( txElement == 0 ) - { - return false; - } - - bzero( txElement, sizeof(TxQueueElement) ); - - releaseTxElement( txElement ); - } - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Transmit Ring - * ----------------------- - * Each transmit ring entry consists of two words to transmit data from buffer - * segments (possibly) spanning a page boundary. This is followed by two DMA commands - * which read transmit frame status and interrupt status from the UniN chip. The last - * DMA command in each transmit ring entry generates a host interrupt. - * The last entry in the ring is followed by a DMA branch to the first - * entry. - *-------------------------------------------------------------------------*/ - -bool UniNEnet::initTxRing() -{ - TxQueueElement * txElement; - UInt32 i; - - /* - * Clear the transmit DMA command memory - */ - bzero( (void *)txDMACommands, sizeof(enet_txdma_cmd_t) * TX_RING_LENGTH); - txCommandHead = 0; - txCommandTail = 0; - - txDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) txDMACommands); - - if ( txDMACommandsPhys == 0 ) - { - IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", - (int)txDMACommands ); - } - - for ( i=0; i < TX_RING_LENGTH; i++ ) - { - txElement = txElementPtrs[i]; - - if ( txElement && ( --txElement->count == 0 ) ) - { - freePacket( txElement->mbuf ); - releaseTxElement( txElement ); - } - - txElementPtrs[i] = 0; - } - - txCommandsAvail = TX_RING_LENGTH - 1; - - txIntCnt = 0; - txWDCount = 0; - - return true; -} - -/*------------------------------------------------------------------------- - * - * Setup the Receive ring - * ---------------------- - * Each receive ring entry consists of two DMA commands to receive data - * into a network buffer (possibly) spanning a page boundary. The second - * DMA command in each entry generates a host interrupt. - * The last entry in the ring is followed by a DMA branch to the first - * entry. - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::initRxRing() -{ - UInt32 i; - bool status; - - /* Clear the receive DMA command memory */ - bzero( (void*)rxDMACommands, sizeof( enet_dma_cmd_t ) * RX_RING_LENGTH ); - - rxDMACommandsPhys = pmap_extract(kernel_pmap, (vm_address_t) rxDMACommands); - if ( rxDMACommandsPhys == 0 ) - { - IOLog( "Ethernet(UniN): Bad dma command buf - %08x\n\r", - (int) rxDMACommands ); - return false; - } - - /* Allocate a receive buffer for each entry in the Receive ring */ - for ( i = 0; i < RX_RING_LENGTH; i++ ) - { - if (rxMbuf[i] == NULL) - { - rxMbuf[i] = allocatePacket(NETWORK_BUFSIZE); - if (rxMbuf[i] == NULL) - { - IOLog("Ethernet(UniN): NULL packet in initRxRing\n"); - return false; - } - } - - /* - * Set the DMA commands for the ring entry to transfer data to the Mbuf. - */ - status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); - if (status == false) - { - IOLog("Ethernet(UniN): updateDescriptorFromMbuf error in " - "initRxRing\n"); - return false; - } - } - - /* - * Set the receive queue head to point to the first entry in the ring. - * Set the receive queue tail to point to a DMA Stop command after the - * last ring entry - */ - i-=4; - rxCommandHead = 0; - rxCommandTail = i; - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::flushRings() -{ - // Free all mbufs from the receive ring: - - for ( UInt32 i = 0; i < RX_RING_LENGTH; i++ ) - { - if (rxMbuf[i]) - { - freePacket( rxMbuf[i] ); - rxMbuf[i] = 0; - } - } - - // Free all mbufs from the transmit ring. - // The TxElement is moved back to the free list. - - for ( UInt32 i = 0; i < TX_RING_LENGTH; i++ ) - { - TxQueueElement * txElement = txElementPtrs[i]; - txElementPtrs[i] = 0; - - if ( txElement && ( --txElement->count == 0 ) ) - { - freePacket( txElement->mbuf ); - releaseTxElement( txElement ); - } - } -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::startChip() -{ - UInt32 gemReg; - -// dumpRegisters(); - - gemReg = READ_REGISTER( TxConfiguration ); - gemReg |= kTxConfiguration_Tx_DMA_Enable; - WRITE_REGISTER( TxConfiguration, gemReg ); - - IOSleep( 20 ); - - gemReg = READ_REGISTER( RxConfiguration ); -/// gemReg |= kRxConfiguration_Rx_DMA_Enable | kRxConfiguration_Batch_Disable; - gemReg |= kRxConfiguration_Rx_DMA_Enable; - WRITE_REGISTER( RxConfiguration, gemReg ); - - IOSleep( 20 ); - - gemReg = READ_REGISTER( TxMACConfiguration ); - gemReg |= kTxMACConfiguration_TxMac_Enable; - WRITE_REGISTER( TxMACConfiguration, gemReg ); - - IOSleep( 20 ); - - rxMacConfigReg = READ_REGISTER( RxMACConfiguration ); - rxMacConfigReg |= kRxMACConfiguration_Rx_Mac_Enable; - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); - - return; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::stopChip() -{ - UInt32 gemReg; - - gemReg = READ_REGISTER( TxConfiguration ); - gemReg &= ~kTxConfiguration_Tx_DMA_Enable; - WRITE_REGISTER( TxConfiguration, gemReg ); - - IOSleep( 20 ); - - gemReg = READ_REGISTER( RxConfiguration ); - gemReg &= ~kRxConfiguration_Rx_DMA_Enable; - WRITE_REGISTER( RxConfiguration, gemReg ); - - IOSleep( 20 ); - - gemReg = READ_REGISTER( TxMACConfiguration ); - gemReg &= ~kTxMACConfiguration_TxMac_Enable; - WRITE_REGISTER( TxMACConfiguration, gemReg ); - - IOSleep( 20 ); - - rxMacConfigReg = READ_REGISTER( RxMACConfiguration ); - rxMacConfigReg &= ~kRxMACConfiguration_Rx_Mac_Enable; - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); - - return; -} - - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::resetChip() -{ - UInt32 resetReg; - UInt16 * pPhyType; - UInt16 phyWord; - - WRITE_REGISTER( SoftwareReset, kSoftwareReset_TX | kSoftwareReset_RX ); - do - { - resetReg = READ_REGISTER( SoftwareReset ); - } - while( resetReg & (kSoftwareReset_TX | kSoftwareReset_RX) ); - - /* - * Determine if PHY chip is configured. Reset and enable it (if present). - */ - if ( phyId == 0xff ) - { - /* - * Generate a hardware PHY reset. - */ - resetPHYChip(); - - if ( miiFindPHY(&phyId) == true ) - { - miiResetPHY( phyId ); - - pPhyType = (UInt16 *)&phyType; - miiReadWord( pPhyType, MII_ID0, phyId ); - miiReadWord( pPhyType+1, MII_ID1, phyId ); - if ( ((phyType & MII_BCM5400_MASK) == MII_BCM5400_ID) - || (((phyType & MII_BCM5400_MASK) == MII_BCM5401_ID)) ) /// mlj temporary quick fix - { - phyBCMType = 5400; - - miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId ); - phyWord |= MII_BCM5400_AUXCONTROL_PWR10BASET; - miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId ); - - miiReadWord( &phyWord, MII_BCM5400_1000BASETCONTROL, phyId ); - phyWord |= MII_BCM5400_1000BASETCONTROL_FULLDUPLEXCAP; - miiWriteWord( phyWord, MII_BCM5400_1000BASETCONTROL, phyId ); - - IODelay(100); - - miiResetPHY( 0x1F ); - - miiReadWord( &phyWord, MII_BCM5201_MULTIPHY, 0x1F ); - phyWord |= MII_BCM5201_MULTIPHY_SERIALMODE; - miiWriteWord( phyWord, MII_BCM5201_MULTIPHY, 0x1F ); - - miiReadWord( &phyWord, MII_BCM5400_AUXCONTROL, phyId ); - phyWord &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; - miiWriteWord( phyWord, MII_BCM5400_AUXCONTROL, phyId ); - - } - else if ( (phyType & MII_BCM5201_MASK) == MII_BCM5201_ID ) - { - phyBCMType = 5201; - } - else - { - phyBCMType = 0; - } - // IOLog("DEBUG:UniNEnet: phy type = %d\n", phyBCMType); - } - } - - return true; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::initChip() -{ - UInt32 i, temp; - mach_timespec_t timeStamp; - UInt32 rxFifoSize; - UInt32 rxOff; - UInt32 rxOn; - u_int16_t *p16; - - if ( phyId == 0xff ) - { - WRITE_REGISTER( DatapathMode, kDatapathMode_ExtSERDESMode ); - WRITE_REGISTER( SerialinkControl, kSerialinkControl_DisableLoopback - | kSerialinkControl_EnableSyncDet ); - WRITE_REGISTER( Advertisement, kAdvertisement_Full_Duplex - | kAdvertisement_PAUSE ); - WRITE_REGISTER( PCSMIIControl, kPCSMIIControl_Auto_Negotiation_Enable - | kPCSMIIControl_Restart_Auto_Negotiation ); - WRITE_REGISTER( PCSConfiguration, kPCSConfiguration_Enable ); - WRITE_REGISTER( XIFConfiguration, kXIFConfiguration_Tx_MII_OE - | kXIFConfiguration_GMIIMODE - | kXIFConfiguration_FDPLXLED ); - } - else - { - WRITE_REGISTER( DatapathMode, kDatapathMode_GMIIMode ); - WRITE_REGISTER( XIFConfiguration, kXIFConfiguration_Tx_MII_OE - | kXIFConfiguration_FDPLXLED ); - } - - WRITE_REGISTER( SendPauseCommand, kSendPauseCommand_default ); - WRITE_REGISTER( MACControlConfiguration,kMACControlConfiguration_Receive_Pause_Enable ); - WRITE_REGISTER( InterruptMask, kInterruptMask_None ); - WRITE_REGISTER( TxMACMask, kTxMACMask_default ); - WRITE_REGISTER( RxMACMask, kRxMACMask_default ); - WRITE_REGISTER( MACControlMask, kMACControlMask_default ); - WRITE_REGISTER( Configuration, kConfiguration_TX_DMA_Limit - | kConfiguration_RX_DMA_Limit - | kConfiguration_Infinite_Burst ); - - WRITE_REGISTER( InterPacketGap0, kInterPacketGap0_default ); - WRITE_REGISTER( InterPacketGap1, kInterPacketGap1_default ); - WRITE_REGISTER( InterPacketGap2, kInterPacketGap2_default ); - WRITE_REGISTER( SlotTime, kSlotTime_default ); - WRITE_REGISTER( MinFrameSize, kMinFrameSize_default ); - WRITE_REGISTER( MaxFrameSize, kMaxFrameSize_default ); - WRITE_REGISTER( PASize, kPASize_default ); - WRITE_REGISTER( JamSize, kJamSize_default ); - WRITE_REGISTER( AttemptLimit, kAttemptLimit_default ); - WRITE_REGISTER( MACControlType, kMACControlType_default ); - - p16 = (u_int16_t *) myAddress.bytes; - for ( i=0; i < sizeof(IOEthernetAddress) / 2; i++ ) - WRITE_REGISTER( MACAddress[ i ], p16[ 2 - i ] ); - - for ( i=0; i < 3; i ++ ) - { - WRITE_REGISTER( MACAddress[ i + 3 ], 0 ); - WRITE_REGISTER( AddressFilter[ i ], 0 ); - } - - WRITE_REGISTER( MACAddress[ 6 ], kMACAddress_default_6 ); - WRITE_REGISTER( MACAddress[ 7 ], kMACAddress_default_7 ); - WRITE_REGISTER( MACAddress[ 8 ], kMACAddress_default_8 ); - - WRITE_REGISTER( AddressFilter2_1Mask, 0 ); - WRITE_REGISTER( AddressFilter0Mask, 0 ); - - for ( i=0; i < 16; i++ ) - WRITE_REGISTER( HashTable[ i ], 0 ); - - WRITE_REGISTER( NormalCollisionCounter, 0 ); - WRITE_REGISTER( FirstAttemptSuccessfulCollisionCounter, 0 ); - WRITE_REGISTER( ExcessiveCollisionCounter, 0 ); - WRITE_REGISTER( LateCollisionCounter, 0 ); - WRITE_REGISTER( DeferTimer, 0 ); - WRITE_REGISTER( PeakAttempts, 0 ); - WRITE_REGISTER( ReceiveFrameCounter, 0 ); - WRITE_REGISTER( LengthErrorCounter, 0 ); - WRITE_REGISTER( AlignmentErrorCounter, 0 ); - WRITE_REGISTER( FCSErrorCounter, 0 ); - WRITE_REGISTER( RxCodeViolationErrorCounter, 0 ); - - IOGetTime(&timeStamp); - WRITE_REGISTER( RandomNumberSeed, timeStamp.tv_nsec & 0xFFFF ); - - WRITE_REGISTER( TxDescriptorBaseLow, txDMACommandsPhys ); - WRITE_REGISTER( TxDescriptorBaseHigh, 0 ); - - temp = kTxConfiguration_TxFIFO_Threshold - | TX_RING_LENGTH_FACTOR << kTxConfiguration_Tx_Desc_Ring_Size_Shift; - WRITE_REGISTER( TxConfiguration, temp ); - - WRITE_REGISTER( TxMACConfiguration, 0 ); - - setDuplexMode( (phyId == 0xff) ? true : false ); - - WRITE_REGISTER( RxDescriptorBaseLow, rxDMACommandsPhys ); - WRITE_REGISTER( RxDescriptorBaseHigh, 0 ); - - WRITE_REGISTER( RxKick, RX_RING_LENGTH - 4 ); - - temp = kRxConfiguration_RX_DMA_Threshold - /// | kRxConfiguration_Batch_Disable may cause 4x primary interrupts - | RX_RING_LENGTH_FACTOR << kRxConfiguration_Rx_Desc_Ring_Size_Shift; - WRITE_REGISTER( RxConfiguration, temp ); - - rxMacConfigReg = 0; - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); - - rxFifoSize = READ_REGISTER( RxFIFOSize ); - - rxOff = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 2 / kPauseThresholds_Factor); - rxOn = rxFifoSize - ((kGEMMacMaxFrameSize_Aligned + 8) * 3 / kPauseThresholds_Factor); - - WRITE_REGISTER( PauseThresholds, - (rxOff << kPauseThresholds_OFF_Threshold_Shift) - | (rxOn << kPauseThresholds_ON_Threshold_Shift) ); - - temp = READ_REGISTER( BIFConfiguration ); - if ( temp & kBIFConfiguration_M66EN ) - temp = kRxBlanking_default_66; - else temp = kRxBlanking_default_33; - WRITE_REGISTER( RxBlanking, temp ); - - return true; -}/* end initChip */ - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::disableAdapterInterrupts() -{ - - WRITE_REGISTER( InterruptMask, kInterruptMask_None ); - return; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::enableAdapterInterrupts() -{ - UInt32 gemReg; - - - gemReg = READ_REGISTER( InterruptMask ); - gemReg &= ~( kStatus_TX_INT_ME | kStatus_RX_DONE ); - WRITE_REGISTER( InterruptMask, gemReg ); - return; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::setDuplexMode( bool duplexMode ) -{ - UInt32 txMacConfig; - UInt32 xifConfig; - - - isFullDuplex = duplexMode; - txMacConfig = READ_REGISTER( TxMACConfiguration ); - - WRITE_REGISTER( TxMACConfiguration, txMacConfig & ~kTxMACConfiguration_TxMac_Enable ); - while( READ_REGISTER( TxMACConfiguration ) & kTxMACConfiguration_TxMac_Enable ) - ; - - xifConfig = READ_REGISTER( XIFConfiguration ); - - if ( isFullDuplex ) - { - txMacConfig |= (kTxMACConfiguration_Ignore_Collisions | kTxMACConfiguration_Ignore_Carrier_Sense); - xifConfig &= ~kXIFConfiguration_Disable_Echo; - } - else - { - txMacConfig &= ~(kTxMACConfiguration_Ignore_Collisions | kTxMACConfiguration_Ignore_Carrier_Sense); - xifConfig |= kXIFConfiguration_Disable_Echo; - } - - WRITE_REGISTER( TxMACConfiguration, txMacConfig ); - WRITE_REGISTER( XIFConfiguration, xifConfig ); - return; -} - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::restartTransmitter() -{ -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::restartReceiver() -{ - // Perform a software reset to the logic in the RX MAC. - // The MAC config register should be re-programmed following - // the reset. Everything else *should* be unaffected. - - WRITE_REGISTER( RxMACSoftwareResetCommand, kRxMACSoftwareResetCommand_Reset ); - - // Poll until the reset bit is cleared by the hardware. - - for ( int i = 0; i < 5000; i++ ) - { - if ( ( READ_REGISTER( RxMACSoftwareResetCommand ) - & kRxMACSoftwareResetCommand_Reset ) == 0 ) - { - break; // 'i' is always 0 or 1 - } - IODelay(1); - } - - // Update the MAC Config register. Watch out for the programming - // restrictions documented in the GEM specification!!! - // - // Disable MAC before setting any other bits in the MAC config - // register. - - WRITE_REGISTER( RxMACConfiguration, 0 ); - - for ( int i = 0; i < 5000; i++ ) - { - if ( ( READ_REGISTER( RxMACConfiguration ) - & kRxMACConfiguration_Rx_Mac_Enable ) == 0 ) - { - break; // 'i' is always 0 - } - IODelay(1); - } - - // Update MAC config register. - - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); - return; -}/* end restartReceiver */ - - -/*------------------------------------------------------------------------- - * - * Orderly stop of receive DMA. - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::stopReceiveDMA() -{ -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::stopTransmitDMA() -{ -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::transmitPacket(struct mbuf *packet) -{ - GEMTxDescriptor *dp; // descriptor pointer - UInt32 i,j,k; - struct mbuf *m; - TxQueueElement *txElement; - UInt32 dataPhys; - - - for ( m = packet, i=1; m->m_next; m=m->m_next, i++ ) - ; - - - if ( i > txCommandsAvail ) - { - return false; - } - - if ( (txElement=getTxElement()) == 0 ) - { - return false; - } - - j = txCommandTail; - - txElement->mbuf = packet; - txElement->slot = j; - txElement->count = i; - - OSAddAtomic( -i, (SInt32*)&txCommandsAvail ); - - m = packet; - - do - { - k = j; - - txElementPtrs[j] = txElement; - - dataPhys = (UInt32)mcl_to_paddr( mtod(m, char *) ); - if ( dataPhys == 0 ) - dataPhys = pmap_extract( kernel_pmap, mtod(m, vm_offset_t) ); - - dp = &txDMACommands[ j ].desc_seg[ 0 ]; - OSWriteLittleInt32( &dp->bufferAddrLo, 0, dataPhys ); - OSWriteLittleInt32( &dp->flags0, 0, m->m_len ); - dp->flags1 = 0; - txIntCnt++; - j = (j + 1) & TX_RING_WRAP_MASK; - } - while ( (m=m->m_next) != 0 ); - - txDMACommands[ k ].desc_seg[ 0 ].flags0 |= OSSwapHostToLittleConstInt32( kGEMTxDescFlags0_EndOfFrame ); - txDMACommands[ txCommandTail ].desc_seg[ 0 ].flags0 |= OSSwapHostToLittleConstInt32( kGEMTxDescFlags0_StartOfFrame ); - if ( txIntCnt >= TX_DESC_PER_INT ) - { - txDMACommands[ txCommandTail ].desc_seg[ 0 ].flags1 |= OSSwapHostToLittleConstInt32( kGEMTxDescFlags1_Int ); - txIntCnt = txIntCnt % TX_DESC_PER_INT; - } - txCommandTail = j; - - WRITE_REGISTER( TxKick, j ); - - return true; -}/* end transmitPacket */ - - -/*------------------------------------------------------------------------- - * _receivePacket - * -------------- - * This routine runs the receiver in polled-mode (yuk!) for the kernel debugger. - * Don't mess with the interrupt source here that can deadlock in the debugger - * - * The _receivePackets allocate MBufs and pass them up the stack. The kernel - * debugger interface passes a buffer into us. To reconsile the two interfaces, - * we allow the receive routine to continue to allocate its own buffers and - * transfer any received data to the passed-in buffer. This is handled by - * _receivePacket calling _packetToDebugger. - *-------------------------------------------------------------------------*/ - -void UniNEnet::receivePacket( void * pkt, - UInt32 * pkt_len, - UInt32 timeout ) -{ - mach_timespec_t startTime; - mach_timespec_t currentTime; - UInt32 elapsedTimeMS; - - *pkt_len = 0; - - if (ready == false) - { - return; - } - - debuggerPkt = pkt; - debuggerPktSize = 0; - - IOGetTime(&startTime); - do - { - receivePackets( true ); - IOGetTime( ¤tTime ); - elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); - } - while ( (debuggerPktSize == 0) && (elapsedTimeMS < timeout) ); - - *pkt_len = debuggerPktSize; - - return; -} - -/*------------------------------------------------------------------------- - * _packetToDebugger - * ----------------- - * This is called by _receivePackets when we are polling for kernel debugger - * packets. It copies the MBuf contents to the buffer passed by the debugger. - * It also sets the var debuggerPktSize which will break the polling loop. - *-------------------------------------------------------------------------*/ - -void UniNEnet::packetToDebugger( struct mbuf * packet, u_int size ) -{ - debuggerPktSize = size; - bcopy( mtod(packet, char *), debuggerPkt, size ); -} - -/*------------------------------------------------------------------------- - * _sendPacket - * ----------- - * - * This routine runs the transmitter in polled-mode (yuk!) for the kernel debugger. - * Don't mess with the interrupt source here that can deadlock in the debugger - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::sendPacket( void *pkt, UInt32 pkt_len ) -{ - mach_timespec_t startTime; - mach_timespec_t currentTime; - UInt32 elapsedTimeMS; - - if (!ready || !pkt || (pkt_len > ETHERMAXPACKET)) - { - return; - } - - /* - * Wait for the transmit ring to empty - */ - IOGetTime(&startTime); - do - { - debugTransmitInterruptOccurred(); - IOGetTime(¤tTime); - elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog( "Ethernet(UniN): Polled tranmit timeout - 1\n\r"); - return; - } - - /* - * Allocate a MBuf and copy the debugger transmit data into it. - * - * jliu - no allocation, just recycle the same buffer dedicated to - * KDB transmit. - */ - txDebuggerPkt->m_next = 0; - txDebuggerPkt->m_data = (caddr_t) pkt; - txDebuggerPkt->m_pkthdr.len = txDebuggerPkt->m_len = pkt_len; - - /* - * Send the debugger packet. txDebuggerPkt must not be freed by - * the transmit routine. - */ - transmitPacket(txDebuggerPkt); - - /* - * Poll waiting for the transmit ring to empty again - */ - do - { - debugTransmitInterruptOccurred(); - IOGetTime(¤tTime); - elapsedTimeMS = (currentTime.tv_nsec - startTime.tv_nsec) / (1000*1000); - } - while ( (txCommandHead != txCommandTail) && - (elapsedTimeMS < TX_KDB_TIMEOUT) ); - - if ( txCommandHead != txCommandTail ) - { - IOLog( "Ethernet(UniN): Polled tranmit timeout - 2\n\r"); - } - - return; -} - -/*------------------------------------------------------------------------- - * _sendDummyPacket - * ---------------- - * The UniN receiver seems to be locked until we send our first packet. - * - *-------------------------------------------------------------------------*/ -void UniNEnet::sendDummyPacket() -{ - union - { - UInt8 bytes[64]; - IOEthernetAddress enet_addr[2]; - } dummyPacket; - - bzero( &dummyPacket, sizeof(dummyPacket) ); - - - dummyPacket.enet_addr[0] = myAddress; - dummyPacket.enet_addr[1] = myAddress; - - sendPacket((void *)dummyPacket.bytes, (unsigned int)sizeof(dummyPacket)); -} - - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::receiveInterruptOccurred() -{ - return receivePackets(false); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::receivePackets( bool fDebugger ) -{ - struct mbuf * packet; - UInt32 i,last; - int receivedFrameSize = 0; - UInt16 dmaFlags; - UInt32 rxPktStatus = 0; - bool passPacketUp; - bool reusePkt; - bool status; - bool useNetif = !fDebugger && netifEnabled; - bool packetsQueued = false; - - - last = (UInt32)-1; - i = rxCommandHead; - - while ( 1 ) - { - passPacketUp = false; - reusePkt = false; - - dmaFlags = OSReadLittleInt16( &rxDMACommands[ i ].desc_seg[ 0 ].frameDataSize, 0 ); - - /* - * If the current entry has not been written, then stop at this entry - */ - if ( dmaFlags & kGEMRxDescFrameSize_Own ) - { - break; - } - - - receivedFrameSize = dmaFlags & kGEMRxDescFrameSize_Mask; - rxPktStatus = OSReadLittleInt32( &rxDMACommands[ i ].desc_seg[ 0 ].flags, 0 ); - - - /* - * Reject packets that are runts or that have other mutations. - */ - if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) || - receivedFrameSize > (ETHERMAXPACKET + ETHERCRC) || - rxPktStatus & kGEMRxDescFlags_BadCRC ) - { - reusePkt = true; - NETWORK_STAT_ADD( inputErrors ); - if ( receivedFrameSize < (ETHERMINPACKET - ETHERCRC) ) - ETHERNET_STAT_ADD( dot3RxExtraEntry.frameTooShorts ); - else ETHERNET_STAT_ADD( dot3StatsEntry.frameTooLongs ); - } - else if ( useNetif == false ) - { - /* - * Always reuse packets in debugger mode. We also refuse to - * pass anything up the stack unless the driver is open. The - * hardware is enabled before the stack has opened us, to - * allow earlier debug interface registration. But we must - * not pass any packets up. - */ - reusePkt = true; - if (fDebugger) - { - packetToDebugger(rxMbuf[i], receivedFrameSize); - } - } - - - /* - * Before we pass this packet up the networking stack. Make sure we - * can get a replacement. Otherwise, hold on to the current packet and - * increment the input error count. - * Thanks Justin! - */ - - packet = 0; - - if ( reusePkt == false ) - { - bool replaced; - - packet = replaceOrCopyPacket(&rxMbuf[i], receivedFrameSize, &replaced); - - reusePkt = true; - - if (packet && replaced) - { - status = updateDescriptorFromMbuf(rxMbuf[i], &rxDMACommands[i], true); - - if (status) - { - reusePkt = false; - } - else - { - // Assume descriptor has not been corrupted. - freePacket(rxMbuf[i]); // release new packet. - rxMbuf[i] = packet; // get the old packet back. - packet = 0; // pass up nothing. - IOLog("Ethernet(UniN): updateDescriptorFromMbuf error\n"); - } - } - - if ( packet == 0 ) - NETWORK_STAT_ADD( inputErrors ); - } - - /* - * Install the new MBuf for the one we're about to pass to the network stack - */ - - if ( reusePkt == true ) - { - rxDMACommands[i].desc_seg[0].flags = 0; - rxDMACommands[i].desc_seg[0].frameDataSize = OSSwapHostToLittleConstInt16( NETWORK_BUFSIZE | kGEMRxDescFrameSize_Own ); - } - - last = i; /* Keep track of the last receive descriptor processed */ - i = (i + 1) & RX_RING_WRAP_MASK; - - if ( (i & 3) == 0 ) // only kick modulo 4 - { - WRITE_REGISTER( RxKick, (i - 4) & RX_RING_WRAP_MASK ); - } - - if (fDebugger) - { - break; - } - - /* - * Transfer received packet to network - */ - if (packet) - { - KERNEL_DEBUG(DBG_UniN_RXCOMPLETE | DBG_FUNC_NONE, (int) packet, - (int)receivedFrameSize, 0, 0, 0 ); - - networkInterface->inputPacket(packet, receivedFrameSize, true); - NETWORK_STAT_ADD( inputPackets ); - packetsQueued = true; - } - }/* end WHILE */ - - if ( last != (UInt32)-1 ) - { - rxCommandTail = last; - rxCommandHead = i; - } - - return packetsQueued; -}/* end receivePackets */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::transmitInterruptOccurred() -{ - UInt32 i; - bool serviced = false; - TxQueueElement *txElement; - - - i = READ_REGISTER( TxCompletion ); - - while ( i != txCommandHead ) // i and txCommandHead race each other - { - do // This DO reduces READ_REGISTER calls which access the PCI bus - { /* Free the MBuf we just transmitted */ - - txElement = txElementPtrs[ txCommandHead ]; - - KERNEL_DEBUG( DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, - (int)txElement->mbuf, 0, 0, 0, 0 ); - - txElementPtrs[ txCommandHead ] = 0; - OSIncrementAtomic( (SInt32*)&txCommandsAvail ); - - if ( --txElement->count == 0 ) - { - freePacket( txElement->mbuf, kDelayFree ); - releaseTxElement( txElement ); - NETWORK_STAT_ADD( outputPackets ); - } - - txCommandHead = (txCommandHead + 1) & TX_RING_WRAP_MASK; - - } while ( i != txCommandHead ); // loop til txCommandHead catches i - - serviced = true; - i = READ_REGISTER( TxCompletion ); // see if i advanced during last batch - }/* end WHILE */ - - // Release all packets in the free queue. - releaseFreePackets(); - return serviced; -}/* end transmitInterruptOccurred */ - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::debugTransmitInterruptOccurred() -{ - bool fServiced = false; - UInt32 i; - TxQueueElement * txElement; - - // Set the debugTxPoll flag to indicate the debugger was active - // and some cleanup may be needed when the driver returns to - // normal operation. - // - debugTxPoll = true; - - i = READ_REGISTER( TxCompletion ); - - while ( i != txCommandHead ) - { - fServiced = true; - - /* - * Free the mbuf we just transmitted. - * - * If it is the debugger packet, just remove it from the ring. - * and reuse the same packet for the next sendPacket() request. - */ - - /* - * While in debugger mode, do not touch the mbuf pool. - * Queue any used mbufs to a local queue. This queue - * will get flushed after we exit from debugger mode. - * - * During continuous debugger transmission and - * interrupt polling, we expect only the txDebuggerPkt - * to show up on the transmit mbuf ring. - */ - txElement = txElementPtrs[txCommandHead]; - txElementPtrs[txCommandHead] = 0; - OSIncrementAtomic( (SInt32*)&txCommandsAvail ); - - KERNEL_DEBUG( DBG_UniN_TXCOMPLETE | DBG_FUNC_NONE, - (int) txElement->mbuf, - (int) txElement->mbuf->m_pkthdr.len, 0, 0, 0 ); - - if ( --txElement->count == 0 ) - { - if (txElement->mbuf != txDebuggerPkt) - { - debugQueue->enqueue( txElement->mbuf ); - } - releaseTxElement( txElement ); - } - - txCommandHead = (txCommandHead + 1) & TX_RING_WRAP_MASK; - } - - return fServiced; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::debugTransmitCleanup() -{ - // Debugger was active, clear all packets in the debugQueue, and - // issue a start(), just in case the debugger became active while the - // ring was full and the output queue stopped. Since the debugger - // does not restart the output queue, to avoid calling - // semaphore_signal() which may reenable interrupts, we need to - // make sure the output queue is not stalled after the debugger has - // flushed the ring. - - debugQueue->flush(); - - transmitQueue->start(); -} - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::updateDescriptorFromMbuf(struct mbuf * m, enet_dma_cmd_t *desc, bool isReceive) -{ - struct IOPhysicalSegment segVector[1]; - UInt32 segments; - - segments = mbufCursor->getPhysicalSegmentsWithCoalesce(m, segVector); - - if ( segments == 0 || segments > 1 ) - { - IOLog("Ethernet(UniN): updateDescriptorFromMbuf error, %d segments\n", (int)segments); - return false; - } - - if ( isReceive ) - { - enet_dma_cmd_t *rxCmd = (enet_dma_cmd_t *)desc; - - OSWriteLittleInt32( &rxCmd->desc_seg[0].bufferAddrLo, 0, segVector[0].location ); - OSWriteLittleInt16( &rxCmd->desc_seg[0].frameDataSize, 0, segVector[0].length | kGEMRxDescFrameSize_Own ); - rxCmd->desc_seg[0].flags = 0; - } - else - { - enet_txdma_cmd_t *txCmd = (enet_txdma_cmd_t *)desc; - - OSWriteLittleInt32( &txCmd->desc_seg[0].bufferAddrLo, 0, segVector[0].location ); - OSWriteLittleInt32( &txCmd->desc_seg[0].flags0, 0, segVector[0].length - | kGEMTxDescFlags0_StartOfFrame - | kGEMTxDescFlags0_EndOfFrame ); - - txCmd->desc_seg[0].flags1 = 0; - txIntCnt += 1; - if ( (txIntCnt % TX_DESC_PER_INT) == 0 ) /// Divide??? - txCmd->desc_seg[0].flags1 = OSSwapHostToLittleConstInt32( kGEMTxDescFlags1_Int ); - } - - return true; -}/* end updateDescriptorFromMbuf */ - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -TxQueueElement * UniNEnet::getTxElement() -{ - TxQueueElement * txElement = 0; - - IOSimpleLockLock( txQueueLock ); - - if ( queue_empty( &txFreeQueue ) == false ) - { - queue_remove_first( &txFreeQueue, txElement, TxQueueElement *, next ); - - txElement->list = &txActiveQueue; - - queue_enter( txElement->list, txElement, TxQueueElement *, next ); - } - - IOSimpleLockUnlock( txQueueLock ); - - return txElement; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::releaseTxElement(TxQueueElement * txElement) -{ - IOSimpleLockLock( txQueueLock ); - - if ( txElement->list != 0 ) - { - queue_remove( txElement->list, txElement, TxQueueElement *, next ); - } - - txElement->list = &txFreeQueue; - - queue_enter( txElement->list, txElement, TxQueueElement *, next); - - IOSimpleLockUnlock( txQueueLock ); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::monitorLinkStatus( bool firstPoll ) -{ - UInt32 gemReg; - UInt16 phyStatus; - UInt16 linkStatus; - UInt16 linkMode; - UInt16 lpAbility; - UInt16 phyStatusChange; - bool fullDuplex = false; - UInt32 linkSpeed = 0; - IOMediumType mediumType = kIOMediumEthernetNone; - IONetworkMedium *medium; - - - if ( firstPoll ) - { - phyStatusPrev = 0; - linkStatusPrev = kLinkStatusUnknown; - } - - if ( phyId == 0xff ) - { - phyStatus = READ_REGISTER( PCSMIIStatus ) & 0x0000FFFF; - lpAbility = READ_REGISTER( PCSMIILinkPartnerAbility ) & 0x0000FFFF; - } - else - { - if ( miiReadWord( &phyStatus, MII_STATUS, phyId) != true ) - { - return; - } - miiReadWord( &lpAbility, MII_STATUS, phyId); - } - - phyStatusChange = (phyStatusPrev ^ phyStatus) & - ( MII_STATUS_LINK_STATUS | - MII_STATUS_NEGOTIATION_COMPLETE ); - - if ( phyStatusChange || firstPoll ) - { - if ( firstPoll ) - { - // For the initial link status poll, wait a bit, then - // re-read the status register to clear any latched bits. - // Why wait? Well, the debugger can kick in shortly after - // this function returns, and we want the duplex setting - // on the MAC to match the PHY. - - miiWaitForAutoNegotiation( phyId ); - miiReadWord(&phyStatus, MII_STATUS, phyId); - miiReadWord(&phyStatus, MII_STATUS, phyId); - } - - gemReg = READ_REGISTER( MACControlConfiguration ); - if ( lpAbility & MII_LPAR_PAUSE ) - gemReg |= kMACControlConfiguration_Send_Pause_Enable; - else gemReg &= ~kMACControlConfiguration_Send_Pause_Enable; - WRITE_REGISTER( MACControlConfiguration, gemReg ); - - if ( (phyStatus & MII_STATUS_LINK_STATUS) && - ( firstPoll || (phyStatus & MII_STATUS_NEGOTIATION_COMPLETE) ) ) - { - if ( phyId == 0xff ) - { - linkSpeed = 1000; - fullDuplex = true; - mediumType = kIOMediumEthernet1000BaseSX; - } - else if ( (phyType & MII_LXT971_MASK) == MII_LXT971_ID ) - { - miiReadWord( &linkStatus, MII_LXT971_STATUS_2, phyId ); - linkSpeed = (linkStatus & MII_LXT971_STATUS_2_SPEED) ? - 100 : 10; - fullDuplex = (linkStatus & MII_LXT971_STATUS_2_DUPLEX) ? - true : false; - mediumType = (linkSpeed == 10) ? kIOMediumEthernet10BaseT : - kIOMediumEthernet100BaseTX; - } - else if ( (phyType & MII_BCM5201_MASK) == MII_BCM5201_ID ) - { - miiReadWord( &linkStatus, MII_BCM5201_AUXSTATUS, phyId ); - linkSpeed = (linkStatus & MII_BCM5201_AUXSTATUS_SPEED) ? - 100 : 10; - fullDuplex = (linkStatus & MII_BCM5201_AUXSTATUS_DUPLEX) ? - true : false; - mediumType = (linkSpeed == 10) ? kIOMediumEthernet10BaseT : - kIOMediumEthernet100BaseTX; - } - else if ( ((phyType & MII_BCM5400_MASK) == MII_BCM5400_ID) - || ((phyType & MII_BCM5400_MASK) == MII_BCM5401_ID) ) /// mlj temporary quick fix - { - miiReadWord( &linkStatus, MII_BCM5400_AUXSTATUS, phyId ); - - linkMode = (linkStatus & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) / - MII_BCM5400_AUXSTATUS_LINKMODE_BIT; - - gemReg = READ_REGISTER( XIFConfiguration ); - if ( linkMode < 6 ) - gemReg &= ~kXIFConfiguration_GMIIMODE; - else gemReg |= kXIFConfiguration_GMIIMODE; - WRITE_REGISTER( XIFConfiguration, gemReg ); - - if ( linkMode == 0 ) - { - linkSpeed = 0; - } - else if ( linkMode < 3 ) - { - linkSpeed = 10; - fullDuplex = ( linkMode < 2 ) ? false : true; - mediumType = kIOMediumEthernet10BaseT; - } - else if ( linkMode < 6 ) - { - linkSpeed = 100; - fullDuplex = ( linkMode < 5 ) ? false : true; - mediumType = kIOMediumEthernet100BaseTX; - } - else - { - linkSpeed = 1000; - fullDuplex = true; - mediumType = kIOMediumEthernet1000BaseTX; - } - } - - if ( fullDuplex != isFullDuplex ) - { - setDuplexMode( fullDuplex ); - } - - if ( ready == true ) - { - startChip(); - } - - if ( linkSpeed != 0 ) - { - mediumType |= (fullDuplex == true) ? - kIOMediumOptionFullDuplex : - kIOMediumOptionHalfDuplex; - } - - medium = IONetworkMedium::getMediumWithType( mediumDict, - mediumType ); - - setLinkStatus( kIONetworkLinkActive | kIONetworkLinkValid, - medium, - linkSpeed * 1000000 ); - - IOLog( "Ethernet(UniN): Link is up at %ld Mbps - %s Duplex\n\r", - linkSpeed, - (fullDuplex) ? "Full" : "Half" ); - - linkStatusPrev = kLinkStatusUp; - } - else - { - if ( (linkStatusPrev == kLinkStatusUp) || - (linkStatusPrev == kLinkStatusUnknown) ) - { - stopChip(); - - medium = IONetworkMedium::getMediumWithType( mediumDict, - mediumType ); - - setLinkStatus( kIONetworkLinkValid, - medium, - 0 ); - - if ( linkStatusPrev != kLinkStatusUnknown ) - { - IOLog( "Ethernet(UniN): Link is down.\n\r" ); - } - - txIntCnt = 0; - - if ( txCommandHead != txCommandTail ) - { - initTxRing(); - - txCommandHead = READ_REGISTER( TxCompletion ); - txCommandTail = txCommandHead; - } - } - - linkStatusPrev = kLinkStatusDown; - } - - phyStatusPrev = phyStatus; - } - return; -} - - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -IOReturn UniNEnet::getHardwareAddress(IOEthernetAddress *ea) -{ - UInt32 i; - OSData *macEntry; - UInt8 *macAddress; - UInt32 len; - - macEntry = OSDynamicCast( OSData, nub->getProperty( "local-mac-address" ) ); - if ( macEntry == 0 ) - { - return kIOReturnError; - } - - macAddress = (UInt8 *)macEntry->getBytesNoCopy(); - if ( macAddress == 0 ) - { - return kIOReturnError; - } - - len = macEntry->getLength(); - if ( len != 6 ) - { - return kIOReturnError; - } - - for (i = 0; i < sizeof(*ea); i++) - { - ea->bytes[i] = macAddress[i]; - } - return kIOReturnSuccess; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -#define ENET_CRCPOLY 0x04c11db7 - -static UInt32 crc416(UInt32 current, UInt16 nxtval ) -{ - register UInt32 counter; - register int highCRCBitSet, lowDataBitSet; - - /* Swap bytes */ - nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); - - /* Compute bit-by-bit */ - for (counter = 0; counter != 16; ++counter) - { /* is high CRC bit set? */ - if ((current & 0x80000000) == 0) - highCRCBitSet = 0; - else - highCRCBitSet = 1; - - current = current << 1; - - if ((nxtval & 0x0001) == 0) - lowDataBitSet = 0; - else - lowDataBitSet = 1; - - nxtval = nxtval >> 1; - - /* do the XOR */ - if (highCRCBitSet ^ lowDataBitSet) - current = current ^ ENET_CRCPOLY; - } - return current; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -static UInt32 mace_crc(UInt16 *address) -{ - register UInt32 newcrc; - - newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ - newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ - newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ - - return(newcrc); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -/* - * Add requested mcast addr to UniN's hash table filter. - * - */ -void UniNEnet::addToHashTableMask(UInt8 *addr) -{ - UInt32 i,j; - UInt32 crcBitIndex; - UInt16 mask; - - j = mace_crc((UInt16 *)addr) & 0xFF; /* Big-endian alert! */ - - for ( crcBitIndex = i = 0; i < 8; i++ ) - { - crcBitIndex >>= 1; - crcBitIndex |= (j & 0x80); - j <<= 1; - } - - crcBitIndex ^= 0xFF; - - if (hashTableUseCount[crcBitIndex]++) - return; /* This bit is already set */ - mask = crcBitIndex % 16; - mask = 1 << mask; - hashTableMask[crcBitIndex/16] |= mask; -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -void UniNEnet::resetHashTableMask() -{ - bzero(hashTableUseCount, sizeof(hashTableUseCount)); - bzero(hashTableMask, sizeof(hashTableMask)); -} - -/*------------------------------------------------------------------------- - * - * - * - *-------------------------------------------------------------------------*/ - -/* - * Sync the adapter with the software copy of the multicast mask - * (logical address filter). - */ -void UniNEnet::updateHashTableMask() -{ - UInt32 i; - - rxMacConfigReg = READ_REGISTER( RxMACConfiguration ); - WRITE_REGISTER( RxMACConfiguration, - rxMacConfigReg & ~(kRxMACConfiguration_Rx_Mac_Enable - | kRxMACConfiguration_Hash_Filter_Enable) ); - - while ( READ_REGISTER( RxMACConfiguration ) & (kRxMACConfiguration_Rx_Mac_Enable - | kRxMACConfiguration_Hash_Filter_Enable) ) - ; - - for ( i= 0; i < 16; i++ ) - WRITE_REGISTER( HashTable[ i ], hashTableMask[ 15 - i ] ); - - rxMacConfigReg |= kRxMACConfiguration_Hash_Filter_Enable; - WRITE_REGISTER( RxMACConfiguration, rxMacConfigReg ); -} diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.h b/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.h deleted file mode 100644 index 939895243..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetPrivate.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Computer - * - * Interface for hardware dependent (relatively) code - * for the UniN Ethernet chip - * - * HISTORY - * - */ - - -#include "UniNEnet.h" -#include "UniNEnetMII.h" -#include <libkern/OSByteOrder.h> - - -///void WriteUniNRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset, u_int32_t data); -///volatile u_int32_t ReadUniNRegister( IOPPCAddress ioEnetBase, u_int32_t reg_offset); diff --git a/iokit/Drivers/network/drvPPCUniN/UniNEnetRegisters.h b/iokit/Drivers/network/drvPPCUniN/UniNEnetRegisters.h deleted file mode 100644 index 7b4b533c0..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNEnetRegisters.h +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-1999 Apple Computer - * - * Interface definition for the Sun GEM (UniN) Ethernet controller. - * - * - */ - -/* - * Miscellaneous defines... - */ -#define CACHE_LINE_SIZE 32 /* Bytes */ - -#define RX_RING_LENGTH_FACTOR 1 // valid from 0 to 8 -#define RX_RING_LENGTH (32 * (1 << RX_RING_LENGTH_FACTOR)) // 128 pkt descs /* Packet descriptors */ -#define RX_RING_WRAP_MASK (RX_RING_LENGTH -1) - -#define TX_RING_LENGTH_FACTOR 2 // valid from 0 to 8 -#define TX_RING_LENGTH (32 * (1 << TX_RING_LENGTH_FACTOR)) // 128 pkt descs -#define TX_RING_WRAP_MASK (TX_RING_LENGTH -1) - -#define TX_MAX_MBUFS (TX_RING_LENGTH / 2) - -#define TX_DESC_PER_INT 32 - -#define NETWORK_BUFSIZE (((ETHERMAXPACKET + ETHERCRC) + 7) & ~7) - -#define TRANSMIT_QUEUE_SIZE 256 - -#define WATCHDOG_TIMER_MS 300 -#define TX_KDB_TIMEOUT 1000 - -#define PCI_PERIOD_33MHz 30 -#define PCI_PERIOD_66MHz 15 -#define RX_INT_LATENCY_uS 250 - - - struct GMAC_Registers - { - /* Global Resources: */ // 0x0000 - - UInt32 SEB_State; // 3 bits for diagnostics - UInt32 Configuration; // - UInt32 filler1; - UInt32 Status; - - UInt32 InterruptMask; // 0x0010 - UInt32 InterruptAck; - UInt32 filler2; - UInt32 StatusAlias; - - UInt8 filler3[ 0x1000 - 0x20 ]; - - UInt32 PCIErrorStatus; // 0x1000 - UInt32 PCIErrorMask; - UInt32 BIFConfiguration; - UInt32 BIFDiagnostic; - - UInt32 SoftwareReset; // 0x1010 - - UInt8 filler4[ 0x2000 - 0x1014 ]; - - /* Transmit DMA registers: */ - - UInt32 TxKick; // 0x2000 - UInt32 TxConfiguration; - UInt32 TxDescriptorBaseLow; - UInt32 TxDescriptorBaseHigh; - - UInt32 filler5; // 0x2010 - UInt32 TxFIFOWritePointer; - UInt32 TxFIFOShadowWritePointer; - UInt32 TxFIFOReadPointer; - - UInt32 TxFIFOShadowReadPointer; // 0x2020 - UInt32 TxFIFOPacketCounter; - UInt32 TxStateMachine; - UInt32 filler6; - - UInt32 TxDataPointerLow; // 0x2030 - UInt32 TxDataPointerHigh; - - UInt8 filler7[ 0x2100 - 0x2038 ]; - - UInt32 TxCompletion; // 0x2100 - UInt32 TxFIFOAddress; - UInt32 TxFIFOTag; - UInt32 TxFIFODataLow; - - UInt32 TxFIFODataHighT1; // 0x2110 - UInt32 TxFIFODataHighT0; - UInt32 TxFIFOSize; - - UInt8 filler8[ 0x4000 - 0x211C ]; - - /* Receive DMA registers: */ - - UInt32 RxConfiguration; // 0x4000 - UInt32 RxDescriptorBaseLow; - UInt32 RxDescriptorBaseHigh; - UInt32 RxFIFOWritePointer; - - UInt32 RxFIFOShadowWritePointer; // 0x4010 - UInt32 RxFIFOReadPointer; - UInt32 RxFIFOPacketCounter; - UInt32 RxStateMachine; - - UInt32 PauseThresholds; // 0x4020 - UInt32 RxDataPointerLow; - UInt32 RxDataPointerHigh; - - UInt8 filler9[ 0x4100 - 0x402C ]; - - UInt32 RxKick; // 0x4100 - UInt32 RxCompletion; - UInt32 RxBlanking; - UInt32 RxFIFOAddress; - - UInt32 RxFIFOTag; // 0x4110 - UInt32 RxFIFODataLow; - UInt32 RxFIFODataHighT0; - UInt32 RxFIFODataHighT1; - - UInt32 RxFIFOSize; // 0x4120 - - UInt8 filler10[ 0x6000 - 0x4124 ]; - - /* MAC registers: */ - - UInt32 TxMACSoftwareResetCommand; // 0x6000 - UInt32 RxMACSoftwareResetCommand; - UInt32 SendPauseCommand; - UInt32 filler11; - - UInt32 TxMACStatus; // 0x6010 - UInt32 RxMACStatus; - UInt32 MACControlStatus; - UInt32 filler12; - - UInt32 TxMACMask; // 0x6020 - UInt32 RxMACMask; - UInt32 MACControlMask; - UInt32 filler13; - - UInt32 TxMACConfiguration; // 0x6030 - UInt32 RxMACConfiguration; - UInt32 MACControlConfiguration; - UInt32 XIFConfiguration; - - UInt32 InterPacketGap0; // 0x6040 - UInt32 InterPacketGap1; - UInt32 InterPacketGap2; - UInt32 SlotTime; - - UInt32 MinFrameSize; // 0x6050 - UInt32 MaxFrameSize; - UInt32 PASize; - UInt32 JamSize; - - UInt32 AttemptLimit; // 0x6060 - UInt32 MACControlType; - UInt8 filler14[ 0x6080 - 0x6068 ]; - - UInt32 MACAddress[ 9 ]; // 0x6080 - - UInt32 AddressFilter[ 3 ]; // 0x60A4 - - UInt32 AddressFilter2_1Mask; // 0x60B0 - UInt32 AddressFilter0Mask; - UInt32 filler15[ 2 ]; - - UInt32 HashTable[ 16 ]; // 0x60C0 - - /* Statistics registers: */ - - UInt32 NormalCollisionCounter; // 0x6100 - UInt32 FirstAttemptSuccessfulCollisionCounter; - UInt32 ExcessiveCollisionCounter; - UInt32 LateCollisionCounter; - - UInt32 DeferTimer; // 0x6110 - UInt32 PeakAttempts; - UInt32 ReceiveFrameCounter; - UInt32 LengthErrorCounter; - - UInt32 AlignmentErrorCounter; // 0x6120 - UInt32 FCSErrorCounter; - UInt32 RxCodeViolationErrorCounter; - UInt32 filler16; - - /* Miscellaneous registers: */ - - UInt32 RandomNumberSeed; // 0x6130 - UInt32 StateMachine; - - UInt8 filler17[ 0x6200 - 0x6138 ]; - - /* MIF registers: */ - - UInt32 MIFBitBangClock; // 0x6200 - UInt32 MIFBitBangData; - UInt32 MIFBitBangOutputEnable; - UInt32 MIFBitBangFrame_Output; - - UInt32 MIFConfiguration; // 0x6210 - UInt32 MIFMask; - UInt32 MIFStatus; - UInt32 MIFStateMachine; - - UInt8 filler18[ 0x9000 - 0x6220 ]; - - /* PCS/Serialink registers: */ - - UInt32 PCSMIIControl; // 0x9000 - UInt32 PCSMIIStatus; - UInt32 Advertisement; - UInt32 PCSMIILinkPartnerAbility; - - UInt32 PCSConfiguration; // 0x9010 - UInt32 PCSStateMachine; - UInt32 PCSInterruptStatus; - - UInt8 filler19[ 0x9050 - 0x901C ]; - - UInt32 DatapathMode; // 0x9050 - UInt32 SerialinkControl; - UInt32 SharedOutputSelect; - UInt32 SerialinkState; - }; /* end GMAC_Registers */ - - -#define kConfiguration_Infinite_Burst 0x00000001 -#define kConfiguration_TX_DMA_Limit (0x1F << 1) -#define kConfiguration_RX_DMA_Limit (0x1F << 6) - - /* The following bits are used in the */ - /* Status, InterruptMask, InterruptAck, and StatusAlias registers: */ - -#define kStatus_TX_INT_ME 0x00000001 -#define kStatus_TX_ALL 0x00000002 -#define kStatus_TX_DONE 0x00000004 -#define kStatus_RX_DONE 0x00000010 -#define kStatus_Rx_Buffer_Not_Available 0x00000020 -#define kStatus_RX_TAG_ERROR 0x00000040 -#define kStatus_PCS_INT 0x00002000 -#define kStatus_TX_MAC_INT 0x00004000 -#define kStatus_RX_MAC_INT 0x00008000 -#define kStatus_MAC_CTRL_INT 0x00010000 -#define kStatus_MIF_Interrupt 0x00020000 -#define kStatus_PCI_ERROR_INT 0x00040000 -#define kStatus_TxCompletion_Shift 19 - -#define kInterruptMask_None 0xFFFFFFFF - -#define kBIFConfiguration_SLOWCLK 0x1 -#define kBIFConfiguration_B64D_DIS 0x2 -#define kBIFConfiguration_M66EN 0x8 - -#define kSoftwareReset_TX 0x1 -#define kSoftwareReset_RX 0x2 -#define kSoftwareReset_RSTOUT 0x4 - - // register TxConfiguration 2004: -#define kTxConfiguration_Tx_DMA_Enable 0x00000001 -#define kTxConfiguration_Tx_Desc_Ring_Size_Shift 1 // bits 1:4 -#define kTxConfiguration_TxFIFO_Threshold 0x001FFC00 // obsolete - - // register RxConfiguration 4000: -#define kRxConfiguration_Rx_DMA_Enable 0x00000001 -#define kRxConfiguration_Rx_Desc_Ring_Size_Shift 1 // bits 1:4 -#define kRxConfiguration_Batch_Disable 0x00000020 -#define kRxConfiguration_First_Byte_Offset_Mask 0x00001C00 -#define kRxConfiguration_Checksum_Start_Offset_Mask 0x000FE000 -#define kRxConfiguration_RX_DMA_Threshold 0x01000000 // 128 bytes - -#define kPauseThresholds_Factor 64 -#define kPauseThresholds_OFF_Threshold_Shift 0 // 9 bit field -#define kPauseThresholds_ON_Threshold_Shift 12 - -#define FACTOR33 ((RX_INT_LATENCY_uS * 1000) / (2048 * PCI_PERIOD_33MHz)) -#define FACTOR66 ((RX_INT_LATENCY_uS * 1000) / (2048 * PCI_PERIOD_66MHz)) - -#define F33 (FACTOR33 << kPauseThresholds_ON_Threshold_Shift ) -#define F66 (FACTOR66 << kPauseThresholds_ON_Threshold_Shift ) - -#define kRxBlanking_default_33 (F33 | 5) -#define kRxBlanking_default_66 (F66 | 5) - -#define kTxMACSoftwareResetCommand_Reset 1 // 1 bit register -#define kRxMACSoftwareResetCommand_Reset 1 - -#define kSendPauseCommand_default 0x1BF0 - // 0x6010: -#define kTX_MAC_Status_Frame_Transmitted 0x001 -#define kTX_MAC_Status_Tx_Underrun 0x002 -#define kTX_MAC_Status_Max_Pkt_Err 0x004 -#define kTX_MAC_Status_Normal_Coll_Cnt_Exp 0x008 -#define kTX_MAC_Status_Excess_Coll_Cnt_Exp 0x010 -#define kTX_MAC_Status_Late_Coll_Cnt_Exp 0x020 -#define kTX_MAC_Status_First_Coll_Cnt_Exp 0x040 -#define kTX_MAC_Status_Defer_Timer_Exp 0x080 -#define kTX_MAC_Status_Peak_Attempts_Cnt_Exp 0x100 - // 0x6014: -#define kRX_MAC_Status_Frame_Received 0x01 -#define kRX_MAC_Status_Rx_Overflow 0x02 // Rx FIFO overflow -#define kRX_MAC_Status_Frame_Cnt_Exp 0x04 -#define kRX_MAC_Status_Align_Err_Cnt_Exp 0x08 -#define kRX_MAC_Status_CRC_Err_Cnt_Exp 0x10 -#define kRX_MAC_Status_Length_Err_Cnt_Exp 0x20 -#define kRX_MAC_Status_Viol_Err_Cnt_Exp 0x40 - - -#ifdef CRAP -#define kTxMACMask_default 0x1FF // was 0xFFFF -#define kRxMACMask_default 0x7F // was 0xFFFF -#define kMACControlMask_default 0X00000007 // was 0xFFFF -#else -#define kTxMACMask_default 1 // enable all but Frame_Transmitted -#define kRxMACMask_default 1 // enable all but Frame_Received -#define kMACControlMask_default 0xFFFFFFF8 // enable Paused stuff -#endif // CRAP - -#define kTxMACConfiguration_TxMac_Enable 0x001 -#define kTxMACConfiguration_Ignore_Carrier_Sense 0x002 -#define kTxMACConfiguration_Ignore_Collisions 0x004 -#define kTxMACConfiguration_Enable_IPG0 0x008 -#define kTxMACConfiguration_Never_Give_Up 0x010 -#define kTxMACConfiguration_Never_Give_Up_Limit 0x020 -#define kTxMACConfiguration_No_Backoff 0x040 -#define kTxMACConfiguration_Slow_Down 0x080 -#define kTxMACConfiguration_No_FCS 0x100 -#define kTxMACConfiguration_TX_Carrier_Extension 0x200 - -#define kRxMACConfiguration_Rx_Mac_Enable 0x001 -#define kRxMACConfiguration_Strip_Pad 0x002 -#define kRxMACConfiguration_Strip_FCS 0x004 -#define kRxMACConfiguration_Promiscuous 0x008 -#define kRxMACConfiguration_Promiscuous_Group 0x010 -#define kRxMACConfiguration_Hash_Filter_Enable 0x020 -#define kRxMACConfiguration_Address_Filter_Enable 0x040 -#define kRxMACConfiguration_Disable_Discard_On_Err 0x080 -#define kRxMACConfiguration_Rx_Carrier_Extension 0x100 - -#define kMACControlConfiguration_Send_Pause_Enable 0x1 -#define kMACControlConfiguration_Receive_Pause_Enable 0x2 -#define kMACControlConfiguration_Pass_MAC_Control 0x4 - -#define kXIFConfiguration_Tx_MII_OE 0x01 // output enable on the MII bus -#define kXIFConfiguration_MII_Int_Loopback 0x02 -#define kXIFConfiguration_Disable_Echo 0x04 -#define kXIFConfiguration_GMIIMODE 0x08 -#define kXIFConfiguration_MII_Buffer_OE 0x10 -#define kXIFConfiguration_LINKLED 0x20 -#define kXIFConfiguration_FDPLXLED 0x40 - -#define kInterPacketGap0_default 0 -#define kInterPacketGap1_default 8 -#define kInterPacketGap2_default 4 - -#define kSlotTime_default 0x0040 -#define kMinFrameSize_default 0x0040 -#define kMaxFrameSize_default 0x05EE - -#define kGEMMacMaxFrameSize_Aligned ((kMaxFrameSize_default + 7) & ~7) - - -#define kPASize_default 0x07 -#define kJamSize_default 0x04 -#define kAttemptLimit_default 0x10 -#define kMACControlType_default 0x8808 - -#define kMACAddress_default_6 0x0001 -#define kMACAddress_default_7 0xC200 -#define kMACAddress_default_8 0x0180 - -#define kMIFBitBangFrame_Output_ST_default 0x40000000 // 2 bits: ST of frame -#define kMIFBitBangFrame_Output_OP_read 0x20000000 // OP code - 2 bits: -#define kMIFBitBangFrame_Output_OP_write 0x10000000 // Read=10; Write=01 -#define kMIFBitBangFrame_Output_PHYAD_shift 23 // 5 bit PHY ADdress -#define kMIFBitBangFrame_Output_REGAD_shift 18 // 5 bit REGister ADdress -#define kMIFBitBangFrame_Output_TA_MSB 0x00020000 // Turn Around MSB -#define kMIFBitBangFrame_Output_TA_LSB 0x00010000 // Turn Around LSB - -#define kMIFConfiguration_PHY_Select 0x01 -#define kMIFConfiguration_Poll_Enable 0x02 -#define kMIFConfiguration_BB_Mode 0x04 -#define kMIFConfiguration_MDI_0 0x10 -#define kMIFConfiguration_MDI_1 0x20 - -#define kPCSMIIControl_1000_Mbs_Speed_Select 0x0040 -#define kPCSMIIControl_Collision_Test 0x0080 -#define kPCSMIIControl_Duplex_Mode 0x0100 -#define kPCSMIIControl_Restart_Auto_Negotiation 0x0200 -#define kPCSMIIControl_Isolate 0x0400 -#define kPCSMIIControl_Power_Down 0x0800 -#define kPCSMIIControl_Auto_Negotiation_Enable 0x1000 -#define kPCSMIIControl_Wrapback 0x4000 -#define kPCSMIIControl_Reset 0x8000 - -#define kAdvertisement_Full_Duplex 0x0020 -#define kAdvertisement_Half_Duplex 0x0040 -#define kAdvertisement_PAUSE 0x0080 // symmetrical to link partner -#define kAdvertisement_ASM_DIR 0x0100 // pause asymmetrical to link partner -#define kAdvertisement_Ack 0x4000 - -#define kPCSConfiguration_Enable 0x01 -#define kPCSConfiguration_Signal_Detect_Override 0x02 -#define kPCSConfiguration_Signal_Detect_Active_Low 0x04 -#define kPCSConfiguration_Jitter_Study // 2 bit field -#define kPCSConfiguration_10ms_Timer_Override 0x20 - -#define kDatapathMode_XMode 0x01 -#define kDatapathMode_ExtSERDESMode 0x02 -#define kDatapathMode_GMIIMode 0x04 -#define kDatapathMode_GMIIOutputEnable 0x08 - -#define kSerialinkControl_DisableLoopback 0x01 -#define kSerialinkControl_EnableSyncDet 0x02 -#define kSerialinkControl_LockRefClk 0x04 - - - - /* Descriptor definitions: */ - /* Note: Own is in the high bit of frameDataSize field: */ - -#define kGEMRxDescFrameSize_Mask 0x7FFF -#define kGEMRxDescFrameSize_Own 0x8000 - - - /* Rx flags field: */ - -#define kGEMRxDescFlags_HashValueBit 0x00001000 -#define kGEMRxDescFlags_HashValueMask 0x0FFFF000 -#define kGEMRxDescFlags_HashPass 0x10000000 -#define kGEMRxDescFlags_AlternateAddr 0x20000000 -#define kGEMRxDescFlags_BadCRC 0x40000000 - - -#define kGEMTxDescFlags0_BufferSizeMask 0x00007FFF -//#define kGEMTxDescFlags0_BufferSizeBit 0x00000001 -#define kGEMTxDescFlags0_ChecksumStartMask 0x00FF8000 -#define kGEMTxDescFlags0_ChecksumStartBit 0x00008000 -#define kGEMTxDescFlags0_ChecksumStuffMask 0x1F000000 -#define kGEMTxDescFlags0_ChecksupStuffBit 0x01000000 -#define kGEMTxDescFlags0_ChecksumEnable 0x20000000 -#define kGEMTxDescFlags0_EndOfFrame 0x40000000 -#define kGEMTxDescFlags0_StartOfFrame 0x80000000 - -#define kGEMTxDescFlags1_Int 0x00000001 -#define kGEMTxDescFlags1_NoCRC 0x00000002 - - -/* - * Receive/Transmit descriptor - * - */ -typedef struct _GEMRxDescriptor -{ - u_int16_t tcpPseudoChecksum; - u_int16_t frameDataSize; - u_int32_t flags; - u_int32_t bufferAddrLo; - u_int32_t bufferAddrHi; -} GEMRxDescriptor; - -/* - * Note: Own is in the high bit of frameDataSize field - */ -#define kGEMRxDescFrameSize_Mask 0x7FFF -#define kGEMRxDescFrameSize_Own 0x8000 - -/* - * Rx flags field - */ -#define kGEMRxDescFlags_HashValueBit 0x00001000 -#define kGEMRxDescFlags_HashValueMask 0x0FFFF000 -#define kGEMRxDescFlags_HashPass 0x10000000 -#define kGEMRxDescFlags_AlternateAddr 0x20000000 -#define kGEMRxDescFlags_BadCRC 0x40000000 - - -typedef struct _GEMTxDescriptor -{ - u_int32_t flags0; - u_int32_t flags1; - u_int32_t bufferAddrLo; - u_int32_t bufferAddrHi; -} GEMTxDescriptor; - -/* - * - */ -#define kGEMTxDescFlags0_BufferSizeMask 0x00007FFF -#define kGEMTxDescFlags0_BufferSizeBit 0x00000001 -#define kGEMTxDescFlags0_ChecksumStartMask 0x00FF8000 -#define kGEMTxDescFlags0_ChecksumStartBit 0x00008000 -#define kGEMTxDescFlags0_ChecksumStuffMask 0x1F000000 -#define kGEMTxDescFlags0_ChecksupStuffBit 0x01000000 -#define kGEMTxDescFlags0_ChecksumEnable 0x20000000 -#define kGEMTxDescFlags0_EndOfFrame 0x40000000 -#define kGEMTxDescFlags0_StartOfFrame 0x80000000 - -#define kGEMTxDescFlags1_Int 0x00000001 -#define kGEMTxDescFlags1_NoCRC 0x00000002 - - - -#define kGEMBurstSize (CACHE_LINE_SIZE / 8) diff --git a/iokit/Drivers/network/drvPPCUniN/UniNPowerSaver.cpp b/iokit/Drivers/network/drvPPCUniN/UniNPowerSaver.cpp deleted file mode 100644 index e1c2edac1..000000000 --- a/iokit/Drivers/network/drvPPCUniN/UniNPowerSaver.cpp +++ /dev/null @@ -1,378 +0,0 @@ - -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - - -#include "UniNEnetPrivate.h" - -#define super IOEthernetController - -// Set EXTRANEOUS_PM_DELAYS to 1 to enable absurdly long delays. -// -#define EXTRANEOUS_PM_DELAYS 0 - -// -------------------------------------------------------------------------- -// Method: registerWithPolicyMaker -// -// Purpose: -// initialize the driver for power managment and register ourselves with -// policy-maker -IOReturn -UniNEnet::registerWithPolicyMaker(IOService * policyMaker) -{ - -/****** -From iokit/IOKit/pwr_mgt/IOPMpowerState.h -struct IOPMPowerState -{ -unsigned long version; // version number of this struct -IOPMPowerFlags capabilityFlags; // bits that describe the capability -IOPMPowerFlags outputPowerCharacter; // description (to power domain children) -IOPMPowerFlags inputPowerRequirement; // description (to power domain parent) -unsigned long staticPower; // average consumption in milliwatts -unsigned long unbudgetedPower; // additional consumption from separate power supply (mw) -unsigned long powerToAttain; // additional power to attain this state from next lower state (in mw) -unsigned long timeToAttain; // (in microseconds) -unsigned long settleUpTime; // (microseconds) -unsigned long timeToLower; // (in microseconds) -unsigned long settleDownTime; // (microseconds) -unsigned long powerDomainBudget; // power in mw a domain in this state can deliver to its children -}; - -*******/ - -#define num_of_power_states 2 - -static IOPMPowerState ourPowerStates[num_of_power_states] = { - {1, 0,0,0,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable | IOPMMaxPerformance, IOPMPowerOn, IOPMPowerOn, 50,0,0, - kUniNsettle_time, kUniNsettle_time, kUniNsettle_time, kUniNsettle_time,0} - // 50 milliwatts above is just a guess right now, since the ethernet is part of Uni-N -}; - - currentPowerState = kMaxUniNEnetPowerState; - return policyMaker->registerPowerDriver(this, ourPowerStates, num_of_power_states); -} - -// Method: maxCapabilityForDomainState -// -// Purpose: -// returns the maximun state of card power, which would be -// power on without any attempt to power manager. -unsigned long -UniNEnet::maxCapabilityForDomainState(IOPMPowerFlags domainState) -{ - if( domainState & IOPMPowerOn ) - return kMaxUniNEnetPowerState; //In reality, it's just array element 1 for Uni-N - else - return 0; -} - -// Method: initialPowerStateForDomainState -// -// Purpose: -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. - -unsigned long -UniNEnet::initialPowerStateForDomainState( IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn ) - return currentPowerState; - else - return 0; -} - - -// Method: powerStateForDomainState -// -// Purpose: -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. -unsigned long -UniNEnet::powerStateForDomainState(IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn ) - return currentPowerState; - else - return 0; -} - -// Method: setPowerState -// -IOReturn UniNEnet::setPowerState(unsigned long powerStateOrdinal, - IOService * whatDevice) -{ - volatile UInt32 clockReg; - - // Do not do anything if the state is invalid. - if (powerStateOrdinal >= num_of_power_states) - return IOPMNoSuchState; - - if (powerStateOrdinal == currentPowerState) - return IOPMAckImplied; //no change required - - // otherwise remember the new state: - currentPowerState = powerStateOrdinal; - - IOLog("UniNEthernet::setPowerState(%d, 0x%08lx)\n", - (int) powerStateOrdinal, - (UInt32) whatDevice); - - switch ( currentPowerState ) - { - case 0: // Ethernet is off - - // Shutdown the hardware unconditionally. - // doDisable(this); - - // Turn off PHY before turning off MAC - // MII_CONTROL_POWERDOWN ? no, it is read-only for Broadcom 5201 - // PHY, but 5400 is R/W - stopPHYChip(false); //In this file - - // Now turn off ethernet clock in Uni-N - callPlatformFunction("EnableUniNEthernetClock", true, - (void *)false, 0, 0, 0); - break; - - case kMaxUniNEnetPowerState: // 1 = max power state, Ethernet is on - - // Now turn on ethernet clock in Uni-N - callPlatformFunction("EnableUniNEthernetClock", true, - (void *)true, 0, 0, 0); - -#if EXTRANEOUS_PM_DELAYS - IODelay(MII_DEFAULT_DELAY * 1000); // 20 milliseconds -#endif - - // Bring up PHY then MAC. - startPHYChip(); - // doEnable(this); - - break; - - default: - // This is illegal, only 0 and 1 are allowed for - // UniN ethernet for now - break; - } - - return IOPMAckImplied; -} - -// This method sets up the PHY registers for low power. -// Copied from stopEthernetController() in OS9. -// The setupWOL value is not really implemented systemwide yet -void -UniNEnet::stopPHYChip(bool setupWOL) -{ - UInt32 val32; - UInt16 i, val16; - - if (phyBCMType == 0) return; - - //IOLog("UniN on stop phy = %d\n", phyBCMType); - - if (setupWOL == false) - { - //disabling MIF interrupts on the 5201 is explicit - if (phyBCMType == 5201) - { - miiWriteWord(0x0000, MII_BCM5201_INTERRUPT, kPHYAddr0); - // 0 or 0x1f or phyId? miiFindPHY returns any integer - } - } - - //Drive the MDIO line high to prevent immediate wakeup - val32 = READ_REGISTER( MIFConfiguration ); - WRITE_REGISTER( MIFConfiguration, val32 & kMIFConfiguration_Poll_Enable ); - - // 5th ADDR in Broadcom PHY docs - miiReadWord( &val16, MII_LINKPARTNER, kPHYAddr0 ); - - // don't know why OS9 writes it back unchanged - miiWriteWord( val16, MII_LINKPARTNER, kPHYAddr0 ); - - /* Put the MDIO pins into a benign state. Note that the management regs - in the PHY will be inaccessible. This is to guarantee max power savings - on Powerbooks and to eliminate damage to Broadcom PHYs. - */ - //bit bang mode - WRITE_REGISTER( MIFConfiguration, kMIFConfiguration_BB_Mode ); - - WRITE_REGISTER( MIFBitBangClock, 0x0000 ); - WRITE_REGISTER( MIFBitBangData, 0x0000 ); - WRITE_REGISTER( MIFBitBangOutputEnable, 0x0000 ); - WRITE_REGISTER( XIFConfiguration, kXIFConfiguration_GMIIMODE - | kXIFConfiguration_MII_Int_Loopback ); - - if (setupWOL) - { - //For multicast filtering these bits must be enabled - WRITE_REGISTER( RxMACConfiguration, - kRxMACConfiguration_Hash_Filter_Enable - | kRxMACConfiguration_Rx_Mac_Enable ); - // set kpfRxMACEnabled in OS9, but I don't see matching OS X flag - } - else - { - WRITE_REGISTER( RxMACConfiguration, 0 ); - // un-set kpfRxMACEnabled in OS9, but I don't see matching OS X flag - } - - WRITE_REGISTER( TxMACConfiguration, 0 ); - WRITE_REGISTER( XIFConfiguration, 0 ); - -#if 0 - // Disable interrupt source on the controller. - // Already disabled from earlier resetAndEnable(false) call. - WRITE_REGISTER( InterruptMask, kInterruptMask_None ); // all FF -#endif - - WRITE_REGISTER( TxConfiguration, 0 ); - WRITE_REGISTER( RxConfiguration, 0 ); - - if (!setupWOL) - { - // this doesn't power down stuff, but if we don't hit it then we can't - // superisolate the transceiver - WRITE_REGISTER( SoftwareReset, kSoftwareReset_TX | kSoftwareReset_RX ); - - // kSoftwareReset_RSTOUT too??? - i = 0; - do { -// IODelay(MII_RESET_DELAY * 1000); // 10 milliseconds - IODelay(10); - if (i++ >= 100) - { - IOLog("UniNEnet timeout on SW reset\n"); - break; - } - val32 = READ_REGISTER( SoftwareReset ); - } while ( (val32 & (kSoftwareReset_TX | kSoftwareReset_RX)) != 0 ); - - WRITE_REGISTER( TxMACSoftwareResetCommand, kTxMACSoftwareResetCommand_Reset ); - WRITE_REGISTER( RxMACSoftwareResetCommand, kRxMACSoftwareResetCommand_Reset ); - - //This is what actually turns off the LINK LED - if (phyBCMType == 5400) - { -#if 0 - // The 5400 has read/write privilege on this bit, - // but 5201 is read-only. - miiWriteWord( MII_CONTROL_POWERDOWN, MII_CONTROL, kPHYAddr0); -#endif - } - else // Only other possibility is Broadcom 5201 (or 5202?) - { -#if 0 - miiReadWord( &val16, MII_BCM5201_AUXMODE2, kPHYAddr0 ); - miiWriteWord( val16 & ~MII_BCM5201_AUXMODE2_LOWPOWER, - MII_BCM5201_AUXMODE2, kPHYAddr0 ); -#endif - - miiWriteWord( MII_BCM5201_MULTIPHY_SUPERISOLATE, - MII_BCM5201_MULTIPHY, - kPHYAddr0 ); - } - } // end of none-WOL case -} - -//start the PHY -void -UniNEnet::startPHYChip() -{ - UInt32 val32; - UInt16 val16; - - // if (netifClient) //MacOS 9 uses numClients == 1? - { - //IOLog("UniN on restart phy = %d\n", phyBCMType); - - val32 = READ_REGISTER( TxConfiguration ); - WRITE_REGISTER( TxConfiguration, val32 | kTxConfiguration_Tx_DMA_Enable ); - - val32 = READ_REGISTER( RxConfiguration ); - WRITE_REGISTER( RxConfiguration, val32 | kRxConfiguration_Rx_DMA_Enable ); - - val32 = READ_REGISTER( TxMACConfiguration ); - WRITE_REGISTER( TxMACConfiguration, val32 | kTxMACConfiguration_TxMac_Enable ); - - val32 = READ_REGISTER( RxMACConfiguration ); - WRITE_REGISTER( RxMACConfiguration, - val32 | kRxMACConfiguration_Rx_Mac_Enable - | kRxMACConfiguration_Hash_Filter_Enable ); - - // Set flag to RxMACEnabled somewhere?? - - /* These registers are only for the Broadcom 5201. - We write the auto low power mode bit here because if we do it earlier - and there is no link then the xcvr registers become unclocked and - unable to be written - */ - if (phyBCMType == 5201) - { - // Ask Enrique why the following 2 lines are not necessary in OS 9. - // These 2 lines should take the PHY out of superisolate mode. All - // MII inputs are ignored until the PHY is out of isolate mode - miiReadWord( &val16, MII_BCM5201_MULTIPHY, kPHYAddr0 ); - miiWriteWord( val16 & ~MII_BCM5201_MULTIPHY_SUPERISOLATE, - MII_BCM5201_MULTIPHY, kPHYAddr0 ); - -#if 0 - // Automatically go into low power mode if no link - miiReadWord( &val16, MII_BCM5201_AUXMODE2, kPHYAddr0 ); - miiWriteWord( val16 | MII_BCM5201_AUXMODE2_LOWPOWER, - MII_BCM5201_AUXMODE2, kPHYAddr0 ); -#endif - -#if EXTRANEOUS_PM_DELAYS - IODelay(MII_DEFAULT_DELAY * 1000); // 20 milliseconds -#endif - } - - // WARNING... this code is untested on gigabit ethernet (5400), there - // should be a case to handle it for MII_CONTROL_POWERDOWN bit here, - // unless it is unnecessary after a hardware reset - - WRITE_REGISTER( RxKick, RX_RING_LENGTH - 4 ); - } -} - -/*------------------------------------------------------------------------- - * Assert the reset pin on the PHY momentarily to initialize it, and also - * to bring the PHY out of low-power mode. - * - *-------------------------------------------------------------------------*/ - -bool UniNEnet::resetPHYChip() -{ - IOReturn result; - - result = keyLargo->callPlatformFunction(keyLargo_resetUniNEthernetPhy, false, 0, 0, 0, 0); - if (result != kIOReturnSuccess) return false; - - return true; -} diff --git a/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp b/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp deleted file mode 100644 index 5572c05ec..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - */ - -#include <IOKit/system.h> - -#include <libkern/c++/OSContainers.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOLib.h> -#include <libkern/OSByteOrder.h> - -#include "AppleGracklePCI.h" - -#include <IOKit/assert.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOPCIBridge - -OSDefineMetaClassAndStructors(AppleGracklePCI, IOPCIBridge) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool AppleGracklePCI::start( IOService * provider ) -{ - IOPCIPhysicalAddress ioAddrCell; - IOPhysicalAddress ioPhys; - IOPhysicalAddress ioPhysLen; - OSArray * array; - IODeviceMemory::InitElement rangeList[ 3 ]; - IORegistryEntry * bridge; - OSData * busProp; - IOPCIAddressSpace grackleSpace; - UInt32 picr1; - - if( 0 == (lock = IOSimpleLockAlloc())) - return( false ); - - ioAddrCell.physHi.bits = 0; - ioAddrCell.physHi.s.space = kIOPCIIOSpace; - ioAddrCell.physMid = 0; - ioAddrCell.physLo = 0; - ioAddrCell.lengthHi = 0; - ioAddrCell.lengthLo = 0x10000; - - bridge = provider; - - if( ! IODTResolveAddressCell( bridge, (UInt32 *) &ioAddrCell, - &ioPhys, &ioPhysLen) ) { - - IOLog("%s: couldn't find my base\n", getName()); - return( false); - } - - /* define more explicit ranges */ - - rangeList[0].start = ioPhys; - rangeList[0].length = ioPhysLen; - rangeList[1].start = ioPhys + 0x00c00000; - rangeList[1].length = 4; - rangeList[2].start = ioPhys + 0x00e00000; - rangeList[2].length = 4; - - array = IODeviceMemory::arrayFromList( rangeList, 3 ); - if( !array) - return( false); - - provider->setDeviceMemory( array ); - array->release(); - ioMemory = (IODeviceMemory *) array->getObject( 0 ); - - if( (configAddrMap = provider->mapDeviceMemoryWithIndex( 1 ))) - configAddr = (volatile UInt32 *) configAddrMap->getVirtualAddress(); - if( (configDataMap = provider->mapDeviceMemoryWithIndex( 2 ))) - configData = (volatile UInt8 *) configDataMap->getVirtualAddress(); - - if( !configAddr || !configData) - return( false); - - busProp = (OSData *) bridge->getProperty("bus-range"); - if( busProp) - primaryBus = *((UInt32 *) busProp->getBytesNoCopy()); - - // Check to see if there is a set loop snoop property. - if( provider->getProperty("set-loop-snoop")) { - // Turn on the Loop Snoop bit in PICR1. - // See: MPC106 User's Manual p. 3-55. - grackleSpace.bits = 0x80000000; - picr1 = configRead32(grackleSpace, 0xA8); - picr1 |= (1 << 4); - configWrite32(grackleSpace, 0xA8, picr1); - } - - // register iteself so we can find it: - registerService(); - - // Publish the AccessMPC106PerformanceRegister platform function. - publishResource("AccessMPC106PerformanceRegister", this); - - return( super::start( provider)); -} - -bool AppleGracklePCI::configure( IOService * provider ) -{ - bool ok; - - ok = addBridgeMemoryRange( 0x80000000, 0x7f000000, true ); - ok = addBridgeIORange( 0, 0x10000 ); - - return( super::configure( provider )); -} - -void AppleGracklePCI::free() -{ - if( configAddrMap) - configAddrMap->release(); - if( configDataMap) - configDataMap->release(); - if( lock) - IOSimpleLockFree( lock); - - super::free(); -} - -IODeviceMemory * AppleGracklePCI::ioDeviceMemory( void ) -{ - return( ioMemory); -} - -UInt8 AppleGracklePCI::firstBusNum( void ) -{ - return( primaryBus ); -} - -UInt8 AppleGracklePCI::lastBusNum( void ) -{ - return( firstBusNum() ); -} - -IOPCIAddressSpace AppleGracklePCI::getBridgeSpace( void ) -{ - IOPCIAddressSpace space; - - space.bits = 0; - space.s.deviceNum = kBridgeSelfDevice; - - return( space ); -} - -inline void AppleGracklePCI::setConfigSpace( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOPCIAddressSpace addrCycle; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset & 0xfc; - - OSWriteSwapInt32( configAddr, 0, addrCycle.bits); - eieio(); - OSReadSwapInt32( configAddr, 0 ); - eieio(); -} - - -UInt32 AppleGracklePCI::configRead32( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt32 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - data = OSReadSwapInt32( configData, 0 ); - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return( data ); -} - -void AppleGracklePCI::configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - OSWriteSwapInt32( configData, 0, data ); - eieio(); - /* read to sync */ - (void) OSReadSwapInt32( configData, 0 ); - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt16 AppleGracklePCI::configRead16( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt16 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - offset = (offset & 2); - - data = OSReadSwapInt16( configData, offset ); - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return( data ); -} - -void AppleGracklePCI::configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - offset = (offset & 2); - - OSWriteSwapInt16( configData, offset, data ); - eieio(); - /* read to sync */ - (void) OSReadSwapInt16( configData, offset ); - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt8 AppleGracklePCI::configRead8( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt8 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - offset = (offset & 3); - - data = configData[ offset ]; - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return( data ); -} - -void AppleGracklePCI::configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - setConfigSpace( space, offset ); - - offset = (offset & 3); - - configData[ offset ] = data; - eieio(); - /* read to sync */ - data = configData[ offset ]; - eieio(); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -IOReturn AppleGracklePCI::callPlatformFunction(const OSSymbol *functionName, - bool waitForFunction, - void *param1, void *param2, - void *param3, void *param4) -{ - if (functionName->isEqualTo("AccessMPC106PerformanceRegister")) { - return accessMPC106PerformanceRegister((bool)param1, (long)param2, - (unsigned long *)param3); - } - - return super::callPlatformFunction(functionName, waitForFunction, - param1, param2, param3, param4); -} - - -enum { - kMCMonitorModeControl = 0, - kMCCommand, - kMCPerformanceMonitor0, - kMCPerformanceMonitor1, - kMCPerformanceMonitor2, - kMCPerformanceMonitor3 -}; - -IOReturn AppleGracklePCI::accessMPC106PerformanceRegister(bool write, - long regNumber, - unsigned long *data) -{ - IOPCIAddressSpace grackleSpace; - unsigned long offset; - - switch (regNumber) { - case kMCMonitorModeControl : offset = kMPC106MMCR0; break; - case kMCCommand : offset = kMPC106CMDR0; break; - case kMCPerformanceMonitor0 : offset = kMPC106PMC0; break; - case kMCPerformanceMonitor1 : offset = kMPC106PMC1; break; - case kMCPerformanceMonitor2 : offset = kMPC106PMC2; break; - case kMCPerformanceMonitor3 : offset = kMPC106PMC3; break; - default : return kIOReturnBadArgument; - } - - if (data == 0) return kIOReturnBadArgument; - - grackleSpace.bits = 0x80000000; - - if (write) { - configWrite32(grackleSpace, offset, *data); - } else { - *data = configRead32(grackleSpace, offset); - } - - return kIOReturnSuccess; -} diff --git a/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.h b/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.h deleted file mode 100644 index 766189c00..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - - -#ifndef _IOKIT_APPLEGRACKLEPCI_H -#define _IOKIT_APPLEGRACKLEPCI_H - -#include <IOKit/pci/IOPCIBridge.h> - -enum { - kBridgeSelfDevice = 0 -}; - -class AppleGracklePCI : public IOPCIBridge -{ - OSDeclareDefaultStructors(AppleGracklePCI) - -protected: - IOSimpleLock * lock; - IODeviceMemory * ioMemory; - IOMemoryMap * configAddrMap; - IOMemoryMap * configDataMap; - - volatile UInt32 * configAddr; - volatile UInt8 * configData; - - UInt8 primaryBus; - - inline void setConfigSpace( IOPCIAddressSpace space, UInt8 offset ); - virtual UInt8 firstBusNum( void ); - virtual UInt8 lastBusNum( void ); - - IOReturn accessMPC106PerformanceRegister(bool write, long regNumber, - unsigned long *data); - -public: - virtual bool start( IOService * provider ); - virtual bool configure( IOService * provider ); - - virtual void free(); - virtual IODeviceMemory * ioDeviceMemory( void ); - - virtual UInt32 configRead32( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ); - virtual UInt16 configRead16( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ); - virtual UInt8 configRead8( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ); - - virtual IOPCIAddressSpace getBridgeSpace( void ); - - virtual IOReturn callPlatformFunction(const OSSymbol *functionName, - bool waitForFunction, - void *param1, void *param2, - void *param3, void *param4); -}; - -// MPC106 Performance Monitoring Registers -#define kMPC106CMDR0 (0x048) -#define kMPC106MMCR0 (0x04C) -#define kMPC106PMC0 (0x050) -#define kMPC106PMC1 (0x054) -#define kMPC106PMC2 (0x058) -#define kMPC106PMC3 (0x05C) - -#endif /* ! _IOKIT_APPLEGRACKLEPCI_H */ diff --git a/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp b/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp deleted file mode 100644 index 40423ac11..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - */ - -#include <IOKit/system.h> - -#include <libkern/c++/OSContainers.h> -#include <IOKit/IODeviceMemory.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOLib.h> - -#include <architecture/i386/kernBootStruct.h> -#include <architecture/i386/pio.h> - -#include "AppleI386PCI.h" - -#include <assert.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOPCIBridge - -OSDefineMetaClassAndStructors(AppleI386PCI, IOPCIBridge) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool AppleI386PCI::start( IOService * provider ) -{ - OSData * prop; - PCI_bus_info_t * info; - - if( 0 == (lock = IOSimpleLockAlloc())) - return( false ); - - prop = (OSData *) provider->getProperty("pci-bus-info"); - if( 0 == prop) - return( false); - - info = (PCI_bus_info_t *) prop->getBytesNoCopy(); - - maxBusNum = info->maxBusNum; - maxDevNum = 0; - majorVersion = info->majorVersion; - minorVersion = info->minorVersion; - BIOS16Present = info->BIOSPresent; - BIOS32Present = false; - BIOS32Entry = 0x00000000; - configMethod1 = info->u_bus.s.configMethod1; - configMethod2 = info->u_bus.s.configMethod2; - specialCycle1 = info->u_bus.s.specialCycle1; - specialCycle2 = info->u_bus.s.specialCycle2; - - /* - if ((BIOS16Present) & !(configMethod1 | configMethod2)) { - // This is a PCI system, but neither method is supported - // Lets try them both just in case (ala NEC ExpressII P60) - if (!(configMethod1 = [self test_M1])) - configMethod2 = [self test_M2]; - } - */ - -#define IFYES(b, s) ((b) ? s : "") - IOLog("PCI Ver=%x.%02x BusCount=%d Features=[ %s%s%s%s%s%s]\n", - majorVersion, minorVersion, maxBusNum+1, - IFYES(BIOS16Present, "BIOS16 "), IFYES(BIOS32Present, "BIOS32 "), - IFYES(configMethod1, "CM1 "), IFYES(configMethod2, "CM2 "), - IFYES(specialCycle1, "SC1 "), IFYES(specialCycle2, "SC2 ") ); - - if (configMethod1) - maxDevNum = 31; - else if (configMethod2) - maxDevNum = 15; - else - return( false ); - - ioMemory = IODeviceMemory::withRange( 0, 65536 ); - if( !ioMemory) - return( false); - ioMemory->setMapping( kernel_task, 0 ); /* mapped to zero in IO space */ - - return( super::start( provider)); -} - -bool AppleI386PCI::configure( IOService * provider ) -{ - bool ok; - - ok = addBridgeMemoryRange( 0x80000000, 0x7f000000, true ); - ok = addBridgeIORange( 0, 0x10000 ); - - return( super::configure( provider )); -} - -void AppleI386PCI::free() -{ - if( ioMemory) - ioMemory->release(); - if( lock) - IOSimpleLockFree( lock); - - super::free(); -} - -IODeviceMemory * AppleI386PCI::ioDeviceMemory( void ) -{ - return( ioMemory); -} - - -UInt8 AppleI386PCI::firstBusNum( void ) -{ - return( 0 ); -} - -UInt8 AppleI386PCI::lastBusNum( void ) -{ - return( firstBusNum() ); -} - -IOPCIAddressSpace AppleI386PCI::getBridgeSpace( void ) -{ - IOPCIAddressSpace space; - - space.bits = 0; - - return( space ); -} - -/* defines for Configuration Method #1 (PCI 2.0 Spec, sec 3.6.4.1.1) */ -#define PCI_CONFIG_ADDRESS 0x0cf8 -#define PCI_CONFIG_DATA 0x0cfc - -/* defines for Configuration Method #2 (PCI 2.0 Spec, sec 3.6.4.1.3) */ -#define PCI_CSE_REGISTER 0x0cf8 -#define PCI_BUS_FORWARD 0x0cfa - -#define PCI_DEFAULT_DATA 0xffffffff - -#if 0 - -- (BOOL) test_M1 -{ - unsigned long address, data; - - for (address = 0x80000000; address < 0x80010000; address += 0x800) { - outl (PCI_CONFIG_ADDRESS, address); - if (inl (PCI_CONFIG_ADDRESS) != address) { - return NO; - } - data = inl(PCI_CONFIG_DATA); - if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) { - outl (PCI_CONFIG_ADDRESS, 0); - return YES; - } - } - - outl (PCI_CONFIG_ADDRESS, 0); - return NO; -} - -- (BOOL) test_M2 -{ - unsigned long address, data; - - /* Enable configuration space at I/O ports Cxxx. */ - - outb (PCI_CSE_REGISTER, 0xF0); - if (inb (PCI_CSE_REGISTER) != 0xF0) { - return NO; - } - - outb (PCI_BUS_FORWARD, 0x00); - if (inb (PCI_BUS_FORWARD) != 0x00) { - return NO; - } - /* Search all devices on the bus. */ - for (address = 0xc000; address <= 0xcfff; address += 0x100) { - data = inl(address); - if ((data != PCI_DEFAULT_DATA) && (data != 0x00)) { - outb (PCI_CSE_REGISTER, 0); - return YES; - } - } - - outb (PCI_CSE_REGISTER, 0); - return NO; -} -#endif - -UInt32 AppleI386PCI::configRead32Method1( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOPCIAddressSpace addrCycle; - UInt32 data = PCI_DEFAULT_DATA; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - data = inl( PCI_CONFIG_DATA); - - outl( PCI_CONFIG_ADDRESS, 0); - - return( data ); -} - - -void AppleI386PCI::configWrite32Method1( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - IOPCIAddressSpace addrCycle; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - outl(PCI_CONFIG_DATA, data); - - outl( PCI_CONFIG_ADDRESS, 0); -} - -UInt16 AppleI386PCI::configRead16Method1( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOPCIAddressSpace addrCycle; - UInt16 data = 0xffff; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - data = inw( PCI_CONFIG_DATA); - - outl( PCI_CONFIG_ADDRESS, 0); - - return( data ); -} - - -void AppleI386PCI::configWrite16Method1( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - IOPCIAddressSpace addrCycle; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - outw(PCI_CONFIG_DATA, data); - - outl( PCI_CONFIG_ADDRESS, 0); -} - -UInt8 AppleI386PCI::configRead8Method1( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOPCIAddressSpace addrCycle; - UInt8 data = 0xff; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - data = inb( PCI_CONFIG_DATA); - - outl( PCI_CONFIG_ADDRESS, 0); - - return( data ); -} - - -void AppleI386PCI::configWrite8Method1( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - IOPCIAddressSpace addrCycle; - - addrCycle = space; - addrCycle.s.reloc = 1; - addrCycle.s.registerNum = offset; - - outl( PCI_CONFIG_ADDRESS, addrCycle.bits); - if (inl( PCI_CONFIG_ADDRESS) == addrCycle.bits) - outb(PCI_CONFIG_DATA, data); - - outl( PCI_CONFIG_ADDRESS, 0); -} - -UInt32 AppleI386PCI::configRead32Method2( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt32 data = PCI_DEFAULT_DATA; - UInt8 cse; - - if( space.s.deviceNum > 15) - return( data); - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - data = inl( 0xc000 - | (offset & 0xfc) - | (space.s.deviceNum << 8)); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); - - return( data ); -} - - -void AppleI386PCI::configWrite32Method2( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - UInt8 cse; - - if( space.s.deviceNum > 15) - return; - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - outl( 0xc000 - | (offset & 0xfc) - | (space.s.deviceNum << 8), data); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); -} - -UInt16 AppleI386PCI::configRead16Method2( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt16 data = 0xffff; - UInt8 cse; - - if( space.s.deviceNum > 15) - return( data); - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - data = inw( 0xc000 - | (offset & 0xfe) - | (space.s.deviceNum << 8)); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); - - return( data ); -} - - -void AppleI386PCI::configWrite16Method2( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - UInt8 cse; - - if( space.s.deviceNum > 15) - return; - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - outw( 0xc000 - | (offset & 0xfe) - | (space.s.deviceNum << 8), data); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); -} - - -UInt8 AppleI386PCI::configRead8Method2( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt16 data = 0xffff; - UInt8 cse; - - if( space.s.deviceNum > 15) - return( data); - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - data = inb( 0xc000 - | (offset) - | (space.s.deviceNum << 8)); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); - - return( data ); -} - - -void AppleI386PCI::configWrite8Method2( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - UInt8 cse; - - if( space.s.deviceNum > 15) - return; - - cse = 0xf0 | (space.s.functionNum << 1); - outb( PCI_CSE_REGISTER, cse); - if (inb( PCI_CSE_REGISTER) == cse) { - outb( PCI_BUS_FORWARD, space.s.busNum); - if (inb( PCI_BUS_FORWARD) == space.s.busNum) { - outb( 0xc000 - | (offset) - | (space.s.deviceNum << 8), data); - } - outb( PCI_BUS_FORWARD, 0x00); - } - outb( PCI_CSE_REGISTER, 0x00); -} - - -UInt32 AppleI386PCI::configRead32( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOInterruptState ints; - UInt32 retval; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - retval = configRead32Method1( space, offset ); - else - retval = configRead32Method2( space, offset ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return(retval); -} - -void AppleI386PCI::configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - configWrite32Method1( space, offset, data ); - else - configWrite32Method2( space, offset, data ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt16 AppleI386PCI::configRead16( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOInterruptState ints; - UInt16 retval; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - retval = configRead16Method1( space, offset ); - else - retval = configRead16Method2( space, offset ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return(retval); -} - -void AppleI386PCI::configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - configWrite16Method1( space, offset, data ); - else - configWrite16Method2( space, offset, data ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt8 AppleI386PCI::configRead8( IOPCIAddressSpace space, - UInt8 offset ) -{ - IOInterruptState ints; - UInt8 retval; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - retval = configRead8Method1( space, offset ); - else - retval = configRead8Method2( space, offset ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - return(retval); -} - -void AppleI386PCI::configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( configMethod1) - configWrite8Method1( space, offset, data ); - else - configWrite8Method2( space, offset, data ); - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - diff --git a/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.h b/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.h deleted file mode 100644 index a22320e9b..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleI386PCI.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - - -#ifndef _IOKIT_APPLEI386PCI_H -#define _IOKIT_APPLEI386PCI_H - -#include <IOKit/pci/IOPCIBridge.h> - -class AppleI386PCI : public IOPCIBridge -{ - OSDeclareDefaultStructors(AppleI386PCI) - - IOSimpleLock * lock; - IODeviceMemory * ioMemory; - - UInt8 maxBusNum; /* Highest valid Bus Number */ - UInt8 maxDevNum; /* Highest valid Device Number */ - bool BIOS16Present; /* booter found PCI BIOS 16 */ - bool configMethod1; /* host bridge supports CM1 */ - bool configMethod2; /* host bridge supports CM2 */ - bool specialCycle1; /* host bridge supports SC1 */ - bool specialCycle2; /* host bridge supports SC2 */ - bool BIOS32Present; /* init found PCI BIOS 32 */ - void *BIOS32Entry; /* Points to 32 bit PCI entry pt */ - int majorVersion; /* Packed BCD Major Rev#: 0x02 */ - int minorVersion; /* Packed BCD Minor Rev#: 0x00 */ - -private: - virtual UInt32 configRead32Method1( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite32Method1( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ); - virtual UInt16 configRead16Method1( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite16Method1( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ); - virtual UInt8 configRead8Method1( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite8Method1( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ); - - virtual UInt32 configRead32Method2( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite32Method2( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ); - virtual UInt16 configRead16Method2( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite16Method2( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ); - virtual UInt8 configRead8Method2( IOPCIAddressSpace space, - UInt8 offset ); - virtual void configWrite8Method2( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ); - - virtual IOPCIAddressSpace getBridgeSpace( void ); - -protected: - virtual UInt8 firstBusNum( void ); - virtual UInt8 lastBusNum( void ); - -public: - virtual bool start( IOService * provider ); - virtual bool configure( IOService * provider ); - - virtual void free(); - virtual IODeviceMemory * ioDeviceMemory( void ); - - virtual UInt32 configRead32( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ); - virtual UInt16 configRead16( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ); - virtual UInt8 configRead8( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ); -}; - -#endif /* ! _IOKIT_APPLEI386PCI_H */ - diff --git a/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.cpp b/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.cpp deleted file mode 100644 index 01a1a65ba..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.cpp +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - * 05 Nov 99 sdouglas added UniNorth AGP based on UniNorthAGPDriver.c - * by Fernando Urbina, Kent Miller. - * - */ - -#include <IOKit/system.h> -#include <ppc/proc_reg.h> - -#include <libkern/c++/OSContainers.h> -#include <libkern/OSByteOrder.h> - -#include <IOKit/IODeviceMemory.h> -#include <IOKit/IORangeAllocator.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOPlatformExpert.h> -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> - -#include "AppleMacRiscPCI.h" - -#define ALLOC_AGP_RANGE 0 - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOPCIBridge - -OSDefineMetaClassAndStructors(AppleMacRiscPCI, IOPCIBridge) - -OSDefineMetaClassAndStructors(AppleMacRiscVCI, AppleMacRiscPCI) - -OSDefineMetaClassAndStructors(AppleMacRiscAGP, AppleMacRiscPCI) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool AppleMacRiscPCI::start( IOService * provider ) -{ - IOPCIPhysicalAddress ioAddrCell; - IOPhysicalAddress ioPhys; - IOPhysicalAddress ioPhysLen; - OSArray * array; - IODeviceMemory::InitElement rangeList[ 3 ]; - IORegistryEntry * bridge; - OSData * busProp; - - if( !IODTMatchNubWithKeys(provider, "('pci', 'vci')")) - return( false); - - if( IODTMatchNubWithKeys(provider, "'uni-north'")) - configDataOffsetMask = 0x7; - else - configDataOffsetMask = 0x3; - - if( 0 == (lock = IOSimpleLockAlloc())) - return( false ); - - ioAddrCell.physHi.bits = 0; - ioAddrCell.physHi.s.space = kIOPCIIOSpace; - ioAddrCell.physMid = 0; - ioAddrCell.physLo = 0; - ioAddrCell.lengthHi = 0; - ioAddrCell.lengthLo = 0x10000; - - bridge = provider; - - if( ! IODTResolveAddressCell( bridge, (UInt32 *) &ioAddrCell, - &ioPhys, &ioPhysLen) ) { - - IOLog("%s: couldn't find my base\n", getName()); - return( false); - } - - /* define more explicit ranges */ - - rangeList[0].start = ioPhys; - rangeList[0].length = ioPhysLen; - rangeList[1].start = ioPhys + 0x00800000; - rangeList[1].length = 4; - rangeList[2].start = ioPhys + 0x00c00000; - rangeList[2].length = 4; - - IORangeAllocator * platformRanges; - platformRanges = IOService::getPlatform()->getPhysicalRangeAllocator(); - assert( platformRanges ); - platformRanges->allocateRange( ioPhys, 0x01000000 ); - - array = IODeviceMemory::arrayFromList( rangeList, 3 ); - if( !array) - return( false); - - provider->setDeviceMemory( array ); - array->release(); - ioMemory = (IODeviceMemory *) array->getObject( 0 ); - - /* map registers */ - - if( (configAddrMap = provider->mapDeviceMemoryWithIndex( 1 ))) - configAddr = (volatile UInt32 *) configAddrMap->getVirtualAddress(); - if( (configDataMap = provider->mapDeviceMemoryWithIndex( 2 ))) - configData = (volatile UInt8 *) configDataMap->getVirtualAddress(); - - if( !configAddr || !configData) - return( false); - - busProp = (OSData *) bridge->getProperty("bus-range"); - if( busProp) - primaryBus = *((UInt32 *) busProp->getBytesNoCopy()); - - return( super::start( provider)); -} - -bool AppleMacRiscPCI::configure( IOService * provider ) -{ - UInt32 addressSelects; - UInt32 index; - bool ok; - - addressSelects = configRead32( getBridgeSpace(), kMacRISCAddressSelect ); - - coarseAddressMask = addressSelects >> 16; - fineAddressMask = addressSelects & 0xffff; - - for( index = 0; index < 15; index++ ) { - if( coarseAddressMask & (1 << index)) { - ok = addBridgeMemoryRange( index << 28, 0x10000000, true ); - } - } - -// if( coarseAddressMask & (1 << 15)) // F segment - for( index = 0; index < 15; index++ ) { - if( fineAddressMask & (1 << index)) { - ok = addBridgeMemoryRange( (0xf0 | index) << 24, - 0x01000000, true ); - } - } - - ok = addBridgeIORange( 0, 0x10000 ); - - return( super::configure( provider)); -} - -void AppleMacRiscPCI::free() -{ - if( configAddrMap) - configAddrMap->release(); - if( configDataMap) - configDataMap->release(); - if( lock) - IOSimpleLockFree( lock); - - super::free(); -} - -IODeviceMemory * AppleMacRiscPCI::ioDeviceMemory( void ) -{ - return( ioMemory); -} - -IODeviceMemory * AppleMacRiscVCI::ioDeviceMemory( void ) -{ - return( 0 ); -} - -bool AppleMacRiscVCI::configure( IOService * provider ) -{ - addBridgeMemoryRange( 0x90000000, 0x10000000, true ); - - return( AppleMacRiscPCI::configure( provider)); -} - -UInt8 AppleMacRiscPCI::firstBusNum( void ) -{ - return( primaryBus ); -} - -UInt8 AppleMacRiscPCI::lastBusNum( void ) -{ - return( firstBusNum() ); -} - -IOPCIAddressSpace AppleMacRiscPCI::getBridgeSpace( void ) -{ - IOPCIAddressSpace space; - - space.bits = 0; - space.s.busNum = primaryBus; - space.s.deviceNum = kBridgeSelfDevice; - - return( space ); -} - -inline bool AppleMacRiscPCI::setConfigSpace( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt32 addrCycle; - - offset &= 0xfc; - if( space.s.busNum == primaryBus) { - - if( space.s.deviceNum < kBridgeSelfDevice) - return( false); - - // primary config cycle - addrCycle = ( (1 << space.s.deviceNum) - | (space.s.functionNum << 8) - | offset ); - - } else { - // pass thru config cycle - addrCycle = ( (space.bits) - | offset - | 1 ); - } - - do { - OSWriteSwapInt32( configAddr, 0, addrCycle); - eieio(); - } while( addrCycle != OSReadSwapInt32( configAddr, 0 )); - eieio(); - - return( true ); -} - - -UInt32 AppleMacRiscPCI::configRead32( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt32 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask & 4; - - data = OSReadSwapInt32( configData, offset ); - eieio(); - - } else - data = 0xffffffff; - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - - return( data ); -} - -void AppleMacRiscPCI::configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask & 4; - - OSWriteSwapInt32( configData, offset, data ); - eieio(); - /* read to sync */ - (void) OSReadSwapInt32( configData, offset ); - eieio(); - sync(); - isync(); - } - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt16 AppleMacRiscPCI::configRead16( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt16 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask & 6; - - data = OSReadSwapInt16( configData, offset ); - eieio(); - - } else - data = 0xffff; - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - - return( data ); -} - -void AppleMacRiscPCI::configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask & 6; - - OSWriteSwapInt16( configData, offset, data ); - eieio(); - /* read to sync */ - (void) OSReadSwapInt16( configData, offset ); - eieio(); - sync(); - isync(); - } - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -UInt8 AppleMacRiscPCI::configRead8( IOPCIAddressSpace space, - UInt8 offset ) -{ - UInt16 data; - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask; - - data = configData[ offset ]; - eieio(); - - } else - data = 0xff; - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); - - return( data ); -} - -void AppleMacRiscPCI::configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - IOInterruptState ints; - - ints = IOSimpleLockLockDisableInterrupt( lock ); - - if( setConfigSpace( space, offset )) { - - offset = offset & configDataOffsetMask; - - configData[ offset ] = data; - eieio(); - /* read to sync */ - data = configData[ offset ]; - eieio(); - sync(); - isync(); - } - - IOSimpleLockUnlockEnableInterrupt( lock, ints ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super AppleMacRiscPCI - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool AppleMacRiscAGP::configure( IOService * provider ) -{ - if( !findPCICapability( getBridgeSpace(), kIOPCIAGPCapability, &targetAGPRegisters )) - return( false ); - - return( super::configure( provider)); -} - -IOPCIDevice * AppleMacRiscAGP::createNub( OSDictionary * from ) -{ - IOPCIDevice * nub; - IOPCIAddressSpace space; - bool isAGP; - UInt8 masterAGPRegisters; - - spaceFromProperties( from, &space); - - isAGP = ( (space.s.deviceNum != getBridgeSpace().s.deviceNum) - && findPCICapability( space, kIOPCIAGPCapability, &masterAGPRegisters )); - - if( isAGP) { - nub = new IOAGPDevice; - if( nub) - ((IOAGPDevice *)nub)->masterAGPRegisters = masterAGPRegisters; - from->setObject( kIOAGPBusFlagsKey, getProperty(kIOAGPBusFlagsKey)); - } else - nub = super::createNub( from ); - - return( nub ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn AppleMacRiscAGP::createAGPSpace( IOAGPDevice * master, - IOOptionBits options, - IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - IOReturn err; - IOPCIAddressSpace target = getBridgeSpace(); - IOPhysicalLength agpLength; - IOPhysicalAddress gartPhys; - - enum { agpSpacePerPage = 4 * 1024 * 1024 }; - enum { agpBytesPerGartByte = 1024 }; - enum { alignLen = 4 * 1024 * 1024 - 1 }; - - destroyAGPSpace( master ); - - agpLength = *length; - if( !agpLength) - agpLength = 32 * 1024 * 1024; - - agpLength = (agpLength + alignLen) & ~alignLen; - - err = kIOReturnVMError; - do { - - gartLength = agpLength / agpBytesPerGartByte; - gartArray = (volatile UInt32 *) IOMallocContiguous( - gartLength, 4096, &gartPhys ); - if( !gartArray) - continue; - // IOMapPages( kernel_map, gartArray, gartPhys, gartLength, kIOMapInhibitCache ); - bzero( (void *) gartArray, gartLength); - -#if ALLOC_AGP_RANGE - IORangeAllocator * platformRanges - = getPlatform()->getPhysicalRangeAllocator(); - for( agpBaseIndex = 0xf; agpBaseIndex > 0; agpBaseIndex--) { - systemBase = agpBaseIndex * 0x10000000; - if( platformRanges->allocateRange( systemBase, agpLength )) { - systemLength = agpLength; - break; - } - } -#else - agpBaseIndex = 0; - systemBase = 0; - systemLength = agpLength; -#endif - if( !systemLength) - continue; - - agpRange = IORangeAllocator::withRange( agpLength, 4096 ); - if( !agpRange) - continue; - - *address = systemBase; - *length = systemLength; -#if 0 - coarseAddressMask |= (1 << agpBaseIndex); - configWrite32( target, kMacRISCAddressSelect, - (coarseAddressMask << 16) | fineAddressMask ); -#endif - configWrite32( target, kUniNAGP_BASE, agpBaseIndex << 28 ); - - assert( 0 == (gartPhys & 0xfff)); - configWrite32( target, kUniNGART_BASE, - gartPhys | (agpLength / agpSpacePerPage)); - - err = kIOReturnSuccess; - - } while( false ); - - if( kIOReturnSuccess == err) - setAGPEnable( master, true, 0 ); - else - destroyAGPSpace( master ); - - return( err ); -} - -IOReturn AppleMacRiscAGP::getAGPSpace( IOAGPDevice * master, - IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - if( systemLength) { - - if( address) - *address = systemBase; - if( length) - *length = systemLength; - return( kIOReturnSuccess ); - - } else - return( kIOReturnNotReady ); -} - -IOReturn AppleMacRiscAGP::destroyAGPSpace( IOAGPDevice * master ) -{ - - setAGPEnable( master, false, 0 ); - - if( gartArray) { - IOFreeContiguous( (void *) gartArray, gartLength); - gartArray = 0; - } - if( agpRange) { - agpRange->release(); - agpRange = 0; - } - if( systemLength) { -#if ALLOC_AGP_RANGE - IORangeAllocator * platformRanges - = getPlatform()->getPhysicalRangeAllocator(); - platformRanges->deallocate( systemBase, systemLength); -#endif - systemLength = 0; - } - - return( kIOReturnSuccess ); -} - -IORangeAllocator * AppleMacRiscAGP::getAGPRangeAllocator( - IOAGPDevice * master ) -{ -// if( agpRange) agpRange->retain(); - return( agpRange ); -} - -IOOptionBits AppleMacRiscAGP::getAGPStatus( IOAGPDevice * master, - IOOptionBits options = 0 ) -{ - IOPCIAddressSpace target = getBridgeSpace(); - - return( configRead32( target, kUniNINTERNAL_STATUS ) ); -} - -IOReturn AppleMacRiscAGP::resetAGPDevice( IOAGPDevice * master, - IOOptionBits options = 0 ) -{ - IOReturn ret; - - if( master->masterState & kIOAGPStateEnablePending) { - ret = setAGPEnable( master, true, 0 ); - master->masterState &= ~kIOAGPStateEnablePending; - } else - ret = kIOReturnSuccess; - - return( ret ); -} - -IOReturn AppleMacRiscAGP::commitAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options = 0 ) -{ - IOPCIAddressSpace target = getBridgeSpace(); - IOReturn err = kIOReturnSuccess; - UInt32 offset = 0; - IOPhysicalAddress physAddr; - IOByteCount len; - -// ok = agpRange->allocate( memory->getLength(), &agpOffset ); - - assert( agpOffset < systemLength ); - agpOffset /= (page_size / 4); - while( (physAddr = memory->getPhysicalSegment( offset, &len ))) { - - offset += len; - len = (len + 0xfff) & ~0xfff; - while( len > 0) { - OSWriteLittleInt32( gartArray, agpOffset, - ((physAddr & ~0xfff) | 1)); - agpOffset += 4; - physAddr += page_size; - len -= page_size; - } - } -#if 1 - flush_dcache( (vm_offset_t) gartArray, gartLength, false); - len = OSReadLittleInt32( gartArray, agpOffset - 4 ); - sync(); - isync(); -#endif - - if( kIOAGPGartInvalidate & options) { - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV ); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - } - - return( err ); -} - -IOReturn AppleMacRiscAGP::releaseAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options ) -{ - IOPCIAddressSpace target = getBridgeSpace(); - IOReturn err = kIOReturnSuccess; - IOByteCount length; - - if( !memory) - return( kIOReturnBadArgument ); - - length = memory->getLength(); - - if( (agpOffset + length) > systemLength) - return( kIOReturnBadArgument ); - -// agpRange->deallocate( agpOffset, length ); - - length = (length + 0xfff) & ~0xfff; - agpOffset /= page_size; - while( length > 0) { - gartArray[ agpOffset++ ] = 0; - length -= page_size; - } -#if 1 - flush_dcache( (vm_offset_t) gartArray, gartLength, false); - length = OSReadLittleInt32( gartArray, 4 * (agpOffset - 1) ); - sync(); - isync(); -#endif - - if( kIOAGPGartInvalidate & options) { - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV ); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - } - - return( err ); -} - -IOReturn AppleMacRiscAGP::setAGPEnable( IOAGPDevice * _master, - bool enable, IOOptionBits options ) -{ - IOReturn err = kIOReturnSuccess; - IOPCIAddressSpace target = getBridgeSpace(); - IOPCIAddressSpace master = _master->space; - UInt32 command; - UInt32 targetStatus, masterStatus; - UInt8 masterAGPRegisters = _master->masterAGPRegisters; - - if( enable) { - - targetStatus = configRead32( target, - targetAGPRegisters + kIOPCIConfigAGPStatusOffset ); - masterStatus = configRead32( master, - masterAGPRegisters + kIOPCIConfigAGPStatusOffset ); - - command = kIOAGPSideBandAddresssing - | kIOAGP4xDataRate | kIOAGP2xDataRate | kIOAGP1xDataRate; - command &= targetStatus; - command &= masterStatus; - - if( command & kIOAGP4xDataRate) - command &= ~(kIOAGP2xDataRate | kIOAGP1xDataRate); - else if( command & kIOAGP2xDataRate) - command &= ~(kIOAGP1xDataRate); - else if( 0 == (command & kIOAGP1xDataRate)) - return( kIOReturnUnsupported ); - - command |= kIOAGPEnable; - - if( targetStatus > masterStatus) - targetStatus = masterStatus; - command |= (targetStatus & kIOAGPRequestQueueMask); - -#if 1 - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV ); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); -#endif - do { - configWrite32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset, command ); - } while( (command & kIOAGPEnable) != - (kIOAGPEnable & configRead32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset))); - - do { - configWrite32( master, - masterAGPRegisters + kIOPCIConfigAGPCommandOffset, command ); - } while( (command & kIOAGPEnable) != - (kIOAGPEnable & configRead32( master, - masterAGPRegisters + kIOPCIConfigAGPCommandOffset))); - - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV ); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_2xRESET); - configWrite32( target, kUniNGART_CTRL, kGART_EN ); - - _master->masterState |= kIOAGPStateEnabled; - - } else { - - while( 0 == (kIOAGPIdle & configRead32( getBridgeSpace(), - kUniNINTERNAL_STATUS ))) - {} - - configWrite32( master, masterAGPRegisters + kIOPCIConfigAGPCommandOffset, 0 ); - configWrite32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset, 0 ); -#if 0 - configWrite32( target, kUniNGART_CTRL, kGART_EN | kGART_INV ); - configWrite32( target, kUniNGART_CTRL, 0 ); - configWrite32( target, kUniNGART_CTRL, kGART_2xRESET); - configWrite32( target, kUniNGART_CTRL, 0 ); -#endif - _master->masterState &= ~kIOAGPStateEnabled; - } - - return( err ); -} - -IOReturn AppleMacRiscAGP::saveDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ) -{ - IOReturn ret; - IOAGPDevice * agpDev; - UInt32 agpSave[3]; - IOPCIAddressSpace target = getBridgeSpace(); - - if( (agpDev = OSDynamicCast( IOAGPDevice, device))) { - agpSave[0] = configRead32( target, kUniNAGP_BASE ); - agpSave[1] = configRead32( target, kUniNGART_BASE ); - agpSave[2] = configRead32( target, targetAGPRegisters + kIOPCIConfigAGPCommandOffset ); - setAGPEnable( agpDev, false, 0 ); - } - - ret = super::saveDeviceState( device, options); - - if( agpDev && (ret == kIOReturnSuccess)) { - agpDev->savedConfig[ kUniNAGP_BASE / 4 ] = agpSave[0]; - agpDev->savedConfig[ kUniNGART_BASE / 4 ] = agpSave[1]; - agpDev->savedConfig[ (targetAGPRegisters + kIOPCIConfigAGPCommandOffset) / 4 ] = agpSave[2]; - } - - return( ret ); -} - -IOReturn AppleMacRiscAGP::restoreDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ) -{ - IOReturn ret; - IOAGPDevice * agpDev; - UInt32 agpSave[3]; - IOPCIAddressSpace target = getBridgeSpace(); - - agpDev = OSDynamicCast( IOAGPDevice, device); - if( agpDev && device->savedConfig) { - agpSave[0] = agpDev->savedConfig[ kUniNAGP_BASE / 4 ]; - agpSave[1] = agpDev->savedConfig[ kUniNGART_BASE / 4 ]; - agpSave[2] = agpDev->savedConfig[ (targetAGPRegisters + kIOPCIConfigAGPCommandOffset) / 4 ]; - } - - ret = super::restoreDeviceState( device, options); - - if( agpDev && (kIOReturnSuccess == ret)) { - configWrite32( target, kUniNAGP_BASE, agpSave[0] ); - configWrite32( target, kUniNGART_BASE, agpSave[1] ); - // soon, grasshopper - if( kIOAGPEnable & agpSave[2]) - agpDev->masterState |= kIOAGPStateEnablePending; - else - agpDev->masterState &= ~kIOAGPStateEnablePending; - } - - return( ret ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.h b/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.h deleted file mode 100644 index 8e044d9a3..000000000 --- a/iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - - -#ifndef _IOKIT_APPLEMACRISCPCI_H -#define _IOKIT_APPLEMACRISCPCI_H - -#include <IOKit/pci/IOPCIBridge.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -enum { - kBridgeSelfDevice = 11 -}; - -enum { - kMacRISCAddressSelect = 0x48 -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class AppleMacRiscPCI : public IOPCIBridge -{ - OSDeclareDefaultStructors(AppleMacRiscPCI) - -protected: - IOSimpleLock * lock; - IODeviceMemory * ioMemory; - IOMemoryMap * configAddrMap; - IOMemoryMap * configDataMap; - - volatile UInt32 * configAddr; - volatile UInt8 * configData; - - UInt16 coarseAddressMask; - UInt16 fineAddressMask; - UInt8 primaryBus; - UInt8 configDataOffsetMask; - - inline bool setConfigSpace( IOPCIAddressSpace space, UInt8 offset ); - virtual UInt8 firstBusNum( void ); - virtual UInt8 lastBusNum( void ); - -public: - virtual bool start( IOService * provider ); - virtual bool configure( IOService * provider ); - - virtual void free(); - - virtual IODeviceMemory * ioDeviceMemory( void ); - - virtual UInt32 configRead32( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ); - virtual UInt16 configRead16( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ); - virtual UInt8 configRead8( IOPCIAddressSpace space, UInt8 offset ); - virtual void configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ); - - virtual IOPCIAddressSpace getBridgeSpace( void ); -}; - -class AppleMacRiscVCI : public AppleMacRiscPCI -{ - OSDeclareDefaultStructors(AppleMacRiscVCI) - -public: - virtual bool configure( IOService * provider ); - - virtual IODeviceMemory * ioDeviceMemory( void ); - -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* Definitions of UniNorth Target config registers */ -enum { - kUniNGART_BASE = 0x8c, - kUniNAGP_BASE = 0x90, - kUniNGART_CTRL = 0x94, - kUniNINTERNAL_STATUS = 0x98 -}; -enum { - kGART_INV = 0x00000001, - kGART_EN = 0x00000100, - kGART_2xRESET = 0x00010000 -}; - -class IORangeAllocator; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class AppleMacRiscAGP : public AppleMacRiscPCI -{ - OSDeclareDefaultStructors(AppleMacRiscAGP) - -protected: - IORangeAllocator * agpRange; - UInt32 agpBaseIndex; - IOPhysicalAddress systemBase; - IOPhysicalLength systemLength; - volatile UInt32 * gartArray; - IOByteCount gartLength; - UInt8 targetAGPRegisters; - -private: - virtual IOReturn setAGPEnable( IOAGPDevice * master, bool enable, - IOOptionBits options = 0 ); - -public: - - virtual bool configure( IOService * provider ); - - virtual IOPCIDevice * createNub( OSDictionary * from ); - - virtual IOReturn saveDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ); - virtual IOReturn restoreDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ); - - virtual IOReturn createAGPSpace( IOAGPDevice * master, - IOOptionBits options, - IOPhysicalAddress * address, - IOPhysicalLength * length ); - - virtual IOReturn destroyAGPSpace( IOAGPDevice * master ); - - virtual IORangeAllocator * getAGPRangeAllocator( IOAGPDevice * master ); - - virtual IOOptionBits getAGPStatus( IOAGPDevice * master, - IOOptionBits options = 0 ); - virtual IOReturn resetAGPDevice( IOAGPDevice * master, - IOOptionBits options = 0 ); - - virtual IOReturn getAGPSpace( IOAGPDevice * master, - IOPhysicalAddress * address, - IOPhysicalLength * length ); - - virtual IOReturn commitAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options = 0 ); - - virtual IOReturn releaseAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options = 0 ); -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#endif /* ! _IOKIT_APPLEMACRISCPCI_H */ - diff --git a/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp b/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp index f88334968..248b41eba 100644 --- a/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp +++ b/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp @@ -79,6 +79,7 @@ #include "AppleCuda.h" +#include "AppleCudaUserClient.h" #include "IOCudaADBController.h" #include <IOKit/IOLib.h> #include <IOKit/IOSyncer.h> @@ -122,6 +123,7 @@ autopollArrived ( OSObject *inCuda, IOInterruptEventSource *, int ); static int set_cuda_power_message ( int command ); static int set_cuda_file_server_mode ( int command ); +static int set_cuda_poweruptime(long secs); static void cuda_async_set_power_message_enable( thread_call_param_t param, thread_call_param_t ); static void cuda_async_set_file_server_mode( thread_call_param_t param, thread_call_param_t ) ; @@ -210,6 +212,7 @@ workLoop = NULL; eventSrc = NULL; ourADBinterface = NULL; _rootDomain = 0; +_wakeup_from_sleep = false; workLoop = IOWorkLoop::workLoop(); if ( !workLoop ) { @@ -391,7 +394,6 @@ bool CudahasRoot( OSObject * us, void *, IOService * yourDevice ) IOReturn AppleCuda::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned long unused1, IOService* unused2) { -//kprintf("will change to %x", theFlags); if ( ! (theFlags & IOPMPowerOn) ) { _cuda_power_state = 0; //0 means sleeping @@ -402,10 +404,10 @@ IOReturn AppleCuda::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned l IOReturn AppleCuda::powerStateDidChangeTo ( IOPMPowerFlags theFlags, unsigned long unused1, IOService* unused2) { -//kprintf("did change to %x", theFlags); if (theFlags & IOPMPowerOn) { _cuda_power_state = 1; //1 means awake + _wakeup_from_sleep = false; //normally it is false } return IOPMAckImplied; } @@ -499,7 +501,6 @@ void AppleCuda::serviceAutopolls ( void ) cuda_packet_t * response; while( inIndex != outIndex ) { - response = &cuda_unsolicited[ outIndex ]; //Check for power messages, which are handled differently from regular @@ -543,7 +544,6 @@ cuda_packet_t * response; } } - if ( ADBid != NULL ) { (*autopoll_handler)(ADBid,response->a_header[2],response->a_bcount,response->a_buffer); } @@ -581,6 +581,11 @@ IOReturn AppleCuda::callPlatformFunction(const OSSymbol *functionName, { *hasint = true; } + + if (_wakeup_from_sleep) + { + *hasint = true; + } return kIOReturnSuccess; } @@ -588,6 +593,134 @@ IOReturn AppleCuda::callPlatformFunction(const OSSymbol *functionName, } +void +AppleCuda::setWakeTime(UInt32 waketime) +{ + //Call this function with waketime=0 in order to allow normal sleep again + _wakeup_from_sleep = false; + if (waketime != 0) { + timerSrc = IOTimerEventSource::timerEventSource((OSObject*)this, WakeupTimeoutHandler); + + if (!timerSrc || (workLoop->addEventSource(timerSrc) != kIOReturnSuccess)) + { + IOLog("Cuda can not register timeout event\n"); + return; + } + + timerSrc->setTimeoutMS(waketime); + } +} + +static void +AppleCuda::WakeupTimeoutHandler(OSObject *object, IOTimerEventSource *timer) +{ + gCuda->_wakeup_from_sleep = true; + if (gCuda->_rootDomain) + { + gCuda->_rootDomain->activityTickle(0,0); + } +} + + +void +AppleCuda::setPowerOnTime(UInt32 newTime) +{ + long long_secs; + + if (newTime != 0) { + Cuda_PE_read_write_time_of_day(kPEReadTOD, &long_secs); + set_cuda_poweruptime((long)newTime + long_secs); + } +} + +void +AppleCuda::setFileServerMode(bool fileServerModeON) +{ + set_cuda_file_server_mode((int) fileServerModeON); +} + +void AppleCuda::demandSleepNow(void) +{ + if (_rootDomain) + { + _rootDomain->receivePowerNotification (kIOPMSleepNow); + } +} + +// -------------------------------------------------------------------------- +// +// Method: newUserClient +// +// Purpose: +// newUserClient is called by the IOKit manager to create the +// kernel receiver of a user request. The "type" is a qualifier +// shared between the kernel and user client class instances.. + +#define kAppleCudaUserClientMagicCookie 0x0C00DA + +IOReturn +AppleCuda::newUserClient(task_t owningTask, + void *securityToken, + UInt32 magicCookie, + IOUserClient **handler) +{ + IOReturn ioReturn = kIOReturnSuccess; + AppleCudaUserClient *client = NULL; + + IOLog("AppleCuda::newUserClient\n"); + + if (IOUserClient::clientHasPrivilege(securityToken, "root") != kIOReturnSuccess) { + IOLog("AppleCuda::newUserClient: Can't create user client, not privileged\n"); + return kIOReturnNotPrivileged; + } + + // Check that this is a user client type that we support. + // type is known only to this driver's user and kernel + // classes. It could be used, for example, to define + // read or write privileges. In this case, we look for + // a private value. + if (magicCookie == kAppleCudaUserClientMagicCookie) { + // Construct a new client instance for the requesting task. + // This is, essentially client = new AppleCudaUserClient; + // ... create metaclasses ... + // client->setTask(owningTask) + client = AppleCudaUserClient::withTask(owningTask); + if (client == NULL) { + ioReturn = kIOReturnNoResources; + IOLog("AppleCuda::newUserClient: Can't create user client\n"); + } + } + else { + ioReturn = kIOReturnInvalid; + IOLog("AppleCuda::newUserClient: bad magic cookie.\n"); + } + + if (ioReturn == kIOReturnSuccess) { + // Attach ourself to the client so that this client instance + // can call us. + if (client->attach(this) == false) { + ioReturn = kIOReturnError; + IOLog("AppleCuda::newUserClient: Can't attach user client\n"); + } + } + + if (ioReturn == kIOReturnSuccess) { + // Start the client so it can accept requests. + if (client->start(this) == false) { + ioReturn = kIOReturnError; + IOLog("AppleCuda::newUserClientt: Can't start user client\n"); + } + } + + if (ioReturn != kIOReturnSuccess && client != NULL) { + client->detach(this); + client->release(); + } + + *handler = client; + return (ioReturn); +} + // ********************************************************************************** // cuda_do_sync_request // @@ -700,6 +833,26 @@ switch( type ) { return cuda_do_sync_request(gCuda, &cmd, true); } +// ********************************************************************************** +// Set the power-on time. 2001 +// ********************************************************************************** +static int set_cuda_poweruptime (long secs) +{ + cuda_request_t cmd; + long localsecs = secs; + + adb_init_request(&cmd); + + cmd.a_cmd.a_hcount = 2; + cmd.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; + + cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_POWER_UPTIME; + cmd.a_cmd.a_buffer = (UInt8 *)&localsecs; + cmd.a_cmd.a_bcount = 4; + + return cuda_do_sync_request(gCuda, &cmd, true); +} + // ********************************************************************************** // In case this machine loses power, it will automatically reboot when power is diff --git a/iokit/Drivers/platform/drvAppleCuda/AppleCuda.h b/iokit/Drivers/platform/drvAppleCuda/AppleCuda.h index f5d19bfc8..7c79a6921 100644 --- a/iokit/Drivers/platform/drvAppleCuda/AppleCuda.h +++ b/iokit/Drivers/platform/drvAppleCuda/AppleCuda.h @@ -77,6 +77,8 @@ * Port to C++ */ +#ifndef APPLECUDA_H +#define APPLECUDA_H #include <mach/mach_types.h> @@ -90,6 +92,7 @@ extern "C" { #include "AppleCudaHW.h" #include <IOKit/adb/adb.h> #include <IOKit/pwr_mgt/RootDomain.h> +#include <IOKit/IOTimerEventSource.h> // // CudaInterruptState - internal to CudaCore.c @@ -138,6 +141,8 @@ IOService * ADBid; IOCudaADBController * ourADBinterface; ADB_callback_func autopoll_handler; UInt8 _cuda_power_state; +IOTimerEventSource * timerSrc; +bool _wakeup_from_sleep; // callPlatformFunction symbols const OSSymbol *cuda_check_any_interrupt; @@ -148,6 +153,7 @@ const OSSymbol *cuda_check_any_interrupt; unsigned char cuda_autopoll_buffers[ NUM_AP_BUFFERS ] [ MAX_AP_RESPONSE ]; +static void WakeupTimeoutHandler(OSObject *object, IOTimerEventSource *timer); protected: @@ -181,6 +187,14 @@ void registerForADBInterrupts ( ADB_callback_func handler, IOService * caller ); IOReturn doSyncRequest ( cuda_request_t * request ); IOReturn powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService*); IOReturn powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService*); +void setWakeTime(UInt32 waketime); +void setPowerOnTime(UInt32 newTime); +void setFileServerMode(bool fileServerModeON); +void demandSleepNow(void); +IOReturn newUserClient(task_t owningTask, void*, // Security id (?!) + UInt32 type, // Magic number + IOUserClient **handler); + virtual IOReturn callPlatformFunction(const OSSymbol *functionName, bool waitForFunction, void *param1, void *param2, @@ -188,3 +202,6 @@ virtual IOReturn callPlatformFunction(const OSSymbol *functionName, }; +#endif /* APPLECUDA_H */ + + diff --git a/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.cpp b/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.cpp new file mode 100644 index 000000000..366a04bd4 --- /dev/null +++ b/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.cpp @@ -0,0 +1,182 @@ +/* +* Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* The contents of this file constitute Original Code as defined in and +* are subject to the Apple Public Source License Version 1.1 (the +* "License"). You may not use this file except in compliance with the +* License. Please obtain a copy of the License at +* http://www.apple.com/publicsource and read it before using this file. +* +* This Original Code and all software distributed under the License are +* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the +* License for the specific language governing rights and limitations +* under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ +#include "AppleCudaUserClient.h" + +#ifndef NULL +#define NULL 0 +#endif + +#define super IOUserClient + +OSDefineMetaClassAndStructors(AppleCudaUserClient, IOUserClient) + +AppleCudaUserClient* +AppleCudaUserClient::withTask(task_t owningTask) +{ + AppleCudaUserClient *client; + + client = new AppleCudaUserClient; + if (client != NULL) { + if (client->init() == false) { + client->release(); + client = NULL; + } + } + if (client != NULL) { + client->fTask = owningTask; + } + return (client); +} + +bool +AppleCudaUserClient::start(IOService *provider) +{ + bool result = false; + + theInterface = OSDynamicCast(AppleCuda, provider); + + if (theInterface != NULL) + result = super::start(provider); + else + result = false; + + if (result == false) { + IOLog("AppleCudaUserClient: provider start failed\n"); + } + + return (result); +} + +IOReturn +AppleCudaUserClient::clientClose(void) +{ + detach(theInterface); + return (kIOReturnSuccess); +} + +IOReturn +AppleCudaUserClient::clientDied(void) +{ + return (clientClose()); +} + +IOReturn +AppleCudaUserClient::connectClient(IOUserClient *client) +{ + return (kIOReturnSuccess); +} + +IOReturn +AppleCudaUserClient::registerNotificationPort(mach_port_t port, UInt32 type) +{ + return (kIOReturnUnsupported); +} + +// -------------------------------------------------------------------------- +// Method: setProperties +// +// Purpose: +// sets the property from the dictionary to the airport properties. + +IOReturn +AppleCudaUserClient::setProperties( OSObject * properties ) +{ + OSDictionary * dict; + + dict = OSDynamicCast( OSDictionary, properties ); + if ((dict) && (theInterface != NULL)) { + OSData *data; + + // Sets the wake on ring: + if( (data = OSDynamicCast( OSData, dict->getObject("WakeOnRing")))) { + UInt8 myBool = *((UInt8*)data->getBytesNoCopy()); + //theInterface->setWakeOnRing(myBool); + + IOLog("AppleCudaUserClient::setProperties WakeOnRing %d\n", myBool); + + // returns success: + return kIOReturnSuccess; + } + + // Sets the file-server mode: + if( (data = OSDynamicCast( OSData, dict->getObject("FileServer")))) { + UInt8 myBool = *((UInt8*)data->getBytesNoCopy()); + theInterface->setFileServerMode(myBool); + + IOLog("AppleCudaUserClient::setProperties FileServer %d\n", myBool != 0); + + // returns success: + return kIOReturnSuccess; + } + + //Demand sleep immediately: + if( (data = OSDynamicCast( OSData, dict->getObject("SleepNow")))) { + UInt8 myBool = *((UInt8*)data->getBytesNoCopy()); + + if (myBool) + { + theInterface->demandSleepNow(); + IOLog("AppleCudaUserClient::setProperties SleepNow\n"); + } + return kIOReturnSuccess; + } + + // Sets the self-wake time: + if( (data = OSDynamicCast( OSData, dict->getObject("AutoWake")))) { + UInt32 newTime; + IOByteCount len = data->getLength(); + + if (len == 4) + newTime = *((UInt32*)data->getBytesNoCopy()); + else + newTime = 0; + + theInterface->setWakeTime(newTime * 1000); //convert to milliseconds + + IOLog("AppleCudaUserClient::setProperties AutoWake 0x%08lx\n", newTime); + + // returns success: + return kIOReturnSuccess; + } + + // Sets the self-poweron time: + if( (data = OSDynamicCast( OSData, dict->getObject("AutoPower")))) { + UInt32 newTime; + IOByteCount len = data->getLength(); + + if (len == 4) + newTime = *((UInt32*)data->getBytesNoCopy()); + else + newTime = 0; + + theInterface->setPowerOnTime(newTime); + + IOLog("AppleCudaUserClient::setProperties AutoPower 0x%08lx\n", newTime); + + // returns success: + return kIOReturnSuccess; + } + + } + + return(kIOReturnBadArgument); +} diff --git a/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.h b/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.h new file mode 100644 index 000000000..8901f6b58 --- /dev/null +++ b/iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.h @@ -0,0 +1,51 @@ +/* +* Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. +* +* @APPLE_LICENSE_HEADER_START@ +* +* The contents of this file constitute Original Code as defined in and +* are subject to the Apple Public Source License Version 1.1 (the +* "License"). You may not use this file except in compliance with the +* License. Please obtain a copy of the License at +* http://www.apple.com/publicsource and read it before using this file. +* +* This Original Code and all software distributed under the License are +* distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the +* License for the specific language governing rights and limitations +* under the License. +* +* @APPLE_LICENSE_HEADER_END@ +*/ + +#ifndef APPLECUDAUSERCLIENT_H +#define APPLECUDAUSERCLIENT_H + +#include <IOKit/IOUserClient.h> +#include <IOKit/IOLib.h> + +#include "AppleCuda.h" + +class AppleCudaUserClient:public IOUserClient +{ + OSDeclareDefaultStructors(AppleCudaUserClient) + +private: + AppleCuda *theInterface; + task_t fTask; + +public: + static AppleCudaUserClient *withTask(task_t owningTask); + virtual IOReturn clientClose(void); + virtual IOReturn clientDied(void); + IOReturn connectClient(IOUserClient *client); + + virtual IOReturn registerNotificationPort(mach_port_t port, UInt32 type); + virtual bool start(IOService *provider); + + IOReturn setProperties( OSObject * properties ); +}; + +#endif /* APPLECUDAUSERCLIENT_H */ diff --git a/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp b/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp index 677bdfc80..e8a0db837 100644 --- a/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp +++ b/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp @@ -50,11 +50,11 @@ return super::init(properties); // ********************************************************************************** bool IOCudaADBController::start ( IOService *nub ) { -if( !super::start(nub)) - return false; -CudaDriver->registerForADBInterrupts ( autopollHandler, this ); -return true; + CudaDriver->registerForADBInterrupts ( autopollHandler, this ); + if( !super::start(nub)) + return false; + return true; } @@ -163,6 +163,16 @@ return CudaDriver->doSyncRequest(&cmd); } +// ********************************************************************************** +// cancelAllIO +// +// ********************************************************************************** +IOReturn IOCudaADBController::cancelAllIO ( void ) +{ + return kIOReturnSuccess; +} + + // ********************************************************************************** // flushDevice // diff --git a/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.h b/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.h index 8f2d00967..83cef9fa1 100644 --- a/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.h +++ b/iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.h @@ -48,6 +48,7 @@ IOReturn setAutoPollList ( UInt16 activeAddressMask ); IOReturn getAutoPollList ( UInt16 * activeAddressMask ); IOReturn setAutoPollEnable ( bool enable ); IOReturn resetBus ( void ); +IOReturn cancelAllIO ( void ); IOReturn flushDevice ( IOADBAddress address ); IOReturn readFromDevice ( IOADBAddress address, IOADBRegister adbRegister, UInt8 * data, IOByteCount * length ); diff --git a/iokit/Drivers/platform/drvAppleGossamerPE/Gossamer.cpp b/iokit/Drivers/platform/drvAppleGossamerPE/Gossamer.cpp index 45166a392..cefb29212 100644 --- a/iokit/Drivers/platform/drvAppleGossamerPE/Gossamer.cpp +++ b/iokit/Drivers/platform/drvAppleGossamerPE/Gossamer.cpp @@ -149,16 +149,6 @@ bool GossamerPE::platformAdjustService(IOService *service) } } - // Publish out the dual display heads on 101. - if (getMachineType() == kGossamerType101) { - if (!strcmp(service->getName(), "ATY,LTProParent")) { - if (kIOReturnSuccess == IONDRVLibrariesInitialize(service)) { - createNubs(this, service->getChildIterator( gIODTPlane )); - } - return true; - } - } - return true; } diff --git a/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.cpp b/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.cpp index 61e6ab5eb..5a7b11264 100644 --- a/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.cpp +++ b/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.cpp @@ -30,7 +30,6 @@ extern "C" { #include <IOKit/IODeviceTreeSupport.h> #include <IOKit/IOPlatformExpert.h> -#include <IOKit/pci/IOPCIBridge.h> #include "GossamerCPU.h" #include "Gossamer.h" @@ -377,7 +376,7 @@ void GossamerCPU::haltCPU(void) long machine_type; grackle = NULL; - grackle = OSDynamicCast(AppleGracklePCI, findIOInterface("AppleGracklePCI")); + grackle = (IOPCIBridge *)findIOInterface("AppleGracklePCI")->metaCast("IOPCIBridge"); if (grackle == NULL) kprintf("GossamerCPU::haltCPU missing grackle\n"); @@ -458,8 +457,8 @@ void GossamerCPU::haltCPU(void) break; } } - IOSleep(5); //allows USB thread to run since no more thread scheduling. 1 ms - // is enough for slow Yosemite, 5 is needed for iMacs. + IOSleep(7); //allows USB thread to run since no more thread scheduling. 1 ms + // is enough for slow Yosemite, 7 is needed for iMacs. } ml_throttle(0); //remove throttle from CPU speed @@ -475,7 +474,7 @@ void GossamerCPU::haltCPU(void) else { pmu = OSDynamicCast(IOService, findIOInterface("ApplePMU")); - processor_exit(machProcessor); +processor_exit(machProcessor); } } diff --git a/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.h b/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.h index ca8a88df0..fa124093e 100644 --- a/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.h +++ b/iokit/Drivers/platform/drvAppleGossamerPE/GossamerCPU.h @@ -28,8 +28,8 @@ #define _IOKIT_GOSSAMERCPU_H #include <IOKit/IOCPU.h> +#include <IOKit/pci/IOPCIBridge.h> -#include "../../pci/drvApplePCI/AppleGracklePCI.h" #include "Gossamer.h" class GossamerCPU : public IOCPU @@ -41,7 +41,7 @@ private: IOService *heathrow; IOCPUInterruptController *cpuIC; static UInt32 restartAddress; - AppleGracklePCI *grackle; + IOPCIBridge *grackle; IOPCI2PCIBridge *pci2pciBridge; unsigned long tbLow, tbHigh, tbHigh2; GossamerPE *gossamerPE; diff --git a/iokit/Drivers/platform/drvAppleMacIO/AppleMacIO.cpp b/iokit/Drivers/platform/drvAppleMacIO/AppleMacIO.cpp index 43fa1520d..062a140d0 100644 --- a/iokit/Drivers/platform/drvAppleMacIO/AppleMacIO.cpp +++ b/iokit/Drivers/platform/drvAppleMacIO/AppleMacIO.cpp @@ -43,7 +43,7 @@ extern "C" { #include <IOKit/ppc/IODBDMA.h> -#include <assert.h> +#include <IOKit/assert.h> /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ diff --git a/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp b/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp index 5f8896351..8220e8511 100644 --- a/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp +++ b/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp @@ -112,13 +112,15 @@ void IOPMUADBController::free ( ) // localSendMiscCommand // // ********************************************************************************** -IOReturn IOPMUADBController::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer) +IOReturn IOPMUADBController::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer) { IOReturn returnValue = kIOReturnError; - + IOByteCount rLength = 1; + UInt8 rBuffer; + // The poupose of this method is to free us from the pain to create a parameter block each time // we wish to talk to the pmu: - SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, rLength, rBuffer}; + SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, &rLength, &rBuffer}; #ifdef VERBOSE_LOGS_ON IOLog("ApplePMUInterface::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n", @@ -148,12 +150,16 @@ IOReturn IOPMUADBController::localSendMiscCommand(int command, IOByteCount sLeng /* static */ void IOPMUADBController::handleADBInterrupt(IOService *client, UInt8 interruptMask, UInt32 length, UInt8 *buffer) { - if (interruptMask & kPMUautopoll) + IOPMUADBController *myThis = OSDynamicCast(IOPMUADBController, client); + + // Check if we are the right client for this interrupt: + if (myThis == NULL) + return; + + if ((interruptMask & kPMUautopoll) && (myThis->autopollOn)) autopollHandler(client, buffer[0], length - 1, buffer + 1); // yes, call adb input handler else { - IOPMUADBController *myThis = OSDynamicCast(IOPMUADBController, client); - - if ((myThis != NULL) && (myThis->waitingForData != NULL)) { + if (myThis->waitingForData != NULL) { // Complets the adb transaction myThis->dataLen = length - 1; bcopy(buffer + 1, myThis->dataBuffer, myThis->dataLen); @@ -162,6 +168,21 @@ IOPMUADBController::handleADBInterrupt(IOService *client, UInt8 interruptMask, U } } + +// ********************************************************************************** +// cancelAllIO +// +// ********************************************************************************** +IOReturn IOPMUADBController::cancelAllIO ( void ) +{ + if (waitingForData != NULL) { + dataLen = 0; // read fails with error, write fails quietly + waitingForData->signal(); + } + return kPMUNoError; +} + + // ********************************************************************************** // setAutoPollPeriod // @@ -197,8 +218,8 @@ IOReturn IOPMUADBController::setAutoPollList ( UInt16 PollBitField ) oBuffer[1] = 0x86; // adb Command op. oBuffer[2] = (UInt8)(PollBitField >> 8); // ?? oBuffer[3] = (UInt8)(PollBitField & 0xff); // ?? - - localSendMiscCommand (kPMUpMgrADB, 4, oBuffer, NULL, NULL); + + localSendMiscCommand (kPMUpMgrADB, 4, oBuffer); } return kPMUNoError; } @@ -223,17 +244,24 @@ IOReturn IOPMUADBController::setAutoPollEnable ( bool enable ) { UInt8 oBuffer[4]; + autopollOn = enable; + if ( enable ) { // enabling autopoll oBuffer[0] = 0; oBuffer[1] = 0x86; oBuffer[2] = (UInt8)(pollList >> 8); oBuffer[3] = (UInt8)(pollList & 0xff); - localSendMiscCommand (kPMUpMgrADB, 4, oBuffer, NULL,NULL); - autopollOn = true; + localSendMiscCommand (kPMUpMgrADB, 4, oBuffer); } else { // disabling autopoll; - localSendMiscCommand (kPMUpMgrADBoff, 0, NULL, NULL, NULL); + /* Waits one second for the trackpads to be up (this is needed only in old machines) + This is placed here because this is the fist call at wake. */ + if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") || + IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'")) + IOSleep(1500); + + localSendMiscCommand (kPMUpMgrADBoff, 0, NULL); } return kPMUNoError; @@ -250,20 +278,25 @@ IOReturn IOPMUADBController::resetBus ( void ) IOLockLock(requestMutexLock); UInt8 oBuffer[4]; - + oBuffer[0] = kPMUResetADBBus; oBuffer[1] = 0; oBuffer[2] = 0; // Reset bus needs to wait for the interrupt to terminate the transaction: waitingForData = IOSyncer::create(); - localSendMiscCommand (kPMUpMgrADB, 3, oBuffer, NULL, NULL); + localSendMiscCommand (kPMUpMgrADB, 3, oBuffer); waitingForData->wait(); // wait till done waitingForData = 0; if (requestMutexLock != NULL) IOLockUnlock(requestMutexLock); - + + /* Waits one second for the trackpads to be up (this is needed only in old machines) */ + if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") || + IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'")) + IOSleep(1500); + return kPMUNoError; } @@ -285,7 +318,7 @@ IOReturn IOPMUADBController::flushDevice ( IOADBAddress address ) // flush device needs to wait for the interrupt to terminate the transaction waitingForData = IOSyncer::create(); - localSendMiscCommand (kPMUpMgrADB, 3, oBuffer, NULL, NULL); + localSendMiscCommand (kPMUpMgrADB, 3, oBuffer); waitingForData->wait(); // wait till done waitingForData = 0; @@ -321,7 +354,7 @@ IOReturn IOPMUADBController::readFromDevice ( IOADBAddress address, IOADBRegiste // read from device needs to wait for the interrupt to terminate the transaction // and to obtain the data from the device. waitingForData = IOSyncer::create(); - localSendMiscCommand (kPMUpMgrADB, 3, oBuffer, NULL, NULL); + localSendMiscCommand (kPMUpMgrADB, 3, oBuffer); waitingForData->wait(); // wait till done waitingForData = 0; @@ -370,7 +403,7 @@ IOReturn IOPMUADBController::writeToDevice ( IOADBAddress address, IOADBRegister // write to the device needs to wait for the interrupt to terminate the transaction waitingForData = IOSyncer::create(); - localSendMiscCommand (kPMUpMgrADB, 3 + *length, oBuffer, NULL, NULL); + localSendMiscCommand (kPMUpMgrADB, 3 + *length, oBuffer); waitingForData->wait(); waitingForData = 0; diff --git a/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.h b/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.h index 21ee01081..e7e8201d5 100644 --- a/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.h +++ b/iokit/Drivers/platform/drvApplePMU/IOPMUADBController.h @@ -93,7 +93,7 @@ private: IOLock *requestMutexLock; // A simpler way to interface with the pmu SendMiscCommand - IOReturn localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer); + IOReturn localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer); public: IOService *probe( IOService * nub, SInt32 * score ); @@ -105,6 +105,7 @@ public: IOReturn getAutoPollList ( UInt16 * activeAddressMask ); IOReturn setAutoPollEnable ( bool enable ); IOReturn resetBus ( void ); + IOReturn cancelAllIO ( void ); IOReturn flushDevice ( IOADBAddress address ); IOReturn readFromDevice ( IOADBAddress address, IOADBRegister adbRegister, UInt8 * data, IOByteCount * length ); IOReturn writeToDevice ( IOADBAddress address, IOADBRegister adbRegister, UInt8 * data, IOByteCount * length ); diff --git a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.cpp b/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.cpp deleted file mode 100644 index f73ced1ee..000000000 --- a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.cpp +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOService.h> -#include <IOKit/IOSyncer.h> -#include <IOKit/IOCommandQueue.h> -#include <IOKit/ps2/ApplePS2KeyboardDevice.h> -#include <IOKit/ps2/ApplePS2MouseDevice.h> -#include "ApplePS2Controller.h" - -extern "C" -{ - #include <architecture/i386/pio.h> - #include <machine/machine_routines.h> -} - -static ApplePS2Controller * gApplePS2Controller = 0; // global variable to self - -// ============================================================================= -// Interrupt-Time Support Functions -// - -static void interruptHandlerMouse(OSObject *, void *, IOService *, int) -{ - // - // Wake our workloop to service the interrupt. This is an edge-triggered - // interrupt, so returning from this routine without clearing the interrupt - // condition is perfectly normal. - // - - gApplePS2Controller->_interruptSourceMouse->interruptOccurred(0, 0, 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void interruptHandlerKeyboard(OSObject *, void *, IOService *, int) -{ -#if DEBUGGER_SUPPORT - // - // The keyboard interrupt handler reads in the pending scan code and stores - // it on our internal queue; should it completes a debugger escape sequence, - // we jump to the debugger function immediately. - // - - UInt8 key; - UInt8 status; - - // Lock out the keyboard interrupt handler [redundant here] and claim - // exclusive access to the internal keyboard queue. - - gApplePS2Controller->lockController(); - - // Verify that data is available on the controller's input port. - - if ( ((status = inb(kCommandPort)) & kOutputReady) ) - { - // Verify that the data is keyboard data, otherwise call mouse handler. - // This case should never really happen, but if it does, we handle it. - - if ( (status & kMouseData) ) - { - interruptHandlerMouse(0, 0, 0, 0); - } - else - { - // Retrieve the keyboard data on the controller's input port. - - key = inb(kDataPort); - - // Call the debugger-key-sequence checking code (if a debugger sequence - // completes, the debugger function will be invoked immediately within - // doEscape). The doEscape call may insist that we drop the scan code - // we just received in some cases (a true return) -- we don't question - // it's judgement and comply. - - if (gApplePS2Controller->doEscape(key) == false) - gApplePS2Controller->enqueueKeyboardData(key); - - // In all cases, we wake up our workloop to service the interrupt data. - gApplePS2Controller->_interruptSourceKeyboard->interruptOccurred(0, 0, 0); - } - } - - // Remove the lockout on the keyboard interrupt handler [ineffective here] - // and release our exclusive access to the internal keyboard queue. - - gApplePS2Controller->unlockController(); -#else - // - // Wake our workloop to service the interrupt. This is an edge-triggered - // interrupt, so returning from this routine without clearing the interrupt - // condition is perfectly normal. - // - - gApplePS2Controller->_interruptSourceKeyboard->interruptOccurred(0, 0, 0); - -#endif DEBUGGER_SUPPORT -} - -// ============================================================================= -// ApplePS2Controller Class Implementation -// - -#define super IOService -OSDefineMetaClassAndStructors(ApplePS2Controller, IOService); - -bool ApplePS2Controller::init(OSDictionary * properties) -{ - if (!super::init(properties)) return false; - - // - // Initialize minimal state. - // - - _commandQueue = 0; - _workLoop = 0; - - _interruptSourceKeyboard = 0; - _interruptSourceMouse = 0; - - _interruptTargetKeyboard = 0; - _interruptTargetMouse = 0; - - _interruptActionKeyboard = NULL; - _interruptActionMouse = NULL; - - _interruptInstalledKeyboard = false; - _interruptInstalledMouse = false; - - _mouseDevice = 0; - _keyboardDevice = 0; - -#if DEBUGGER_SUPPORT - _extendedState = false; - _modifierState = 0x00; - - _keyboardQueueAlloc = NULL; - queue_init(&_keyboardQueue); - queue_init(&_keyboardQueueUnused); - - _controllerLockOldSpl = 0; - usimple_lock_init(&_controllerLock, ETAP_NO_TRACE); -#endif DEBUGGER_SUPPORT - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Controller::start(IOService * provider) -{ - // - // The driver has been instructed to start. Allocate all our resources. - // - - if (!super::start(provider)) return false; - -#if DEBUGGER_SUPPORT - _keyboardQueueAlloc = (KeyboardQueueElement *) - IOMalloc(kKeyboardQueueSize*sizeof(KeyboardQueueElement)); - if (!_keyboardQueueAlloc) return false; - - // Add the allocated keyboard queue entries to "unused" queue. - for (int index = 0; index < kKeyboardQueueSize; index++) - queue_enter(&_keyboardQueueUnused, &_keyboardQueueAlloc[index], - KeyboardQueueElement *, chain); -#endif DEBUGGER_SUPPORT - - // - // Initialize the mouse and keyboard hardware to a known state -- the IRQs - // are disabled (don't want interrupts), the clock line is enabled (want to - // be able to send commands), and the device itself is disabled (don't want - // asynchronous data arrival for key/mouse events). We call the read/write - // port routines directly, since no other thread will conflict with us. - // - - UInt8 commandByte; - writeCommandPort(kCP_GetCommandByte); - commandByte = readDataPort(kDT_Keyboard); - commandByte &= ~(kCB_EnableMouseIRQ | kCB_DisableMouseClock); - writeCommandPort(kCP_SetCommandByte); - writeDataPort(commandByte); - - writeDataPort(kDP_SetDefaultsAndDisable); - readDataPort(kDT_Keyboard); // (discard acknowledge; success irrelevant) - - writeCommandPort(kCP_TransmitToMouse); - writeDataPort(kDP_SetDefaultsAndDisable); - readDataPort(kDT_Mouse); // (discard acknowledge; success irrelevant) - - // - // Clear out garbage in the controller's input streams, before starting up - // the work loop. - // - - while ( inb(kCommandPort) & kOutputReady ) - { - inb(kDataPort); - IODelay(kDataDelay); - } - - // - // Initialize our work loop, our command queue, and our interrupt event - // sources. The work loop can accept requests after this step. - // - - _workLoop = IOWorkLoop::workLoop(); - _commandQueue = IOCommandQueue::commandQueue( - this, (IOCommandQueueAction) &ApplePS2Controller::processRequest); - _interruptSourceMouse = IOInterruptEventSource::interruptEventSource( - this, (IOInterruptEventAction) &ApplePS2Controller::interruptOccurred); - _interruptSourceKeyboard = IOInterruptEventSource::interruptEventSource( - this, (IOInterruptEventAction) &ApplePS2Controller::interruptOccurred); - - if ( !_workLoop || - !_commandQueue || - !_interruptSourceMouse || - !_interruptSourceKeyboard ) return false; - - if ( _workLoop->addEventSource(_commandQueue) != kIOReturnSuccess ) - return false; - - // - // Create the keyboard nub and the mouse nub. The keyboard and mouse drivers - // will query these nubs to determine the existence of the keyboard or mouse, - // and should they exist, will attach themselves to the nub as clients. - // - - _keyboardDevice = new ApplePS2KeyboardDevice; - - if ( !_keyboardDevice || - !_keyboardDevice->init() || - !_keyboardDevice->attach(this) ) return false; - - _mouseDevice = new ApplePS2MouseDevice; - - if ( !_mouseDevice || - !_mouseDevice->init() || - !_mouseDevice->attach(this) ) return false; - - gApplePS2Controller = this; - - _keyboardDevice->registerService(); - _mouseDevice->registerService(); - - return true; // success -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::stop(IOService * provider) -{ - // - // The driver has been instructed to stop. Note that we must break all - // connections to other service objects now (ie. no registered actions, - // no pointers and retains to objects, etc), if any. - // - - // Ensure that the interrupt handlers have been uninstalled (ie. no clients). - assert(_interruptInstalledKeyboard == false); - assert(_interruptInstalledMouse == false); - - // Free the nubs we created. - if (_keyboardDevice) _keyboardDevice->release(); - if (_mouseDevice) _mouseDevice->release(); - - // Free the work loop. - if (_workLoop) _workLoop->release(); - - // Free the interrupt source and command queue. - if (_commandQueue) _commandQueue->release(); - if (_interruptSourceKeyboard) _interruptSourceKeyboard->release(); - if (_interruptSourceMouse) _interruptSourceMouse->release(); - -#if DEBUGGER_SUPPORT - // Free the keyboard queue allocation space (after disabling interrupt). - if (_keyboardQueueAlloc) - IOFree(_keyboardQueueAlloc,kKeyboardQueueSize*sizeof(KeyboardQueueElement)); -#endif DEBUGGER_SUPPORT - - gApplePS2Controller = 0; - - super::stop(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOWorkLoop * ApplePS2Controller::getWorkLoop() const -{ - return _workLoop; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::installInterruptAction(PS2DeviceType deviceType, - OSObject * target, - PS2InterruptAction action) -{ - // - // Install the keyboard or mouse interrupt handler. - // - // This method assumes only one possible mouse and only one possible - // keyboard client (ie. callers), and assumes two distinct interrupt - // handlers for each, hence needs no protection against races. - // - - // Is it the keyboard or the mouse interrupt handler that was requested? - // We only install it if it is currently uninstalled. - - if (deviceType == kDT_Keyboard && _interruptInstalledKeyboard == false) - { - target->retain(); - _interruptTargetKeyboard = target; - _interruptActionKeyboard = action; - _workLoop->addEventSource(_interruptSourceKeyboard); - getProvider()->registerInterrupt(kIRQ_Keyboard,0, interruptHandlerKeyboard); - getProvider()->enableInterrupt(kIRQ_Keyboard); - _interruptInstalledKeyboard = true; - } - - else if (deviceType == kDT_Mouse && _interruptInstalledMouse == false) - { - target->retain(); - _interruptTargetMouse = target; - _interruptActionMouse = action; - _workLoop->addEventSource(_interruptSourceMouse); - getProvider()->registerInterrupt(kIRQ_Mouse, 0, interruptHandlerMouse); - getProvider()->enableInterrupt(kIRQ_Mouse); - _interruptInstalledMouse = true; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::uninstallInterruptAction(PS2DeviceType deviceType) -{ - // - // Uninstall the keyboard or mouse interrupt handler. - // - // This method assumes only one possible mouse and only one possible - // keyboard client (ie. callers), and assumes two distinct interrupt - // handlers for each, hence needs no protection against races. - // - - // Is it the keyboard or the mouse interrupt handler that was requested? - // We only install it if it is currently uninstalled. - - if (deviceType == kDT_Keyboard && _interruptInstalledKeyboard == true) - { - getProvider()->disableInterrupt(kIRQ_Keyboard); - getProvider()->unregisterInterrupt(kIRQ_Keyboard); - _workLoop->removeEventSource(_interruptSourceMouse); - _interruptInstalledKeyboard = false; - _interruptActionKeyboard = NULL; - _interruptTargetKeyboard->release(); - _interruptTargetKeyboard = 0; - } - - else if (deviceType == kDT_Mouse && _interruptInstalledMouse == true) - { - getProvider()->disableInterrupt(kIRQ_Mouse); - getProvider()->unregisterInterrupt(kIRQ_Mouse); - _workLoop->removeEventSource(_interruptSourceMouse); - _interruptInstalledMouse = false; - _interruptActionMouse = NULL; - _interruptTargetMouse->release(); - _interruptTargetMouse = 0; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PS2Request * ApplePS2Controller::allocateRequest() -{ - // - // Allocate a request structure. Blocks until successful. Request structure - // is guaranteed to be zeroed. - // - - PS2Request * request = (PS2Request *) IOMalloc(sizeof(PS2Request)); - bzero(request, sizeof(PS2Request)); - return request; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::freeRequest(PS2Request * request) -{ - // - // Deallocate a request structure. - // - - IOFree(request, sizeof(PS2Request)); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2Controller::submitRequest(PS2Request * request) -{ - // - // Submit the request to the controller for processing, asynchronously. - // - - return (_commandQueue->enqueueCommand(false, request) == KERN_SUCCESS); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::submitRequestAndBlock(PS2Request * request) -{ - // - // Submit the request to the controller for processing, synchronously. - // - - IOSyncer * completionSyncer = IOSyncer::create(); - - assert(completionSyncer); - request->completionTarget = this; - request->completionAction = submitRequestAndBlockCompletion; - request->completionParam = completionSyncer; - - _commandQueue->enqueueCommand(true, request); - - completionSyncer->wait(); // wait 'till done -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::submitRequestAndBlockCompletion(void *, void * param) -{ // PS2CompletionAction - IOSyncer * completionSyncer = (IOSyncer *) param; - completionSyncer->signal(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::interruptOccurred(IOInterruptEventSource *, int) -{ // IOInterruptEventAction - // - // Our work loop has informed us of an interrupt, that is, asynchronous - // data has arrived on our input stream. Read the data and dispatch it - // to the appropriate driver. - // - // This method should only be called from our single-threaded work loop. - // - - UInt8 status; - -#if DEBUGGER_SUPPORT - lockController(); // (lock out interrupt + access to queue) - while (1) - { - // See if data is available on the keyboard input stream (off queue); - // we do not read keyboard data from the real data port if it should - // be available. - - if (dequeueKeyboardData(&status)) - { - unlockController(); - dispatchDriverInterrupt(kDT_Keyboard, status); - lockController(); - } - - // See if data is available on the mouse input stream (off real port). - - else if ( (inb(kCommandPort) & (kOutputReady | kMouseData)) == - (kOutputReady | kMouseData)) - { - unlockController(); - dispatchDriverInterrupt(kDT_Mouse, inb(kDataPort)); - lockController(); - } - else break; // out of loop - } - unlockController(); // (release interrupt lockout + access to queue) -#else - // Loop only while there is data currently on the input stream. - - while ( ((status = inb(kCommandPort)) & kOutputReady) ) - { - // Read in and dispatch the data, but only if it isn't what is required - // by the active command. - - dispatchDriverInterrupt((status&kMouseData)?kDT_Mouse:kDT_Keyboard, - inb(kDataPort)); - } -#endif DEBUGGER_SUPPORT -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::dispatchDriverInterrupt(PS2DeviceType deviceType, - UInt8 data) -{ - // - // The supplied data is passed onto the interrupt handler in the appropriate - // driver, if one is registered, otherwise the data byte is thrown away. - // - // This method should only be called from our single-threaded work loop. - // - - if ( deviceType == kDT_Mouse ) - { - // Dispatch the data to the mouse driver. - if (_interruptInstalledMouse) - (*_interruptActionMouse)(_interruptTargetMouse, data); - } - else if ( deviceType == kDT_Keyboard ) - { - // Dispatch the data to the keyboard driver. - if (_interruptInstalledKeyboard) - (*_interruptActionKeyboard)(_interruptTargetKeyboard, data); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::processRequest(PS2Request * request, - void * /* field1 */, - void * /* field2 */, - void * /* field3 */) - // IOCommandQueueAction -{ - // - // Our work loop has informed us of a request submission. Process - // the request. Note that this code "figures out" when the mouse - // input stream should be read over the keyboard input stream. - // - // This method should only be called from our single-threaded work loop. - // - - UInt8 byte; - PS2DeviceType deviceMode = kDT_Keyboard; - bool failed = false; - bool transmitToMouse = false; - unsigned index; - - // Process each of the commands in the list. - - for (index = 0; index < request->commandsCount; index++) - { - switch (request->commands[index].command) - { - case kPS2C_ReadDataPort: - request->commands[index].inOrOut = readDataPort(deviceMode); - break; - - case kPS2C_ReadDataPortAndCompare: -#if OUT_OF_ORDER_DATA_CORRECTION_FEATURE - byte = readDataPort(deviceMode, request->commands[index].inOrOut); -#else - byte = readDataPort(deviceMode); -#endif - failed = (byte != request->commands[index].inOrOut); - break; - - case kPS2C_WriteDataPort: - writeDataPort(request->commands[index].inOrOut); - if (transmitToMouse) // next reads from mouse input stream - { - deviceMode = kDT_Mouse; - transmitToMouse = false; - } - else - { - deviceMode = kDT_Keyboard; - } - break; - - case kPS2C_WriteCommandPort: - writeCommandPort(request->commands[index].inOrOut); - if (request->commands[index].inOrOut == kCP_TransmitToMouse) - transmitToMouse = true; // preparing to transmit data to mouse - break; - } - - if (failed) break; - } - - // If a command failed and stopped the request processing, store its - // index into the commandsCount field. - - if (failed) request->commandsCount = index; - - // Invoke the completion routine, if one was supplied. - - if (request->completionTarget && request->completionAction) - { - (*request->completionAction)(request->completionTarget, - request->completionParam); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt8 ApplePS2Controller::readDataPort(PS2DeviceType deviceType) -{ - // - // Blocks until keyboard or mouse data is available from the controller - // and returns that data. Note, if mouse data is requested but keyboard - // data is what is available, the data is delivered to the appropriate - // driver interrupt routine immediately (effectively, the request is - // "preempted" temporarily). - // - // There is a built-in timeout for this command of (timeoutCounter X - // kDataDelay) microseconds, approximately. - // - // This method should only be called from our single-threaded work loop. - // - - UInt8 readByte; - UInt8 status; - UInt32 timeoutCounter = 10000; // (timeoutCounter * kDataDelay = 70 ms) - - while (1) - { -#if DEBUGGER_SUPPORT - lockController(); // (lock out interrupt + access to queue) - if (deviceType == kDT_Keyboard && dequeueKeyboardData(&readByte)) - { - unlockController(); - return readByte; - } -#endif DEBUGGER_SUPPORT - - // - // Wait for the controller's output buffer to become ready. - // - - while (timeoutCounter && !((status = inb(kCommandPort)) & kOutputReady)) - { - timeoutCounter--; - IODelay(kDataDelay); - } - - // - // If we timed out, something went awfully wrong; return a fake value. - // - - if (timeoutCounter == 0) - { -#if DEBUGGER_SUPPORT - unlockController(); // (release interrupt lockout + access to queue) -#endif DEBUGGER_SUPPORT - - IOLog("%s: Timed out on %s input stream.\n", getName(), - (deviceType == kDT_Keyboard) ? "keyboard" : "mouse"); - return 0; - } - - // - // Read in the data. We return the data, however, only if it arrived on - // the requested input stream. - // - - readByte = inb(kDataPort); - -#if DEBUGGER_SUPPORT - unlockController(); // (release interrupt lockout + access to queue) -#endif DEBUGGER_SUPPORT - - if ( (status & kMouseData) ) - { - if (deviceType == kDT_Mouse) return readByte; - } - else - { - if (deviceType == kDT_Keyboard) return readByte; - } - - // - // The data we just received is for the other input stream, not the one - // that was requested, so dispatch other device's interrupt handler. - // - - dispatchDriverInterrupt((deviceType==kDT_Keyboard)?kDT_Mouse:kDT_Keyboard, - readByte); - } // while (forever) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#if OUT_OF_ORDER_DATA_CORRECTION_FEATURE - -UInt8 ApplePS2Controller::readDataPort(PS2DeviceType deviceType, - UInt8 expectedByte) -{ - // - // Blocks until keyboard or mouse data is available from the controller - // and returns that data. Note, if mouse data is requested but keyboard - // data is what is available, the data is delivered to the appropriate - // driver interrupt routine immediately (effectively, the request is - // "preempted" temporarily). - // - // There is a built-in timeout for this command of (timeoutCounter X - // kDataDelay) microseconds, approximately. - // - // This method should only be called from our single-threaded work loop. - // - // This version of readDataPort does exactly the same as the original, - // except that if the value that should be read from the (appropriate) - // input stream is not what is expected, we make these assumptions: - // - // (a) the data byte we did get was "asynchronous" data being sent by - // the device, which has not figured out that it has to respond to - // the command we just sent to it. - // (b) that the real "expected" response will be the next byte in the - // stream; so what we do is put aside the first byte we read and - // wait for the next byte; if it's the expected value, we dispatch - // the first byte we read to the driver's interrupt handler, then - // return the expected byte. The caller will have never known that - // asynchronous data arrived at a very bad time. - // (c) that the real "expected" response will arrive within (kDataDelay - // X timeoutCounter) microseconds from the time the call is made. - // - - UInt8 firstByte = 0; - bool firstByteHeld = false; - UInt8 readByte; - bool requestedStream; - UInt8 status; - UInt32 timeoutCounter = 10000; // (timeoutCounter * kDataDelay = 70 ms) - - while (1) - { -#if DEBUGGER_SUPPORT - lockController(); // (lock out interrupt + access to queue) - if (deviceType == kDT_Keyboard && dequeueKeyboardData(&readByte)) - { - requestedStream = true; - goto skipForwardToY; - } -#endif DEBUGGER_SUPPORT - - // - // Wait for the controller's output buffer to become ready. - // - - while (timeoutCounter && !((status = inb(kCommandPort)) & kOutputReady)) - { - timeoutCounter--; - IODelay(kDataDelay); - } - - // - // If we timed out, we return the first byte we read, unless THIS IS the - // first byte we are trying to read, then something went awfully wrong - // and we return a fake value rather than lock up the controller longer. - // - - if (timeoutCounter == 0) - { -#if DEBUGGER_SUPPORT - unlockController(); // release interrupt lockout + access to queue -#endif DEBUGGER_SUPPORT - - if (firstByteHeld) return firstByte; - - IOLog("%s: Timed out on %s input stream.\n", getName(), - (deviceType == kDT_Keyboard) ? "keyboard" : "mouse"); - return 0; - } - - // - // Read in the data. We process the data, however, only if it arrived on - // the requested input stream. - // - - readByte = inb(kDataPort); - requestedStream = false; - - if ( (status & kMouseData) ) - { - if (deviceType == kDT_Mouse) requestedStream = true; - } - else - { - if (deviceType == kDT_Keyboard) requestedStream = true; - } - -#if DEBUGGER_SUPPORT -skipForwardToY: - unlockController(); // (release interrupt lockout + access to queue) -#endif DEBUGGER_SUPPORT - - if (requestedStream) - { - if (readByte == expectedByte) - { - if (firstByteHeld == false) - { - // - // Normal case. Return first byte received. - // - - return readByte; - } - else - { - // - // Our assumption was correct. The second byte matched. Dispatch - // the first byte to the interrupt handler, and return the second. - // - - dispatchDriverInterrupt(deviceType, firstByte); - return readByte; - } - } - else // (readByte does not match expectedByte) - { - if (firstByteHeld == false) - { - // - // The first byte was received, and does not match the byte we are - // expecting. Put it aside for the moment. - // - - firstByteHeld = true; - firstByte = readByte; - } - else if (readByte != expectedByte) - { - // - // The second byte mismatched as well. I have yet to see this case - // occur [Dan], however I do think it's plausible. No error logged. - // - - dispatchDriverInterrupt(deviceType, readByte); - return firstByte; - } - } - } - else - { - // - // The data we just received is for the other input stream, not ours, - // so dispatch appropriate interrupt handler. - // - - dispatchDriverInterrupt((deviceType==kDT_Keyboard)?kDT_Mouse:kDT_Keyboard, - readByte); - } - } // while (forever) -} - -#endif - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::writeDataPort(UInt8 byte) -{ - // - // Block until room in the controller's input buffer is available, then - // write the given byte to the Data Port. - // - // This method should only be dispatched from our single-threaded work loop. - // - - while (inb(kCommandPort) & kInputBusy) IODelay(kDataDelay); - outb(kDataPort, byte); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2Controller::writeCommandPort(UInt8 byte) -{ - // - // Block until room in the controller's input buffer is available, then - // write the given byte to the Command Port. - // - // This method should only be dispatched from our single-threaded work loop. - // - - while (inb(kCommandPort) & kInputBusy) IODelay(kDataDelay); - outb(kCommandPort, byte); -} - -// ============================================================================= -// Escape-Key Processing Stuff Localized Here (eg. Mini-Monitor) -// - -#if DEBUGGER_SUPPORT - -#define kModifierShiftLeft 0x01 -#define kModifierShiftRight 0x02 -#define kModifierCtrlLeft 0x04 -#define kModifierCtrlRight 0x08 -#define kModifierAltLeft 0x10 -#define kModifierAltRight 0x20 -#define kModifierWindowsLeft 0x40 -#define kModifierWindowsRight 0x80 - -#define kModifierShiftMask (kModifierShiftLeft | kModifierShiftRight ) -#define kModifierCtrlMask (kModifierCtrlLeft | kModifierCtrlRight ) -#define kModifierAltMask (kModifierAltLeft | kModifierAltRight ) -#define kModifierWindowsMask (kModifierWindowsLeft | kModifierWindowsRight) - -bool ApplePS2Controller::doEscape(UInt8 scancode) -{ - static struct - { - UInt8 scancode; - UInt8 extended; - UInt16 modifier; - } modifierTable[] = { { kSC_Alt, false, kModifierAltLeft }, - { kSC_Alt, true, kModifierAltRight }, - { kSC_Ctrl, false, kModifierCtrlLeft }, - { kSC_Ctrl, true, kModifierCtrlRight }, - { kSC_ShiftLeft, false, kModifierShiftLeft }, - { kSC_ShiftRight, false, kModifierShiftRight }, - { kSC_WindowsLeft, true, kModifierWindowsLeft }, - { kSC_WindowsRight, true, kModifierWindowsRight }, - { 0, 0, 0 } }; - - UInt32 index; - bool releaseModifiers = false; - bool upBit = (scancode & kSC_UpBit) ? true : false; - - // - // See if this is an extened scancode sequence. - // - - if (scancode == kSC_Extend) - { - _extendedState = true; - return false; - } - - // - // Update the modifier state, if applicable. - // - - scancode &= ~kSC_UpBit; - - for (index = 0; modifierTable[index].scancode; index++) - { - if ( modifierTable[index].scancode == scancode && - modifierTable[index].extended == _extendedState ) - { - if (upBit) _modifierState &= ~modifierTable[index].modifier; - else _modifierState |= modifierTable[index].modifier; - - _extendedState = false; - return false; - } - } - - // - // Call the debugger function, if applicable. - // - - if (scancode == kSC_Delete) // (both extended and non-extended scancodes) - { - if ( _modifierState == kModifierAltLeft || - _modifierState == kModifierAltRight ) - { - // Disable the mouse by forcing the clock line low. - - while (inb(kCommandPort) & kInputBusy) IODelay(kDataDelay); - outb(kCommandPort, kCP_DisableMouseClock); - - // Call the debugger function. - - Debugger("Programmer Key"); - - // Re-enable the mouse by making the clock line active. - - while (inb(kCommandPort) & kInputBusy) IODelay(kDataDelay); - outb(kCommandPort, kCP_EnableMouseClock); - - releaseModifiers = true; - } - } - - // - // Release all the modifier keys that were down before the debugger - // function was called (assumption is that they are no longer held - // down after the debugger function returns). - // - - if (releaseModifiers) - { - for (index = 0; modifierTable[index].scancode; index++) - { - if ( _modifierState & modifierTable[index].modifier ) - { - if (modifierTable[index].extended) enqueueKeyboardData(kSC_Extend); - enqueueKeyboardData(modifierTable[index].scancode | kSC_UpBit); - } - } - _modifierState = 0x00; - } - - // - // Update all other state and return status. - // - - _extendedState = false; - return (releaseModifiers); -} - -void ApplePS2Controller::enqueueKeyboardData(UInt8 key) -{ - // - // Enqueue the supplied keyboard data onto our internal queues. The - // controller must already be locked. - // - - KeyboardQueueElement * element; - - // Obtain an unused keyboard data element. - if (!queue_empty(&_keyboardQueueUnused)) - { - queue_remove_first(&_keyboardQueueUnused, - element, KeyboardQueueElement *, chain); - - // Store the new keyboard data element on the queue. - element->data = key; - queue_enter(&_keyboardQueue, element, KeyboardQueueElement *, chain); - } -} - -bool ApplePS2Controller::dequeueKeyboardData(UInt8 * key) -{ - // - // Dequeue keyboard data from our internal queues, if the queue is not - // empty. Should the queue be empty, false is returned. The controller - // must already be locked. - // - - KeyboardQueueElement * element; - - // Obtain an unused keyboard data element. - if (!queue_empty(&_keyboardQueue)) - { - queue_remove_first(&_keyboardQueue, element, KeyboardQueueElement *, chain); - *key = element->data; - - // Place the unused keyboard data element onto the unused queue. - queue_enter(&_keyboardQueueUnused, element, KeyboardQueueElement *, chain); - - return true; - } - return false; -} - -void ApplePS2Controller::unlockController(void) -{ - usimple_unlock(&_controllerLock); - ml_set_interrupts_enabled(_controllerLockOldSpl); -} - -void ApplePS2Controller::lockController(void) -{ - int oldSpl = ml_set_interrupts_enabled(FALSE); - usimple_lock(&_controllerLock); - _controllerLockOldSpl = oldSpl; -} - -#endif DEBUGGER_SUPPORT diff --git a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h b/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h deleted file mode 100644 index d275c9520..000000000 --- a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2CONTROLLER_H -#define _APPLEPS2CONTROLLER_H - -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOService.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/IOCommandQueue.h> -#include <IOKit/ps2/ApplePS2Device.h> - -class ApplePS2KeyboardDevice; -class ApplePS2MouseDevice; - -// -// This section describes the problem with the PS/2 controller design and what -// we are doing about it (OUT_OF_ORDER_DATA_CORRECTION_FEATURE). -// -// While the controller processes requests sent by the client drivers, at some -// point in most requests, a read needs to be made from the data port to check -// an acknowledge or receive some sort of data. We illustrate this issue with -// an example -- a write LEDs request to the keyboard: -// -// 1. Write Write LED command. -// 2. Read 0xFA Verify the acknowledge (0xFA). -// 3. Write Write LED state. -// 4. Read 0xFA Verify the acknowledge (0xFA). -// -// The problem is that the keyboard (when it is enabled) can send key events -// to the controller at any time, including when the controller is expecting -// to read an acknowledge next. What ends up happening is this sequence: -// -// a. Write Write LED command. -// b. Read 0x21 Keyboard reports [F] key was depressed, not realizing that -// we're still expecting a response to the command we JUST -// sent the keyboard. We receive 0x21 as a response to our -// command, and figure the command failed. -// c. Get 0xFA Keyboard NOW decides to respond to the command with an -// acknowledge. We're not waiting to read anything, so -// this byte gets dispatched to the driver's interrupt -// handler, which spews out an error message saying it -// wasn't expecting an acknowledge. -// -// What can we do about this? In the above case, we can take note of the fact -// that we are specifically looking for the 0xFA acknowledgement byte (through -// the information passed in the kPS2C_ReadAndCompare primitive). If we don't -// receive this byte next on the input data stream, we put the byte we did get -// aside for a moment, and give the keyboard (or mouse) a second chance to -// respond correctly. -// -// If we receive the 0xFA acknowledgement byte on the second read, that we -// assume that situation described above just happened. We transparently -// dispatch the first byte to the driver's interrupt handler, where it was -// meant to go, and return the second correct byte to the read-and-compare -// logic, where it was meant to go. Everyone wins. -// -// The only situation this feature cannot help is where a kPS2C_ReadDataPort -// primitive is issued in place of a kPS2C_ReadDataPortAndCompare primitive. -// This is necessary in some requests because the driver does not know what -// it is going to receive. This can be illustrated in the mouse get info -// command. -// -// 1. Write Prepare to write to mouse. -// 2. Write Write information command. -// 3. Read 0xFA Verify the acknowledge (0xFA). __-> mouse can report mouse -// 4. Read Get first information byte. __-> packet bytes in between -// 5. Read Get second information byte. __-> these reads -// 6. Rrad Get third information byte. -// -// Controller cannot build any defenses against this. It is suggested that the -// driver writer disable the mouse first, then send any dangerous commands, and -// re-enable the mouse when the command completes. -// -// Note that the OUT_OF_ORDER_DATA_CORRECTION_FEATURE can be turned off at -// compile time. Please see the readDataPort:expecting: method for more -// information about the assumptions necessary for this feature. -// - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Definitions -// - -// Enable debugger support (eg. mini-monitor). - -#define DEBUGGER_SUPPORT 1 - -// Enable dynamic "second chance" re-ordering of input stream data if a -// command response fails to match the expected byte. - -#define OUT_OF_ORDER_DATA_CORRECTION_FEATURE 1 - -// PS/2 device types. - -typedef enum { kDT_Keyboard, kDT_Mouse } PS2DeviceType; - -// Interrupt definitions. - -#define kIRQ_Keyboard 1 -#define kIRQ_Mouse 12 -#define kIPL_Keyboard 6 -#define kIPL_Mouse 3 - -// Port timings. - -#define kDataDelay 7 // usec to delay before data is valid - -// Ports used to control the PS/2 keyboard/mouse and read data from it. - -#define kDataPort 0x60 // keyboard data & cmds (read/write) -#define kCommandPort 0x64 // keybd status (read), command (write) - -// Bit definitions for kCommandPort read values (status). - -#define kOutputReady 0x01 // output (from keybd) buffer full -#define kInputBusy 0x02 // input (to keybd) buffer full -#define kSystemFlag 0x04 // "System Flag" -#define kCommandLastSent 0x08 // 1 = cmd, 0 = data last sent -#define kKeyboardInhibited 0x10 // 0 if keyboard inhibited -#define kMouseData 0x20 // mouse data available - -#if DEBUGGER_SUPPORT -// Definitions for our internal keyboard queue (holds keys processed by the -// interrupt-time mini-monitor-key-sequence detection code). - -#define kKeyboardQueueSize 32 // number of KeyboardQueueElements - -typedef struct KeyboardQueueElement KeyboardQueueElement; -struct KeyboardQueueElement -{ - queue_chain_t chain; - UInt8 data; -}; -#endif DEBUGGER_SUPPORT - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ApplePS2Controller Class Declaration -// - -class ApplePS2Controller : public IOService -{ - OSDeclareDefaultStructors(ApplePS2Controller); - -public: // interrupt-time variables and functions - IOInterruptEventSource * _interruptSourceKeyboard; - IOInterruptEventSource * _interruptSourceMouse; - -#if DEBUGGER_SUPPORT - void lockController(void); - void unlockController(void); - - bool doEscape(UInt8 key); - bool dequeueKeyboardData(UInt8 * key); - void enqueueKeyboardData(UInt8 key); -#endif DEBUGGER_SUPPORT - -private: - IOCommandQueue * _commandQueue; - IOWorkLoop * _workLoop; - - OSObject * _interruptTargetKeyboard; - OSObject * _interruptTargetMouse; - PS2InterruptAction _interruptActionKeyboard; - PS2InterruptAction _interruptActionMouse; - bool _interruptInstalledKeyboard; - bool _interruptInstalledMouse; - - ApplePS2MouseDevice * _mouseDevice; // mouse nub - ApplePS2KeyboardDevice * _keyboardDevice; // keyboard nub - -#if DEBUGGER_SUPPORT - usimple_lock_data_t _controllerLock; // mach simple spin lock - int _controllerLockOldSpl; // spl before lock taken - - KeyboardQueueElement * _keyboardQueueAlloc; // queues' allocation space - queue_head_t _keyboardQueue; // queue of available keys - queue_head_t _keyboardQueueUnused; // queue of unused entries - - bool _extendedState; - UInt16 _modifierState; -#endif DEBUGGER_SUPPORT - - virtual void dispatchDriverInterrupt(PS2DeviceType deviceType, UInt8 data); - virtual void interruptOccurred(IOInterruptEventSource *, int); - virtual void processRequest(PS2Request * request, void *, void *, void *); - static void submitRequestAndBlockCompletion(void *, void * param); - - virtual UInt8 readDataPort(PS2DeviceType deviceType); - virtual void writeCommandPort(UInt8 byte); - virtual void writeDataPort(UInt8 byte); - -#if OUT_OF_ORDER_DATA_CORRECTION_FEATURE - virtual UInt8 readDataPort(PS2DeviceType deviceType, UInt8 expectedByte); -#endif - -public: - virtual bool init(OSDictionary * properties); - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); - - virtual IOWorkLoop * getWorkLoop() const; - - virtual void installInterruptAction(PS2DeviceType deviceType, - OSObject * target, - PS2InterruptAction action); - virtual void uninstallInterruptAction(PS2DeviceType deviceType); - - virtual PS2Request * allocateRequest(); - virtual void freeRequest(PS2Request * request); - virtual bool submitRequest(PS2Request * request); - virtual void submitRequestAndBlock(PS2Request * request); -}; - -#endif /* _APPLEPS2CONTROLLER_H */ diff --git a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2KeyboardDevice.cpp b/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2KeyboardDevice.cpp deleted file mode 100644 index 3418e2b62..000000000 --- a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2KeyboardDevice.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/ps2/ApplePS2KeyboardDevice.h> -#include "ApplePS2Controller.h" - -// ============================================================================= -// ApplePS2KeyboardDevice Class Implementation -// - -#define super IOService -OSDefineMetaClassAndStructors(ApplePS2KeyboardDevice, IOService); - -bool ApplePS2KeyboardDevice::attach( IOService * provider ) -{ - if( !super::attach(provider) ) return false; - - assert(_controller == 0); - _controller = (ApplePS2Controller *)provider; - _controller->retain(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2KeyboardDevice::detach( IOService * provider ) -{ - assert(_controller == provider); - _controller->release(); - _controller = 0; - - super::detach(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2KeyboardDevice::installInterruptAction(OSObject * target, - PS2InterruptAction action) -{ - _controller->installInterruptAction(kDT_Keyboard, target, action); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2KeyboardDevice::uninstallInterruptAction() -{ - _controller->uninstallInterruptAction(kDT_Keyboard); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PS2Request * ApplePS2KeyboardDevice::allocateRequest() -{ - return _controller->allocateRequest(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2KeyboardDevice::freeRequest(PS2Request * request) -{ - _controller->freeRequest(request); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2KeyboardDevice::submitRequest(PS2Request * request) -{ - return _controller->submitRequest(request); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2KeyboardDevice::submitRequestAndBlock(PS2Request * request) -{ - _controller->submitRequestAndBlock(request); -} diff --git a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2MouseDevice.cpp b/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2MouseDevice.cpp deleted file mode 100644 index 7294baba0..000000000 --- a/iokit/Drivers/platform/drvApplePS2Controller/ApplePS2MouseDevice.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/ps2/ApplePS2MouseDevice.h> -#include "ApplePS2Controller.h" - -// ============================================================================= -// ApplePS2MouseDevice Class Implementation -// - -#define super IOService -OSDefineMetaClassAndStructors(ApplePS2MouseDevice, IOService); - -bool ApplePS2MouseDevice::attach(IOService * provider) -{ - if( !super::attach(provider) ) return false; - - assert(_controller == 0); - _controller = (ApplePS2Controller *)provider; - _controller->retain(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2MouseDevice::detach( IOService * provider ) -{ - assert(_controller == provider); - _controller->release(); - _controller = 0; - - super::detach(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2MouseDevice::installInterruptAction(OSObject * target, - PS2InterruptAction action) -{ - _controller->installInterruptAction(kDT_Mouse, target, action); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2MouseDevice::uninstallInterruptAction() -{ - _controller->uninstallInterruptAction(kDT_Mouse); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -PS2Request * ApplePS2MouseDevice::allocateRequest() -{ - return _controller->allocateRequest(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2MouseDevice::freeRequest(PS2Request * request) -{ - _controller->freeRequest(request); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool ApplePS2MouseDevice::submitRequest(PS2Request * request) -{ - return _controller->submitRequest(request); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void ApplePS2MouseDevice::submitRequestAndBlock(PS2Request * request) -{ - _controller->submitRequestAndBlock(request); -} diff --git a/iokit/Drivers/platform/drvAppleRootDomain/RootDomain.cpp b/iokit/Drivers/platform/drvAppleRootDomain/RootDomain.cpp index 680e40b22..f3373a0dc 100644 --- a/iokit/Drivers/platform/drvAppleRootDomain/RootDomain.cpp +++ b/iokit/Drivers/platform/drvAppleRootDomain/RootDomain.cpp @@ -27,6 +27,7 @@ #include <IOKit/pwr_mgt/IOPM.h> #include <IOKit/IOMessage.h> #include "RootDomainUserClient.h" +#include "IOKit/pwr_mgt/IOPowerConnection.h" extern "C" { extern void kprintf(const char *, ...); @@ -35,24 +36,32 @@ extern void kprintf(const char *, ...); extern const IORegistryPlane * gIOPowerPlane; void PMreceiveCmd ( OSObject *, void *, void *, void *, void * ); -bool rootHasPMU( OSObject * us, void *, IOService * yourDevice ); +static void sleepTimerExpired(thread_call_param_t); -#define number_of_power_states 3 +#define number_of_power_states 5 #define OFF_STATE 0 -#define SLEEP_STATE 1 -#define ON_STATE 2 +#define RESTART_STATE 1 +#define SLEEP_STATE 2 +#define DOZE_STATE 3 +#define ON_STATE 4 -#define ON_POWER IOPMPowerOn -#define SLEEP_POWER IOPMAuxPowerOn +#define ON_POWER kIOPMPowerOn +#define RESTART_POWER kIOPMRestart +#define SLEEP_POWER kIOPMAuxPowerOn +#define DOZE_POWER kIOPMDoze static IOPMPowerState ourPowerStates[number_of_power_states] = { - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,0,0,SLEEP_POWER,0,0,0,0,0,0,0,0}, - {1,IOPMPowerOn,IOPMPowerOn,ON_POWER,0,0,0,0,0,0,0,0}, + {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off + {1,kIOPMRestartCapability, kIOPMRestart, RESTART_POWER,0,0,0,0,0,0,0,0}, // state 1, restart + {1,kIOPMSleepCapability, kIOPMSleep, SLEEP_POWER,0,0,0,0,0,0,0,0}, // state 2, sleep + {1,kIOPMDoze, kIOPMDoze, DOZE_POWER,0,0,0,0,0,0,0,0}, // state 3, doze + {1,kIOPMPowerOn, kIOPMPowerOn, ON_POWER,0,0,0,0,0,0,0,0}, // state 4, on }; static IOPMrootDomain * gRootDomain; +static UInt32 gSleepOrShutdownPending = 0; + #define super IOService OSDefineMetaClassAndStructors(IOPMrootDomain,IOService) @@ -64,13 +73,108 @@ extern "C" return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref ); } + IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref = 0) + { + return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref ); + } + IOReturn acknowledgeSleepWakeNotification(void * PMrefcon) { return gRootDomain->allowPowerChange ( (unsigned long)PMrefcon ); } + IOReturn vetoSleepWakeNotification(void * PMrefcon) + { + return gRootDomain->cancelPowerChange ( (unsigned long)PMrefcon ); + } + + IOReturn rootDomainRestart ( void ) + { + return gRootDomain->restartSystem(); + } + + IOReturn rootDomainShutdown ( void ) + { + return gRootDomain->shutdownSystem(); + } + + void IOSystemShutdownNotification ( void ) + { + for ( int i = 0; i < 100; i++ ) + { + if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) ) break; + IOSleep( 100 ); + } + } + + int sync_internal(void); } +/* +A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain +children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by +calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children +express their desires by calling requestPowerDomainState(). + +The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just +like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc. + +The sleep/doze policy is as follows: +Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards. +Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero. +The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep. + +These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is +opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or +the state of the other clamp. + +Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item. +In this case the root's parent actually initiates the power state change so that the root has no choice and does not give +applications the opportunity to veto the change. + +Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's +children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE) +to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and +the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if +the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes, +when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root +sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake, +so it falls asleep. + +Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of +boot, a flag is cleared, and this allows subsequent Demand Sleep. + +The system will not Sleep, but will Doze if some object calls setSleepSupported(kPCICantSleep) during a power change to the sleep state (this can be done by the PCI Aux Power Supply drivers, Slots99, MacRISC299, etc.). This is not enforced with +a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up +one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and +ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler +to be tickled)). +*/ + + +// ********************************************************************************** + +IOPMrootDomain * IOPMrootDomain::construct( void ) +{ + IOPMrootDomain * root; + + root = new IOPMrootDomain; + if( root) + root->init(); + + return( root ); +} + +// ********************************************************************************** + +static void disk_sync_callout(thread_call_param_t p0, thread_call_param_t p1) +{ + IOService * rootDomain = (IOService *) p0; + unsigned long pmRef = (unsigned long) p1; + + sync_internal(); + rootDomain->allowPowerChange(pmRef); +} // ********************************************************************************** // start @@ -78,6 +182,8 @@ extern "C" // We don't do much here. The real initialization occurs when the platform // expert informs us we are the root. // ********************************************************************************** + + bool IOPMrootDomain::start ( IOService * nub ) { super::start(nub); @@ -85,19 +191,26 @@ bool IOPMrootDomain::start ( IOService * nub ) gRootDomain = this; PMinit(); + setProperty("IOSleepSupported",""); allowSleep = true; - sleepIsSupported = false; - idlePeriod = 0; + sleepIsSupported = true; systemBooting = true; -// systemBooting = false; // temporary work-around for 2589847 - ignoringClamshell = false; - + ignoringClamshell = true; + sleepSlider = 0; + idleSleepPending = false; + canSleep = true; + wrangler = NULL; + sleepASAP = false; + pm_vars->PMworkloop = IOWorkLoop::workLoop(); // make the workloop pm_vars->commandQueue = IOCommandQueue::commandQueue(this, PMreceiveCmd); // make a command queue if (! pm_vars->commandQueue || ( pm_vars->PMworkloop->addEventSource( pm_vars->commandQueue) != kIOReturnSuccess) ) { return IOPMNoErr; } + extraSleepTimer = thread_call_allocate((thread_call_func_t)sleepTimerExpired, (thread_call_param_t) this); + + diskSyncCalloutEntry = thread_call_allocate(&disk_sync_callout, (thread_call_param_t) this); patriarch = new IORootParent; // create our parent patriarch->init(); @@ -109,10 +222,13 @@ bool IOPMrootDomain::start ( IOService * nub ) registerPowerDriver(this,ourPowerStates,number_of_power_states); - // Clamp power on. We will revisit this decision when the login window is displayed - // and we receive preferences via SetAggressiveness. - changePowerStateToPriv(ON_STATE); // clamp power on - powerOverrideOnPriv(); + setPMRootDomain(this); + changePowerStateToPriv(ON_STATE); // set a clamp until we sleep + + registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0); // install power change handler + + // Register for a notification when IODisplayWrangler is published + addNotification( gIOPublishNotification, serviceMatching("IODisplayWrangler"), &displayWranglerPublished, this, 0); registerService(); // let clients find us @@ -133,7 +249,6 @@ IOReturn IOPMrootDomain::youAreRoot ( void ) return IOPMNoErr; } - // ********************************************************************************** // command_received // @@ -144,14 +259,36 @@ IOReturn IOPMrootDomain::youAreRoot ( void ) void IOPMrootDomain::command_received ( void * command, void * x, void * y, void * z ) { switch ( (int)command ) { - case kPMbroadcastAggressiveness: + case kIOPMBroadcastAggressiveness: + + super::setAggressiveness((unsigned long)x,(unsigned long)y); + + // Save user's spin down timer to restore after we replace it for idle sleep + if( (int)x == kPMMinutesToSpinDown ) user_spindown = (unsigned int) y; + + // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer + longestNonSleepSlider = pm_vars->current_aggressiveness_values[kPMMinutesToDim]; + + if ( (int)x == kPMMinutesToSleep ) { - idlePeriod = (int)y*60; - if ( allowSleep && sleepIsSupported ) { - setIdleTimerPeriod(idlePeriod); // set new timeout + if ( (sleepSlider == 0) && ((int)y != 0) ) { + sleepSlider = (int)y; + adjustPowerState(); // idle sleep is now enabled, maybe sleep now } + sleepSlider = (int)y; + if ( sleepSlider == 0 ) { + adjustPowerState(); // idle sleep is now disabled + patriarch->wakeSystem(); // make sure we're powered + } + } + if ( sleepSlider > longestNonSleepSlider ) { + extraSleepDelay = sleepSlider - longestNonSleepSlider ; + } + else { + extraSleepDelay = 0; } break; + default: super::command_received(command,x,y,z); break; @@ -159,6 +296,33 @@ void IOPMrootDomain::command_received ( void * command, void * x, void * y, void } +// ********************************************************************************** +// sleepTimerExpired +// +// ********************************************************************************** +static void sleepTimerExpired ( thread_call_param_t us) +{ + ((IOPMrootDomain *)us)->handleSleepTimerExpiration(); + } + + +// ********************************************************************************** +// handleSleepTimerExpiration +// +// The time between the sleep idle timeout and the next longest one has elapsed. +// It's time to sleep. Start that by removing the clamp that's holding us awake. +// ********************************************************************************** +void IOPMrootDomain::handleSleepTimerExpiration ( void ) +{ + // accelerate disk spin down if spin down timer is non-zero (zero = never spin down) + if(0 != user_spindown) + setQuickSpinDownTimeout(); + + sleepASAP = true; + adjustPowerState(); +} + + //********************************************************************************* // setAggressiveness // @@ -171,10 +335,13 @@ void IOPMrootDomain::command_received ( void * command, void * x, void * y, void IOReturn IOPMrootDomain::setAggressiveness ( unsigned long type, unsigned long newLevel ) { - systemBooting = false; // when the finder launches, this method gets called -- system booting is done. + if ( systemBooting && (type == kPMMinutesToDim) ) { + systemBooting = false; // when the login window launches, this method gets called -- system booting is done. + IOLog("Root power domain receiving initial preferences\n"); + adjustPowerState(); + } - pm_vars->commandQueue->enqueueCommand(true, (void *)kPMbroadcastAggressiveness, (void *) type, (void *) newLevel ); - super::setAggressiveness(type,newLevel); + pm_vars->commandQueue->enqueueCommand(true, (void *)kIOPMBroadcastAggressiveness, (void *) type, (void *) newLevel ); return kIOReturnSuccess; } @@ -189,7 +356,34 @@ IOReturn IOPMrootDomain::sleepSystem ( void ) kprintf("sleep demand received\n"); if ( !systemBooting && allowSleep && sleepIsSupported ) { patriarch->sleepSystem(); + return kIOReturnSuccess; } + if ( !systemBooting && allowSleep && !sleepIsSupported ) { + patriarch->dozeSystem(); + return kIOReturnSuccess; + } + return kIOReturnSuccess; +} + + +// ********************************************************************************** +// shutdownSystem +// +// ********************************************************************************** +IOReturn IOPMrootDomain::shutdownSystem ( void ) +{ + patriarch->shutDownSystem(); + return kIOReturnSuccess; +} + + +// ********************************************************************************** +// restartSystem +// +// ********************************************************************************** +IOReturn IOPMrootDomain::restartSystem ( void ) +{ + patriarch->restartSystem(); return kIOReturnSuccess; } @@ -198,18 +392,96 @@ IOReturn IOPMrootDomain::sleepSystem ( void ) // powerChangeDone // // This overrides powerChangeDone in IOService. -// If we just finished switching to state zero, call the platform expert to -// sleep the kernel. -// Then later, when we awake, the kernel returns here and we wake the system. +// +// Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE. +// In this case: +// If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep, +// sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost +// everything as off as it can get. +// +// ********************************************************************************** +void IOPMrootDomain::powerChangeDone ( unsigned long previousState ) +{ + OSNumber * propertyPtr; + unsigned short theProperty; + AbsoluteTime deadline; + + switch ( pm_vars->myCurrentState ) { + case SLEEP_STATE: + if ( canSleep && sleepIsSupported ) { + idleSleepPending = false; // re-enable this timer for next sleep + IOLog("System Sleep\n"); + pm_vars->thePlatform->sleepKernel(); // sleep now + + // now we're waking + clock_interval_to_deadline(30, kSecondScale, &deadline); // stay awake for at least 30 seconds + thread_call_enter_delayed(extraSleepTimer, deadline); + idleSleepPending = true; // this gets turned off when we sleep again + gSleepOrShutdownPending = 0; // sleep transition complete + patriarch->wakeSystem(); // get us some power + + IOLog("System Wake\n"); + systemWake(); // tell the tree we're waking + + propertyPtr = OSDynamicCast(OSNumber,getProperty("WakeEvent")); + if ( propertyPtr ) { // find out what woke us + theProperty = propertyPtr->unsigned16BitValue(); + IOLog("Wake event %04x\n",theProperty); + if ( (theProperty == 0x0008) || //lid + (theProperty == 0x0800) || // front panel button + (theProperty == 0x0020) || // external keyboard + (theProperty == 0x0001) ) { // internal keyboard + reportUserInput(); + } + } + else { + IOLog("Unknown wake event\n"); + reportUserInput(); // don't know, call it user input then + } + + changePowerStateToPriv(ON_STATE); // wake for thirty seconds + powerOverrideOffPriv(); + } + else { + patriarch->sleepToDoze(); // allow us to step up a power state + changePowerStateToPriv(DOZE_STATE); // and do it + } + break; + + case DOZE_STATE: + if ( previousState != DOZE_STATE ) { + IOLog("System Doze\n"); + } + idleSleepPending = false; // re-enable this timer for next sleep + gSleepOrShutdownPending = 0; + break; + + case RESTART_STATE: + IOLog("System Restart\n"); + PEHaltRestart(kPERestartCPU); + break; + + case OFF_STATE: + IOLog("System Halt\n"); + PEHaltRestart(kPEHaltCPU); + break; + } +} + + +// ********************************************************************************** +// wakeFromDoze +// +// The Display Wrangler calls here when it switches to its highest state. If the +// system is currently dozing, allow it to wake by making sure the parent is +// providing power. // ********************************************************************************** -void IOPMrootDomain::powerChangeDone ( unsigned long powerStateOrdinal ) +void IOPMrootDomain::wakeFromDoze( void ) { - if ( powerStateOrdinal == SLEEP_STATE ) { - pm_vars->thePlatform->sleepKernel(); - activityTickle(kIOPMSubclassPolicy); // reset idle sleep - systemWake(); // tell the tree we're waking - patriarch->wakeSystem(); // make sure we have power - changePowerStateToPriv(ON_STATE); // and wake + if ( pm_vars->myCurrentState == DOZE_STATE ) { + canSleep = true; // reset this till next attempt + powerOverrideOffPriv(); + patriarch->wakeSystem(); // allow us to wake if children so desire } } @@ -252,10 +524,6 @@ IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg) (void) sleepSystem (); } - if (msg & kIOPMPowerButton) { - (void) sleepSystem (); - } - if (msg & kIOPMPowerEmergency) { (void) sleepSystem (); } @@ -266,27 +534,44 @@ IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg) } } - if (msg & kIOPMIgnoreClamshell) { + if (msg & kIOPMEnableClamshell) { + ignoringClamshell = false; + } + if (msg & kIOPMDisableClamshell) { ignoringClamshell = true; } - if (msg & kIOPMAllowSleep) { - if ( sleepIsSupported ) { - setIdleTimerPeriod(idlePeriod); + if (msg & kIOPMPowerButton) { // toggle state of sleep/wake + if ( pm_vars->myCurrentState == DOZE_STATE ) { // are we dozing? + systemWake(); // yes, tell the tree we're waking + reportUserInput(); // wake the Display Wrangler + } + else { + (void) sleepSystem (); } + } + + // if the case has been closed, we allow + // the machine to be put to sleep or to idle sleep + + if ( (msg & kIOPMAllowSleep) && !allowSleep ) { allowSleep = true; - changePowerStateTo (0); + adjustPowerState(); } - // if the case is open on some machines, we must now - // allow the machine to be put to sleep or to idle sleep + // if the case has been opened, we disallow sleep/doze if (msg & kIOPMPreventSleep) { - if ( sleepIsSupported ) { - setIdleTimerPeriod(0); - } allowSleep = false; - changePowerStateTo (number_of_power_states-1); + if ( pm_vars->myCurrentState == DOZE_STATE ) { // are we dozing? + systemWake(); // yes, tell the tree we're waking + adjustPowerState(); + reportUserInput(); // wake the Display Wrangler + } + else { + adjustPowerState(); + patriarch->wakeSystem(); // make sure we have power to clamp + } } return 0; @@ -300,19 +585,79 @@ IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg) void IOPMrootDomain::setSleepSupported( IOOptionBits flags ) { - platformSleepSupport = flags; - if ( flags & kRootDomainSleepSupported ) { - sleepIsSupported = true; - setProperty("IOSleepSupported",""); + if ( flags & kPCICantSleep ) { + canSleep = false; } - else - { - sleepIsSupported = false; - removeProperty("IOSleepSupported"); + else { + platformSleepSupport = flags; + } + +} + +//********************************************************************************* +// requestPowerDomainState +// +// The root domain intercepts this call to the superclass. +// +// If the clamp bit is not set in the desire, then the child doesn't need the power +// state it's requesting; it just wants it. The root ignores desires but not needs. +// If the clamp bit is not set, the root takes it that the child can tolerate no +// power and interprets the request accordingly. If all children can thus tolerate +// no power, we are on our way to idle sleep. +//********************************************************************************* + +IOReturn IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPowerConnection * whichChild, unsigned long specification ) +{ + OSIterator * iter; + OSObject * next; + IOPowerConnection * connection; + unsigned long powerRequestFlag = 0; + IOPMPowerFlags editedDesire = desiredState; + + if ( !(desiredState & kIOPMPreventIdleSleep) ) { // if they don't really need it, they don't get it + editedDesire = 0; + } + + + IOLockLock(pm_vars->childLock); // recompute sleepIsSupported + // and see if all children are asleep + iter = getChildIterator(gIOPowerPlane); + sleepIsSupported = true; + + if ( iter ) { + while ( (next = iter->getNextObject()) ) { + if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { + if ( connection == whichChild ) { + powerRequestFlag += editedDesire; + if ( desiredState & kIOPMPreventSystemSleep ) { + sleepIsSupported = false; + } + } + else { + powerRequestFlag += connection->getDesiredDomainState(); + if ( connection->getPreventSystemSleepFlag() ) { + sleepIsSupported = false; + } + } + } + } + iter->release(); + } + + if ( (extraSleepDelay == 0) && (powerRequestFlag == 0) ) { + sleepASAP = true; } + + adjustPowerState(); // this may put the system to sleep + + IOLockUnlock(pm_vars->childLock); + + editedDesire |= desiredState & kIOPMPreventSystemSleep; + return super::requestPowerDomainState(editedDesire,whichChild,specification); } + //********************************************************************************* // getSleepSupported // @@ -333,10 +678,16 @@ IOOptionBits IOPMrootDomain::getSleepSupported( void ) bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum ) { - if ( stateNum == SLEEP_STATE ) { - return super::tellClientsWithResponse(kIOMessageSystemWillSleep); + switch ( stateNum ) { + case DOZE_STATE: + case SLEEP_STATE: + return super::tellClientsWithResponse(kIOMessageSystemWillSleep); + case RESTART_STATE: + return super::tellClientsWithResponse(kIOMessageSystemWillRestart); + case OFF_STATE: + return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff); } - return super::tellChangeDown(stateNum); + return super::tellChangeDown(stateNum); // this shouldn't execute } @@ -345,14 +696,13 @@ bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum ) // // We override the superclass implementation so we can send a different message // type to the client or application being notified. +// +// This must be idle sleep since we don't ask apps during any other power change. //********************************************************************************* -bool IOPMrootDomain::askChangeDown (unsigned long stateNum) +bool IOPMrootDomain::askChangeDown ( unsigned long ) { - if ( stateNum == SLEEP_STATE ) { - return super::tellClientsWithResponse(kIOMessageCanSystemSleep); - } - return super::askChangeDown(stateNum); + return super::tellClientsWithResponse(kIOMessageCanSystemSleep); } @@ -364,6 +714,8 @@ bool IOPMrootDomain::askChangeDown (unsigned long stateNum) // // We override the superclass implementation so we can send a different message // type to the client or application being notified. +// +// This must be a vetoed idle sleep, since no other power change can be vetoed. //********************************************************************************* void IOPMrootDomain::tellNoChangeDown ( unsigned long ) @@ -386,19 +738,264 @@ void IOPMrootDomain::tellChangeUp ( unsigned long ) return tellClients(kIOMessageSystemHasPoweredOn); } +//********************************************************************************* +// reportUserInput +// +//********************************************************************************* + +void IOPMrootDomain::reportUserInput ( void ) +{ + OSIterator * iter; -// ********************************************************************************** -// activityTickle + if(!wrangler) { + iter = getMatchingServices(serviceMatching("IODisplayWrangler")); + if(iter) { + wrangler = (IOService *) iter->getNextObject(); + iter->release(); + } + } + + if(wrangler) + wrangler->activityTickle(0,0); +} + +//********************************************************************************* +// setQuickSpinDownTimeout // -// This is called by the HID system and calls the superclass in turn. -// ********************************************************************************** +//********************************************************************************* + +void IOPMrootDomain::setQuickSpinDownTimeout ( void ) +{ + //IOLog("setQuickSpinDownTimeout\n"); + super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)1); +} + +//********************************************************************************* +// restoreUserSpinDownTimeout +// +//********************************************************************************* + +void IOPMrootDomain::restoreUserSpinDownTimeout ( void ) +{ + if(systemBooting) { + IOLog("!!!!! WARNING !!!!! restoreUserSpinDownTimeout called too early\n"); + } + //IOLog("restoreUserSpinDownTimeout, user_spindown = %u\n", user_spindown); + + super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)user_spindown); +} + + +//********************************************************************************* +// sysPowerDownHandler +// +// Receives a notification when the RootDomain changes state. +// +// Allows us to take action on system sleep, power down, and restart after +// applications have received their power change notifications and replied, +// but before drivers have powered down. We perform a vfs sync on power down. +//********************************************************************************* + +IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon, + UInt32 messageType, IOService * service, + void * messageArgument, vm_size_t argSize ) +{ + IOReturn ret; + IOPowerStateChangeNotification * params = (IOPowerStateChangeNotification *) messageArgument; + IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, service); + + if(!rootDomain) + return kIOReturnUnsupported; + + switch (messageType) { + case kIOMessageSystemWillSleep: + rootDomain->powerOverrideOnPriv(); // start ignoring children's requests + // (fall through to other cases) + case kIOMessageSystemWillPowerOff: + case kIOMessageSystemWillRestart: + + // Interested applications have been notified of an impending power + // change and have acked (when applicable). + // This is our chance to save whatever state we can before powering + // down. + // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c, + // via callout + + // We will ack within 20 seconds + params->returnValue = 20 * 1000 * 1000; + + if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) ) + { + // Purposely delay the ack and hope that shutdown occurs quickly. + // Another option is not to schedule the thread and wait for + // ack timeout... + AbsoluteTime deadline; + clock_interval_to_deadline( 15, kSecondScale, &deadline ); + thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry, + (thread_call_param_t)params->powerRef, + deadline ); + } + else + thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef); + ret = kIOReturnSuccess; + break; + default: + ret = kIOReturnUnsupported; + break; + } + return ret; +} + +//********************************************************************************* +// displayWranglerNotification +// +// Receives a notification when the IODisplayWrangler changes state. +// +// Allows us to take action on display dim/undim. +// +// When the display goes dim we: +// - Start the idle sleep timer +// - set the quick spin down timeout +// +// On wake from display dim: +// - Cancel the idle sleep timer +// - restore the user's chosen spindown timer from the "quick" spin down value +//********************************************************************************* -bool IOPMrootDomain::activityTickle ( unsigned long, unsigned long x=0 ) +IOReturn IOPMrootDomain::displayWranglerNotification( void * target, void * refCon, + UInt32 messageType, IOService * service, + void * messageArgument, vm_size_t argSize ) { - return super::activityTickle (kIOPMSuperclassPolicy1,ON_STATE); + IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target); + AbsoluteTime deadline; + static bool deviceAlreadyPoweredOff = false; + + if(!rootDomain) + return kIOReturnUnsupported; + + switch (messageType) { + case kIOMessageDeviceWillPowerOff: + // The IODisplayWrangler has powered off either because of idle display sleep + // or force system sleep. + + // The display wrangler will send the DeviceWillPowerOff message 4 times until + // it gets into its lowest state. We only want to act on the first of those 4. + if( deviceAlreadyPoweredOff ) return kIOReturnUnsupported; + + deviceAlreadyPoweredOff = true; + + if( rootDomain->extraSleepDelay ) { + + // start the extra sleep timer + clock_interval_to_deadline(rootDomain->extraSleepDelay*60, kSecondScale, &deadline ); + thread_call_enter_delayed(rootDomain->extraSleepTimer, deadline); + rootDomain->idleSleepPending = true; + + } else { + + // accelerate disk spin down if spin down timer is non-zero (zero = never spin down) + if(0 != rootDomain->user_spindown) + rootDomain->setQuickSpinDownTimeout(); + } + + break; + + case kIOMessageDeviceHasPoweredOn: + + // The display has powered on either because of UI activity or wake from sleep/doze + deviceAlreadyPoweredOff = false; + rootDomain->adjustPowerState(); + + + // cancel any pending idle sleep + if(rootDomain->idleSleepPending) { + thread_call_cancel(rootDomain->extraSleepTimer); + rootDomain->idleSleepPending = false; + } + + // Change the spindown value back to the user's selection from our accelerated setting + if(0 != rootDomain->user_spindown) + rootDomain->restoreUserSpinDownTimeout(); + + // Put on the policy maker's on clamp. + + break; + + default: + break; + } + return kIOReturnUnsupported; + } + +//********************************************************************************* +// displayWranglerPublished +// +// Receives a notification when the IODisplayWrangler is published. +// When it's published we install a power state change handler. +// +//********************************************************************************* + +bool IOPMrootDomain::displayWranglerPublished( void * target, void * refCon, + IOService * newService) +{ + IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target); + + if(!rootDomain) + return false; + + rootDomain->wrangler = newService; + + // we found the display wrangler, now install a handler + if( !rootDomain->wrangler->registerInterest( gIOGeneralInterest, &displayWranglerNotification, target, 0) ) { + IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n"); + return false; + } + + return true; } +//********************************************************************************* +// adjustPowerState +// +// Some condition that affects our wake/sleep/doze decision has changed. +// +// If the sleep slider is in the off position, we cannot sleep or doze. +// If the enclosure is open, we cannot sleep or doze. +// If the system is still booting, we cannot sleep or doze. +// +// In those circumstances, we prevent sleep and doze by holding power on with +// changePowerStateToPriv(ON). +// +// If the above conditions do not exist, and also the sleep timer has expired, we +// allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or +// changePowerStateToPriv(DOZE) depending on whether or not we already know the +// platform cannot sleep. +// +// In this case, sleep or doze will either occur immediately or at the next time +// that no children are holding the system out of idle sleep via the +// kIOPMPreventIdleSleep flag in their power state arrays. +//********************************************************************************* + +void IOPMrootDomain::adjustPowerState( void ) +{ + if ( (sleepSlider == 0) || + ! allowSleep || + systemBooting ) { + changePowerStateToPriv(ON_STATE); + } + else { + if ( sleepASAP ) { + sleepASAP = false; + if ( sleepIsSupported ) { + changePowerStateToPriv(SLEEP_STATE); + } + else { + changePowerStateToPriv(DOZE_STATE); + } + } + } +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -408,24 +1005,26 @@ bool IOPMrootDomain::activityTickle ( unsigned long, unsigned long x=0 ) OSDefineMetaClassAndStructors(IORootParent, IOService) -#define number_of_patriarch_power_states 3 +// This array exactly parallels the state array for the root domain. +// Power state changes initiated by a device can be vetoed by a client of the device, and +// power state changes initiated by the parent of a device cannot be vetoed by a client of the device, +// so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks +// its parent to make the change. That is the reason for this complexity. -static IOPMPowerState patriarchPowerStates[number_of_patriarch_power_states] = { +static IOPMPowerState patriarchPowerStates[number_of_power_states] = { {1,0,0,0,0,0,0,0,0,0,0,0}, // off + {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep + {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze {1,0,ON_POWER,0,0,0,0,0,0,0,0,0} // running }; -#define PATRIARCH_OFF 0 -#define PATRIARCH_SLEEP 1 -#define PATRIARCH_ON 2 - - bool IORootParent::start ( IOService * nub ) { + mostRecentChange = ON_STATE; super::start(nub); PMinit(); - registerPowerDriver(this,patriarchPowerStates,number_of_patriarch_power_states); + registerPowerDriver(this,patriarchPowerStates,number_of_power_states); powerOverrideOnPriv(); return true; } @@ -433,18 +1032,47 @@ bool IORootParent::start ( IOService * nub ) void IORootParent::shutDownSystem ( void ) { - changePowerStateToPriv(PATRIARCH_OFF); + mostRecentChange = OFF_STATE; + changePowerStateToPriv(OFF_STATE); +} + + +void IORootParent::restartSystem ( void ) +{ + mostRecentChange = RESTART_STATE; + changePowerStateToPriv(RESTART_STATE); } void IORootParent::sleepSystem ( void ) { - changePowerStateToPriv(PATRIARCH_SLEEP); + mostRecentChange = SLEEP_STATE; + changePowerStateToPriv(SLEEP_STATE); +} + + +void IORootParent::dozeSystem ( void ) +{ + mostRecentChange = DOZE_STATE; + changePowerStateToPriv(DOZE_STATE); +} + +// Called in demand sleep when sleep discovered to be impossible after actually attaining that state. +// This brings the parent to doze, which allows the root to step up from sleep to doze. + +// In idle sleep, do nothing because the parent is still on and the root can freely change state. + +void IORootParent::sleepToDoze ( void ) +{ + if ( mostRecentChange == SLEEP_STATE ) { + changePowerStateToPriv(DOZE_STATE); + } } void IORootParent::wakeSystem ( void ) { - changePowerStateToPriv(PATRIARCH_ON); + mostRecentChange = ON_STATE; + changePowerStateToPriv(ON_STATE); } diff --git a/iokit/Drivers/platform/drvAppleRootDomain/RootDomainUserClient.cpp b/iokit/Drivers/platform/drvAppleRootDomain/RootDomainUserClient.cpp index 598cbaf9a..35fd5aa28 100644 --- a/iokit/Drivers/platform/drvAppleRootDomain/RootDomainUserClient.cpp +++ b/iokit/Drivers/platform/drvAppleRootDomain/RootDomainUserClient.cpp @@ -91,6 +91,18 @@ bool RootDomainUserClient::start( IOService * provider ) fMethods[kPMCancelPowerChange].count1 = 0; fMethods[kPMCancelPowerChange].flags = kIOUCScalarIScalarO; + fMethods[kPMShutdownSystem].object = provider; // 5 + fMethods[kPMShutdownSystem].func = (IOMethod)&IOPMrootDomain::shutdownSystem; + fMethods[kPMShutdownSystem].count0 = 0; + fMethods[kPMShutdownSystem].count1 = 0; + fMethods[kPMShutdownSystem].flags = kIOUCScalarIScalarO; + + fMethods[kPMRestartSystem].object = provider; // 6 + fMethods[kPMRestartSystem].func = (IOMethod)&IOPMrootDomain::restartSystem; + fMethods[kPMRestartSystem].count0 = 0; + fMethods[kPMRestartSystem].count1 = 0; + fMethods[kPMRestartSystem].flags = kIOUCScalarIScalarO; + return true; } diff --git a/iokit/Families/IOADBBus/IOADBController.cpp b/iokit/Families/IOADBBus/IOADBController.cpp index 14cafcc48..c0c75b0b9 100644 --- a/iokit/Families/IOADBBus/IOADBController.cpp +++ b/iokit/Families/IOADBBus/IOADBController.cpp @@ -151,13 +151,12 @@ bool ADBhasRoot( OSObject * us, void *, IOService * yourDevice ) IOReturn IOADBController::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*) { int i; - - if ( ! (theFlags & IOPMPowerOn) ) { + if ( ! (theFlags & kIOPMPowerOn) && ! (theFlags & kIOPMDoze) ) { busProbed = false; for ( i = 1; i < ADB_DEVICE_COUNT; i++ ) { if( adbDevices[ i ] != NULL ) { if ( adbDevices[ i ]->nub ) { - adbDevices[ i ]->nub->terminate(kIOServiceRequired); + adbDevices[ i ]->nub->terminate(kIOServiceRequired | kIOServiceSynchronous); adbDevices[ i ]->nub->release(); } IOFree( adbDevices[ i ], sizeof (ADBDeviceControl)); @@ -178,7 +177,7 @@ IOReturn IOADBController::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsi //********************************************************************************* IOReturn IOADBController::powerStateDidChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*) { - if ( theFlags & IOPMPowerOn ) { + if ( (theFlags & kIOPMPowerOn) || (theFlags & kIOPMDoze) ) { if ( ! busProbed ) { thread_call_enter(probeThread); busProbed = true; @@ -288,14 +287,9 @@ IOReturn IOADBController::probeBus ( void ) const OSNumber * object; const OSSymbol * key; - /* Waits one second for the trackpads to be up */ - - IOSleep(1500); - /* Kill the auto poll until a new dev id's have been setup */ - setAutoPollEnable(false); - + /* * Send a ADB bus reset - reply is sent after bus has reset, * so there is no need to wait for the reset to complete. @@ -303,10 +297,6 @@ IOReturn IOADBController::probeBus ( void ) resetBus(); - /* Waits one second for the trackpads to be up */ - - IOSleep(1500); - /* * Okay, now attempt reassign the * bus @@ -323,7 +313,7 @@ IOReturn IOADBController::probeBus ( void ) } } - /* Now attempt to reassign the addresses */ +/* Now attempt to reassign the addresses */ while( unresolvedAddrs) { if( !freeAddrs) { panic("ADB: Cannot find a free ADB slot for reassignment!"); @@ -471,8 +461,9 @@ IOReturn IOADBController::probeBus ( void ) newDev->release(); continue; } - newDev->registerService(); newDev->start(this); + newDev->registerService(); + newDev->waitQuiet(); } // repeat loop return kIOReturnSuccess; } @@ -556,8 +547,8 @@ IOReturn IOADBController::setOwner ( void * device, IOService * client, ADB_call { ADBDeviceControl * deviceInfo = (ADBDeviceControl *)device; - deviceInfo->owner = client; deviceInfo->handler = handler; + deviceInfo->owner = client; return kIOReturnSuccess; } @@ -687,6 +678,16 @@ UInt8 IOADBController::defaultHandlerID ( ADBDeviceControl * busRef ) } +// ********************************************************************************** +// cancelAllIO +// +// ********************************************************************************** +IOReturn IOADBController::cancelAllIO ( void ) +{ + return kIOReturnSuccess; +} + + // ********************************************************************************** // flush // diff --git a/iokit/Drivers/hidsystem/drvAppleADBDevices/IOADBDevice.cpp b/iokit/Families/IOADBBus/IOADBDevice.cpp similarity index 97% rename from iokit/Drivers/hidsystem/drvAppleADBDevices/IOADBDevice.cpp rename to iokit/Families/IOADBBus/IOADBDevice.cpp index b416c86e6..999517b5a 100644 --- a/iokit/Drivers/hidsystem/drvAppleADBDevices/IOADBDevice.cpp +++ b/iokit/Families/IOADBBus/IOADBDevice.cpp @@ -95,6 +95,9 @@ void IOADBDevice::releaseFromClient ( IORegistryEntry * ) // ********************************************************************************** IOReturn IOADBDevice::flush ( void ) { +if ( isInactive() ) { + return kIOReturnNotOpen; +} return( bus->flush(fBusRef) ); } @@ -106,6 +109,9 @@ return( bus->flush(fBusRef) ); IOReturn IOADBDevice::readRegister ( IOADBRegister adbRegister, UInt8 * data, IOByteCount * length ) { +if ( isInactive() ) { + return kIOReturnNotOpen; +} return( bus->readRegister(fBusRef,adbRegister,data,length) ); } @@ -117,6 +123,9 @@ return( bus->readRegister(fBusRef,adbRegister,data,length) ); IOReturn IOADBDevice::writeRegister ( IOADBRegister adbRegister, UInt8 * data, IOByteCount * length ) { +if ( isInactive() ) { + return kIOReturnNotOpen; +} return( bus->writeRegister(fBusRef,adbRegister,data,length) ); } diff --git a/iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp b/iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp deleted file mode 100644 index 8cfd30563..000000000 --- a/iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAHDCommand.cpp - Performs ATA command processing. - * - * HISTORY - * Aug 27, 1999 jliu - Ported from AppleATADrive. - */ - -#include <IOKit/assert.h> -#include <IOKit/IOSyncer.h> -#include <IOKit/storage/ata/IOATAHDDrive.h> - -// Enable this define to generate debugging messages. -// #define DEBUG_LOG 1 - -//--------------------------------------------------------------------------- -// Select the device timing protocol. - -bool -IOATAHDDrive::selectTimingProtocol() -{ - bool ret; - UInt8 ataReadCmd; - UInt8 ataWriteCmd; - ATATimingProtocol timing; - char * protocolName; - - ret = _ataDevice->getTimingsSupported(&timing); - if (ret == false) - { - IOLog("%s: getTimingsSupported() error\n", getName()); - timing = kATATimingPIO; - } - - // IOLog("%s: device supported timings: %08x\n", getName(), timing); - - if (timing & (kATATimingUltraDMA66 | kATATimingUltraDMA33 | kATATimingDMA)) - { - if (timing & kATATimingUltraDMA66) - { - protocolName = "U-DMA/66"; - timing = kATATimingUltraDMA66; - } - else if (timing & kATATimingUltraDMA33) - { - protocolName = "U-DMA/33"; - timing = kATATimingUltraDMA33; - } - else - { - protocolName = "DMA"; - timing = kATATimingDMA; - } - - selectCommandProtocol(true); - - switch ( _ataProtocol ) - { - case kATAProtocolDMAQueued: - ataReadCmd = kIOATACommandReadDMAQueued; - ataWriteCmd = kIOATACommandWriteDMAQueued; - break; - - case kATAProtocolDMA: - default: - ataReadCmd = kIOATACommandReadDMA; - ataWriteCmd = kIOATACommandWriteDMA; - } - } - else - { - protocolName = "PIO"; - timing = kATATimingPIO; - ataReadCmd = kIOATACommandReadPIO; - ataWriteCmd = kIOATACommandWritePIO; - selectCommandProtocol(false); - } - - _timingProtocol = timing; - _ataReadCmd = ataReadCmd; - _ataWriteCmd = ataWriteCmd; - ret = true; - - // Select device timing. - // - ret = _ataDevice->selectTiming( _timingProtocol, false ); - - if (ret == false) - { - IOLog("%s: %s selectTiming() failed\n", getName(), protocolName); - - if (_timingProtocol != kATATimingPIO) - { - // Non PIO mode selection failed, defaulting to PIO mode and - // try one more time. - - protocolName = "PIO"; - _timingProtocol = kATATimingPIO; - _ataReadCmd = kIOATACommandReadPIO; - _ataWriteCmd = kIOATACommandWritePIO; - selectCommandProtocol(false); - - ret = _ataDevice->selectTiming( _timingProtocol, false ); - if (ret == false) - IOLog("%s: %s selectTiming() retry failed\n", - getName(), protocolName); - } - } - - if (ret && _logSelectedTimingProtocol) - IOLog("%s: Using %s transfers\n", getName(), protocolName); - - return ret; -} - -//--------------------------------------------------------------------------- -// Select the command protocol to use (e.g. ataProtocolPIO, ataProtocolDMA). - -bool -IOATAHDDrive::selectCommandProtocol(bool isDMA) -{ - ATAProtocol protocolsSupported; - - if ( _ataDevice->getProtocolsSupported( &protocolsSupported ) == false ) - { - IOLog("%s: getProtocolsSupported() failed\n", getName()); - return false; - } - - if ( (protocolsSupported & kATAProtocolDMAQueued) != 0 ) - { -#if 0 - _ataProtocol = kATAProtocolDMAQueued; -#else - _ataProtocol = kATAProtocolDMA; -#endif - } - else if ( (protocolsSupported & kATAProtocolDMA) != 0 ) - { - _ataProtocol = kATAProtocolDMA; - } - else - { - _ataProtocol = kATAProtocolPIO; - } - - return true; -} - -//--------------------------------------------------------------------------- -// Configure the ATA/ATAPI device when the driver is initialized, and -// after every device reset. - -bool -IOATAHDDrive::configureDevice(IOATADevice * device) -{ - bool ret; - - // Select device timing. - // - ret = device->selectTiming( _timingProtocol, true ); - if (ret == false) { - IOLog("%s: selectTiming() failed\n", getName()); - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// Setup an ATATaskFile from the parameters given, and write the taskfile -// to the ATATaskfile structure pointer provided. -// -// taskfile - pointer to a taskfile structure. -// protocol - An ATA transfer protocol (ataProtocolPIO, ataProtocolDMA, etc) -// command - ATA command byte. -// block - Initial transfer block. -// nblks - Number of blocks to transfer. - -void -IOATAHDDrive::setupReadWriteTaskFile(ATATaskfile * taskfile, - ATAProtocol protocol, - UInt8 command, - UInt32 block, - UInt32 nblks) -{ - bzero( taskfile, sizeof(ATATaskfile) ); - - taskfile->protocol = protocol; - - // Mask of all taskfile registers that shall contain valid - // data and should be written to the hardware registers. - // - taskfile->regmask = ATARegtoMask(kATARegSectorNumber) | - ATARegtoMask(kATARegCylinderLow) | - ATARegtoMask(kATARegCylinderHigh) | - ATARegtoMask(kATARegDriveHead) | - ATARegtoMask(kATARegSectorCount) | - ATARegtoMask(kATARegFeatures) | - ATARegtoMask(kATARegCommand); - - taskfile->resultmask = 0; - - taskfile->ataRegs[kATARegSectorNumber] = block & 0x0ff; - taskfile->ataRegs[kATARegCylinderLow] = (block >> 8) & 0xff; - taskfile->ataRegs[kATARegCylinderHigh] = (block >> 16) & 0xff; - taskfile->ataRegs[kATARegDriveHead] = ((block >> 24) & 0x0f) | - kATAModeLBA | (_unit << 4); - - if ( protocol == kATAProtocolDMAQueued ) - { - taskfile->ataRegs[kATARegFeatures] = - (nblks == kIOATAMaxBlocksPerXfer) ? 0 : nblks; - taskfile->ataRegs[kATARegSectorCount] = 0; - } - else - { - taskfile->ataRegs[kATARegFeatures] = 0; - taskfile->ataRegs[kATARegSectorCount] = - (nblks == kIOATAMaxBlocksPerXfer) ? 0 : nblks; - } - - taskfile->ataRegs[kATARegCommand] = command; -} - -//--------------------------------------------------------------------------- -// Allocate and return an IOATACommand that is initialized to perform -// a read/write operation. -// -// buffer - IOMemoryDescriptor object describing this transfer. -// block - Initial transfer block. -// nblks - Number of blocks to transfer. - -IOATACommand * -IOATAHDDrive::ataCommandReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - ATATaskfile taskfile; - bool isWrite; - IOATACommand * cmd = allocateCommand(); - - assert(buffer); - - if (!cmd) return 0; // error, command allocation failed. - - isWrite = (buffer->getDirection() == kIODirectionOut) ? - true : false; - -#ifdef DEBUG_LOG - IOLog("%s::ataCommandReadWrite %08x (%d) %s %d %d\n", - getName(), - buffer, - buffer->getLength(), - isWrite ? "WR" : "RD", - block, - nblks); -#endif - -#if 0 // used for testing - force PIO mode - setupReadWriteTaskFile(&taskfile, - kATAProtocolPIO, - isWrite ? kIOATACommandWritePIO : - kIOATACommandReadPIO, - block, - nblks); -#else - - // Setup the taskfile structure with the size and direction of the - // transfer. This structure will be written to the actual taskfile - // registers when this command is processed. - // - setupReadWriteTaskFile(&taskfile, - _ataProtocol, - isWrite ? _ataWriteCmd : _ataReadCmd, - block, - nblks); -#endif - - // Get a pointer to the client data buffer, and record parameters - // which shall be later used by the completion routine. - // - ATA_CLIENT_DATA(cmd)->buffer = buffer; - - cmd->setTaskfile(&taskfile); - - cmd->setPointers(buffer, /* (IOMemoryDescriptor *) */ - buffer->getLength(), /* transferCount (bytes) */ - isWrite); /* isWrite */ - - return cmd; -} - -//--------------------------------------------------------------------------- -// Allocate and return a ATA SetFeatures command. - -IOATACommand * -IOATAHDDrive::ataCommandSetFeatures(UInt8 features, - UInt8 SectorCount, - UInt8 SectorNumber, - UInt8 CylinderLow, - UInt8 CyclinderHigh) -{ - ATATaskfile taskfile; - IOATACommand * cmd = allocateCommand(); - - if (!cmd) return 0; // error, command allocation failed. - - taskfile.protocol = kATAProtocolPIO; - - taskfile.regmask = ATARegtoMask(kATARegSectorNumber) | - ATARegtoMask(kATARegCylinderLow) | - ATARegtoMask(kATARegCylinderHigh) | - ATARegtoMask(kATARegDriveHead) | - ATARegtoMask(kATARegSectorCount) | - ATARegtoMask(kATARegCommand); - - taskfile.resultmask = ATARegtoMask(kATARegError) | - ATARegtoMask(kATARegStatus); - - taskfile.ataRegs[kATARegFeatures] = features; - taskfile.ataRegs[kATARegSectorNumber] = SectorNumber; - taskfile.ataRegs[kATARegCylinderLow] = CylinderLow; - taskfile.ataRegs[kATARegCylinderHigh] = CyclinderHigh; - taskfile.ataRegs[kATARegDriveHead] = kATAModeLBA | (_unit << 4); - taskfile.ataRegs[kATARegSectorCount] = SectorCount; - taskfile.ataRegs[kATARegCommand] = kIOATACommandSetFeatures; - - cmd->setTaskfile(&taskfile); - - // This is a way to issue a command which will wait - // for an interrupt, but does no data transfer. - - cmd->setPointers(0, 0, false); - - return cmd; -} - -//--------------------------------------------------------------------------- -// Return a Flush Cache command. - -IOATACommand * -IOATAHDDrive::ataCommandFlushCache() -{ - ATATaskfile taskfile; - IOATACommand * cmd = allocateCommand(); - - if (!cmd) return 0; // error, command allocation failed. - - // kATAProtocolSetRegs does not wait for an interrupt from the drive. - - taskfile.protocol = kATAProtocolPIO; - - taskfile.regmask = ATARegtoMask(kATARegDriveHead) | - ATARegtoMask(kATARegCommand); - - taskfile.resultmask = ATARegtoMask(kATARegError) | - ATARegtoMask(kATARegSectorNumber) | - ATARegtoMask(kATARegCylinderLow) | - ATARegtoMask(kATARegCylinderHigh) | - ATARegtoMask(kATARegDriveHead) | - ATARegtoMask(kATARegStatus); - - taskfile.ataRegs[kATARegDriveHead] = kATAModeLBA | (_unit << 4); - taskfile.ataRegs[kATARegCommand] = kIOATACommandFlushCache; - - cmd->setTaskfile(&taskfile); - - // This is a way to issue a command which will wait - // for an interrupt, but does no data transfer. - - cmd->setPointers(0, 0, false); - - return cmd; -} - -//--------------------------------------------------------------------------- -// Return a STANDBY IMMEDIATE command. - -IOATACommand * -IOATAHDDrive::ataCommandStandby() -{ - ATATaskfile taskfile; - IOATACommand * cmd = allocateCommand(); - - if (!cmd) return 0; // error, command allocation failed. - - // kATAProtocolSetRegs does not wait for an interrupt from the drive. - - taskfile.protocol = kATAProtocolPIO; - - taskfile.regmask = ATARegtoMask(kATARegDriveHead) | - ATARegtoMask(kATARegCommand); - - taskfile.resultmask = ATARegtoMask(kATARegError) | - ATARegtoMask(kATARegStatus); - - taskfile.ataRegs[kATARegDriveHead] = kATAModeLBA | (_unit << 4); - taskfile.ataRegs[kATARegCommand] = kIOATACommandStandbyImmediate; - - cmd->setTaskfile(&taskfile); - - // This is a way to issue a command which will wait - // for an interrupt, but does no data transfer. - - cmd->setPointers(0, 0, false); - - return cmd; -} - -//--------------------------------------------------------------------------- -// This routine is called by our provider when a command processing has -// completed. - -void -IOATAHDDrive::sHandleCommandCompletion(IOATAHDDrive * self, - IOATACommand * cmd) -{ - ATAResults results; - IOATADevice * device; - IOATAClientData * clientData; - - assert(cmd); - device = cmd->getDevice(kIOATADevice); - assert(device); - - clientData = ATA_CLIENT_DATA(cmd); - assert(clientData); - - if ((cmd->getResults(&results) != kIOReturnSuccess) && - (clientData->maxRetries-- > 0)) - { - cmd->execute(); - return; - } - -#if 0 - // Force command retry to test retry logic. - // Controller will reset the IOMemoryDescriptor's position, right? - // - cmd->getResults(&results); - if (clientData->maxRetries-- > 2) { - cmd->execute(); - return; - } -#endif - -#ifdef DEBUG_LOG - IOLog("%s: sHandleCommandCompletion %08x %08x %08x %08x %d\n", - getName(), device, cmd, refcon, results.returnCode, - results.bytesTransferred); -#endif - - // Return IOReturn for sync commands. - // - clientData->returnCode = results.returnCode; - - if (clientData->isSync) { - // For sync commands, unblock the client thread. - // - assert(clientData->completion.syncLock); - clientData->completion.syncLock->signal(); // unblock the client. - } - else { - // Signal the completion routine that the request has been completed. - // - - IOStorage::complete(clientData->completion.async, - results.returnCode, - (UInt64) results.bytesTransferred); - } - - // Release the IOMemoryDescriptor. - // - if (clientData->buffer) - clientData->buffer->release(); - - // Command processing is complete, release the command object. - // - cmd->release(); -} - -//--------------------------------------------------------------------------- -// Issue a synchronous ATA command. - -IOReturn -IOATAHDDrive::syncExecute(IOATACommand * cmd, /* command object */ - UInt32 timeout, /* timeout in ms */ - UInt retries, /* max retries */ - IOMemoryDescriptor * senseData) -{ - IOATAClientData * clientData = ATA_CLIENT_DATA(cmd); - - if ( _pmReady ) - { - activityTickle( kIOPMSuperclassPolicy1, 1 ); - } - - // Bump the retain count on the command. The completion handler - // will decrement the retain count. - // - cmd->retain(); - - // Set timeout and register the completion handler. - // - cmd->setPointers(senseData, - senseData ? senseData->getLength() : 0, - false, /* isWrite */ - true ); /* isSense */ - cmd->setTimeout(timeout); - cmd->setCallback(this, - (CallbackFn) &IOATAHDDrive::sHandleCommandCompletion, - (void *) cmd); - - // Increment the retain count on the IOMemoryDescriptor. - // Release when the completion routine gets called. - // - if (clientData->buffer) - clientData->buffer->retain(); - - // Set the max retry count. If retry count is 0, then the command shall - // not be retried if an error occurs. - // - clientData->maxRetries = retries; - clientData->completion.syncLock = IOSyncer::create(); - clientData->isSync = true; - - cmd->execute(); - - // Block client thread on lock until the completion handler - // receives an indication that the processing is complete. - // - clientData->completion.syncLock->wait(); - - return clientData->returnCode; -} - -//--------------------------------------------------------------------------- -// Issue an asynchronous ATA command. - -IOReturn -IOATAHDDrive::asyncExecute(IOATACommand * cmd, /* command object */ - IOStorageCompletion completion, - UInt32 timeout, /* timeout in ms */ - UInt retries) /* max retries */ -{ - IOATAClientData * clientData = ATA_CLIENT_DATA(cmd); - - if ( _pmReady ) - { - activityTickle( kIOPMSuperclassPolicy1, 1 ); - } - - // Bump the retain count on the command. The completion handler - // will decrement the retain count. - // - cmd->retain(); - - // Set timeout and register the completion handler. - // - cmd->setTimeout(timeout); - cmd->setCallback(this, - (CallbackFn) &IOATAHDDrive::sHandleCommandCompletion, - (void *) cmd); - - // Increment the retain count on the IOMemoryDescriptor. - // Release when the completion routine gets called. - // - if (clientData->buffer) - clientData->buffer->retain(); - - // Set the max retry count. If retry count is 0, then the command shall - // not be retried if an error occurs. - // - clientData->maxRetries = retries; - clientData->isSync = false; - - clientData->completion.async = completion; - - return (cmd->execute() ? kIOReturnSuccess : kIOReturnNoResources); -} - -//--------------------------------------------------------------------------- -// Allocate an IOATACommand object with a fixed client data area. - -IOATACommand * -IOATAHDDrive::allocateCommand() -{ - return _ataDevice->allocCommand(kIOATADevice, sizeof(IOATAClientData)); -} diff --git a/iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp b/iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp deleted file mode 100644 index af28e9a54..000000000 --- a/iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAHDDrive.cpp - Generic ATA disk driver. - * - * HISTORY - * Aug 27, 1999 jliu - Ported from AppleATADrive. - */ - -#include <IOKit/assert.h> -#include <IOKit/storage/ata/IOATAHDDrive.h> -#include <IOKit/storage/ata/IOATAHDDriveNub.h> - -#define super IOService -OSDefineMetaClassAndStructors( IOATAHDDrive, IOService ) - -//--------------------------------------------------------------------------- -// C to C++ glue. - -void -IOATAHDDrive::sHandleConfigureDevice(IOATAHDDrive * self) -{ - self->configureDevice(self->_ataDevice); -} - -//--------------------------------------------------------------------------- -// init() method. - -bool -IOATAHDDrive::init(OSDictionary * properties) -{ - return (super::init(properties)); -} - -//--------------------------------------------------------------------------- -// Override probe() method inherited from IOService. - -IOService * -IOATAHDDrive::probe(IOService * provider, SInt32 * score) -{ - if (!super::probe(provider, score)) - return 0; - - // Our provider must be a IOATADevice nub, most likely created - // by an IOATAController instance. - // - IOATADevice * device = OSDynamicCast(IOATADevice, provider); - if (device == 0) - return 0; // Provider is not an IOATADevice. - - // Do ATA device type matching. Does the nub match my device type? - // - if (device->getDeviceType() != reportATADeviceType()) - return 0; // error, type mismatch (probably ATAPI). - - // Cache the drive unit number (master/slave assignment). - // - _unit = device->getUnit(); - - return this; // probe successful. -} - -//--------------------------------------------------------------------------- -// Starts up the driver and spawn a nub. - -bool -IOATAHDDrive::start(IOService * provider) -{ - // First call start() in our superclass. - // - if (super::start(provider) == false) - return false; - - _configThreadCall = (void *) thread_call_allocate( - (thread_call_func_t) sHandleConfigureDevice, - (thread_call_param_t) this); - if (!_configThreadCall) - return false; - - // Cache our provider. - // - _ataDevice = OSDynamicCast(IOATADevice, provider); - if (_ataDevice == 0) - return false; - - // Open our provider. - // - _ataDevice->retain(); - if (_ataDevice->open(this) == false) - return false; - - // Inspect the provider. - // - if (inspectDevice(_ataDevice) == false) - return false; - - // Select ATA timing. - // - _logSelectedTimingProtocol = true; - - if (selectTimingProtocol() == false) - return false; - - // Create an IOCommandGate (for power management support) and attach - // this event source to the provider's workloop. - // - _cmdGate = IOCommandGate::commandGate(this); - if (_cmdGate == 0) - return false; - - IOWorkLoop * workloop = _ataDevice->getWorkLoop(); - if ((workloop == 0) || - (workloop->addEventSource(_cmdGate) != kIOReturnSuccess)) - return false; - - // Starts up in the active state. - // - _currentATAPowerState = kIOATAPowerStateActive; - - // A policy-maker must make these calls to join the PM tree, - // and to initialize its state. - // - PMinit(); /* initialize power management variables */ - provider->joinPMtree(this); /* join power management tree */ - setIdleTimerPeriod(300); /* 300 sec inactivity timer */ - - if (_supportedFeatures & kIOATAFeaturePowerManagement) - initForPM(); - - return (createNub(provider)); -} - -//--------------------------------------------------------------------------- -// Stop the driver. - -void -IOATAHDDrive::stop(IOService * provider) -{ - PMstop(); - - super::stop(provider); -} - -//--------------------------------------------------------------------------- -// Release allocated resources. - -void -IOATAHDDrive::free() -{ - if (_configThreadCall) { - thread_call_cancel((thread_call_t) _configThreadCall); - thread_call_free((thread_call_t) _configThreadCall); - } - - if (_cmdGate) { - if (_ataDevice && (_ataDevice->getWorkLoop())) - _ataDevice->getWorkLoop()->removeEventSource(_cmdGate); - _cmdGate->release(); - } - - if (_ataDevice) - _ataDevice->release(); - - super::free(); -} - -//--------------------------------------------------------------------------- -// Fetch information about the ATA device nub. - -bool -IOATAHDDrive::inspectDevice(IOATADevice * ataDevice) -{ - OSString * string; - ATAIdentify * identify; - - // Fetch ATA device information from the nub. - // - string = OSDynamicCast(OSString, - ataDevice->getProperty(kATAPropertyModelNumber)); - if (string) { - strncpy(_model, string->getCStringNoCopy(), 40); - _model[40] = '\0'; - } - - string = OSDynamicCast(OSString, - ataDevice->getProperty(kATAPropertyFirmwareRev)); - if (string) { - strncpy(_revision, string->getCStringNoCopy(), 8); - _revision[8] = '\0'; - } - - // Fetch Word 82 (commandSetsSupported1) in Identify data. - // - identify = (ATAIdentify *) IOMalloc(sizeof(*identify)); - if (!identify) - return false; - - ataDevice->getIdentifyData(identify); - - if (identify->commandSetsSupported1 & 0x8) - _supportedFeatures |= kIOATAFeaturePowerManagement; - - if (identify->commandSetsSupported1 & 0x20) - _supportedFeatures |= kIOATAFeatureWriteCache; - - IOFree(identify, sizeof(*identify)); - - // Add an OSNumber property indicating the supported features. - // - setProperty(kIOATASupportedFeaturesKey, - _supportedFeatures, - sizeof(_supportedFeatures) * 8); - - return true; -} - -//--------------------------------------------------------------------------- -// Report the type of ATA device (ATA vs. ATAPI). - -ATADeviceType -IOATAHDDrive::reportATADeviceType() const -{ - return kATADeviceATA; -} - -//--------------------------------------------------------------------------- -// Returns the device type. - -const char * -IOATAHDDrive::getDeviceTypeName() -{ - return kIOBlockStorageDeviceTypeGeneric; -} - -//--------------------------------------------------------------------------- -// Instantiate an ATA specific subclass of IOBlockStorageDevice. - -IOService * IOATAHDDrive::instantiateNub() -{ - IOService * nub = new IOATAHDDriveNub; - return nub; -} - -//--------------------------------------------------------------------------- -// Returns an IOATAHDDriveNub. - -bool IOATAHDDrive::createNub(IOService * provider) -{ - IOService * nub; - - // Instantiate a generic hard disk nub so a generic driver - // can match above us. - // - nub = instantiateNub(); - - if (nub == 0) { - IOLog("%s: instantiateNub() failed\n", getName()); - return false; - } - - nub->init(); - - if (!nub->attach(this)) - IOPanic("IOATAHDDrive::createNub() unable to attach nub"); - - nub->registerService(); - - return true; -} - -//--------------------------------------------------------------------------- -// Handles read/write requests. - -IOReturn IOATAHDDrive::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - IOReturn ret; - IOATACommand * cmd = ataCommandReadWrite(buffer, block, nblks); - - if (cmd == 0) - return kIOReturnNoMemory; - - ret = asyncExecute(cmd, completion); - - cmd->release(); - - return ret; -} - -IOReturn IOATAHDDrive::doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - IOReturn ret; - IOATACommand * cmd = ataCommandReadWrite(buffer, block, nblks); - - if (cmd == 0) - return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Eject the media in the drive. - -IOReturn IOATAHDDrive::doEjectMedia() -{ - return kIOReturnUnsupported; // No support for removable ATA devices. -} - -//--------------------------------------------------------------------------- -// Format the media in the drive. -// ATA devices does not support low level formatting. - -IOReturn IOATAHDDrive::doFormatMedia(UInt64 byteCapacity) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Returns disk capacity. - -UInt32 IOATAHDDrive::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - UInt32 blockCount = 0; - UInt32 blockSize = 0; - - assert(_ataDevice); - - if (_ataDevice->getDeviceCapacity(&blockCount, &blockSize) && - (capacities != NULL) && (capacitiesMaxCount > 0)) - { - UInt64 count = blockCount; - UInt64 size = blockSize; - - *capacities = size * (count + 1); - - return 1; - } - - return 0; -} - -//--------------------------------------------------------------------------- -// Lock the media and prevent a user-initiated eject. - -IOReturn IOATAHDDrive::doLockUnlockMedia(bool doLock) -{ - return kIOReturnUnsupported; // No removable ATA device support. -} - -//--------------------------------------------------------------------------- -// Flush the write-cache to the physical media. - -IOReturn IOATAHDDrive::doSynchronizeCache() -{ - IOReturn ret; - IOATACommand * cmd = ataCommandFlushCache(); - - if (cmd == 0) - return kIOReturnNoMemory; - - ret = syncExecute(cmd, 60000); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Handle a Start Unit command. - -IOReturn -IOATAHDDrive::doStart() -{ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Handle a Stop Unit command. - -IOReturn -IOATAHDDrive::doStop() -{ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Return device identification strings. - -char * IOATAHDDrive::getAdditionalDeviceInfoString() -{ - return ("[ATA]"); -} - -char * IOATAHDDrive::getProductString() -{ - return _model; -} - -char * IOATAHDDrive::getRevisionString() -{ - return _revision; -} - -char * IOATAHDDrive::getVendorString() -{ - return NULL; -} - -//--------------------------------------------------------------------------- -// Report the device block size in bytes. We ask the device nub for the -// block size. We expect this to be 512-bytes. - -IOReturn IOATAHDDrive::reportBlockSize(UInt64 * blockSize) -{ - UInt32 blkCount = 0; - UInt32 blkSize = 0; - - assert(_ataDevice); - - if (!_ataDevice->getDeviceCapacity(&blkCount, &blkSize)) - return kIOReturnNoDevice; - - *blockSize = blkSize; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report the media in the ATA device as non-ejectable. - -IOReturn IOATAHDDrive::reportEjectability(bool * isEjectable) -{ - *isEjectable = false; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Fixed media, locking is invalid. - -IOReturn IOATAHDDrive::reportLockability(bool * isLockable) -{ - *isLockable = false; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report the polling requirements for a removable media. - -IOReturn IOATAHDDrive::reportPollRequirements(bool * pollRequired, - bool * pollIsExpensive) -{ - *pollIsExpensive = false; - *pollRequired = false; - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report the max number of bytes transferred for an ATA read command. - -IOReturn IOATAHDDrive::reportMaxReadTransfer(UInt64 blocksize, UInt64 * max) -{ - *max = blocksize * kIOATAMaxBlocksPerXfer; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report the max number of bytes transferred for an ATA write command. - -IOReturn IOATAHDDrive::reportMaxWriteTransfer(UInt64 blocksize, UInt64 * max) -{ - // Same as read transfer limits. - // - return reportMaxReadTransfer(blocksize, max); -} - -//--------------------------------------------------------------------------- -// Returns the maximum addressable sector number. - -IOReturn IOATAHDDrive::reportMaxValidBlock(UInt64 * maxBlock) -{ - UInt32 blockCount = 0; - UInt32 blockSize = 0; - - assert(_ataDevice && maxBlock); - - if (!_ataDevice->getDeviceCapacity(&blockCount, &blockSize)) - return kIOReturnNoDevice; - - *maxBlock = blockCount; - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report whether the media is currently present, and whether a media -// change has been registered since the last reporting. - -IOReturn IOATAHDDrive::reportMediaState(bool * mediaPresent, bool * changed) -{ - *mediaPresent = true; - *changed = true; - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report whether the media is removable. - -IOReturn IOATAHDDrive::reportRemovability(bool * isRemovable) -{ - *isRemovable = false; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report if the media is write-protected. - -IOReturn IOATAHDDrive::reportWriteProtection(bool * isWriteProtected) -{ - *isWriteProtected = false; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Handles messages from our provider. - -IOReturn -IOATAHDDrive::message(UInt32 type, IOService * provider, void * argument) -{ - IOReturn ret = kIOReturnSuccess; - -// IOLog("IOATAHDDrive::message %p %lx\n", this, type); - - switch (type) - { - case kATAClientMsgBusReset: - _ataDevice->holdQueue(kATAQTypeNormalQ); - break; - - case kATAClientMsgBusReset | kATAClientMsgDone: - configureDevice( _ataDevice ); - break; - - case kATAClientMsgSelectTiming | kATAClientMsgDone: - _ataDevice->releaseQueue(kATAQTypeNormalQ); - break; - - default: - ret = super::message(type, provider, argument); - break; - } - - return ret; -} diff --git a/iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp b/iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp deleted file mode 100644 index a917fec7a..000000000 --- a/iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAHDDriveNub.cpp - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * Aug 27, 1999 jliu - Created. - */ - -#include <IOKit/IOLib.h> -#include <IOKit/storage/ata/IOATAHDDriveNub.h> -#include <IOKit/storage/ata/IOATAHDDrive.h> - -#define super IOBlockStorageDevice -OSDefineMetaClassAndStructors( IOATAHDDriveNub, IOBlockStorageDevice ) - -//--------------------------------------------------------------------------- -// attach to provider. - -bool IOATAHDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) - return false; - - _provider = OSDynamicCast(IOATAHDDrive, provider); - if (_provider == 0) { - IOLog("IOATAHDDriveNub: attach; wrong provider type!\n"); - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// detach from provider. - -void IOATAHDDriveNub::detach(IOService * provider) -{ - if (_provider == provider) - _provider = 0; - - super::detach(provider); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - return _provider->doAsyncReadWrite(buffer, block, nblks, completion); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doSyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks) -{ - return _provider->doSyncReadWrite(buffer, block, nblks); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doEjectMedia() -{ - return _provider->doEjectMedia(); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return _provider->doFormatMedia(byteCapacity); -} - -//--------------------------------------------------------------------------- -// - -UInt32 -IOATAHDDriveNub::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return _provider->doGetFormatCapacities(capacities, capacitiesMaxCount); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doLockUnlockMedia(bool doLock) -{ - return _provider->doLockUnlockMedia(doLock); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::doSynchronizeCache() -{ - return _provider->doSynchronizeCache(); -} - -//--------------------------------------------------------------------------- -// - -char * IOATAHDDriveNub::getVendorString() -{ - return _provider->getVendorString(); -} - -//--------------------------------------------------------------------------- -// - -char * IOATAHDDriveNub::getProductString() -{ - return _provider->getProductString(); -} - -//--------------------------------------------------------------------------- -// - -char * IOATAHDDriveNub::getRevisionString() -{ - return _provider->getRevisionString(); -} - -//--------------------------------------------------------------------------- -// - -char * IOATAHDDriveNub::getAdditionalDeviceInfoString() -{ - return _provider->getAdditionalDeviceInfoString(); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportBlockSize(UInt64 * blockSize) -{ - return _provider->reportBlockSize(blockSize); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportEjectability(bool * isEjectable) -{ - return _provider->reportEjectability(isEjectable); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportLockability(bool * isLockable) -{ - return _provider->reportLockability(isLockable); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive) -{ - return _provider->reportPollRequirements(pollIsRequired, pollIsExpensive); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportMaxReadTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxReadTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportMaxValidBlock(UInt64 * maxBlock) -{ - return _provider->reportMaxValidBlock(maxBlock); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportMaxWriteTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxWriteTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportMediaState(bool * mediaPresent, - bool * changed) -{ - return _provider->reportMediaState(mediaPresent, changed); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportRemovability(bool * isRemovable) -{ - return _provider->reportRemovability(isRemovable); -} - -//--------------------------------------------------------------------------- -// - -IOReturn IOATAHDDriveNub::reportWriteProtection(bool * isWriteProtected) -{ - return _provider->reportWriteProtection(isWriteProtected); -} diff --git a/iokit/Families/IOATAHDDrive/IOATAHDPower.cpp b/iokit/Families/IOATAHDDrive/IOATAHDPower.cpp deleted file mode 100644 index bbbbbafcc..000000000 --- a/iokit/Families/IOATAHDDrive/IOATAHDPower.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOATAHDPower.cpp - Power management support. - * - * HISTORY - * - */ - -#include <IOKit/storage/ata/IOATAHDDrive.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#define super IOService - -//--------------------------------------------------------------------------- -// Inform the policy-maker that an ATA hard-drive is capable of two power -// states (a simplification). The ourPowerStates[] array encodes information -// about each state. - -#define kIOATAPowerStates 2 - -static IOPMPowerState ourPowerStates[kIOATAPowerStates] = -{ - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0,0,0,0,0,0,0,0} -}; - -static const char * ataPowerStateNames[] = -{ - "Sleep", - "Standby", - "Idle", - "Active" -}; - -//--------------------------------------------------------------------------- -// Maps the power state ordinal, used by our policy maker, -// to an ATA power states. - -IOATAPowerState -IOATAHDDrive::getATAPowerStateForStateOrdinal(UInt32 stateOrdinal) -{ - IOATAPowerState stateOrdinalToATAPowerState[kIOATAPowerStates] = - { - kIOATAPowerStateStandby, /* state 0 */ - kIOATAPowerStateActive, /* state 1 */ - }; - - if (stateOrdinal > (kIOATAPowerStates - 1)) - stateOrdinal = (kIOATAPowerStates - 1); - - return stateOrdinalToATAPowerState[stateOrdinal]; -} - -//--------------------------------------------------------------------------- -// Register the driver with our policy-maker (also in the same class). - -void -IOATAHDDrive::initForPM() -{ - registerPowerDriver(this, ourPowerStates, kIOATAPowerStates); - _pmReady = true; -} - -//--------------------------------------------------------------------------- -// Policy-maker code which intercepts kPMMinutesToSpinDown settings -// and then call setIdleTimerPeriod() to adjust the idle timer. - -IOReturn -IOATAHDDrive::setAggressiveness(UInt32 type, UInt32 minutes) -{ - if (type == kPMMinutesToSpinDown) - { - // IOLog("IOATAHDDrive: setting idle timer to %ld min\n", minutes); - setIdleTimerPeriod(minutes * 60); // argument is in seconds - } - return super::setAggressiveness(type, minutes); -} - -//--------------------------------------------------------------------------- -// Policy-maker calls this function to find find out what power state -// the device is in, given the current power domain state. -// -// We respond to this message in the following fashion: -// If domain power is off, drive must be off. -// If domain power is on, return _currentATAPowerState. - -UInt32 -IOATAHDDrive::initialPowerStateForDomainState(IOPMPowerFlags domainState) -{ - UInt32 ret; - - _cmdGate->runAction((IOCommandGate::Action) - &IOATAHDDrive::sHandleInitialPowerStateForDomainState, - (void *) domainState, - (void *) &ret); - - return ret; -} - -//--------------------------------------------------------------------------- -// Static member function called by the IOCommandGate to translate -// initialPowerStateForDomainState() calls to the synchronized -// handleInitialPowerStateForDomainState() call. - -void -IOATAHDDrive::sHandleInitialPowerStateForDomainState(IOATAHDDrive * self, - IOPMPowerFlags domainState, - UInt32 * state) -{ - *state = self->handleInitialPowerStateForDomainState(domainState); -} - -//--------------------------------------------------------------------------- -// The synchronized form of initialPowerStateForDomainState(). - -UInt32 -IOATAHDDrive::handleInitialPowerStateForDomainState(IOPMPowerFlags domainState) -{ - if (domainState & IOPMPowerOn) - return ((_currentATAPowerState == kIOATAPowerStateActive) ? 1 : 0); - else - return 0; -} - -//--------------------------------------------------------------------------- -// Set/Change the power state of the ATA hard-drive. - -IOReturn -IOATAHDDrive::setPowerState(UInt32 powerStateOrdinal, - IOService * whatDevice) -{ - IOReturn ret; - - // Power state transitions are synchronized by our IOCommandGate object, - // (attached to the ATA controller's workloop). - - _cmdGate->runAction((IOCommandGate::Action) - &IOATAHDDrive::sHandleSetPowerState, - (void *) powerStateOrdinal, - (void *) whatDevice, - (void *) &ret); - - kprintf("%s::%s(0x%08lx, 0x%08lx) returns 0x%08lx\n",getName(), __FUNCTION__,powerStateOrdinal, whatDevice, ret); - return ret; -} - -//--------------------------------------------------------------------------- -// Static member function called by the IOCommandGate to translate -// setPowerState() calls to the synchronized handleSetPowerState() call. - -void -IOATAHDDrive::sHandleSetPowerState(IOATAHDDrive * self, - UInt32 powerStateOrdinal, - IOService * whatDevice, - IOReturn * handlerReturn) -{ - *handlerReturn = self->handleSetPowerState(powerStateOrdinal, whatDevice); -} - -//--------------------------------------------------------------------------- -// A static member function that calls handleStandbyStateTransition(). -// This function can be registered as the completion handler for an -// IOATACommand. - -void -IOATAHDDrive::sHandleStandbyStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred) -{ - self->handleStandbyStateTransition((UInt32) stage, status); -} - -//--------------------------------------------------------------------------- -// A static member function that calls handleActiveStateTransition(). -// This function can be registered as the completion handler for an -// IOATACommand. - -void -IOATAHDDrive::sHandleActiveStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred) -{ - self->handleActiveStateTransition((UInt32) stage, status); -} - -//--------------------------------------------------------------------------- -// A static member function that calls handleIdleStateTransition(). -// This function can be registered as the completion handler for an -// IOATACommand. - -void -IOATAHDDrive::sHandleIdleStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred) -{ - self->handleIdleStateTransition((UInt32) stage, status); -} - -//--------------------------------------------------------------------------- -// A static member function that calls handleSleepStateTransition(). -// This function can be registered as the completion handler for an -// IOATACommand. - -void -IOATAHDDrive::sHandleSleepStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred) -{ - self->handleSleepStateTransition((UInt32) stage, status); -} - -//--------------------------------------------------------------------------- -// IOATAHDDrive provide a default implementation for handleSetPowerState(). -// This (IOCommandGate synchronized) function is called by our policy-maker. - -IOReturn -IOATAHDDrive::handleSetPowerState(UInt32 powerStateOrdinal, - IOService * whatDevice) -{ - IOATAPowerState ataPowerState = - getATAPowerStateForStateOrdinal(powerStateOrdinal); - -#if 1 - kprintf("%s::%s %d (%d) %lx\n", getName(), __FUNCTION__, ataPowerState, - _currentATAPowerState, (UInt32) whatDevice); -#endif - - // We cannot change power state while we are still transitioning - // the power state from a previous state change request. - - if (_powerStateChanging) { - kprintf("%s::%s overlap detected\n",getName(), __FUNCTION__); - IOLog("%s::%s overlap detected\n",getName(), __FUNCTION__); - return IOPMAckImplied; // FIXME - should return something else - } - - // If we are already in the desired power state, return success. - - if (ataPowerState == _currentATAPowerState) { - kprintf("%s::%s already in the given sate\n",getName(), __FUNCTION__); - return IOPMAckImplied; - } - - _powerStateChanging = true; - _setPowerAckPending = true; - - startATAPowerStateTransition(ataPowerState); - - // Return the number of microseconds it may take for the drive to - // complete the power state transition. Report 100 seconds max. - - return (100 * 1000 * 1000); -} - -//--------------------------------------------------------------------------- -// Start transitioning into the specified ATA power state. - -void -IOATAHDDrive::startATAPowerStateTransition(IOATAPowerState ataPowerState) -{ - _proposedATAPowerState = ataPowerState; - - switch (ataPowerState) - { - case kIOATAPowerStateStandby: - - // Register sHandleStandbyStateTransition to be called when the - // IOATADevice becomes idle. Or, if the device is already idle, - // the function will be called immediately. - - _ataDevice->notifyIdle(this, - (CallbackFn) &IOATAHDDrive::sHandleStandbyStateTransition, - (void *) kIOATAStandbyStage0); - break; - - case kIOATAPowerStateActive: - - // Call sHandleActiveStateTransition and begin processing - // at stage 0. - - sHandleActiveStateTransition(this, - (void *) kIOATAActiveStage0, - kIOReturnSuccess, - 0); - break; - - default: - IOPanic("IOATAHDDrive::startATAPowerStateTransition\n"); - } -} - -//--------------------------------------------------------------------------- -// Abort the current state transition and retore the current state. - -void -IOATAHDDrive::abortATAPowerStateTransition() -{ - // Do not ack the setPowerState request if the power state - // transition is aborted. - - _setPowerAckPending = false; - - // Transition to the previous state. However, if we are unable - // to transition to the previous state, then give up. - - if (_proposedATAPowerState != _currentATAPowerState) - { - startATAPowerStateTransition(_currentATAPowerState); - } - else - { - IOLog("%s::%s Unable to revert to previous state\n", - getName(), __FUNCTION__); - - endATAPowerStateTransition(_currentATAPowerState); - } -} - -//--------------------------------------------------------------------------- -// Complete the ATA power state transition. - -void -IOATAHDDrive::endATAPowerStateTransition(IOATAPowerState ataPowerState) -{ - _currentATAPowerState = ataPowerState; - - // In the future, a NACK response may be sent to indicate state change - // failure. - - if (_setPowerAckPending) { - thread_call_func(acknowledgeATAPowerStateTransition, this, 1); - //acknowledgeATAPowerStateTransition(this, NULL); - } - - //kprintf("%s::%s %s \n", getName(), __FUNCTION__, ataPowerStateNames[_currentATAPowerState]); -} - -//--------------------------------------------------------------------------- -// To avoid deadlocks between the PM and the IOATAHDDrive workloop the -// actual acknolegment wuns on a different thread. - -/* static */ void -IOATAHDDrive::acknowledgeATAPowerStateTransition(void *castMeToIOATAHDDrive, void*) -{ - IOATAHDDrive *myThis = OSDynamicCast(IOATAHDDrive, (OSObject*)castMeToIOATAHDDrive); - - if (myThis !=NULL) { - myThis->_powerStateChanging = false; - myThis->acknowledgeSetPowerState(); - } -} - -//--------------------------------------------------------------------------- -// A function called by startATAPowerStateTransition() to transition the -// drive into the STANDBY state. It may also be called by the IOATACommand -// completion handler to advance to the next stage of the state transition. -// -// stage: The current stage in the state transition. -// status: The status from the previous stage. - -void -IOATAHDDrive::handleStandbyStateTransition(UInt32 stage, IOReturn status) -{ - bool doAbort = false; - IOATACommand * cmd = 0; - IOStorageCompletion completion; - -// IOLog("IOATAHDDrive::handleStandbyStateTransition %ld %x\n", stage, status); - - switch (stage) - { - case kIOATAStandbyStage0: - // Device is idle. Hold the normal queue. - _ataDevice->holdQueue(kATAQTypeNormalQ); - status = kIOReturnSuccess; - - case kIOATAStandbyStage1: - - if ( reportATADeviceType() == kATADeviceATA ) - { - // Issue a flush cache command. - - if ((cmd = ataCommandFlushCache()) == 0) - { - doAbort = true; break; - } - cmd->setQueueInfo(kATAQTypeBypassQ); - - // Must issue an async command here, otherwise the thread will - // deadlock. - - completion.target = this; - completion.action = sHandleStandbyStateTransition; - completion.parameter = (void *) kIOATAStandbyStage2; - - asyncExecute(cmd, - completion, - 60000, /* 1 min timeout */ - 0); /* no retry for flush cache command */ - break; - } - - case kIOATAStandbyStage2: - - if ( reportATADeviceType() == kATADeviceATA ) - { - // Issue an ATA STANDBY IMMEDIATE command. We ignore the - // status from the flush cache command since not all drives - // implement this. - - if ((cmd = ataCommandStandby()) == 0) - { - doAbort = true; break; - } - cmd->setQueueInfo(kATAQTypeBypassQ); - - // Must issue an async command here, otherwise the thread will - // deadlock. - - completion.target = this; - completion.action = sHandleStandbyStateTransition; - completion.parameter = (void *) kIOATAStandbyStage3; - - asyncExecute(cmd, - completion, - 30000, /* 30 sec timeout */ - 0); /* no retry for STANDBY command */ - break; - } - - case kIOATAStandbyStage3: - // Final stage in the STANDBY state transition. - - if (status != kIOReturnSuccess) { - // STANDBY command failed, abort the state transition. - doAbort = true; break; - } - else { - endATAPowerStateTransition(kIOATAPowerStateStandby); - } - - break; - - default: - IOLog("%s::%s unknown stage %ld\n", getName(), __FUNCTION__, stage); - } - - if (cmd) cmd->release(); - - if (doAbort) - abortATAPowerStateTransition(); -} - -//--------------------------------------------------------------------------- -// Called by startATAPowerStateTransition() to transition the drive into -// the ACTIVE state. It may also be called by the IOATACommand completion -// handler to advance to the next stage of the state transition. -// -// stage: The current stage in the state transition. -// status: The status from the previous stage. - -void -IOATAHDDrive::handleActiveStateTransition(UInt32 stage, IOReturn status) -{ - IOStorageCompletion completion; - -#if 0 - IOLog("IOATAHDDrive::handleActiveStateTransition %p %ld %x\n", - this, stage, status); -#endif - - switch (stage) - { - case kIOATAActiveStage0: - kprintf("kIOATAActiveStage0 current power state is sleep %d\n", _currentATAPowerState == kIOATAPowerStateSleep); - -#if 0 // This des not work. - // Issue a software reset. Only necessary if the current - // state is kATAPowerStateSleep. - - // if (_currentATAPowerState == kIOATAPowerStateSleep) // Marco: Commenting because it looks that the power state is wrong - { - kprintf("Attempting to reset on kIOATAActiveStage0\n"); - _ataDevice->reset(); - } -#endif - - case kIOATAActiveStage1: - kprintf("kIOATAActiveStage1\n"); - - if ( reportATADeviceType() == kATADeviceATA ) - { - // Spin up the drive before releasing the queue. A media - // access command is issued with an extra long timeout. - - completion.target = this; - completion.action = sHandleActiveStateTransition, - completion.parameter = (void *) kIOATAActiveStage2; - - readSector(completion); - break; - } - - case kIOATAActiveStage2: - kprintf("kIOATAActiveStage2\n"); - // Release the normal queue. - _ataDevice->releaseQueue(kATAQTypeNormalQ); - - case kIOATAActiveStage3: - kprintf("kIOATAActiveStage3\n"); - // Finalize ACTIVE state transition. - endATAPowerStateTransition(kIOATAPowerStateActive); - break; - - default: - IOLog("%s::%s unknown stage %ld\n", getName(), __FUNCTION__, stage); - } -} - -//--------------------------------------------------------------------------- -// Unimplemented state transition handlers. - -void -IOATAHDDrive::handleIdleStateTransition(UInt32 stage, IOReturn status) -{ - IOLog("%s::%s unimplemented!\n", getName(), __FUNCTION__); -} - -void -IOATAHDDrive::handleSleepStateTransition(UInt32 stage, IOReturn status) -{ - IOLog("%s::%s unimplemented!\n", getName(), __FUNCTION__); -} - -//--------------------------------------------------------------------------- -// Read a single sector from the disk. The data read is discarded. - -IOReturn IOATAHDDrive::readSector(IOStorageCompletion completion, - UInt32 sector = 0) -{ - IOBufferMemoryDescriptor * desc; - IOATACommand * cmd; - IOReturn ret; - - desc = IOBufferMemoryDescriptor::withCapacity(kIOATASectorSize, - kIODirectionIn); - if (!desc) - return kIOReturnNoMemory; - - desc->setLength(desc->getCapacity()); - - cmd = ataCommandReadWrite(desc, sector, 1); - if (!cmd) - return kIOReturnNoMemory; - - cmd->setQueueInfo(kATAQTypeBypassQ); - - ret = asyncExecute(cmd, completion, 60000); - - // Don't worry, asyncExecute has retained both the command - // and the memory descriptor object. - - desc->release(); - cmd->release(); - - return kIOReturnSuccess; -} diff --git a/iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp b/iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp deleted file mode 100644 index a6e6c7cbd..000000000 --- a/iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/storage/ata/IOATAPICDDrive.h> - -//--------------------------------------------------------------------------- -// ATAPI Read TOC command (43). - -IOATACommand * -IOATAPICDDrive::atapiCommandReadTOC(IOMemoryDescriptor * buffer, - bool msf, - UInt8 format, - UInt8 startTrackSession) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandReadTOC; - atapiCmd.cdb[1] = msf ? 0x02 : 0x00; - atapiCmd.cdb[6] = startTrackSession; - atapiCmd.cdb[7] = (UInt8)(buffer->getLength() >> 8); - atapiCmd.cdb[8] = (UInt8)(buffer->getLength()); - - if ((format & 0x04)) - atapiCmd.cdb[2] = (format & 0x07); // new format field - else - atapiCmd.cdb[9] = (format & 0x03) << 6; // old format field - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// atapiCommandPlayAudioMSF - -IOATACommand * -IOATAPICDDrive::atapiCommandPlayAudioMSF(CDMSF timeStart, CDMSF timeStop) -{ - ATACDBInfo atapiCmd; - - bzero(&atapiCmd, sizeof(atapiCmd)); - atapiCmd.cdbLength = 12; - - atapiCmd.cdb[0] = kIOATAPICommandPlayAudioMSF; - - // starting MSF address - atapiCmd.cdb[3] = timeStart.minute; - atapiCmd.cdb[4] = timeStart.second; - atapiCmd.cdb[5] = timeStart.frame; - - // ending MSF address - atapiCmd.cdb[6] = timeStop.minute; - atapiCmd.cdb[7] = timeStop.second; - atapiCmd.cdb[8] = timeStop.frame; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// atapiCommandPauseResume - -IOATACommand * -IOATAPICDDrive::atapiCommandPauseResume(bool resume) -{ - ATACDBInfo atapiCmd; - - bzero(&atapiCmd, sizeof(atapiCmd)); - atapiCmd.cdbLength = 12; - - atapiCmd.cdb[0] = kIOATAPICommandPauseResume; - - // set resume bit - if (resume) atapiCmd.cdb[8] = 0x01; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// atapiCommandStopPlay - -IOATACommand * -IOATAPICDDrive::atapiCommandStopPlay() -{ - ATACDBInfo atapiCmd; - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandStopPlay; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// atapiCommandReadSubChannel - -IOATACommand * -IOATAPICDDrive::atapiCommandReadSubChannel(IOMemoryDescriptor * buffer, - UInt8 dataFormat, - UInt8 trackNumber) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandReadSubChannel; - atapiCmd.cdb[1] = 0x02; - atapiCmd.cdb[2] = 0x40; - atapiCmd.cdb[3] = dataFormat; - atapiCmd.cdb[6] = trackNumber; - atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; - atapiCmd.cdb[8] = buffer->getLength() & 0xff; - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// atapiCommandScan - -IOATACommand * -IOATAPICDDrive::atapiCommandScan(CDMSF timeStart, bool reverse) -{ - ATACDBInfo atapiCmd; - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandScan; - atapiCmd.cdb[1] = reverse ? 0x10 : 0x00; - atapiCmd.cdb[3] = timeStart.minute; - atapiCmd.cdb[4] = timeStart.second; - atapiCmd.cdb[5] = timeStart.frame; - atapiCmd.cdb[9] = 0x40; // MSF - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// Allocates and return an IOATACommand to perform a read/write operation. - -IOATACommand * -IOATAPICDDrive::atapiCommandReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[ 0] = kIOATAPICommandReadCD; - atapiCmd.cdb[ 1] = (sectorType & 0x7) << 2; - atapiCmd.cdb[ 2] = (block >> 24) & 0xFF; - atapiCmd.cdb[ 3] = (block >> 16) & 0xFF; - atapiCmd.cdb[ 4] = (block >> 8) & 0xFF; - atapiCmd.cdb[ 5] = (block ) & 0xFF; - atapiCmd.cdb[ 6] = (nblks >> 16) & 0xFF; - atapiCmd.cdb[ 7] = (nblks >> 8) & 0xFF; - atapiCmd.cdb[ 8] = (nblks ) & 0xFF; - atapiCmd.cdb[ 9] = (sectorArea & ~kCDSectorAreaSubChannel); - atapiCmd.cdb[10] = (sectorArea & kCDSectorAreaSubChannel); - - return atapiCommand(&atapiCmd, buffer); -} diff --git a/iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp b/iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp deleted file mode 100644 index a937999ee..000000000 --- a/iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPICDDrive.h - Generic ATAPI CD-ROM driver. - * - * HISTORY - * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. - */ - -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/storage/ata/IOATAPICDDrive.h> -#include <IOKit/storage/ata/IOATAPICDDriveNub.h> - -#define super IOATAPIHDDrive -OSDefineMetaClassAndStructors( IOATAPICDDrive, IOATAPIHDDrive ) - -//--------------------------------------------------------------------------- -// Looks for an ATAPI device which is a CD-ROM device. - -bool -IOATAPICDDrive::matchATAPIDeviceType(UInt8 type, SInt32 * score) -{ - if (type == kIOATAPIDeviceTypeCDROM) - return true; - - return false; -} - -//--------------------------------------------------------------------------- -// Instantiate an ATAPI specific subclass of IOCDBlockStorageDevice. - -IOService * -IOATAPICDDrive::instantiateNub() -{ - IOService * nub = new IOATAPICDDriveNub; - return nub; -} - -//--------------------------------------------------------------------------- -// Report whether media is write-protected. - -IOReturn -IOATAPICDDrive::reportWriteProtection(bool * isWriteProtected) -{ - *isWriteProtected = true; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Returns the device type. - -const char * -IOATAPICDDrive::getDeviceTypeName() -{ - return kIOBlockStorageDeviceTypeCDROM; -} - -//--------------------------------------------------------------------------- -// Read the Table of Contents. -// -// The LG DVD-ROM DRN8080B LAB8 drive returns a TOC Data Length field which -// describes the number of bytes *returned* in the transfer, not the number -// bytes available to be transferred like it should. There is a workaround -// that addresses this problem here, however the workaround should be moved -// into a separate drive-specific subclass in the future. - -#define LG_DVD_ROM_DRN8080B_SUPPORT - -IOReturn -IOATAPICDDrive::readTOC(IOMemoryDescriptor * buffer) -{ - IOReturn ret; - IOATACommand * cmd; - - assert(buffer); - -#ifdef LG_DVD_ROM_DRN8080B_SUPPORT - IOMemoryDescriptor * bufferOrig = buffer; - bool isLG_DVD_ROM_DRN8080B = - ( getVendorString() && - getProductString() && - !strcmp(getVendorString(), "LG") && - !strcmp(getProductString(), "DVD-ROM DRN8080B") ); - - if (isLG_DVD_ROM_DRN8080B) { - buffer = IOBufferMemoryDescriptor::withCapacity( - max(4096, (bufferOrig->getLength()+1) & (~1)), - kIODirectionIn); - if (!buffer) - return kIOReturnNoMemory; - } -#endif LG_DVD_ROM_DRN8080B_SUPPORT - - cmd = atapiCommandReadTOC(buffer, true, 2, 0); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the Read TOC command. - // - ret = syncExecute(cmd); - -#ifdef LG_DVD_ROM_DRN8080B_SUPPORT - if (isLG_DVD_ROM_DRN8080B) { - void * toc; - UInt16 tocSize; - ATAResults results; - - cmd->getResults(&results); - toc = ((IOBufferMemoryDescriptor *)buffer)->getBytesNoCopy(); - tocSize = min(results.bytesTransferred, bufferOrig->getLength()); - - if (bufferOrig->writeBytes(0, toc, tocSize) < bufferOrig->getLength()) - ret = (ret == kIOReturnSuccess) ? kIOReturnUnderrun : ret; - else - ret = (ret == kIOReturnUnderrun) ? kIOReturnSuccess : ret; - - buffer->release(); - } -#endif LG_DVD_ROM_DRN8080B_SUPPORT - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Start analog audio play - -IOReturn -IOATAPICDDrive::audioPlay(CDMSF timeStart,CDMSF timeStop) -{ - IOATACommand * cmd; - IOReturn ret; - - // IOLog("IOATAPICDDrive::audioPlay %x %x\n",timeStart,timeStop); - cmd = atapiCommandPlayAudioMSF(timeStart, timeStop); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the audio play command. - // - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::audioPause(bool pause) -{ - IOATACommand * cmd; - IOReturn ret; - - // IOLog("IOATAPICDDrive::audioPause\n"); - cmd = atapiCommandPauseResume(!pause); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the audio pause/resume command. - // - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::audioScan(CDMSF timeStart, bool reverse) -{ - IOATACommand * cmd; - IOReturn ret; - - cmd = atapiCommandScan(timeStart, reverse); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the audio scan command. - // - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::audioStop() -{ - IOATACommand * cmd; - IOReturn ret; - - cmd = atapiCommandStopPlay(); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the audio stop play command. - // - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::getAudioVolume(UInt8 * leftVolume, UInt8 * rightVolume) -{ - UInt8 audio_control[24]; - IOReturn status; - - status = readModeSense(audio_control,sizeof(audio_control),(UInt32)0xe); - - if (status == kIOReturnSuccess) { - assert((audio_control[0] ) == 0x00); - assert((audio_control[1] ) == sizeof(audio_control) - 2); - assert((audio_control[8] & 0x3f) == 0x0e); - assert((audio_control[9] ) == 0x0e); - - *leftVolume = audio_control[17]; - *rightVolume = audio_control[19]; - } - - return status; -} - -IOReturn -IOATAPICDDrive::setAudioVolume(UInt8 leftVolume, UInt8 rightVolume) -{ - UInt8 audio_control[24]; - IOReturn status; - - // get current values - status = readModeSense(audio_control,sizeof(audio_control),(UInt32)0xe); - - if (status == kIOReturnSuccess) { - assert((audio_control[0] ) == 0x00); - assert((audio_control[1] ) == sizeof(audio_control) - 2); - assert((audio_control[8] & 0x3f) == 0x0e); - assert((audio_control[9] ) == 0x0e); - - // set new values - audio_control[17] = audio_control[21] = leftVolume; - audio_control[19] = audio_control[23] = rightVolume; - - status = writeModeSelect(audio_control,sizeof(audio_control)); - } - - return status; -} - -IOReturn -IOATAPICDDrive::readModeSense(UInt8 * buffer, - UInt32 length, - UInt8 pageCode, - UInt8 pageControl = 0) -{ - IOReturn ret; - IOATACommand * cmd; - IOMemoryDescriptor * senseDesc; - - assert(buffer); - - // IOLog("IOATAPICDDrive::readModeSense len=%d page=%d\n",length,pageCode); - - senseDesc = IOMemoryDescriptor::withAddress(buffer, - length, - kIODirectionIn); - if (!senseDesc) - return kIOReturnNoMemory; - - cmd = atapiCommandModeSense(senseDesc, pageCode, pageControl); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the Mode Sense command. - // - ret = syncExecute(cmd); - - // Release the memory descriptor. - // - senseDesc->release(); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::writeModeSelect(UInt8 * buffer, UInt32 length) -{ - IOReturn ret; - IOATACommand * cmd; - IOMemoryDescriptor * selectDesc; - - // IOLog("IOATAPICDDrive::writeModeSelect %d %d\n",length); - assert(buffer); - - selectDesc = IOMemoryDescriptor::withAddress(buffer, - length, - kIODirectionOut); - if (!selectDesc) - return kIOReturnNoMemory; - - cmd = atapiCommandModeSelect(selectDesc); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the Mode Select command. - // - ret = syncExecute(cmd); - - // Release the memory descriptor. - // - selectDesc->release(); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::getAudioStatus(CDAudioStatus * status) -{ - UInt8 * channel_data; - IOReturn ret; - - // init - channel_data = (UInt8 *)IOMalloc(16); - if (!channel_data) return kIOReturnNoMemory; - - // get audio status - ret = readSubChannel(channel_data,16,0x01,0x00); - - if (ret == kIOReturnSuccess) { - // state our assumptions - assert(channel_data[2] == 0); - assert(channel_data[3] == 12); - assert(channel_data[4] == 1); - - // get current status - status->status = channel_data[ 1]; - - // get current track and track index - status->position.track.number = channel_data[ 6]; - status->position.track.index = channel_data[ 7]; - - // get current absolute address - status->position.time.minute = channel_data[ 9]; - status->position.time.second = channel_data[10]; - status->position.time.frame = channel_data[11]; - - // get current relative address - status->position.track.time.minute = channel_data[13]; - status->position.track.time.second = channel_data[14]; - status->position.track.time.frame = channel_data[15]; - } - - // cleanup - IOFree(channel_data,16); - return ret; -} - -IOReturn -IOATAPICDDrive::readMCN(CDMCN mcn) -{ - UInt8 * channel_data; - IOReturn ret; - - // init - channel_data = (UInt8 *)IOMalloc(24); - if (!channel_data) return kIOReturnNoMemory; - - // get audio status - ret = readSubChannel(channel_data,24,0x02,0x00); - - if (ret == kIOReturnSuccess) { - // state our assumptions - assert(channel_data[2] == 0); - assert(channel_data[3] == 20); - assert(channel_data[4] == 2); - - // check if found - if ((channel_data[8] & 0x80)) { - // copy the data - bcopy(&channel_data[9],mcn,kCDMCNMaxLength); - mcn[kCDMCNMaxLength] = '\0'; - } else { - ret = kIOReturnNotFound; - } - } - - // cleanup - IOFree(channel_data,24); - return ret; -} - -IOReturn -IOATAPICDDrive::readISRC(UInt8 track, CDISRC isrc) -{ - UInt8 * channel_data; - IOReturn ret; - - // init - channel_data = (UInt8 *)IOMalloc(24); - if (!channel_data) return kIOReturnNoMemory; - - // get audio status - ret = readSubChannel(channel_data,24,0x03,track); - - if (ret == kIOReturnSuccess) { - // state our assumptions - assert(channel_data[2] == 0); - assert(channel_data[3] == 20); - assert(channel_data[4] == 3); - - // check if found - if ((channel_data[8] & 0x80)) { - // copy the data - bcopy(&channel_data[9],isrc,kCDISRCMaxLength); - isrc[kCDISRCMaxLength] = '\0'; - } else { - ret = kIOReturnNotFound; - } - } - - // cleanup - IOFree(channel_data,24); - return ret; -} - -IOReturn -IOATAPICDDrive::readSubChannel(UInt8 * buffer, - UInt32 length, - UInt8 dataFormat, - UInt8 trackNumber) -{ - IOReturn ret; - IOATACommand * cmd; - IOMemoryDescriptor * readDesc; - - assert(buffer); - - // IOLog("IOATAPICDDrive::readSubChannel len=%d\n",length); - - readDesc = IOMemoryDescriptor::withAddress(buffer, - length, - kIODirectionIn); - if (!readDesc) - return kIOReturnNoMemory; - - cmd = atapiCommandReadSubChannel(readDesc, dataFormat, trackNumber); - if (!cmd) - return kIOReturnNoMemory; - - // Execute the Mode Sense command. - // - ret = syncExecute(cmd); - - // Release the memory descriptor. - // - readDesc->release(); - - cmd->release(); - - return ret; -} - -IOReturn -IOATAPICDDrive::doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - IOReturn ret; - IOATACommand * cmd; - - cmd = atapiCommandReadCD(buffer,block,nblks,sectorArea,sectorType); - - if (!cmd) - return kIOReturnNoMemory; - - ret = asyncExecute(cmd, completion); - - cmd->release(); - - return ret; -} diff --git a/iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp b/iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp deleted file mode 100644 index a70f6aa3d..000000000 --- a/iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPICDDriveNub.cpp - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * 2-Sep-1999 Joe Liu (jliu) created. - */ - -#include <IOKit/IOLib.h> -#include <IOKit/storage/ata/IOATAPICDDriveNub.h> -#include <IOKit/storage/ata/IOATAPICDDrive.h> - -#define super IOCDBlockStorageDevice -OSDefineMetaClassAndStructors( IOATAPICDDriveNub, IOCDBlockStorageDevice ) - -//--------------------------------------------------------------------------- -// attach to provider. - -bool IOATAPICDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) - return false; - - _provider = OSDynamicCast(IOATAPICDDrive, provider); - if (_provider == 0) { - IOLog("IOATAPICDDriveNub: attach; wrong provider type!\n"); - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// detach from provider. - -void IOATAPICDDriveNub::detach(IOService * provider) -{ - if (_provider == provider) - _provider = 0; - - super::detach(provider); -} - - -//--------------------------------------------------------------------------- -// doAsyncReadCD - -IOReturn IOATAPICDDriveNub::doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - return _provider->doAsyncReadCD(buffer, - block, - nblks, - sectorArea, - sectorType, - completion); -} - -//--------------------------------------------------------------------------- -// doAsyncReadWrite - -IOReturn IOATAPICDDriveNub::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - if (buffer->getDirection() == kIODirectionOut) - return kIOReturnNotWritable; - - return _provider->doAsyncReadWrite(buffer, block, nblks, completion); -} - -//--------------------------------------------------------------------------- -// doSyncReadWrite - -IOReturn -IOATAPICDDriveNub::doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - if (buffer->getDirection() == kIODirectionOut) - return kIOReturnNotWritable; - - return _provider->doSyncReadWrite(buffer, block, nblks); -} - -//--------------------------------------------------------------------------- -// doFormatMedia - -IOReturn -IOATAPICDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// doGetFormatCapacities - -UInt32 -IOATAPICDDriveNub::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return _provider->doGetFormatCapacities(capacities, capacitiesMaxCount); -} - -//--------------------------------------------------------------------------- -// doEjectMedia - -IOReturn IOATAPICDDriveNub::doEjectMedia() -{ - return _provider->doEjectMedia(); -} - -//--------------------------------------------------------------------------- -// doLockUnlockMedia - -IOReturn IOATAPICDDriveNub::doLockUnlockMedia(bool doLock) -{ - return _provider->doLockUnlockMedia(doLock); -} - -//--------------------------------------------------------------------------- -// getMediaType - -UInt32 IOATAPICDDriveNub::getMediaType() -{ - return kCDMediaTypeROM; -} - -//--------------------------------------------------------------------------- -// getVendorString - -char * IOATAPICDDriveNub::getVendorString() -{ - return _provider->getVendorString(); -} - -//--------------------------------------------------------------------------- -// getProductString - -char * IOATAPICDDriveNub::getProductString() -{ - return _provider->getProductString(); -} - -//--------------------------------------------------------------------------- -// getRevisionString - -char * IOATAPICDDriveNub::getRevisionString() -{ - return _provider->getRevisionString(); -} - -//--------------------------------------------------------------------------- -// getAdditionalDeviceInfoString - -char * IOATAPICDDriveNub::getAdditionalDeviceInfoString() -{ - return _provider->getAdditionalDeviceInfoString(); -} - -//--------------------------------------------------------------------------- -// reportBlockSize - -IOReturn IOATAPICDDriveNub::reportBlockSize(UInt64 * blockSize) -{ - return _provider->reportBlockSize(blockSize); -} - -//--------------------------------------------------------------------------- -// reportEjectability - -IOReturn IOATAPICDDriveNub::reportEjectability(bool * isEjectable) -{ - return _provider->reportEjectability(isEjectable); -} - -//--------------------------------------------------------------------------- -// reportLockability - -IOReturn IOATAPICDDriveNub::reportLockability(bool * isLockable) -{ - return _provider->reportLockability(isLockable); -} - -//--------------------------------------------------------------------------- -// reportMediaState - -IOReturn IOATAPICDDriveNub::reportMediaState(bool * mediaPresent, - bool * changed) -{ - return _provider->reportMediaState(mediaPresent, changed); -} - -//--------------------------------------------------------------------------- -// reportPollRequirements - -IOReturn IOATAPICDDriveNub::reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive) -{ - return _provider->reportPollRequirements(pollIsRequired, pollIsExpensive); -} - -//--------------------------------------------------------------------------- -// reportMaxReadTransfer - -IOReturn IOATAPICDDriveNub::reportMaxReadTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxReadTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMaxValidBlock - -IOReturn IOATAPICDDriveNub::reportMaxValidBlock(UInt64 * maxBlock) -{ - return _provider->reportMaxValidBlock(maxBlock); -} - -//--------------------------------------------------------------------------- -// reportRemovability - -IOReturn IOATAPICDDriveNub::reportRemovability(bool * isRemovable) -{ - return _provider->reportRemovability(isRemovable); -} - -//--------------------------------------------------------------------------- -// readISRC - -IOReturn IOATAPICDDriveNub::readISRC(UInt8 track, CDISRC isrc) -{ - return _provider->readISRC(track, isrc); -} - -//--------------------------------------------------------------------------- -// readMCN - -IOReturn IOATAPICDDriveNub::readMCN(CDMCN mcn) -{ - return _provider->readMCN(mcn); -} - -//--------------------------------------------------------------------------- -// readTOC - -IOReturn IOATAPICDDriveNub::readTOC(IOMemoryDescriptor * buffer) -{ - return _provider->readTOC(buffer); -} - -//--------------------------------------------------------------------------- -// audioPause - -IOReturn IOATAPICDDriveNub::audioPause(bool pause) -{ - return _provider->audioPause(pause); -} - -//--------------------------------------------------------------------------- -// audioPlay - -IOReturn IOATAPICDDriveNub::audioPlay(CDMSF timeStart, CDMSF timeStop) -{ - return _provider->audioPlay(timeStart, timeStop); -} - -//--------------------------------------------------------------------------- -// audioScan - -IOReturn IOATAPICDDriveNub::audioScan(CDMSF timeStart, bool reverse) -{ - return _provider->audioScan(timeStart, reverse); -} - -//--------------------------------------------------------------------------- -// audioStop - -IOReturn IOATAPICDDriveNub::audioStop() -{ - return _provider->audioStop(); -} - -//--------------------------------------------------------------------------- -// getAudioStatus - -IOReturn IOATAPICDDriveNub::getAudioStatus(CDAudioStatus * status) -{ - return _provider->getAudioStatus(status); -} - -//--------------------------------------------------------------------------- -// getAudioVolume - -IOReturn IOATAPICDDriveNub::getAudioVolume(UInt8 * leftVolume, - UInt8 * rightVolume) -{ - return _provider->getAudioVolume(leftVolume, rightVolume); -} - -//--------------------------------------------------------------------------- -// setVolume - -IOReturn IOATAPICDDriveNub::setAudioVolume(UInt8 leftVolume, UInt8 rightVolume) -{ - return _provider->setAudioVolume(leftVolume, rightVolume); -} - -//--------------------------------------------------------------------------- -// doSynchronizeCache - -IOReturn IOATAPICDDriveNub::doSynchronizeCache() -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// reportMaxWriteTransfer - -IOReturn IOATAPICDDriveNub::reportMaxWriteTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxWriteTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMaxWriteTransfer - -IOReturn IOATAPICDDriveNub::reportWriteProtection(bool * isWriteProtected) -{ - return _provider->reportWriteProtection(isWriteProtected); -} diff --git a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp b/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp deleted file mode 100644 index e93273e33..000000000 --- a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/storage/ata/IOATAPIDVDDrive.h> - -//--------------------------------------------------------------------------- -// SEND KEY command. - -IOATACommand * -IOATAPIDVDDrive::atapiCommandSendKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandSendKey; - atapiCmd.cdb[7] = keyClass; - atapiCmd.cdb[8] = (UInt8)(buffer->getLength() >> 8); - atapiCmd.cdb[9] = (UInt8)(buffer->getLength()); - atapiCmd.cdb[10] = agid << 6 | keyFormat; - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// REPORT KEY command. - -IOATACommand * -IOATAPIDVDDrive::atapiCommandReportKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandReportKey; - - if (keyFormat == kTitleKey) { - atapiCmd.cdb[2] = (UInt8)(lba >> 24); - atapiCmd.cdb[3] = (UInt8)(lba >> 16); - atapiCmd.cdb[4] = (UInt8)(lba >> 8); - atapiCmd.cdb[5] = (UInt8)(lba); - } - atapiCmd.cdb[7] = keyClass; - atapiCmd.cdb[8] = (UInt8)(buffer->getLength() >> 8); - atapiCmd.cdb[9] = (UInt8)(buffer->getLength()); - atapiCmd.cdb[10] = agid << 6 | keyFormat; - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// GET CONFIGURATION command. - -IOATACommand * -IOATAPIDVDDrive::atapiCommandGetConfiguration(IOMemoryDescriptor * buffer, - UInt8 rt, - UInt16 sfn = 0) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandGetConfiguration; - atapiCmd.cdb[1] = rt & 0x03; - atapiCmd.cdb[2] = (UInt8)(sfn >> 8); // starting feature number MSB - atapiCmd.cdb[3] = (UInt8)(sfn); // starting feature number LSB - atapiCmd.cdb[7] = (UInt8)(buffer->getLength() >> 8); - atapiCmd.cdb[8] = (UInt8)(buffer->getLength()); - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// READ DVD STRUCTURE command. - -IOATACommand * -IOATAPIDVDDrive::atapiCommandReadDVDStructure(IOMemoryDescriptor * buffer, - UInt8 format, - UInt32 address = 0, - UInt8 layer = 0, - UInt8 agid = 0) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandReadDVDStructure; - atapiCmd.cdb[2] = (UInt8)(address >> 24); - atapiCmd.cdb[3] = (UInt8)(address >> 16); - atapiCmd.cdb[4] = (UInt8)(address >> 8); - atapiCmd.cdb[5] = (UInt8)(address); - atapiCmd.cdb[6] = layer; - atapiCmd.cdb[7] = format; - atapiCmd.cdb[8] = (UInt8)(buffer->getLength() >> 8); - atapiCmd.cdb[9] = (UInt8)(buffer->getLength()); - atapiCmd.cdb[10] = (agid & 0x3) << 6; - - return atapiCommand(&atapiCmd, buffer); -} diff --git a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp b/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp deleted file mode 100644 index 2e8b9cdef..000000000 --- a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/storage/ata/IOATAPIDVDDrive.h> -#include <IOKit/storage/ata/IOATAPIDVDDriveNub.h> -#include <IOKit/storage/IODVDTypes.h> -#include <libkern/OSByteOrder.h> - -// Define this to log debug messages. -// -// #define LOG_DVD_MESSAGES 1 - -#ifdef LOG_DVD_MESSAGES -#define DEBUG_LOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DEBUG_LOG(fmt, args...) -#endif - -#define super IOATAPICDDrive -OSDefineMetaClassAndStructors( IOATAPIDVDDrive, IOATAPICDDrive ) - -//--------------------------------------------------------------------------- -// Feature header and descriptor definition. - -struct featureHdr { - UInt32 totalLen; - UInt8 reserved1[2]; - UInt16 currentProfile; -}; - -struct featureDescriptor { - UInt16 featureCode; - UInt8 versionPC; - UInt8 additionalLength; -}; - -#define kConfigBufferSize 2048 -#define kConfigFeatureHeaderBytes sizeof(struct featureHdr) -#define kConfigDataLengthBytes sizeof(UInt32) -#define kConfigMinDataLength (sizeof(struct featureHdr) - \ - kConfigDataLengthBytes + \ - sizeof(struct featureDescriptor)) - -//--------------------------------------------------------------------------- -// Classify an ATAPI CD-ROM drive as a CD or a DVD drive. - -IOReturn IOATAPIDVDDrive::classifyDrive(bool * isDVDDrive) -{ - IOATACommand * cmd = 0; - IOBufferMemoryDescriptor * copyrightDesc; - IOBufferMemoryDescriptor * senseDesc; - IOReturn ret = kIOReturnSuccess; - - do { - // Buffer descriptor to hold Copyright Information. - - copyrightDesc = IOBufferMemoryDescriptor::withCapacity(8, - kIODirectionIn); - - // Buffer descriptor to hold sense data. - - senseDesc = IOBufferMemoryDescriptor::withCapacity( - sizeof(ATASenseData), - kIODirectionIn); - - if ( (copyrightDesc == 0) || (senseDesc == 0) ) - { - ret = kIOReturnNoMemory; - break; - } - - bzero(senseDesc->getBytesNoCopy(), senseDesc->getCapacity()); - - // READ DVD STRUCTURE command - DVD Copyright Information - - cmd = atapiCommandReadDVDStructure(copyrightDesc, - kIODVDReadStructureCopyright); - if (cmd == 0) - { - ret = kIOReturnNoMemory; - break; - } - - // Execute the command, and get sense data. - - ret = syncExecute(cmd, - kATADefaultTimeout, - kATADefaultRetries, - senseDesc); - - // By default, consider it a DVD drive, unless the drive - // returns an error, and the sense data contains, - // - // KEY = 0x05 - // ASC = 0x20 - // ASCQ = 0x00 - - *isDVDDrive = true; - - if (ret != kIOReturnSuccess) - { - ATASenseData * senseData; - - senseData = (ATASenseData *) senseDesc->getBytesNoCopy(); - - if ((senseData->errorCode == kATAPISenseCurrentErr) || - (senseData->errorCode == kATAPISenseDeferredErr)) - { - if ((senseData->senseKey == kATAPISenseIllegalReq) && - (senseData->additionalSenseCode == 0x20) && - (senseData->additionalSenseQualifier == 0x0)) - { - *isDVDDrive = false; - } - } - - ret = kIOReturnSuccess; - } - } - while (false); - - if (senseDesc) senseDesc->release(); - if (copyrightDesc) copyrightDesc->release(); - if (cmd) cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Determine the media type (book type) in the DVD drive. - -IOReturn -IOATAPIDVDDrive::determineMediaType(UInt32 * mediaType) -{ - IOATACommand * cmd = 0; - IOBufferMemoryDescriptor * dataDesc; - IODVDStructurePhysical * data; - IOReturn ret = kIOReturnSuccess; - - *mediaType = kDVDMediaTypeUnknown; - - do { - // Buffer descriptor to hold Physical Format Information. - - dataDesc = IOBufferMemoryDescriptor::withCapacity(sizeof(*data), - kIODirectionIn); - - if ( dataDesc == 0 ) - { - ret = kIOReturnNoMemory; - break; - } - - data = (IODVDStructurePhysical *) dataDesc->getBytesNoCopy(); - bzero(data, sizeof(data->length)); - - // READ DVD STRUCTURE command - Physical Format Information - - cmd = atapiCommandReadDVDStructure(dataDesc, - kIODVDReadStructurePhysical); - if ( cmd == 0 ) - { - ret = kIOReturnNoMemory; - break; - } - - // Execute the command. - - if ( syncExecute(cmd) != kIOReturnSuccess ) - { - *mediaType = kCDMediaTypeROM; // Assume its a CD. - } - else if ( IODVDGetDataLength16(data->length) < - (sizeof(*data) - sizeof(data->length)) ) - { - ret = kIOReturnUnderrun; - } - else - { - DEBUG_LOG("%s: DVD Book Type: %x Part Version: %x\n", - getName(), data->bookType, data->partVersion); - - switch (data->bookType) - { - default: - case kIODVDBookTypeDVDROM: - case kIODVDBookTypeDVDR: - case kIODVDBookTypeDVDRW: - case kIODVDBookTypeDVDPlusRW: - *mediaType = kDVDMediaTypeROM; - break; - - case kIODVDBookTypeDVDRAM: - *mediaType = kDVDMediaTypeRAM; - break; - } - } - } - while (false); - - if (dataDesc) dataDesc->release(); - if (cmd) cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Perform active matching with an ATAPI device nub published by the -// ATA controller driver. - -bool -IOATAPIDVDDrive::matchATAPIDeviceType(UInt8 type, SInt32 * score) -{ - bool isDVDDrive; - bool match = false; - - do { - // If the device type reported by INQUIRY data is not a CD-ROM type, - // then give up immediately. - - if ( type != kIOATAPIDeviceTypeCDROM ) - break; - - // Select timing protocol before performing I/O. - - if ( selectTimingProtocol() == false ) - break; - - // Is this unit a DVD drive? - - if ( classifyDrive(&isDVDDrive) != kIOReturnSuccess ) - break; - - if ( isDVDDrive ) - { - // Indicate a strong affinity for the DVD drive by setting - // a higher probe score when a DVD drive is detected. - - DEBUG_LOG("%s::%s DVD drive detected\n", getName(), __FUNCTION__); - *score = 20; - match = true; - } - else - { - // Not a DVD drive. - DEBUG_LOG("%s::%s Not a DVD drive\n", getName(), __FUNCTION__); - } - } - while (false); - - return match; -} - -//--------------------------------------------------------------------------- -// GET CONFIGURATION command. - -IOReturn -IOATAPIDVDDrive::getConfiguration(UInt8 * buf, - UInt32 length, - UInt32 * actualLength, - bool current) -{ - IOMemoryDescriptor * bufDesc = 0; - IOATACommand * cmd = 0; - IOReturn ret = kIOReturnNoMemory; - ATAResults results; - - do { - bufDesc = IOMemoryDescriptor::withAddress(buf, length, kIODirectionIn); - if (bufDesc == 0) - break; - - cmd = atapiCommandGetConfiguration(bufDesc, 0x01); - if (cmd == 0) - break; - - ret = syncExecute(cmd); - - cmd->getResults(&results); - *actualLength = results.bytesTransferred; - } - while (0); - - if (cmd) cmd->release(); - if (bufDesc) bufDesc->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Report disk type. - -const char * -IOATAPIDVDDrive::getDeviceTypeName() -{ - return kIOBlockStorageDeviceTypeDVD; -} - -//--------------------------------------------------------------------------- -// Report the type of media in the DVD drive. - -UInt32 -IOATAPIDVDDrive::getMediaType() -{ - UInt32 mediaType; - - determineMediaType(&mediaType); - - return mediaType; -} - -//--------------------------------------------------------------------------- -// Initialize the IOATAPIDVDDrive object. - -bool -IOATAPIDVDDrive::init(OSDictionary * properties) -{ - return super::init(properties); -} - -//--------------------------------------------------------------------------- -// Instantiate an IOATAPIDVDDriveNub nub. - -IOService * -IOATAPIDVDDrive::instantiateNub(void) -{ - IOService * nub = new IOATAPIDVDDriveNub; - - /* Instantiate a generic DVD nub so a generic driver can match above us. */ - - return nub; -} - -//--------------------------------------------------------------------------- -// Report the media state. - -IOReturn -IOATAPIDVDDrive::reportMediaState(bool * mediaPresent, bool * changed) -{ - IOReturn result; - - // Let superclass check for media in a generic fashion. - - result = super::reportMediaState(mediaPresent, changed); - -#if 0 // For testing only - - if (result != kIOReturnSuccess) - { - return result; - } - - // For a new media, determine its type. - - if (*mediaPresent && *changed) - { - getMediaType(); - } -#endif - - return result; -} - -//--------------------------------------------------------------------------- -// Report random write support. - -IOReturn -IOATAPIDVDDrive::reportWriteProtection(bool * isWriteProtected) -{ - UInt32 len; - struct featureHdr * fh; - struct featureDescriptor * fdp; - IOReturn result; - UInt8 * configBuf; - UInt32 configBufSize; /* not used */ - - *isWriteProtected = true; - - /* Allocate memory for the configuration data. - Theoretically, this can be up to 65534 bytes. */ - - configBuf = (UInt8 *) IOMalloc(kConfigBufferSize); - if ( configBuf == 0 ) - return kIOReturnNoMemory; - - bzero((void *) configBuf, kConfigBufferSize); - - /* Get the *current* configuration information, relating to the media. */ - - do { - result = getConfiguration(configBuf, - kConfigBufferSize, - &configBufSize, - true); /* Get current (active) features */ - - if (result == kIOReturnUnderrun) - { - // getConfiguration() will report an underrun. - result = kIOReturnSuccess; - } - - if (result != kIOReturnSuccess) - { - DEBUG_LOG("%s::%s getConfiguration() error = %s\n", - getName(), __FUNCTION__, stringFromReturn(result)); - result = kIOReturnSuccess; - break; - } - - fh = (struct featureHdr *) configBuf; - len = OSSwapBigToHostInt32(fh->totalLen); - - if (len < kConfigMinDataLength) - { - result = kIOReturnUnderrun; - break; - } - - // total length, including the Data Length field. - // - len += kConfigDataLengthBytes; - len = min(len, kConfigBufferSize); - DEBUG_LOG("%s::%s config length = %ld\n", getName(), __FUNCTION__, len); - - // Points to the first Feature Descriptor after the Feature Header. - // - fdp = (struct featureDescriptor *) - &configBuf[kConfigFeatureHeaderBytes]; - - do { - if (OSSwapBigToHostInt16(fdp->featureCode) == - kIOATAPIFeatureRandomWrite) - { - *isWriteProtected = false; - break; - } - - fdp = (struct featureDescriptor *)((char *)fdp + - sizeof(struct featureDescriptor) + - fdp->additionalLength); - } - while ( ((UInt8 *)fdp + sizeof(*fdp)) <= &configBuf[len] ); - } - while (false); - - IOFree((void *) configBuf, kConfigBufferSize); - - return result; -} - -//--------------------------------------------------------------------------- -// SEND KEY command. - -IOReturn -IOATAPIDVDDrive::sendKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - IOATACommand * cmd = 0; - IOReturn ret = kIOReturnNoMemory; - - do { - assert(buffer); - - cmd = atapiCommandSendKey(buffer, keyClass, agid, keyFormat); - if (cmd == 0) - break; - - ret = syncExecute(cmd); - } - while (0); - - if (cmd) - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// REPORT KEY command. - -IOReturn -IOATAPIDVDDrive::reportKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - IOATACommand * cmd = 0; - IOReturn ret = kIOReturnNoMemory; - - do { - assert(buffer); - - cmd = atapiCommandReportKey(buffer, keyClass, lba, agid, keyFormat); - if (cmd == 0) - break; - - ret = syncExecute(cmd); - } - while (0); - - if (cmd) - cmd->release(); - - return ret; -} diff --git a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp b/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp deleted file mode 100644 index 7ad606b1c..000000000 --- a/iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOLib.h> -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/ata/IOATAPIDVDDriveNub.h> -#include <IOKit/storage/ata/IOATAPIDVDDrive.h> - -class IOMemoryDescriptor; - -#define super IODVDBlockStorageDevice -OSDefineMetaClassAndStructors(IOATAPIDVDDriveNub, IODVDBlockStorageDevice) - -//--------------------------------------------------------------------------- -// attach to provider. - -bool -IOATAPIDVDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) - return false; - - _provider = OSDynamicCast(IOATAPIDVDDrive, provider); - if (_provider == 0) { - IOLog("IOATAPIDVDDriveNub: attach; wrong provider type!\n"); - return false; - } - return true; -} - -//--------------------------------------------------------------------------- -// detach from provider. - -void -IOATAPIDVDDriveNub::detach(IOService * provider) -{ - if (_provider == provider) - _provider = 0; - - super::detach(provider); -} - -//--------------------------------------------------------------------------- -// audioPlay - -IOReturn -IOATAPIDVDDriveNub::audioPlay(CDMSF timeStart, CDMSF timeStop) -{ - return _provider->audioPlay(timeStart, timeStop); -} - -//--------------------------------------------------------------------------- -// audioPause - -IOReturn -IOATAPIDVDDriveNub::audioPause(bool pause) -{ - return _provider->audioPause(pause); -} - -//--------------------------------------------------------------------------- -// audioScan - -IOReturn -IOATAPIDVDDriveNub::audioScan(CDMSF timeStart, bool reverse) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// audioStop - -IOReturn IOATAPIDVDDriveNub::audioStop() -{ - return _provider->audioStop(); -} - -//--------------------------------------------------------------------------- -// doAsyncReadCD - -IOReturn IOATAPIDVDDriveNub::doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - return _provider->doAsyncReadCD(buffer, - block, - nblks, - sectorArea, - sectorType, - completion); -} - -//--------------------------------------------------------------------------- -// doAsyncReadWrite - -IOReturn -IOATAPIDVDDriveNub::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - return _provider->doAsyncReadWrite(buffer, block, nblks, completion); -} - -//--------------------------------------------------------------------------- -// doSyncReadWrite - -IOReturn -IOATAPIDVDDriveNub::doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - return _provider->doSyncReadWrite(buffer, block, nblks); -} - -//--------------------------------------------------------------------------- -// doEjectMedia - -IOReturn -IOATAPIDVDDriveNub::doEjectMedia() -{ - return _provider->doEjectMedia(); -} - -//--------------------------------------------------------------------------- -// doFormatMedia - -IOReturn -IOATAPIDVDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return _provider->doFormatMedia(byteCapacity); -} - -//--------------------------------------------------------------------------- -// doGetFormatCapacities - -UInt32 -IOATAPIDVDDriveNub::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return _provider->doGetFormatCapacities(capacities, capacitiesMaxCount); -} - -//--------------------------------------------------------------------------- -// doLockUnlockMedia - -IOReturn -IOATAPIDVDDriveNub::doLockUnlockMedia(bool doLock) -{ - return _provider->doLockUnlockMedia(doLock); -} - -//--------------------------------------------------------------------------- -// doSynchronizeCache - -IOReturn -IOATAPIDVDDriveNub::doSynchronizeCache() -{ - return _provider->doSynchronizeCache(); -} - -//--------------------------------------------------------------------------- -// getAudioStatus - -IOReturn -IOATAPIDVDDriveNub::getAudioStatus(CDAudioStatus * status) -{ - return _provider->getAudioStatus(status); -} - -//--------------------------------------------------------------------------- -// getAudioVolume - -IOReturn -IOATAPIDVDDriveNub::getAudioVolume(UInt8 * leftVolume, UInt8 * rightVolume) -{ - return _provider->getAudioVolume(leftVolume, rightVolume); -} - -//--------------------------------------------------------------------------- -// getMediaType - -UInt32 -IOATAPIDVDDriveNub::getMediaType() -{ - return _provider->getMediaType(); -} - -//--------------------------------------------------------------------------- -// getVendorString - -char * -IOATAPIDVDDriveNub::getVendorString() -{ - return _provider->getVendorString(); -} - -//--------------------------------------------------------------------------- -// getProductString - -char * -IOATAPIDVDDriveNub::getProductString() -{ - return _provider->getProductString(); -} - -//--------------------------------------------------------------------------- -// getRevisionString - -char * -IOATAPIDVDDriveNub::getRevisionString() -{ - return _provider->getRevisionString(); -} - -//--------------------------------------------------------------------------- -// getAdditionalDeviceInfoString - -char * -IOATAPIDVDDriveNub::getAdditionalDeviceInfoString() -{ - return _provider->getAdditionalDeviceInfoString(); -} - -//--------------------------------------------------------------------------- -// readISRC - -IOReturn -IOATAPIDVDDriveNub::readISRC(UInt8 track, CDISRC isrc) -{ - return _provider->readISRC(track, isrc); -} - -//--------------------------------------------------------------------------- -// readMCN - -IOReturn -IOATAPIDVDDriveNub::readMCN(CDMCN mcn) -{ - return _provider->readMCN(mcn); -} - -//--------------------------------------------------------------------------- -// readTOC - -IOReturn -IOATAPIDVDDriveNub::readTOC(IOMemoryDescriptor * buffer) -{ - return _provider->readTOC(buffer); -} - -//--------------------------------------------------------------------------- -// reportBlockSize - -IOReturn -IOATAPIDVDDriveNub::reportBlockSize(UInt64 * blockSize) -{ - return _provider->reportBlockSize(blockSize); -} - -//--------------------------------------------------------------------------- -// reportEjectability - -IOReturn -IOATAPIDVDDriveNub::reportEjectability(bool * isEjectable) -{ - return _provider->reportEjectability(isEjectable); -} - -//--------------------------------------------------------------------------- -// reportKey - -IOReturn -IOATAPIDVDDriveNub::reportKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - return _provider->reportKey(buffer, keyClass, lba, agid, keyFormat); -} - -//--------------------------------------------------------------------------- -// sendKey - -IOReturn -IOATAPIDVDDriveNub::sendKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat) -{ - return _provider->sendKey(buffer, keyClass, agid, keyFormat); -} - -//--------------------------------------------------------------------------- -// reportLockability - -IOReturn -IOATAPIDVDDriveNub::reportLockability(bool * isLockable) -{ - return _provider->reportLockability(isLockable); -} - -//--------------------------------------------------------------------------- -// reportPollRequirements - -IOReturn -IOATAPIDVDDriveNub::reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive) -{ - return _provider->reportPollRequirements(pollIsRequired, pollIsExpensive); -} - -//--------------------------------------------------------------------------- -// reportMaxReadTransfer - -IOReturn -IOATAPIDVDDriveNub::reportMaxReadTransfer(UInt64 blockSize, UInt64 * max) -{ - return _provider->reportMaxReadTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMaxValidBlock - -IOReturn -IOATAPIDVDDriveNub::reportMaxValidBlock(UInt64 * maxBlock) -{ - return _provider->reportMaxValidBlock(maxBlock); -} - -//--------------------------------------------------------------------------- -// reportMaxWriteTransfer - -IOReturn -IOATAPIDVDDriveNub::reportMaxWriteTransfer(UInt64 blockSize, UInt64 * max) -{ - return _provider->reportMaxWriteTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMediaState - -IOReturn -IOATAPIDVDDriveNub::reportMediaState(bool * mediaPresent, bool * changed) -{ - return _provider->reportMediaState(mediaPresent, changed); -} - -//--------------------------------------------------------------------------- -// reportRemovability - -IOReturn -IOATAPIDVDDriveNub::reportRemovability(bool * isRemovable) -{ - return _provider->reportRemovability(isRemovable); -} - -//--------------------------------------------------------------------------- -// reportWriteProtection - -IOReturn -IOATAPIDVDDriveNub::reportWriteProtection(bool * isWriteProtected) -{ - return _provider->reportWriteProtection(isWriteProtected); -} - -//--------------------------------------------------------------------------- -// setAudioVolume - -IOReturn -IOATAPIDVDDriveNub::setAudioVolume(UInt8 leftVolume, UInt8 rightVolume) -{ - return _provider->setAudioVolume(leftVolume, rightVolume); -} diff --git a/iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp b/iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp deleted file mode 100644 index 959d18250..000000000 --- a/iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIHDCommand.cpp - Performs ATAPI command processing. - * - * HISTORY - * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. - */ - -#include <IOKit/assert.h> -#include <IOKit/storage/ata/IOATAPIHDDrive.h> - -#define super IOATAHDDrive - -// Enable this define to generate debugging messages. -// #define DEBUG_LOG 1 - -//--------------------------------------------------------------------------- -// Returns the Command protocol to use (e.g. ataProtocolPIO, ataProtocolDMA). - -bool -IOATAPIHDDrive::selectCommandProtocol(bool isDMA) -{ - super::selectCommandProtocol(isDMA); - - if (isDMA) - _atapiProtocol = kATAProtocolATAPIDMA; - else - _atapiProtocol = kATAProtocolATAPIPIO; - - return true; -} - -//--------------------------------------------------------------------------- -// Setup a ATATaskFile for an ATAPI packet command from the parameters given. - -void -IOATAPIHDDrive::setupPacketTaskFile(ATATaskfile * taskfile, - ATAProtocol protocol, - UInt16 byteCount) -{ - bzero( taskfile, sizeof(ATATaskfile) ); - - taskfile->protocol = protocol; - - taskfile->regmask = ATARegtoMask(kATARegATAPIDeviceSelect) - | ATARegtoMask(kATARegATAPICommand) - | ATARegtoMask(kATARegATAPIByteCountLow) - | ATARegtoMask(kATARegATAPIByteCountHigh) - | ATARegtoMask(kATARegATAPIFeatures); - - taskfile->resultmask = ATARegtoMask(kATARegATAPIError); - - taskfile->ataRegs[kATARegATAPIDeviceSelect] = kATAModeLBA | (_unit << 4); - taskfile->ataRegs[kATARegATAPICommand] = kATACommandATAPIPacket; - taskfile->ataRegs[kATARegATAPIByteCountLow] = byteCount & 0xff; - taskfile->ataRegs[kATARegATAPIByteCountHigh] = (byteCount >> 8) & 0xff; - taskfile->ataRegs[kATARegATAPIFeatures] = (protocol == - kATAProtocolATAPIPIO) ? - 0 : kIOATAPIFeaturesDMA; -} - -//--------------------------------------------------------------------------- -// Create a generic ATAPI command object. - -IOATACommand * -IOATAPIHDDrive::atapiCommand(ATACDBInfo * packetCommand, - IOMemoryDescriptor * transferBuffer = 0) -{ - ATATaskfile taskfile; - bool isWrite; - UInt32 transferLength; - IOATACommand * cmd = allocateCommand(); - - if (!cmd) return 0; // error, command allocation failed. - - // Create ATA packet command. - // - setupPacketTaskFile(&taskfile, _atapiProtocol, kIOATAPIMaxTransfer); - - // Get a pointer to the client data buffer, and record parameters - // which shall be later used by the completion routine. - // - IOATAClientData * clientData = ATA_CLIENT_DATA(cmd); - assert(clientData); - - clientData->buffer = transferBuffer; - - cmd->setTaskfile(&taskfile); - cmd->setCDB(packetCommand); - - if (transferBuffer) { - isWrite = (transferBuffer->getDirection() == kIODirectionOut); - transferLength = transferBuffer->getLength(); - } - else { - isWrite = false; - transferLength = 0; - } - cmd->setPointers(transferBuffer, transferLength, isWrite); - - return cmd; -} - -//--------------------------------------------------------------------------- -// Allocates and return an IOATACommand to perform a read/write operation. - -IOATACommand * -IOATAPIHDDrive::atapiCommandReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - -#ifdef DEBUG_LOG - IOLog("%s: atapiCommandReadWrite %08x (%d) %s %d %d\n", - getName(), - buffer, - buffer->getLength(), - (buffer->getDirection() == kIODirectionOut) ? "WR" : - "RD", - block, - nblks); -#endif - - // Create the ATAPI packet (bytes 1, 10, 11 are reserved). - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = (buffer->getDirection() == kIODirectionOut) ? - kIOATAPICommandWrite : kIOATAPICommandRead; - atapiCmd.cdb[2] = (UInt8)(block >> 24); - atapiCmd.cdb[3] = (UInt8)(block >> 16); - atapiCmd.cdb[4] = (UInt8)(block >> 8); - atapiCmd.cdb[5] = (UInt8)(block); - atapiCmd.cdb[6] = (UInt8)(nblks >> 24); - atapiCmd.cdb[7] = (UInt8)(nblks >> 16); - atapiCmd.cdb[8] = (UInt8)(nblks >> 8); - atapiCmd.cdb[9] = (UInt8)(nblks); - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// ATAPI Start/Stop Unit command (1B). - -IOATACommand * -IOATAPIHDDrive::atapiCommandStartStopUnit(bool doStart, - bool doLoadEject, - bool immediate) -{ - ATACDBInfo atapiCmd; - -#ifdef DEBUG_LOG - IOLog("%s: atapiCommandStartStopUnit: %s\n", getName(), - doStart ? "start" : "stop"); -#endif - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandStartStopUnit; - atapiCmd.cdb[1] = immediate ? 0x01 : 0x00; - atapiCmd.cdb[4] = (doStart ? 0x01 : 0) | - (doLoadEject ? 0x02 : 0); - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// ATAPI Format Unit command (04). - -IOATACommand * -IOATAPIHDDrive::atapiCommandFormatUnit(UInt16 interleave, - UInt8 flagBits, - UInt8 vendorBits, - IOMemoryDescriptor * formatData) -{ - ATACDBInfo atapiCmd; - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandFormatUnit; - atapiCmd.cdb[1] = flagBits; - atapiCmd.cdb[3] = (UInt8)(interleave >> 8); - atapiCmd.cdb[4] = (UInt8)(interleave); - atapiCmd.cdb[5] = vendorBits; - - if (formatData) - atapiCmd.cdb[1] |= 0x10; - - return atapiCommand(&atapiCmd, formatData); -} - -//--------------------------------------------------------------------------- -// ATAPI Synchronize Cache command (35). - -IOATACommand * -IOATAPIHDDrive::atapiCommandSynchronizeCache() -{ - ATACDBInfo atapiCmd; - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandSynchronizeCache; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// ATAPI Prevent/Allow medium removal command (1E). - -IOATACommand * -IOATAPIHDDrive::atapiCommandPreventAllowRemoval(bool doLock) -{ - ATACDBInfo atapiCmd; - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandPreventAllow; - atapiCmd.cdb[4] = doLock ? 0x01 : 0; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// ATAPI Test Unit Ready command (00). - -IOATACommand * -IOATAPIHDDrive::atapiCommandTestUnitReady() -{ - ATACDBInfo atapiCmd; - -#ifdef DEBUG_LOG - IOLog("%s: atapiCommandTestUnitReady\n", getName()); -#endif - - // Create the ATAPI packet. - // - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandTestUnitReady; - - return atapiCommand(&atapiCmd); -} - -//--------------------------------------------------------------------------- -// atapiCommandModeSense - -IOATACommand * -IOATAPIHDDrive::atapiCommandModeSense(IOMemoryDescriptor * buffer, - UInt8 pageCode, - UInt8 pageControl) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandModeSense; - atapiCmd.cdb[2] = (pageCode & 0x3f) | ((pageControl & 0x3) << 6); - atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; - atapiCmd.cdb[8] = buffer->getLength() & 0xff; - - return atapiCommand(&atapiCmd, buffer); -} - -//--------------------------------------------------------------------------- -// atapiCommandModeSelect - -IOATACommand * -IOATAPIHDDrive::atapiCommandModeSelect(IOMemoryDescriptor * buffer) -{ - ATACDBInfo atapiCmd; - - assert(buffer); - - bzero(&atapiCmd, sizeof(atapiCmd)); - - atapiCmd.cdbLength = 12; - atapiCmd.cdb[0] = kIOATAPICommandModeSelect; - atapiCmd.cdb[1] = 0x10; - atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; - atapiCmd.cdb[8] = buffer->getLength() & 0xff; - - return atapiCommand(&atapiCmd, buffer); -} diff --git a/iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp b/iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp deleted file mode 100644 index 7016edd1d..000000000 --- a/iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIHDDrive.h - Generic ATAPI Direct-Access driver. - * - * HISTORY - * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. - */ - -#include <IOKit/assert.h> -#include <IOKit/storage/ata/IOATAPIHDDrive.h> -#include <IOKit/storage/ata/IOATAPIHDDriveNub.h> - -#define super IOATAHDDrive -OSDefineMetaClassAndStructors( IOATAPIHDDrive, IOATAHDDrive ) - -//--------------------------------------------------------------------------- -// Override the init() method in IOATAHDDrive. - -bool -IOATAPIHDDrive::init(OSDictionary * properties) -{ - _mediaPresent = false; - _isRemovable = false; - - return super::init(properties); -} - -//--------------------------------------------------------------------------- -// Override probe() method inherited from IOATAHDDrive. We need to -// perform additional matching on ATAPI device type based on the -// Inquiry data revealed by an ATA(PI) device nub. - -IOService * -IOATAPIHDDrive::probe(IOService * provider, SInt32 * score) -{ - UInt8 deviceType; - IOService * ret = 0; - bool wasOpened = false; - - // Let superclass have a go at probe first. - // - if (!super::probe(provider, score)) - return 0; - - // Our provider must be a IOATADevice nub, most likely created - // by an IOATAController instance. - // - _ataDevice = OSDynamicCast(IOATADevice, provider); - if (_ataDevice == 0) - return 0; // IOATADevice nub not found. - - do { - // Since we may issue command to the IOATADevice to perform - // device matching, we express interest in using the device by - // performing an open. - // - if (_ataDevice->open(this) == false) - break; - - wasOpened = true; - - // Perform ATAPI type matching, CD-ROM, Direct-Access, Tape, etc. - // - if (!_ataDevice->getInquiryData(1, (ATAPIInquiry *) &deviceType) || - !matchATAPIDeviceType(deviceType & 0x1f, score)) - break; - - ret = this; - } - while (false); - - if (wasOpened) - _ataDevice->close(this); - - _ataDevice = 0; - - return ret; -} - -//--------------------------------------------------------------------------- -// Report as an ATAPI device. - -ATADeviceType -IOATAPIHDDrive::reportATADeviceType() const -{ - return kATADeviceATAPI; -} - -//--------------------------------------------------------------------------- -// Looks for an ATAPI device which is a direct-access device. - -bool -IOATAPIHDDrive::matchATAPIDeviceType(UInt8 type, SInt32 * score) -{ - if (type == kIOATAPIDeviceTypeDirectAccess) - return true; - - return false; -} - -//--------------------------------------------------------------------------- -// Gather information about the ATAPI device nub. - -bool -IOATAPIHDDrive::inspectDevice(IOATADevice * device) -{ - OSString * string; - - // Fetch ATAPI device information from the nub. - // - string = OSDynamicCast(OSString, - device->getProperty(kATAPropertyVendorName)); - if (string) { - strncpy(_vendor, string->getCStringNoCopy(), 8); - _vendor[8] = '\0'; - } - - string = OSDynamicCast(OSString, - device->getProperty(kATAPropertyProductName)); - if (string) { - strncpy(_product, string->getCStringNoCopy(), 16); - _product[16] = '\0'; - } - - string = OSDynamicCast(OSString, - device->getProperty(kATAPropertyProductRevision)); - if (string) { - strncpy(_revision, string->getCStringNoCopy(), 4); - _revision[4] = '\0'; - } - - // Device wants to be power-managed. - // - _supportedFeatures |= kIOATAFeaturePowerManagement; - - return true; -} - -//--------------------------------------------------------------------------- -// Async read/write requests. - -IOReturn -IOATAPIHDDrive::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandReadWrite(buffer, block, nblks); - - if (!cmd) - return kIOReturnNoMemory; - - ret = asyncExecute(cmd, completion); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Sync read/write requests. - -IOReturn -IOATAPIHDDrive::doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandReadWrite(buffer, block, nblks); - - if (!cmd) - return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Eject the media in the removable drive. - -IOReturn -IOATAPIHDDrive::doEjectMedia() -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandStartStopUnit(false, /* start unit */ - true, /* Load/Eject */ - false); /* Immediate */ - - if (!cmd) - return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Format the media in the drive. - -IOReturn -IOATAPIHDDrive::doFormatMedia(UInt64 byteCapacity, - IOMemoryDescriptor * formatData = 0) -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandFormatUnit(0, 0, 0, formatData); - - if (!cmd) - return kIOReturnNoMemory; - - ret = syncExecute(cmd, 15 * 60 * 1000); // 15 min timeout - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Lock/unlock the media in the removable drive. - -IOReturn -IOATAPIHDDrive::doLockUnlockMedia(bool doLock) -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandPreventAllowRemoval(doLock); - - if (!cmd) - return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - // Cache the state on the media lock, and restore it when - // the driver wakes up from sleep. - - _isLocked = doLock; - - return ret; -} - -//--------------------------------------------------------------------------- -// Sync the write cache. - -IOReturn -IOATAPIHDDrive::doSynchronizeCache() -{ - IOReturn ret; - IOATACommand * cmd = atapiCommandSynchronizeCache(); - - if (!cmd) - return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Start up the drive. - -IOReturn -IOATAPIHDDrive::doStart() -{ - return doStartStop(true); -} - -//--------------------------------------------------------------------------- -// Stop the drive. - -IOReturn -IOATAPIHDDrive::doStop() -{ - return doStartStop(false); -} - -//--------------------------------------------------------------------------- -// Issue a START/STOP Unit command. - -IOReturn -IOATAPIHDDrive::doStartStop(bool doStart) -{ - IOReturn ret; - IOATACommand * cmd; - - cmd = atapiCommandStartStopUnit(doStart, /* start unit */ - false, /* Load/Eject */ - false); /* Immediate operation */ - - if (!cmd) return kIOReturnNoMemory; - - ret = syncExecute(cmd); - - cmd->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Return device identification strings - -char * IOATAPIHDDrive::getVendorString() -{ - return _vendor; -} - -char * IOATAPIHDDrive::getProductString() -{ - return _product; -} - -char * IOATAPIHDDrive::getRevisionString() -{ - return _revision; -} - -char * IOATAPIHDDrive::getAdditionalDeviceInfoString() -{ - return ("[ATAPI]"); -} - -//--------------------------------------------------------------------------- -// Report whether the media in the drive is ejectable. - -IOReturn -IOATAPIHDDrive::reportEjectability(bool * isEjectable) -{ - *isEjectable = true; /* default: if it's removable, it's ejectable */ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report whether the drive can prevent user-initiated ejects by locking -// the media in the drive. - -IOReturn -IOATAPIHDDrive::reportLockability(bool * isLockable) -{ - *isLockable = true; /* default: if it's removable, it's lockable */ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report our polling requirments. - -IOReturn -IOATAPIHDDrive::reportPollRequirements(bool * pollRequired, - bool * pollIsExpensive) -{ - *pollIsExpensive = false; - *pollRequired = _isRemovable; - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report the current state of the media. - -IOReturn -IOATAPIHDDrive::reportMediaState(bool * mediaPresent, - bool * changed) -{ - IOATACommand * cmd = 0; - IOMemoryDescriptor * senseData = 0; - UInt8 senseBuf[18]; - ATAResults results; - IOReturn ret; - - assert(mediaPresent && changed); - - do { - ret = kIOReturnNoMemory; - - bzero((void *) senseBuf, sizeof(senseBuf)); - senseData = IOMemoryDescriptor::withAddress(senseBuf, - sizeof(senseBuf), - kIODirectionIn); - if (!senseData) - break; - - cmd = atapiCommandTestUnitReady(); - if (!cmd) - break; - - // Execute the Test Unit Ready command with no retries. - // - syncExecute(cmd, kATADefaultTimeout, kATAZeroRetry, senseData); - - ret = kIOReturnSuccess; - - if (cmd->getResults(&results) == kIOReturnSuccess) - { - *mediaPresent = true; - *changed = (*mediaPresent != _mediaPresent); - _mediaPresent = true; - } - else - { - UInt8 errorCode = senseBuf[0]; - UInt8 senseKey = senseBuf[2]; - -#ifdef DEBUG_LOG - UInt8 senseCode = senseBuf[12]; - UInt8 senseQualifier = senseBuf[13]; - - IOLog("-- IOATAPIHDDrive::reportMediaState --\n"); - IOLog("Error code: %02x\n", errorCode); - IOLog("Sense Key : %02x\n", senseKey); - IOLog("ASC : %02x\n", senseCode); - IOLog("ASCQ : %02x\n", senseQualifier); -#endif - - *mediaPresent = false; - *changed = (*mediaPresent != _mediaPresent); - _mediaPresent = false; - - // The error code field for ATAPI request sense should always - // be 0x70 or 0x71. Otherwise ignore the sense data. - // - if ((errorCode == 0x70) || (errorCode == 0x71)) - { - switch (senseKey) { - case 5: /* Invalid ATAPI command */ - ret = kIOReturnIOError; - break; - - case 2: /* Not ready */ - break; - - default: - break; - } - } - } - } - while (false); - - if (cmd) - cmd->release(); - - if (senseData) - senseData->release(); - -#if 0 - IOLog("%s: media present %s, changed %s\n", getName(), - *mediaPresent ? "Y" : "N", - *changed ? "Y" : "N" - ); -#endif - - return ret; -} - -//--------------------------------------------------------------------------- -// Report media removability. - -IOReturn -IOATAPIHDDrive::reportRemovability(bool * isRemovable) -{ - UInt8 inqBuf[2]; - - *isRemovable = false; - - if (_ataDevice->getInquiryData(sizeof(inqBuf), (ATAPIInquiry *) inqBuf)) - { - if (inqBuf[1] & 0x80) - *isRemovable = _isRemovable = true; - else - *isRemovable = _isRemovable = false; - } - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Report whether media is write-protected. - -IOReturn -IOATAPIHDDrive::reportWriteProtection(bool * isWriteProtected) -{ - *isWriteProtected = false; // defaults to read-write - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Instantiate an ATAPI specific subclass of IOBlockStorageDevice. - -IOService * -IOATAPIHDDrive::instantiateNub() -{ - IOService * nub = new IOATAPIHDDriveNub; - return nub; -} - -//--------------------------------------------------------------------------- -// Override the handleActiveStateTransition() method in IOATAHDDrive and -// perform ATAPI specific handling. - -void -IOATAPIHDDrive::handleActiveStateTransition( UInt32 stage, IOReturn status ) -{ - // Restore the lock on the media after the ATAPI device wakes up from - // sleep. Assume that the drive will always power up in the unlocked state. - // Technically, some drives may have a jumper to set the default state - // at power up. - - if ( ( stage == kIOATAActiveStage0 ) && _isLocked ) - { - IOStorageCompletion completion; - IOReturn ret; - IOATACommand * cmd = atapiCommandPreventAllowRemoval( true ); - - completion.target = this; - completion.action = sHandleActiveStateTransition; - completion.parameter = (void *) kIOATAActiveStage1; - - if ( cmd ) - { - cmd->setQueueInfo( kATAQTypeBypassQ ); - ret = asyncExecute( cmd, completion ); - cmd->release(); - } - } - else - { - super::handleActiveStateTransition( stage, status ); - } -} diff --git a/iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp b/iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp deleted file mode 100644 index 668d717e9..000000000 --- a/iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIHDDriveNub.cpp - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * 2-Sep-1999 Joe Liu (jliu) created. - */ - -#include <IOKit/IOLib.h> -#include <IOKit/storage/ata/IOATAPIHDDriveNub.h> -#include <IOKit/storage/ata/IOATAPIHDDrive.h> - -#define super IOBlockStorageDevice -OSDefineMetaClassAndStructors( IOATAPIHDDriveNub, IOBlockStorageDevice ) - -//--------------------------------------------------------------------------- -// attach to provider. - -bool IOATAPIHDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) - return false; - - _provider = OSDynamicCast(IOATAPIHDDrive, provider); - if (_provider == 0) { - IOLog("IOATAPIHDDriveNub: attach; wrong provider type!\n"); - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// detach from provider. - -void IOATAPIHDDriveNub::detach(IOService * provider) -{ - if (_provider == provider) - _provider = 0; - - super::detach(provider); -} - -//--------------------------------------------------------------------------- -// doAsyncReadWrite - -IOReturn IOATAPIHDDriveNub::doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion) -{ - return _provider->doAsyncReadWrite(buffer, block, nblks, completion); -} - -//--------------------------------------------------------------------------- -// doSyncReadWrite - -IOReturn IOATAPIHDDriveNub::doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks) -{ - return _provider->doSyncReadWrite(buffer, block, nblks); -} - - -//--------------------------------------------------------------------------- -// doEjectMedia - -IOReturn IOATAPIHDDriveNub::doEjectMedia() -{ - return _provider->doEjectMedia(); -} - -//--------------------------------------------------------------------------- -// doFormatMedia - -IOReturn IOATAPIHDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return _provider->doFormatMedia(byteCapacity); -} - -//--------------------------------------------------------------------------- -// doGetFormatCapacities - -UInt32 -IOATAPIHDDriveNub::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return _provider->doGetFormatCapacities(capacities, capacitiesMaxCount); -} - -//--------------------------------------------------------------------------- -// doLockUnlockMedia - -IOReturn IOATAPIHDDriveNub::doLockUnlockMedia(bool doLock) -{ - return _provider->doLockUnlockMedia(doLock); -} - -//--------------------------------------------------------------------------- -// doSynchronizeCache - -IOReturn IOATAPIHDDriveNub::doSynchronizeCache() -{ - return _provider->doSynchronizeCache(); -} - -//--------------------------------------------------------------------------- -// getVendorString - -char * IOATAPIHDDriveNub::getVendorString() -{ - return _provider->getVendorString(); -} - -//--------------------------------------------------------------------------- -// getProductString - -char * IOATAPIHDDriveNub::getProductString() -{ - return _provider->getProductString(); -} - -//--------------------------------------------------------------------------- -// getRevisionString - -char * IOATAPIHDDriveNub::getRevisionString() -{ - return _provider->getRevisionString(); -} - -//--------------------------------------------------------------------------- -// getAdditionalDeviceInfoString - -char * IOATAPIHDDriveNub::getAdditionalDeviceInfoString() -{ - return _provider->getAdditionalDeviceInfoString(); -} - -//--------------------------------------------------------------------------- -// reportBlockSize - -IOReturn IOATAPIHDDriveNub::reportBlockSize(UInt64 * blockSize) -{ - return _provider->reportBlockSize(blockSize); -} - -//--------------------------------------------------------------------------- -// reportEjectability - -IOReturn IOATAPIHDDriveNub::reportEjectability(bool * isEjectable) -{ - return _provider->reportEjectability(isEjectable); -} - -//--------------------------------------------------------------------------- -// reportLockability - -IOReturn IOATAPIHDDriveNub::reportLockability(bool * isLockable) -{ - return _provider->reportLockability(isLockable); -} - -//--------------------------------------------------------------------------- -// reportPollRequirements - -IOReturn IOATAPIHDDriveNub::reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive) -{ - return _provider->reportPollRequirements(pollIsRequired, pollIsExpensive); -} - -//--------------------------------------------------------------------------- -// reportMaxReadTransfer - -IOReturn IOATAPIHDDriveNub::reportMaxReadTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxReadTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMaxValidBlock - -IOReturn IOATAPIHDDriveNub::reportMaxValidBlock(UInt64 * maxBlock) -{ - return _provider->reportMaxValidBlock(maxBlock); -} - -//--------------------------------------------------------------------------- -// reportMaxWriteTransfer - -IOReturn IOATAPIHDDriveNub::reportMaxWriteTransfer(UInt64 blockSize, - UInt64 * max) -{ - return _provider->reportMaxWriteTransfer(blockSize, max); -} - -//--------------------------------------------------------------------------- -// reportMediaState - -IOReturn IOATAPIHDDriveNub::reportMediaState(bool * mediaPresent, - bool * changed) -{ - return _provider->reportMediaState(mediaPresent, changed); -} - -//--------------------------------------------------------------------------- -// reportRemovability - -IOReturn IOATAPIHDDriveNub::reportRemovability(bool * isRemovable) -{ - return _provider->reportRemovability(isRemovable); -} - -//--------------------------------------------------------------------------- -// reportWriteProtection - -IOReturn IOATAPIHDDriveNub::reportWriteProtection(bool * isWriteProtected) -{ - return _provider->reportWriteProtection(isWriteProtected); -} diff --git a/iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp b/iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp index 2ad22be97..a7195b903 100644 --- a/iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp +++ b/iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp @@ -289,6 +289,10 @@ void IOATAStandardDriver::doATAPIProtocolDma( IOATAStandardCommand *ataCmd ) } } + // Wait for BSY = 0 and DRQ = 0 before issuing a packet command. + + waitForStatus( 0, kATAStatusBSY | kATAStatusDRQ, kATABusyTimeoutmS ); + for ( i = 0; regmask; i++ ) { if ( regmask & 1 ) diff --git a/iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp b/iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp index d1b4c4c30..6f2c43c7d 100644 --- a/iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp +++ b/iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp @@ -304,6 +304,10 @@ void IOATAStandardDriver::doATAPIProtocolPio( IOATAStandardCommand *ataCmd ) } } + // Wait for BSY = 0 and DRQ = 0 before issuing a packet command. + + waitForStatus( 0, kATAStatusBSY | kATAStatusDRQ, kATABusyTimeoutmS ); + for ( i = 0; regmask; i++ ) { if ( regmask & 1 ) diff --git a/iokit/Families/IOBlockStorage/IOBlockStorageDevice.cpp b/iokit/Families/IOBlockStorage/IOBlockStorageDevice.cpp deleted file mode 100644 index abf724844..000000000 --- a/iokit/Families/IOBlockStorage/IOBlockStorageDevice.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOBlockStorageDevice.h> - -#define super IOService -OSDefineMetaClass(IOBlockStorageDevice,IOService) -OSDefineAbstractStructors(IOBlockStorageDevice,IOService) - -bool -IOBlockStorageDevice::init(OSDictionary * properties) -{ - bool result; - - result = super::init(properties); - if (result) { - result = setProperty(kIOBlockStorageDeviceTypeKey, - kIOBlockStorageDeviceTypeGeneric); - } - - return(result); -} - -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 0); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 1); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 2); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 3); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 4); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 5); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 6); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 7); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 8); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 9); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 10); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 11); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 12); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 13); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 14); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 15); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 16); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 17); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 18); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 19); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 20); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 21); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 22); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 23); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 24); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 25); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 26); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 27); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 28); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 29); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 30); -OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 31); diff --git a/iokit/Families/IOCDBlockStorage/IOCDBlockStorageDevice.cpp b/iokit/Families/IOCDBlockStorage/IOCDBlockStorageDevice.cpp deleted file mode 100644 index e3bd887ed..000000000 --- a/iokit/Families/IOCDBlockStorage/IOCDBlockStorageDevice.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/storage/IOCDBlockStorageDevice.h> - -#define super IOBlockStorageDevice -OSDefineMetaClass(IOCDBlockStorageDevice,IOBlockStorageDevice) -OSDefineAbstractStructors(IOCDBlockStorageDevice,IOBlockStorageDevice) - -bool -IOCDBlockStorageDevice::init(OSDictionary * properties) -{ - bool result; - - result = super::init(properties); - if (result) { - setProperty(kIOBlockStorageDeviceTypeKey, - kIOBlockStorageDeviceTypeCDROM); - } - - return(result); -} - -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 0); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 1); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 2); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 3); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 4); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 5); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 6); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 7); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 8); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 9); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 10); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 11); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 12); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 13); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 14); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDevice, 15); diff --git a/iokit/Families/IOCDStorage/IOCDAudioControl.cpp b/iokit/Families/IOCDStorage/IOCDAudioControl.cpp deleted file mode 100644 index 7c1636144..000000000 --- a/iokit/Families/IOCDStorage/IOCDAudioControl.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/storage/IOCDAudioControl.h> -#include <IOKit/storage/IOCDAudioControlUserClient.h> -#include <IOKit/storage/IOCDBlockStorageDriver.h> - -#define super IOService -OSDefineMetaClassAndStructors(IOCDAudioControl, IOService) - -IOCDBlockStorageDriver * -IOCDAudioControl::getProvider() const -{ - return (IOCDBlockStorageDriver *) IOService::getProvider(); -} - -IOReturn -IOCDAudioControl::getStatus(CDAudioStatus *status) -{ - return(getProvider()->getAudioStatus(status)); -} - -CDTOC * -IOCDAudioControl::getTOC(void) -{ - return(getProvider()->getTOC()); -} - -IOReturn -IOCDAudioControl::getVolume(UInt8 *left,UInt8 *right) -{ - return(getProvider()->getAudioVolume(left,right)); -} - -IOReturn -IOCDAudioControl::newUserClient(task_t task, - void * /* security */, - UInt32 /* type */, - IOUserClient ** object ) - -{ - IOReturn err = kIOReturnSuccess; - IOCDAudioControlUserClient * client; - - client = IOCDAudioControlUserClient::withTask(task); - - if( !client || (false == client->attach( this )) || - (false == client->start( this )) ) { - if(client) { - client->detach( this ); - client->release(); - } - err = kIOReturnNoMemory; - } - - *object = client; - return( err ); -} - -IOReturn -IOCDAudioControl::pause(bool pause) -{ - return(getProvider()->audioPause(pause)); -} - -IOReturn -IOCDAudioControl::play(CDMSF timeStart,CDMSF timeStop) -{ - return(getProvider()->audioPlay(timeStart,timeStop)); -} - -IOReturn -IOCDAudioControl::scan(CDMSF timeStart,bool reverse) -{ - return(getProvider()->audioScan(timeStart,reverse)); -} - -IOReturn -IOCDAudioControl::stop() -{ - return(getProvider()->audioStop()); -} - -IOReturn -IOCDAudioControl::setVolume(UInt8 left,UInt8 right) -{ - return(getProvider()->setAudioVolume(left,right)); -} - -OSMetaClassDefineReservedUnused(IOCDAudioControl, 0); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 1); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 2); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 3); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 4); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 5); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 6); -OSMetaClassDefineReservedUnused(IOCDAudioControl, 7); diff --git a/iokit/Families/IOCDStorage/IOCDAudioControlUserClient.cpp b/iokit/Families/IOCDStorage/IOCDAudioControlUserClient.cpp deleted file mode 100644 index 8dfb84946..000000000 --- a/iokit/Families/IOCDStorage/IOCDAudioControlUserClient.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOCDAudioControlUserClient.h> - -#define super IOUserClient -OSDefineMetaClassAndStructors(IOCDAudioControlUserClient, IOUserClient) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOCDAudioControl * IOCDAudioControlUserClient::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method - // to return a more specific subclass of IOService -- IOCDAudioControl. - // This method serves simply as a convenience to subclass developers. - // - - return (IOCDAudioControl *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOCDAudioControlUserClient * IOCDAudioControlUserClient::withTask(task_t) -{ - // - // Create a new IOCDAudioControlUserClient. - // - - IOCDAudioControlUserClient * me = new IOCDAudioControlUserClient; - - if ( me && me->init() == false ) - { - me->release(); - me = 0; - } - - return me; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOCDAudioControlUserClient::start(IOService * provider) -{ - // - // Prepare the user client for usage. - // - - // State our assumptions. - - assert(OSDynamicCast(IOCDAudioControl, provider)); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Open our provider. - - if ( provider->open(this) == false ) return false; - - // Prepare our method dispatch table. - - _methods[kIOCDAudioControlMethodGetStatus].func = (IOMethod) &IOCDAudioControlUserClient::getStatus; - _methods[kIOCDAudioControlMethodGetStatus].flags = kIOUCScalarIStructO; - _methods[kIOCDAudioControlMethodGetStatus].count0 = 0; - _methods[kIOCDAudioControlMethodGetStatus].count1 = sizeof(CDAudioStatus); - _methods[kIOCDAudioControlMethodGetStatus].object = this; - - _methods[kIOCDAudioControlMethodGetTOC ].func = (IOMethod) &IOCDAudioControlUserClient::getTOC; - _methods[kIOCDAudioControlMethodGetTOC ].flags = kIOUCScalarIStructO; - _methods[kIOCDAudioControlMethodGetTOC ].count0 = 0; - _methods[kIOCDAudioControlMethodGetTOC ].count1 = 0xFFFFFFFF; - _methods[kIOCDAudioControlMethodGetTOC ].object = this; - - _methods[kIOCDAudioControlMethodGetVolume].func = (IOMethod) &IOCDAudioControlUserClient::getVolume; - _methods[kIOCDAudioControlMethodGetVolume].flags = kIOUCScalarIScalarO; - _methods[kIOCDAudioControlMethodGetVolume].count0 = 0; - _methods[kIOCDAudioControlMethodGetVolume].count1 = 2; - _methods[kIOCDAudioControlMethodGetVolume].object = this; - - _methods[kIOCDAudioControlMethodSetVolume].func = (IOMethod) &IOCDAudioControlUserClient::setVolume; - _methods[kIOCDAudioControlMethodSetVolume].flags = kIOUCScalarIScalarO; - _methods[kIOCDAudioControlMethodSetVolume].count0 = 2; - _methods[kIOCDAudioControlMethodSetVolume].count1 = 0; - _methods[kIOCDAudioControlMethodSetVolume].object = this; - - _methods[kIOCDAudioControlMethodPause ].func = (IOMethod) &IOCDAudioControlUserClient::pause; - _methods[kIOCDAudioControlMethodPause ].flags = kIOUCScalarIScalarO; - _methods[kIOCDAudioControlMethodPause ].count0 = 1; - _methods[kIOCDAudioControlMethodPause ].count1 = 0; - _methods[kIOCDAudioControlMethodPause ].object = this; - - _methods[kIOCDAudioControlMethodPlay ].func = (IOMethod) &IOCDAudioControlUserClient::play; - _methods[kIOCDAudioControlMethodPlay ].flags = kIOUCScalarIScalarO; - _methods[kIOCDAudioControlMethodPlay ].count0 = 2; - _methods[kIOCDAudioControlMethodPlay ].count1 = 0; - _methods[kIOCDAudioControlMethodPlay ].object = this; - - _methods[kIOCDAudioControlMethodScan ].func = (IOMethod) &IOCDAudioControlUserClient::scan; - _methods[kIOCDAudioControlMethodScan ].flags = kIOUCScalarIScalarO; - _methods[kIOCDAudioControlMethodScan ].count0 = 2; - _methods[kIOCDAudioControlMethodScan ].count1 = 0; - _methods[kIOCDAudioControlMethodScan ].object = this; - - _methods[kIOCDAudioControlMethodStop ].func = (IOMethod) &IOCDAudioControlUserClient::stop; - _methods[kIOCDAudioControlMethodStop ].flags = 0; - _methods[kIOCDAudioControlMethodStop ].count0 = 0; - _methods[kIOCDAudioControlMethodStop ].count1 = 0; - _methods[kIOCDAudioControlMethodStop ].object = this; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::clientClose() -{ - // - // Relinquish the user client. - // - - IOCDAudioControl * provider = getProvider(); - - if ( provider && provider->isOpen(this) ) - { - provider->close(this); - detach(provider); - } - - return kIOReturnSuccess; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOExternalMethod * IOCDAudioControlUserClient::getExternalMethodForIndex( - UInt32 index ) -{ - // - // Obtain the method definition given a method index. - // - - if (index >= kIOCDAudioControlMethodCount) return 0; - - return _methods + index; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::getStatus( CDAudioStatus * status, - UInt32 * statusSize ) -{ - // - // Get the current audio play status information. - // - - if ( *statusSize != sizeof(CDAudioStatus) ) return kIOReturnBadArgument; - - return getProvider()->getStatus(status); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::getTOC(CDTOC * toc, UInt32 * tocMaxSize) -{ - // - // Get the full Table Of Contents. - // - - CDTOC * original = getProvider()->getTOC(); - - if (original == 0) return kIOReturnBadMedia; - - *tocMaxSize = min(original->length + sizeof(UInt16), *tocMaxSize); - bcopy(original, toc, *tocMaxSize); - - return kIOReturnSuccess; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::getVolume(UInt32 * left, UInt32 * right) -{ - // - // Get the current audio volume. - // - - IOReturn status; - - if ( ((*left) & ~0xFF) || ((*right) & ~0xFF) ) return kIOReturnBadArgument; - - status = getProvider()->getVolume((UInt8 *) left, (UInt8 *) right); - - *left = *((UInt8 *) left ); - *right = *((UInt8 *) right); - - return status; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::setVolume(UInt32 left, UInt32 right) -{ - // - // Set the current audio volume. - // - - if ( (left & ~0xFF) || (right & ~0xFF) ) return kIOReturnBadArgument; - - return getProvider()->setVolume((UInt8) left, (UInt8) right); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::pause(UInt32 pause) -{ - // - // Pause or resume the audio playback. - // - - return getProvider()->pause((bool) pause); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::play(UInt32 msfStart, UInt32 msfStop) -{ - // - // Play audio. - // - - CDMSF timeStart; - CDMSF timeStop; - - timeStart.minute = (msfStart >> 16) & 0xFF; - timeStart.second = (msfStart >> 8) & 0xFF; - timeStart.frame = (msfStart >> 0) & 0xFF; - - timeStop.minute = (msfStop >> 16) & 0xFF; - timeStop.second = (msfStop >> 8) & 0xFF; - timeStop.frame = (msfStop >> 0) & 0xFF; - - return getProvider()->play(timeStart, timeStop); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::scan(UInt32 msfStart, UInt32 reverse) -{ - // - // Perform a fast-forward or fast-backward operation. - // - - CDMSF timeStart; - - timeStart.minute = (msfStart >> 16) & 0xFF; - timeStart.second = (msfStart >> 8) & 0xFF; - timeStart.frame = (msfStart >> 0) & 0xFF; - - return getProvider()->scan(timeStart, reverse ? true : false); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDAudioControlUserClient::stop() -{ - // - // Stop the audio playback (or audio scan). - // - - return getProvider()->stop(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDAudioControlUserClient, 7); diff --git a/iokit/Families/IOCDStorage/IOCDBlockStorageDriver.cpp b/iokit/Families/IOCDStorage/IOCDBlockStorageDriver.cpp deleted file mode 100644 index 1e15e5ff1..000000000 --- a/iokit/Families/IOCDStorage/IOCDBlockStorageDriver.cpp +++ /dev/null @@ -1,607 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOCDBlockStorageDriver.h> -#include <IOKit/storage/IOCDMedia.h> -#include <IOKit/storage/IOCDAudioControl.h> -#include <IOKit/storage/IOCDBlockStorageDevice.h> -#include <libkern/OSByteOrder.h> - - -// Hack for Cheetah to prevent sleep if there's disk activity. -static IOService * gIORootPowerDomain = NULL; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define super IOBlockStorageDriver -OSDefineMetaClassAndStructors(IOCDBlockStorageDriver,IOBlockStorageDriver) - -IOCDBlockStorageDevice * -IOCDBlockStorageDriver::getProvider() const -{ - return (IOCDBlockStorageDevice *) IOService::getProvider(); -} - - -/* Accept a new piece of media, doing whatever's necessary to make it - * show up properly to the system. The arbitration lock is assumed to - * be held during the call. - */ -IOReturn -IOCDBlockStorageDriver::acceptNewMedia(void) -{ - IOReturn result; - bool ok; - int i; - UInt64 nblocks; - int nentries; - int nDataTracks; - int nAudioTracks; - char name[128]; - bool nameSep; - - /* First, we cache information about the tracks on the disc: */ - - result = cacheTocInfo(); - if (result != kIOReturnSuccess) { - assert(_toc == NULL); - } - - /* Scan thru the track list, counting up the number of Data and Audio tracks. */ - - nDataTracks = 0; - nAudioTracks = 0; - nblocks = 0; - - if (_toc) { - nentries = (_toc->length - sizeof(UInt16)) / sizeof(CDTOCDescriptor); - - for (i = 0; i < nentries; i++) { - /* tracks 1-99, not leadout or skip intervals */ - if (_toc->descriptors[i].point <= 99 && _toc->descriptors[i].adr == 1) { - if ((_toc->descriptors[i].control & 0x04)) { - /* it's a data track */ - nDataTracks++; - } else { - nAudioTracks++; - } - /* leadout */ - } else if (_toc->descriptors[i].point == 0xA2 && _toc->descriptors[i].adr == 1) { - if (nblocks < CDConvertMSFToLBA(_toc->descriptors[i].p)) { - nblocks = CDConvertMSFToLBA(_toc->descriptors[i].p); - } - } - } - - if (nblocks < _maxBlockNumber + 1) { - nblocks = _maxBlockNumber + 1; - } - } else if (_maxBlockNumber) { - nblocks = _maxBlockNumber + 1; - } - - /* Instantiate a CD Media nub above ourselves. */ - - name[0] = 0; - nameSep = false; - if (getProvider()->getVendorString()) { - strcat(name, getProvider()->getVendorString()); - nameSep = true; - } - if (getProvider()->getProductString()) { - if (nameSep == true) strcat(name, " "); - strcat(name, getProvider()->getProductString()); - nameSep = true; - } - if (nameSep == true) strcat(name, " "); - strcat(name, "Media"); - - _mediaObject = instantiateMediaObject(0,nblocks*kBlockSizeCD,kBlockSizeCD,name); - result = (_mediaObject) ? kIOReturnSuccess : kIOReturnBadArgument; - - if (result == kIOReturnSuccess) { - ok = _mediaObject->attach(this); - } else { - IOLog("%s[IOCDBlockStorageDriver]::acceptNewMedia; can't instantiate CD media nub.\n",getName()); - return(result); /* give up now */ - } - if (!ok) { - IOLog("%s[IOCDBlockStorageDriver]::acceptNewMedia; can't attach CD media nub.\n",getName()); - _mediaObject->release(); - _mediaObject = NULL; - return(kIOReturnNoMemory); /* give up now */ - } - - /* Instantiate an audio control nub for the audio portion of the media. */ - - if (nAudioTracks) { - _acNub = new IOCDAudioControl; - if (_acNub) { - _acNub->init(); - ok = _acNub->attach(this); - if (!ok) { - IOLog("%s[IOCDBlockStorageDriver]::acceptNewMedia; can't attach audio control nub.\n",getName()); - _acNub->release(); - _acNub = NULL; - } - } else { - IOLog("%s[IOCDBlockStorageDriver]::acceptNewMedia; can't instantiate audio control nub.\n", - getName()); - } - } - - /* Now that the nubs are attached, register them. */ - - _mediaPresent = true; - if (_toc) { - _mediaObject->setProperty(kIOCDMediaTOCKey,(void*)_toc,_tocSize); - } - _mediaObject->registerService(); - - if (_acNub) { - _acNub->registerService(); - } - - return(result); -} - -IOReturn -IOCDBlockStorageDriver::audioPause(bool pause) -{ - return(getProvider()->audioPause(pause)); -} - -IOReturn -IOCDBlockStorageDriver::audioPlay(CDMSF timeStart,CDMSF timeStop) -{ - return(getProvider()->audioPlay(timeStart,timeStop)); -} - -IOReturn -IOCDBlockStorageDriver::audioScan(CDMSF timeStart,bool reverse) -{ - return(getProvider()->audioScan(timeStart,reverse)); -} - -IOReturn -IOCDBlockStorageDriver::audioStop() -{ - return(getProvider()->audioStop()); -} - -IOReturn -IOCDBlockStorageDriver::cacheTocInfo(void) -{ - IOBufferMemoryDescriptor *buffer = NULL; - IOReturn result; - CDTOC *toc; - UInt16 tocSize; - - assert(sizeof(CDTOC) == 4); /* (compiler/platform check) */ - assert(sizeof(CDTOCDescriptor) == 11); /* (compiler/platform check) */ - - assert(_toc == NULL); - - /* Read the TOC header: */ - - buffer = IOBufferMemoryDescriptor::withCapacity(sizeof(CDTOC),kIODirectionIn); - if (buffer == NULL) { - return(kIOReturnNoMemory); - } - - result = getProvider()->readTOC(buffer); - if (result != kIOReturnSuccess) { - buffer->release(); - return(result); - } - - toc = (CDTOC *) buffer->getBytesNoCopy(); - tocSize = OSSwapBigToHostInt16(toc->length) + sizeof(UInt16); - - buffer->release(); - - /* Read the TOC in full: */ - - buffer = IOBufferMemoryDescriptor::withCapacity(tocSize,kIODirectionIn); - if (buffer == NULL) { - return(kIOReturnNoMemory); - } - - result = getProvider()->readTOC(buffer); - if (result != kIOReturnSuccess) { - buffer->release(); - return(result); - } - - toc = (CDTOC *) IOMalloc(tocSize); - if (toc == NULL) { - buffer->release(); - return(kIOReturnNoMemory); - } - - if (buffer->readBytes(0,toc,tocSize) != tocSize) { - buffer->release(); - IOFree(toc,tocSize); - return(kIOReturnNoMemory); - } - - _toc = toc; - _tocSize = tocSize; - - buffer->release(); - - /* Convert big-endian values in TOC to host-endianess: */ - - if (_tocSize >= sizeof(UInt16)) { - _toc->length = OSSwapBigToHostInt16(_toc->length); - } - - return(result); -} - -/* Decommission all nubs. The arbitration lock is assumed to - * be held during the call. - */ -IOReturn -IOCDBlockStorageDriver::decommissionMedia(bool forcible) -{ - IOReturn result; - - if (_mediaObject) { - /* If this is a forcible decommission (i.e. media is gone), we don't - * care whether the teardown worked; we forget about the media. - */ - if (_mediaObject->terminate(forcible ? kIOServiceRequired : 0) || forcible) { - _mediaObject->release(); - _mediaObject = 0; - - initMediaState(); /* clear all knowledge of the media */ - result = kIOReturnSuccess; - - } else { - result = kIOReturnBusy; - } - } else { - result = kIOReturnNoMedia; - } - - /* We only attempt to decommission the audio portion of the - * CD if all the data tracks decommissioned successfully. - */ - - if (result == kIOReturnSuccess) { - if (_acNub) { - _acNub->terminate(kIOServiceRequired); - _acNub->release(); - _acNub = 0; - } - if (_toc) { - IOFree(_toc,_tocSize); - _toc = NULL; - _tocSize = 0; - } - } - - return(result); -} - -/* We should check with other clients using the other nubs before we allow - * the client of the IOCDMedia to eject the media. - */ -IOReturn -IOCDBlockStorageDriver::ejectMedia(void) -{ - /* For now, we don't check with the other clients. */ - - return(super::ejectMedia()); -} - -void -IOCDBlockStorageDriver::executeRequest(UInt64 byteStart, - IOMemoryDescriptor *buffer, - IOStorageCompletion completion, - IOBlockStorageDriver::Context *context) -{ - UInt32 block; - UInt32 nblks; - IOReturn result; - - if (!_mediaPresent) { /* no media? you lose */ - complete(completion, kIOReturnNoMedia,0); - return; - } - - /* We know that we are never called with a request too large, - * nor one that is misaligned with a block. - */ - assert((byteStart % context->block.size) == 0); - assert((buffer->getLength() % context->block.size) == 0); - - block = byteStart / context->block.size; - nblks = buffer->getLength() / context->block.size; - -/* Now the protocol-specific provider implements the actual - * start of the data transfer: */ - - // Tickle the root power domain to reset the sleep countdown. - if (gIORootPowerDomain) { - gIORootPowerDomain->activityTickle(kIOPMSubclassPolicy); - } - - if (context->block.type == kBlockTypeCD) { - result = getProvider()->doAsyncReadCD(buffer,block,nblks, - (CDSectorArea)context->block.typeSub[0], - (CDSectorType)context->block.typeSub[1], - completion); - } else { - result = getProvider()->doAsyncReadWrite(buffer,block,nblks,completion); - } - - if (result != kIOReturnSuccess) { /* it failed to start */ - complete(completion,result); - return; - } -} - -IOReturn -IOCDBlockStorageDriver::getAudioStatus(CDAudioStatus *status) -{ - return(getProvider()->getAudioStatus(status)); -} - -IOReturn -IOCDBlockStorageDriver::getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) -{ - return(getProvider()->getAudioVolume(leftVolume,rightVolume)); -} - -const char * -IOCDBlockStorageDriver::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeCDROM); -} - -UInt64 -IOCDBlockStorageDriver::getMediaBlockSize(CDSectorArea area,CDSectorType type) -{ - UInt64 blockSize = 0; - - const SInt16 areaSize[kCDSectorTypeCount][8] = - { /* 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 */ - /* Unknown */ { 96, 294, -1, 280, 2048, 4, 8, 12 }, - /* CDDA */ { 96, 294, -1, 0, 2352, 0, 0, 0 }, - /* Mode1 */ { 96, 294, -1, 288, 2048, 4, 0, 12 }, - /* Mode2 */ { 96, 294, -1, 0, 2336, 4, 0, 12 }, - /* Mode2Form1 */ { 96, 294, -1, 280, 2048, 4, 8, 12 }, - /* Mode2Form2 */ { 96, 294, -1, 0, 2328, 4, 8, 12 }, - }; - - if ( type >= kCDSectorTypeCount ) return 0; - - for ( UInt32 index = 0; index < 8; index++ ) - { - if ( ((area >> index) & 0x01) ) - { - if ( areaSize[type][index] == -1 ) return 0; - blockSize += areaSize[type][index]; - } - } - - return blockSize; -} - -UInt32 -IOCDBlockStorageDriver::getMediaType(void) -{ - return(getProvider()->getMediaType()); -} - -CDTOC * -IOCDBlockStorageDriver::getTOC(void) -{ - return(_toc); -} - -bool -IOCDBlockStorageDriver::init(OSDictionary * properties) -{ - _acNub = NULL; - _toc = NULL; - _tocSize = 0; - - // Hack for Cheetah to prevent sleep if there's disk activity. - if (!gIORootPowerDomain) { - // No danger of race here as we're ultimately just setting - // the gIORootPowerDomain variable. - - do { - IOService * root = NULL; - OSIterator * iterator = NULL; - OSDictionary * pmDict = NULL; - - root = IOService::getServiceRoot(); - if (!root) break; - - pmDict = root->serviceMatching("IOPMrootDomain"); - if (!pmDict) break; - - iterator = root->getMatchingServices(pmDict); - pmDict->release(); - if (!iterator) break; - - if (iterator) { - gIORootPowerDomain = OSDynamicCast(IOService, iterator->getNextObject()); - iterator->release(); - } - } while (false); - } - - return(super::init(properties)); -} - -IOMedia * -IOCDBlockStorageDriver::instantiateDesiredMediaObject(void) -{ - return(new IOCDMedia); -} - -IOMedia * -IOCDBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName) -{ - IOMedia *media; - - media = super::instantiateMediaObject(base,byteSize,blockSize,mediaName); - - if (media) { - char *description = NULL; - - switch (getMediaType()) { - case kCDMediaTypeROM: - description = kIOCDMediaTypeROM; - break; - case kCDMediaTypeR: - description = kIOCDMediaTypeR; - break; - case kCDMediaTypeRW: - description = kIOCDMediaTypeRW; - break; - } - - if (description) { - media->setProperty(kIOCDMediaTypeKey, description); - } - } - - return media; -} - -void -IOCDBlockStorageDriver::readCD(IOService *client, - UInt64 byteStart, - IOMemoryDescriptor *buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - assert(buffer->getDirection() == kIODirectionIn); - - prepareRequest(byteStart, buffer, sectorArea, sectorType, completion); -} - -void -IOCDBlockStorageDriver::prepareRequest(UInt64 byteStart, - IOMemoryDescriptor *buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - Context * context; - IOReturn status; - - // Allocate a context structure to hold some of our state. - - context = allocateContext(); - - if (context == 0) - { - complete(completion, kIOReturnNoMemory); - return; - } - - // Prepare the transfer buffer. - - status = buffer->prepare(); - - if (status != kIOReturnSuccess) - { - deleteContext(context); - complete(completion, status); - return; - } - - // Fill in the context structure with some of our state. - - if ( ( sectorArea == kCDSectorAreaUser ) && - ( sectorType == kCDSectorTypeMode1 || - sectorType == kCDSectorTypeMode2Form1 ) ) - { - context->block.size = _mediaBlockSize; - context->block.type = kBlockTypeStandard; - } - else - { - context->block.size = getMediaBlockSize(sectorArea, sectorType); - context->block.type = kBlockTypeCD; - context->block.typeSub[0] = sectorArea; - context->block.typeSub[1] = sectorType; - } - - context->original.byteStart = byteStart; - context->original.buffer = buffer; - context->original.buffer->retain(); - context->original.completion = completion; - - completion.target = this; - completion.action = prepareRequestCompletion; - completion.parameter = context; - - // Deblock the transfer. - - deblockRequest(byteStart, buffer, completion, context); -} - -IOReturn -IOCDBlockStorageDriver::readISRC(UInt8 track,CDISRC isrc) -{ - return(getProvider()->readISRC(track,isrc)); -} - -IOReturn -IOCDBlockStorageDriver::readMCN(CDMCN mcn) -{ - return(getProvider()->readMCN(mcn)); -} - -IOReturn -IOCDBlockStorageDriver::setAudioVolume(UInt8 leftVolume,UInt8 rightVolume) -{ - return(getProvider()->setAudioVolume(leftVolume,rightVolume)); -} - -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 0); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 1); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 2); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 3); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 4); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 5); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 6); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 7); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 8); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 9); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 10); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 11); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 12); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 13); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 14); -OSMetaClassDefineReservedUnused(IOCDBlockStorageDriver, 15); diff --git a/iokit/Families/IOCDStorage/IOCDMedia.cpp b/iokit/Families/IOCDStorage/IOCDMedia.cpp deleted file mode 100644 index 5b1061668..000000000 --- a/iokit/Families/IOCDStorage/IOCDMedia.cpp +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOSyncer.h> -#include <IOKit/storage/IOCDBlockStorageDriver.h> -#include <IOKit/storage/IOCDMedia.h> - -#define super IOMedia -OSDefineMetaClassAndStructors(IOCDMedia, IOMedia) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Local Functions - -static void readCDCompletion(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount) -{ - // - // Internal completion routine for synchronous version of readCD. - // - - if (parameter) *((UInt64 *)parameter) = actualByteCount; - ((IOSyncer *)target)->signal(status); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOCDBlockStorageDriver * IOCDMedia::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method to - // return a more specific subclass of IOService -- IOCDBlockStorageDriver. - // This method serves simply as a convenience to subclass developers. - // - - return (IOCDBlockStorageDriver *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOCDMedia::read(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // Read data from the storage object at the specified byte offset into the - // specified buffer, asynchronously. When the read completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the read. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - complete(completion, kIOReturnNoMedia); - return; - } - - if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock) - { - complete(completion, kIOReturnNotOpen); - return; - } - - if (_mediaSize == 0 || _preferredBlockSize == 0) - { - complete(completion, kIOReturnUnformattedMedia); - return; - } - - if (_mediaSize < byteStart + buffer->getLength()) - { - complete(completion, kIOReturnBadArgument); - return; - } - - byteStart += _mediaBase; - getProvider()->readCD( /* client */ this, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* sectorArea */ (CDSectorArea) 0xF8, // (2352 bytes) - /* sectorType */ (CDSectorType) 0x00, // ( all types) - /* completion */ completion ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDMedia::readCD(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - UInt64 * actualByteCount = 0) -{ - // - // Read data from the CD media object at the specified byte offset into the - // specified buffer, synchronously. Special areas of the CD sector can be - // read via this method, such as the header and subchannel data. When the - // read completes, this method will return to the caller. The actual byte - // count field is optional. - // - // This method will work even when the media is in the terminated state. - // - - IOStorageCompletion completion; - IOSyncer * completionSyncer; - - // Initialize the lock we will synchronize against. - - completionSyncer = IOSyncer::create(); - - // Fill in the completion information for this request. - - completion.target = completionSyncer; - completion.action = readCDCompletion; - completion.parameter = actualByteCount; - - // Issue the asynchronous read. - - readCD(client, byteStart, buffer, sectorArea, sectorType, completion); - - // Wait for the read to complete. - - return completionSyncer->wait(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOCDMedia::readCD(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - // - // Read data from the CD media object at the specified byte offset into the - // specified buffer, asynchronously. Special areas of the CD sector can be - // read via this method, such as the header and subchannel data. When the - // read completes, the caller will be notified via the specified completion - // action. - // - // The buffer will be retained for the duration of the read. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - complete(completion, kIOReturnNoMedia); - return; - } - - if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock) - { - complete(completion, kIOReturnNotOpen); - return; - } - - if (_mediaSize == 0 || _preferredBlockSize == 0) - { - complete(completion, kIOReturnUnformattedMedia); - return; - } - - if (_mediaSize < byteStart + buffer->getLength()) - { - complete(completion, kIOReturnBadArgument); - return; - } - - byteStart += _mediaBase; - getProvider()->readCD( /* client */ this, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* sectorArea */ sectorArea, - /* sectorType */ sectorType, - /* completion */ completion ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDMedia::readISRC(UInt8 track, CDISRC isrc) -{ - // - // Read the International Standard Recording Code for the specified track. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - return kIOReturnNoMedia; - } - - return getProvider()->readISRC(track, isrc); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOCDMedia::readMCN(CDMCN mcn) -{ - // - // Read the Media Catalog Number (also known as the Universal Product Code). - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - return kIOReturnNoMedia; - } - - return getProvider()->readMCN(mcn); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CDTOC * IOCDMedia::getTOC() -{ - // - // Get the full Table Of Contents. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - return 0; - } - - return getProvider()->getTOC(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDMedia, 15); diff --git a/iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp b/iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp deleted file mode 100644 index 2dbdcb34c..000000000 --- a/iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp +++ /dev/null @@ -1,800 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOCDPartitionScheme.h> - -#define super IOPartitionScheme -OSDefineMetaClassAndStructors(IOCDPartitionScheme, IOPartitionScheme); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define kIOCDPartitionSchemeContentTable "Content Table" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOCDMedia * IOCDPartitionScheme::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method - // to return a more specific subclass of OSObject -- IOCDMedia. This - // method serves simply as a convenience to subclass developers. - // - - return (IOCDMedia *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOCDPartitionScheme::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - // State our assumptions. - - assert(sizeof(CDTOC) == 4); // (compiler/platform check) - assert(sizeof(CDTOCDescriptor) == 11); // (compiler/platform check) - - // Ask our superclass' opinion. - - if (super::init(properties) == false) return false; - - // Initialize our state. - - _partitions = 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOCDPartitionScheme::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _partitions ) _partitions->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOService * IOCDPartitionScheme::probe(IOService * provider, SInt32 * score) -{ - // - // Determine whether the provider media contains CD partitions. - // - - // State our assumptions. - - assert(OSDynamicCast(IOCDMedia, provider)); - - // Ask superclass' opinion. - - if (super::probe(provider, score) == 0) return 0; - - // Scan the provider media for CD partitions. - - _partitions = scan(score); - - return ( _partitions ) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOCDPartitionScheme::start(IOService * provider) -{ - // - // Publish the new media objects which represent our partitions. - // - - IOMedia * partition; - OSIterator * partitionIterator; - - // State our assumptions. - - assert(_partitions); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Attach and register the new media objects representing our partitions. - - partitionIterator = OSCollectionIterator::withCollection(_partitions); - if ( partitionIterator == 0 ) return false; - - while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) - { - if ( partition->attach(this) ) - { - partition->registerService(); - } - } - - partitionIterator->release(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSSet * IOCDPartitionScheme::scan(SInt32 * score) -{ - // - // Scan the provider media for CD partitions (in TOC). Returns the set - // of media objects representing each of the partitions (the retain for - // the set is passed to the caller), or null should no CD partitions be - // found. The default probe score can be adjusted up or down, based on - // the confidence of the scan. - // - - struct CDSession - { - UInt32 isFormX:1; - UInt32 leadOut; - }; - - struct CDTrack - { - UInt32 block; - CDSectorSize blockSize; - CDSectorType blockType; - CDTOCDescriptor * descriptor; - UInt32 session:8; - }; - - #define kCDSessionMaxIndex 0x63 - - #define kCDTrackMinIndex 0x01 - #define kCDTrackMaxIndex 0x63 - - IOBufferMemoryDescriptor * buffer = 0; - IOCDMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - bool mediaIsOpen = false; - OSSet * partitions = 0; - CDSession * sessions = 0; - UInt32 sessionMinIndex = kCDSessionMaxIndex + 1; - UInt32 sessionMaxIndex = 0; - CDTOC * toc = 0; - UInt32 tocCount = 0; - CDTrack * tracks = 0; - UInt32 trackMinIndex = kCDTrackMaxIndex + 1; - UInt32 trackMaxIndex = 0; - CDTrack * trackMaxLinked = 0; - - // State our assumptions. - - assert(mediaBlockSize == kCDSectorSizeWhole); - - // Determine whether this media is formatted. - - if ( media->isFormatted() == false ) goto scanErr; - - // Allocate a buffer large enough to hold a whole 2352-byte sector. - - buffer = IOBufferMemoryDescriptor::withCapacity( - /* capacity */ mediaBlockSize, - /* withDirection */ kIODirectionIn ); - if ( buffer == 0 ) goto scanErr; - - // Allocate a set to hold the set of media objects representing partitions. - - partitions = OSSet::withCapacity(2); - if ( partitions == 0 ) goto scanErr; - - // Open the media with read access. - - mediaIsOpen = media->open(this, 0, kIOStorageAccessReader); - if ( mediaIsOpen == false ) goto scanErr; - - // Obtain the table of contents. - - toc = media->getTOC(); - if ( toc == 0 ) goto scanErr; - - tocCount = (toc->length - sizeof(UInt16)) / sizeof(CDTOCDescriptor); - - // Allocate a list large enough to hold information about each session. - - sessions = IONew(CDSession, kCDSessionMaxIndex + 1); - if ( sessions == 0 ) goto scanErr; - - bzero(sessions, (kCDSessionMaxIndex + 1) * sizeof(CDSession)); - - // Allocate a list large enough to hold information about each track. - - tracks = IONew(CDTrack, kCDTrackMaxIndex + 1); - if ( tracks == 0 ) goto scanErr; - - bzero(tracks, (kCDTrackMaxIndex + 1) * sizeof(CDTrack)); - - // Scan the table of contents, gathering information about the sessions - // and tracks on the CD, but without making assumptions about the order - // of the entries in the table. - - for ( unsigned index = 0; index < tocCount; index++ ) - { - CDTOCDescriptor * descriptor = toc->descriptors + index; - - // Determine whether this is an audio or data track descriptor. - - if ( descriptor->point >= kCDTrackMinIndex && - descriptor->point <= kCDTrackMaxIndex && - descriptor->adr == 0x01 && - descriptor->session <= kCDSessionMaxIndex ) - { - CDTrack * track = tracks + descriptor->point; - - // Record the relevant information about this track. - - track->block = CDConvertMSFToLBA(descriptor->p); - track->descriptor = descriptor; - track->session = descriptor->session; - - if ( (descriptor->control & 0x04) ) // (data track?) - { - track->blockSize = kCDSectorSizeMode1; - track->blockType = kCDSectorTypeMode1; - } - else // (audio track?) - { - track->blockSize = kCDSectorSizeCDDA; - track->blockType = kCDSectorTypeCDDA; - } - - trackMinIndex = min(descriptor->point, trackMinIndex); - trackMaxIndex = max(descriptor->point, trackMaxIndex); - } - - // Determine whether this is a lead-in (A0) descriptor. - - else if ( descriptor->point == 0xA0 && - descriptor->adr == 0x01 && - descriptor->session <= kCDSessionMaxIndex ) - { - CDSession * session = sessions + descriptor->session; - - // Record whether the session has "form 1" or "form 2" tracks. - - session->isFormX = (descriptor->p.second) ? true : false; - } - - // Determine whether this is a lead-out (A2) descriptor. - - else if ( descriptor->point == 0xA2 && - descriptor->adr == 0x01 && - descriptor->session <= kCDSessionMaxIndex ) - { - CDSession * session = sessions + descriptor->session; - - // Record the position of the session lead-out. - - session->leadOut = CDConvertMSFToLBA(descriptor->p); - - sessionMinIndex = min(descriptor->session, sessionMinIndex); - sessionMaxIndex = max(descriptor->session, sessionMaxIndex); - } - } - - if ( sessionMinIndex > kCDSessionMaxIndex ) // (no sessions?) - { - goto scanErr; - } - - if ( trackMinIndex > kCDTrackMaxIndex ) // (no tracks?) - { - goto scanErr; - } - - // Pre-scan the ordered list of tracks. - - for ( unsigned index = trackMinIndex; index <= trackMaxIndex; index++ ) - { - CDTrack * track = tracks + index; - - // Validate the existence of this track (and its session). - - if ( track->descriptor == 0 || sessions[track->session].leadOut == 0 ) - { - goto scanErr; - } - - // Determine the block type, and linkage requirement, for this track. - - if ( track->blockType == kCDSectorTypeMode1 ) // (data track?) - { - IOReturn status; - - // Read a whole sector from the data track into our buffer. - -///m:2333367:workaround:commented:start -// status = media->read( /* client */ this, -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read( /* client */ this, -///m:2333367:workaround:added:stop - /* byteStart */ track->block * mediaBlockSize, - /* buffer */ buffer ); - - if ( status == kIOReturnSuccess ) - { - UInt8 * sector = (UInt8 *) buffer->getBytesNoCopy(); - - // Determine whether this is a "mode 2" data track. - - if ( sector[15] == 0x02 ) - { - // Determine whether this is a "mode 2 formless", - // "mode 2 form 1" or "mode 2 form 2" data track. - - if ( sessions[track->session].isFormX ) - { - if ( (sector[18] & 0x20) ) - { - track->blockSize = kCDSectorSizeMode2Form2; - track->blockType = kCDSectorTypeMode2Form2; - } - else - { - track->blockSize = kCDSectorSizeMode2Form1; - track->blockType = kCDSectorTypeMode2Form1; - - // Determine whether this is a linked data track. - - if ( track->block && memcmp(sector + 24, "ER", 2) ) - { - trackMaxLinked = track; - } - } - } - else - { - track->blockSize = kCDSectorSizeMode2; - track->blockType = kCDSectorTypeMode2; - } - } - - // Determine whether this is a linked "mode 1" data track. - - else if ( track->block && memcmp(sector + 16, "ER", 2) ) - { - trackMaxLinked = track; - } - } - } - } - - // Create a media object to represent the linked data tracks, the hidden - // pre-gap-area data track, or even both, if it is applicable to this CD. - - if ( trackMaxLinked || tracks[trackMinIndex].block ) - { - CDTOCDescriptor descriptor; - UInt32 trackBlockNext; - CDSectorSize trackBlockSize; - CDSectorType trackBlockType; - UInt64 trackSize; - - descriptor.session = sessionMinIndex; - descriptor.control = 0x04; - descriptor.adr = 0x01; - descriptor.tno = 0x00; - descriptor.point = 0x00; - descriptor.address.minute = 0x00; - descriptor.address.second = 0x00; - descriptor.address.frame = 0x00; - descriptor.zero = 0x00; - descriptor.p = CDConvertLBAToMSF(0); - - if ( trackMaxLinked ) - { - descriptor.session = sessionMaxIndex; - descriptor.control = trackMaxLinked->descriptor->control; - - trackBlockNext = sessions[sessionMaxIndex].leadOut; - trackBlockSize = trackMaxLinked->blockSize; - trackBlockType = trackMaxLinked->blockType; - } - else - { - trackBlockNext = tracks[trackMinIndex].block; - trackBlockSize = kCDSectorSizeMode1; - trackBlockType = kCDSectorTypeMode1; - } - - trackSize = trackBlockNext * trackBlockSize; - - // Create a media object to represent this partition. - - IOMedia * newMedia = instantiateMediaObject( - /* partition */ &descriptor, - /* partitionSize */ trackSize, - /* partitionBlockSize */ trackBlockSize, - /* partitionBlockType */ trackBlockType, - /* toc */ toc ); - - if ( newMedia ) - { - partitions->setObject(newMedia); - newMedia->release(); - } - } - - // Scan the ordered list of tracks. - - for ( unsigned index = trackMinIndex; index <= trackMaxIndex; index++ ) - { - CDTrack * track = tracks + index; - UInt32 trackBlockNext; - UInt64 trackSize; - - // Determine whether this is a linked data track (skipped). - - if ( ( trackMaxLinked ) && - ( track->blockType == kCDSectorTypeMode1 || - track->blockType == kCDSectorTypeMode2Form1 ) ) - { - continue; - } - - // Determine where the partitions ends. - - if ( index < trackMaxIndex && track->session == (track + 1)->session ) - { - trackBlockNext = (track + 1)->block; - } - else - { - trackBlockNext = sessions[track->session].leadOut; - } - - if ( track->block >= trackBlockNext ) - { - goto scanErr; - } - - trackSize = (trackBlockNext - track->block) * track->blockSize; - - // Determine whether the partition is corrupt (fatal). - - if ( isPartitionCorrupt( /* partition */ track->descriptor, - /* partitionSize */ trackSize, - /* partitionBlockSize */ track->blockSize, - /* partitionBlockType */ track->blockType, - /* toc */ toc ) ) - { - goto scanErr; - } - - // Determine whether the partition is invalid (skipped). - - if ( isPartitionInvalid( /* partition */ track->descriptor, - /* partitionSize */ trackSize, - /* partitionBlockSize */ track->blockSize, - /* partitionBlockType */ track->blockType, - /* toc */ toc ) ) - { - continue; - } - - // Create a media object to represent this partition. - - IOMedia * newMedia = instantiateMediaObject( - /* partition */ track->descriptor, - /* partitionSize */ trackSize, - /* partitionBlockSize */ track->blockSize, - /* partitionBlockType */ track->blockType, - /* toc */ toc ); - - if ( newMedia ) - { - partitions->setObject(newMedia); - newMedia->release(); - } - } - - // Release our resources. - - media->close(this); - buffer->release(); - IODelete(tracks, CDTrack, kCDTrackMaxIndex + 1); - IODelete(sessions, CDSession, kCDSessionMaxIndex + 1); - - return partitions; - -scanErr: - - // Release our resources. - - if ( mediaIsOpen ) media->close(this); - if ( partitions ) partitions->release(); - if ( buffer ) buffer->release(); - if ( tracks ) IODelete(tracks, CDTrack, kCDTrackMaxIndex + 1); - if ( sessions ) IODelete(sessions, CDSession, kCDSessionMaxIndex + 1); - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOCDPartitionScheme::isPartitionCorrupt( - CDTOCDescriptor * /* partition */ , - UInt64 /* partitionSize */ , - UInt32 /* partitionBlockSize */ , - CDSectorType /* partitionBlockType */ , - CDTOC * /* toc */ ) -{ - // - // Ask whether the given partition appears to be corrupt. A partition that - // is corrupt will cause the failure of the CD partition scheme altogether. - // - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOCDPartitionScheme::isPartitionInvalid( - CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ) -{ - // - // Ask whether the given partition appears to be invalid. A partition that - // is invalid will cause it to be skipped in the scan, but will not cause a - // failure of the CD partition scheme. - // - - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - UInt64 partitionBase = 0; - - // Compute the relative byte position and size of the new partition, - // relative to the provider media's natural blocking factor of 2352. - - partitionBase = CDConvertMSFToLBA(partition->p) * mediaBlockSize; - partitionSize = (partitionSize / partitionBlockSize) * mediaBlockSize; - - // Determine whether the partition begins before the 00:02:00 mark. - - if ( partition->p.minute == 0 && partition->p.second < 2 ) return true; - - // Determine whether the partition leaves the confines of the container. - - if ( partitionBase + partitionSize > media->getSize() ) return true; - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOCDPartitionScheme::instantiateMediaObject( - CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ) -{ - // - // Instantiate a new media object to represent the given partition. - // - - IOMedia * media = getProvider(); - UInt64 partitionBase = 0; - char * partitionHint = 0; - - // Compute the relative byte position of the new partition and encode it - // into the designated "logical space", given the partition's block type. - // - // 0x0000000000 through 0x00FFFFFFFF is the "don't care" space. - // 0x0100000000 through 0x01FFFFFFFF is the "audio" space. - // 0x0200000000 through 0x02FFFFFFFF is the "mode 1" space. - // 0x0300000000 through 0x03FFFFFFFF is the "mode 2 formless" space. - // 0x0400000000 through 0x04FFFFFFFF is the "mode 2 form 1" space. - // 0x0500000000 through 0x05FFFFFFFF is the "mode 2 form 2" space. - - partitionBase = CDConvertMSFToLBA(partition->p) * partitionBlockSize; - partitionBase += ((UInt64) partitionBlockType) << 32; - - // Look up a type for the new partition. - - OSDictionary * hintTable = OSDynamicCast( - /* type */ OSDictionary, - /* instance */ getProperty(kIOCDPartitionSchemeContentTable) ); - - if ( hintTable ) - { - char hintIndex[5]; - OSString * hintValue; - - sprintf(hintIndex, "0x%02X", partitionBlockType & 0xFF); - - hintValue = OSDynamicCast(OSString, hintTable->getObject(hintIndex)); - - if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy(); - } - - // Create the new media object. - - IOMedia * newMedia = instantiateDesiredMediaObject( - /* partition */ partition, - /* partitionSize */ partitionSize, - /* partitionBlockSize */ partitionBlockSize, - /* partitionBlockType */ partitionBlockType, - /* toc */ toc ); - - if ( newMedia ) - { - if ( newMedia->init( - /* base */ partitionBase, - /* size */ partitionSize, - /* preferredBlockSize */ partitionBlockSize, - /* isEjectable */ media->isEjectable(), - /* isWhole */ false, - /* isWritable */ media->isWritable(), - /* contentHint */ partitionHint ) ) - { - // Set a name for this partition. - - char name[24]; - sprintf(name, "Untitled %d", partition->point); - newMedia->setName(name); - - // Set a location value (the partition number) for this partition. - - char location[12]; - sprintf(location, "%d", partition->point); - newMedia->setLocation(location); - - // Set the "Partition ID" key for this partition. - - newMedia->setProperty(kIOMediaPartitionIDKey, partition->point, 32); - - // Set the "Session ID" key for this partition. - - newMedia->setProperty(kIOMediaSessionIDKey, partition->session, 32); - } - else - { - newMedia->release(); - newMedia = 0; - } - } - - return newMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOCDPartitionScheme::instantiateDesiredMediaObject( - CDTOCDescriptor * /* partition */ , - UInt64 /* partitionSize */ , - UInt32 /* partitionBlockSize */ , - CDSectorType /* partitionBlockType */ , - CDTOC * /* toc */ ) -{ - // - // Allocate a new media object (called from instantiateMediaObject). - // - - return new IOMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOCDPartitionScheme::read( IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion ) -{ - // - // Read data from the storage object at the specified byte offset into the - // specified buffer, asynchronously. When the read completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the read. - // - // For the CD partition scheme, we convert the read from a partition - // object into the appropriate readCD command to our provider media. - // - - getProvider()->readCD( /* client */ this, - /* byteStart */ (byteStart & 0xFFFFFFFF), - /* buffer */ buffer, - /* sectorArea */ (CDSectorArea) kCDSectorAreaUser, - /* sectorType */ (CDSectorType) (byteStart >> 32), - /* completion */ completion ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOCDPartitionScheme, 15); diff --git a/iokit/Families/IODVDBlockStorage/IODVDBlockStorageDevice.cpp b/iokit/Families/IODVDBlockStorage/IODVDBlockStorageDevice.cpp deleted file mode 100644 index 5ed3a43f3..000000000 --- a/iokit/Families/IODVDBlockStorage/IODVDBlockStorageDevice.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/storage/IODVDBlockStorageDevice.h> - -#define super IOCDBlockStorageDevice -OSDefineMetaClass(IODVDBlockStorageDevice,IOCDBlockStorageDevice) -OSDefineAbstractStructors(IODVDBlockStorageDevice,IOCDBlockStorageDevice) - -bool -IODVDBlockStorageDevice::init(OSDictionary * properties) -{ - bool result; - - result = super::init(properties); - if (result) { - setProperty(kIOBlockStorageDeviceTypeKey,kIOBlockStorageDeviceTypeDVD); - } - - return(result); -} - -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 0); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 1); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 2); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 3); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 4); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 5); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 6); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 7); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 8); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 9); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 10); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 11); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 12); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 13); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 14); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 15); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 16); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 17); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 18); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 19); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 20); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 21); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 22); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 23); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 24); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 25); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 26); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 27); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 28); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 29); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 30); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDevice, 31); diff --git a/iokit/Families/IODVDStorage/IODVDBlockStorageDriver.cpp b/iokit/Families/IODVDStorage/IODVDBlockStorageDriver.cpp deleted file mode 100644 index a6a56c453..000000000 --- a/iokit/Families/IODVDStorage/IODVDBlockStorageDriver.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOLib.h> -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/IODVDBlockStorageDriver.h> -#include <IOKit/storage/IODVDMedia.h> - -#define super IOCDBlockStorageDriver -OSDefineMetaClassAndStructors(IODVDBlockStorageDriver,IOCDBlockStorageDriver) - -IODVDBlockStorageDevice * -IODVDBlockStorageDriver::getProvider() const -{ - return (IODVDBlockStorageDevice *) IOService::getProvider(); -} - -/* Accept a new piece of media, doing whatever's necessary to make it - * show up properly to the system. - */ -IOReturn -IODVDBlockStorageDriver::acceptNewMedia(void) -{ - UInt32 mediaType = getMediaType(); - - if (mediaType >= kCDMediaTypeMin && mediaType <= kCDMediaTypeMax) { - return IOCDBlockStorageDriver::acceptNewMedia(); - } else { - return IOBlockStorageDriver::acceptNewMedia(); - } -} - -const char * -IODVDBlockStorageDriver::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeDVD); -} - -IOMedia * -IODVDBlockStorageDriver::instantiateDesiredMediaObject(void) -{ - UInt32 mediaType = getMediaType(); - - if (mediaType >= kCDMediaTypeMin && mediaType <= kCDMediaTypeMax) { - return IOCDBlockStorageDriver::instantiateDesiredMediaObject(); - } else { - return(new IODVDMedia); - } -} - -IOMedia * -IODVDBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName) -{ - IOMedia *media = NULL; - UInt32 mediaType = getMediaType(); - - if (mediaType >= kCDMediaTypeMin && mediaType <= kCDMediaTypeMax) { - return IOCDBlockStorageDriver::instantiateMediaObject( - base,byteSize,blockSize,mediaName); - } else { - media = IOBlockStorageDriver::instantiateMediaObject( - base,byteSize,blockSize,mediaName); - } - - if (media) { - char *description = NULL; - - switch (mediaType) { - case kDVDMediaTypeROM: - description = kIODVDMediaTypeROM; - break; - case kDVDMediaTypeRAM: - description = kIODVDMediaTypeRAM; - break; - case kDVDMediaTypeR: - description = kIODVDMediaTypeR; - break; - case kDVDMediaTypeRW: - description = kIODVDMediaTypeRW; - break; - case kDVDMediaTypePlusRW: - description = kIODVDMediaTypePlusRW; - break; - } - - if (description) { - media->setProperty(kIODVDMediaTypeKey, description); - } - } - - return media; -} - -IOReturn -IODVDBlockStorageDriver::reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat) -{ - return(getProvider()->reportKey(buffer,keyClass,lba,agid,keyFormat)); -} - -IOReturn -IODVDBlockStorageDriver::sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat) -{ - return(getProvider()->sendKey(buffer,keyClass,agid,keyFormat)); -} - -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 0); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 1); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 2); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 3); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 4); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 5); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 6); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 7); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 8); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 9); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 10); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 11); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 12); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 13); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 14); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 15); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 16); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 17); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 18); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 19); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 20); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 21); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 22); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 23); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 24); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 25); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 26); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 27); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 28); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 29); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 30); -OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 31); diff --git a/iokit/Families/IODVDStorage/IODVDMedia.cpp b/iokit/Families/IODVDStorage/IODVDMedia.cpp deleted file mode 100644 index 4586a4b8f..000000000 --- a/iokit/Families/IODVDStorage/IODVDMedia.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/storage/IODVDBlockStorageDriver.h> -#include <IOKit/storage/IODVDMedia.h> - -#define super IOMedia -OSDefineMetaClassAndStructors(IODVDMedia, IOMedia) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IODVDBlockStorageDriver * IODVDMedia::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method to - // return a more specific subclass of IOService -- IODVDBlockStorageDriver. - // This method serves simply as a convenience to subclass developers. - // - - return (IODVDBlockStorageDriver *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 15); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 16); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 17); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 18); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 19); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 20); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 21); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 22); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 23); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 24); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 25); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 26); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 27); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 28); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 29); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 30); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IODVDMedia, 31); diff --git a/iokit/Families/IOGraphics/ADBTest.m b/iokit/Families/IOGraphics/ADBTest.m deleted file mode 100644 index a3b09d671..000000000 --- a/iokit/Families/IOGraphics/ADBTest.m +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <driverkit/IODevice.h> -#include <driverkit/IODeviceMaster.h> -#include <stdlib.h> - -void main( void ) -{ - IOReturn err; - IOString kind; - int reg[ 2 ]; - int retCount; - IOObjectNumber obj; - int i; - - err = _IOLookupByDeviceName( device_master_self(), "display@Display0", - &obj, &kind); - printf("_IOLookupByDeviceName = %d\n", err ); - - retCount = sizeof(int); - err = _IOCallDeviceMethod( device_master_self(), obj, - "IOSMADBGetAVDeviceID:size:", - nil, 0, - &retCount, - ®[ 1 ], - &retCount); - printf("IOSMADBGetAVDeviceID(%d) = %08x\n", err, reg[ 1 ] ); - - reg[0] = 0xff; - reg[1] = 0xff; - retCount = 0; - err = _IOCallDeviceMethod( device_master_self(), obj, - "IOSMADBSetLogicalRegister:size:", - reg, sizeof( reg), - &retCount, - nil, - &retCount); - printf("IOSMADBSetLogicalRegister(%d)\n", err ); - - for( i = 0; i < 4; i++) { - reg[0] = 0xff; - retCount = sizeof(int); - err = _IOCallDeviceMethod( device_master_self(), obj, - "IOSMADBGetLogicalRegister:size:result:size:", - reg, sizeof( int), - &retCount, - ®[ 1 ], - &retCount); - printf("IOSMADBGetLogicalRegister(%d) = %08x\n", err, reg[ 1 ] ); - } -} diff --git a/iokit/Families/IOGraphics/AppleDDCDisplay.cpp b/iokit/Families/IOGraphics/AppleDDCDisplay.cpp deleted file mode 100644 index 8fb6d59d2..000000000 --- a/iokit/Families/IOGraphics/AppleDDCDisplay.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 23 Jul 98 - start IOKit - * sdouglas 08 Dec 98 - start cpp - */ - -#include <IOKit/graphics/IODisplay.h> -#include <libkern/c++/OSContainers.h> -#include <IOKit/IOLib.h> - -#include <IOKit/assert.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -struct EDID { - UInt8 header[8]; - UInt8 vendorProduct[4]; - UInt8 serialNumber[4]; - UInt8 weekOfManufacture; - UInt8 yearOfManufacture; - UInt8 version; - UInt8 revision; - UInt8 displayParams[5]; - UInt8 colorCharacteristics[10]; - UInt8 establishedTimings[3]; - UInt16 standardTimings[8]; - UInt8 detailedTimings[72]; - UInt8 extension; - UInt8 checksum; -}; - -struct TimingToEDID { - UInt32 timingID; - UInt8 spare; - UInt8 establishedBit; - UInt16 standardTiming; -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class AppleDDCDisplay : public IODisplay -{ - OSDeclareDefaultStructors(AppleDDCDisplay) - -private: - OSData * edidData; - OSData * additions; - OSData * deletions; - TimingToEDID * timingToEDID; - int numEDIDEntries; - -public: - virtual IOService * probe( IOService * provider, - SInt32 * score ); - - virtual bool start( IOService * provider ); - - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ); -}; - -#undef super -#define super IODisplay - -OSDefineMetaClassAndStructors(AppleDDCDisplay, IODisplay) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOService * AppleDDCDisplay::probe( IOService * provider, - SInt32 * score ) -{ - IODisplayConnect * connect; - IOFramebuffer * framebuffer; - IOService * ret = 0; - - do { - - if( 0 == super::probe( provider, score )) - continue; - - connect = getConnection(); - framebuffer = connect->getFramebuffer(); - assert( framebuffer ); - - if( kIOReturnSuccess != framebuffer->getAttributeForConnection( - connect->getConnection(), - kConnectionSupportsHLDDCSense, NULL )) - continue; - - if( framebuffer->hasDDCConnect( connect->getConnection())) - ret = this; - - } while( false); - - return( ret ); -} - - -bool AppleDDCDisplay::start( IOService * provider ) -{ - IOReturn err; - IODisplayConnect * connect; - IOFramebuffer * framebuffer; - OSData * data; - OSData * overrideData; - OSArray * array; - OSDictionary * dict; - OSNumber * off; - IOByteCount length; - EDID readEDID; - EDID * edid; - UInt32 vendorProd; - UInt32 index; - UInt32 numExts; - - connect = getConnection(); - framebuffer = connect->getFramebuffer(); - assert( framebuffer ); - - do { - length = sizeof( EDID); - err = framebuffer->getDDCBlock( connect->getConnection(), - 1, kIODDCBlockTypeEDID, 0, (UInt8 *) &readEDID, &length ); - if( err || (length != sizeof( EDID))) - continue; - - IOLog("%s EDID Version %d, Revision %d\n", framebuffer->getName(), - readEDID.version, readEDID.revision ); - if( readEDID.version != 1) - continue; - - if( (data = (OSData *) getProperty( "appleDDC" ))) { - timingToEDID = (TimingToEDID *) data->getBytesNoCopy(); - numEDIDEntries = data->getLength() / sizeof(TimingToEDID); - } else - continue; - - vendorProd = (readEDID.vendorProduct[0] << 24) - | (readEDID.vendorProduct[1] << 16) - | (readEDID.vendorProduct[2] << 8) - | (readEDID.vendorProduct[3] << 0); - -#if 1 - IOLog("Vendor/product 0x%08lx, ", vendorProd ); - IOLog("Est: "); - for( index = 0; index < 3; index++) - IOLog(" 0x%02x,", readEDID.establishedTimings[ index ] ); - IOLog("\nStd: " ); - for( index = 0; index < 8; index++) - IOLog(" 0x%04x,", readEDID.standardTimings[ index ] ); - IOLog("\n"); -#endif - - data = OSData::withBytes( &readEDID, sizeof( EDID )); - if( !data) - continue; - - numExts = readEDID.extension; - for( index = 2; index < (2 + numExts); index++) { - length = sizeof( EDID); - err = framebuffer->getDDCBlock( connect->getConnection(), - index, kIODDCBlockTypeEDID, 0, (UInt8 *) &readEDID, &length ); - if( err || (length != sizeof( EDID))) - break; - if( !data->appendBytes( &readEDID, sizeof( EDID ) )) - break; - } - - overrideData = 0; - additions = 0; - if( (array = OSDynamicCast(OSArray, getProperty("overrides")))) { - for( index = 0; - (dict = OSDynamicCast(OSDictionary, array->getObject(index))); - index++ ) { - if( 0 == (off = OSDynamicCast(OSNumber, dict->getObject("ID")))) - continue; - if( vendorProd == off->unsigned32BitValue()) { - overrideData = OSDynamicCast(OSData, - dict->getObject( "EDID")); - additions = OSDynamicCast(OSData, - dict->getObject("additions")); - deletions = OSDynamicCast(OSData, - dict->getObject("deletions")); - break; - } - } - } - - if( overrideData) - data = overrideData; - - setProperty( kIODisplayEDIDKey, data ); - data->release(); - edidData = data; - - edid = (EDID *) edidData->getBytesNoCopy(); - // vendor - vendorProd = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1]; - setProperty( kDisplayVendorID, vendorProd, 32); - // product - vendorProd = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2]; - setProperty( kDisplayProductID, vendorProd, 32); - - return( super::start( provider)); - - } while( false); - - return( false); -} - -IOReturn AppleDDCDisplay::getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ) -{ - IOReturn err; - IODisplayConnect * connect; - IOFramebuffer * framebuffer; - IOTimingInformation info; - const TimingToEDID * lookTiming; - UInt32 estBit, i; - EDID * edid; - UInt32 * dataModes; - UInt32 numData; - UInt32 appleTimingID; - bool supported = false; - bool deleted = false; - enum { kSetFlags = (kDisplayModeValidFlag - | kDisplayModeSafeFlag) }; - - - connect = getConnection(); - framebuffer = connect->getFramebuffer(); - assert( framebuffer ); - - if( kIOReturnSuccess != framebuffer->connectFlags( connect->getConnection(), - mode, flags )) - *flags = 0; - - err = framebuffer->getTimingInfoForDisplayMode( mode, &info ); - if( err != kIOReturnSuccess) - return( err); - - appleTimingID = info.appleTimingID; - - if( deletions) { - numData = deletions->getLength() / sizeof( UInt32); - dataModes = (UInt32 *) deletions->getBytesNoCopy(); - for( i = 0; (!deleted) && (i < numData); i++) - deleted = (dataModes[ i ] == appleTimingID); - } - - if( !deleted) { - - if( additions) { - numData = additions->getLength() / sizeof( UInt32); - dataModes = (UInt32 *) additions->getBytesNoCopy(); - for( i = 0; (!supported) && (i < numData); i++) - supported = (dataModes[ i ] == appleTimingID); - } - - edid = (EDID *) edidData->getBytesNoCopy(); - assert( edid ); - for( lookTiming = timingToEDID; - (!supported) && ((lookTiming - timingToEDID) < numEDIDEntries); - lookTiming++ ) { - - if( lookTiming->timingID == appleTimingID) { - estBit = lookTiming->establishedBit; - if( estBit != 0xff) - supported = (0 != (edid->establishedTimings[ estBit / 8 ] - & (1 << (estBit % 8)))); - - for( i = 0; (!supported) && (i < 8); i++ ) - supported = (lookTiming->standardTiming - == edid->standardTimings[i] ); - } - } - } - - if( supported) - *flags = ((*flags) & ~kDisplayModeSafetyFlags) | kSetFlags; - - // Pass the existing flags (from framebuffer) thru - return( err); -} - diff --git a/iokit/Families/IOGraphics/AppleG3SeriesDisplay.cpp b/iokit/Families/IOGraphics/AppleG3SeriesDisplay.cpp deleted file mode 100644 index 9e9e451c4..000000000 --- a/iokit/Families/IOGraphics/AppleG3SeriesDisplay.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOLib.h> -#include <IOKit/graphics/IODisplay.h> -#include <IOKit/ndrvsupport/IOMacOSVideo.h> - -#include <Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.h> - -#define kNumber_of_power_states 4 -#define kNumber_of_power_levels 32 - -#define kScreenBit 0x01 -#define kPowerOn 0x80 -#define kPowerOff 0x00 -#define kDisplayOn kScreenBit | kPowerOn -#define kDisplayOff kScreenBit | kPowerOff - -class AppleG3SeriesDisplay : public AppleSenseDisplay -{ - OSDeclareDefaultStructors(AppleG3SeriesDisplay) - -private: - -int current_user_brightness; // 0-31. The brightness level last selected via the brightness buttons. -int current_level; // 0-31. The current brightness level -IOService * PMUdriver; // points to PMU driver -int * rawTable; // points to table of raw brightess levels - -// the constants used to talk with the pmu: -enum { - kPMUpower1Read = 0x19, // more power status (DBLite) - kPMUReadBrightness = 0x49, // read the brightness value - kPMUpower1Cntl = 0x11, // more power control (DBLite) - kPMUSetBrightness = 0x41 // set screen brightness -}; - -// We need this to callPlatformFunction when sending to sendMiscCommand -typedef struct SendMiscCommandParameterBlock { - int command; - IOByteCount sLength; - UInt8 *sBuffer; - IOByteCount *rLength; - UInt8 *rBuffer; -} SendMiscCommandParameterBlock; -typedef SendMiscCommandParameterBlock *SendMiscCommandParameterBlockPtr; - -// A simpler way to interface with the pmu SendMiscCommand -IOReturn localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer); - -public: - IOService * probe ( IOService *, SInt32 * ); - virtual void initForPM ( IOService* ); - virtual IOReturn setPowerState ( unsigned long, IOService* ); - virtual unsigned long maxCapabilityForDomainState ( IOPMPowerFlags ); - virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags ); - virtual unsigned long powerStateForDomainState ( IOPMPowerFlags ); - virtual void ourButtonHandler ( unsigned int ); - virtual void setBrightness ( long ); -}; - -void upButtonHandler(AppleG3SeriesDisplay *); -void downButtonHandler(AppleG3SeriesDisplay *); - - -/* - The actual display panel has 128 power levels. Copying the MacOS, we only implement 32 of them. - We further divide the 32 into four IOKit power states which we export to our superclass. - - In the lowest state, the display is off. This state consists of only one of the 32 power levels, the lowest. - In the next state it is in the dimmest usable state. This state also consists of only one of the 32 levels, the second lowest. - The next state is also dim and consists of seven of the 32 levels. - The highest state consists of the highest 23 levels. - - The display has no state or configuration or programming that would be saved/restored over power state changes, - and the driver does not register with the superclass as an interested driver. - - This driver doesn't have much to do. It changes between the four power state brightnesses on command - from the superclass, and it raises and lowers the display brightness by one of the 32 brightness levels - when it receives a brightness-button interrupt from the ADB stack. - - The only smart thing it does is keep track of which of the 32 brightness levels the user has selected by button, and it - never exceeds that on command from the display device object. It only raises above that on an brightness-up-button - interrupt. - - */ - - -static IOPMPowerState ourPowerStates[kNumber_of_power_states] = { - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0} -}; - -static int max_brightness_level[kNumber_of_power_states] = {0,1,8,31}; - -static int HooperTable[ ] = {127,71,69,67,65,63,61,59, - 58,56,54,52,50,48,46,44, - 42,40,38,37,35,33,31,29, - 27,25,23,21,19,18,16,14 }; - -bool ourNotificationHandler( OSObject *, void *, IOService * ); - -#define super AppleSenseDisplay - -OSDefineMetaClassAndStructors(AppleG3SeriesDisplay, AppleSenseDisplay) - - -// ********************************************************************************** -// probe -// -// ********************************************************************************** -IOService * AppleG3SeriesDisplay::probe ( IOService * provider, SInt32 * score ) -{ - IOFramebuffer * framebuffer; - IOService * ret = 0; - UInt32 displayType; - IOIndex ourIndex; - - do { - if ( 0 == super::probe( provider, score ) ) { - continue; - } - - framebuffer = (IOFramebuffer *)getConnection()->getFramebuffer(); // point to our framebuffer - ourIndex = getConnection()->getConnection(); // get our connection index on this framebuffer - - if ( kIOReturnSuccess != framebuffer->getAppleSense(ourIndex,NULL,NULL,NULL,&displayType) ) { - continue; - } - - if ( !(displayType == kPanelTFTConnect) ) { // does it have a panel attached? - continue; // no - } - ret = this; // yes, we will control the panel - - } while ( false ); - - return ( ret ); -} - -// ********************************************************************************** -// localSendMiscCommand -// -// ********************************************************************************** -IOReturn AppleG3SeriesDisplay::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer, IOByteCount *rLength, UInt8 *rBuffer) -{ - IOReturn returnValue = kIOReturnError; - - // The poupose of this method is to free us from the pain to create a parameter block each time - // we wish to talk to the pmu: - SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, rLength, rBuffer}; - - IOLog("AppleG3SeriesDisplay::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n", - command, sLength, sBuffer, rLength, rBuffer); - - if (PMUdriver != NULL) { - IOLog("AppleG3SeriesDisplay::localSendMiscCommand calling PMUdriver->callPlatformFunction\n"); - returnValue = PMUdriver->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock, NULL, NULL, NULL); - } - - // If we are here we do not have a dreive to talk to: - IOLog("AppleG3SeriesDisplay::localSendMiscCommand end 0x%08lx\n", returnValue); - - return returnValue; -} - -// ********************************************************************************** -// initForPM -// -// This method overrides the one in IODisplay.h to do PowerBook-only -// power management of the display. -// ********************************************************************************** -void AppleG3SeriesDisplay::initForPM ( IOService * provider ) -{ - unsigned long i; - - UInt8 PMUreceiveBuffer[10]; // (I think 1 is enough, but it scares me) - IOByteCount unused = sizeof(PMUreceiveBuffer); - - displayPMVars->powerControllable = true; - - PMinit(); // initialize superclass variables - - PMUdriver = waitForService(serviceMatching("ApplePMU")); - - rawTable = HooperTable; - - localSendMiscCommand(kPMUpower1Read,0, NULL, &unused,PMUreceiveBuffer); - - if ( PMUreceiveBuffer[0] & kScreenBit ) { // is the screen currently on? - unused = sizeof(PMUreceiveBuffer); - localSendMiscCommand(kPMUReadBrightness,0, NULL, &unused,PMUreceiveBuffer); // yes, figure out the brightness - current_user_brightness = kNumber_of_power_levels - 1; // ( in case the for-loop doesn't break) - current_level = kNumber_of_power_levels - 1; - - for ( i = 0; i < kNumber_of_power_levels; i++ ) { - if ( PMUreceiveBuffer[0] >= rawTable[i] ) { - current_user_brightness = i; - current_level = i; - break; - } - } - } - else { // no - current_user_brightness = 0; - current_level = 0; - } - - addNotification( gIOPublishNotification,serviceMatching("AppleADBButtons"), // look for the button driver - (IOServiceNotificationHandler)ourNotificationHandler, this, 0 ); - - provider->joinPMtree(this); // attach into the power management hierarchy - registerPowerDriver(this,ourPowerStates,kNumber_of_power_states); // register with policy-maker (us) -} - - -// ********************************************************************************** -// ourNotificationHandler -// -// The ADB button driver has appeared. Tell it we are interested in the -// brightness-up button and the brightness-down button. -// ********************************************************************************** -bool ourNotificationHandler( OSObject * us, void * ref, IOService * yourDevice ) -{ - if ( yourDevice != NULL ) { - ((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_up,(IOService *)us,(button_handler)upButtonHandler,true); - ((AppleADBButtons *)yourDevice)->registerForButton(kBrightness_down,(IOService *)us,(button_handler)downButtonHandler,true); - } - return true; -} - - -// ********************************************************************************** -// setPowerState -// -// All power state changes require a call to the PMU driver, which -// blocks the thread till the command completes. -// ********************************************************************************** -IOReturn AppleG3SeriesDisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ) -{ - UInt8 displayOn = kDisplayOn; - UInt8 displayOff = kDisplayOff; - unsigned long i; - - if ( powerStateOrdinal < kNumber_of_power_states ) { - if ( powerStateOrdinal > pm_vars->myCurrentState ) { // raising power - if ( pm_vars->myCurrentState == 0 ) { // is it currently off? - IOByteCount unused = 0; - localSendMiscCommand(kPMUpower1Cntl,1, &displayOn, &unused,NULL); - } - current_level = max_brightness_level[powerStateOrdinal]; - if ( current_user_brightness < current_level ) { - current_level = current_user_brightness; // don't exceed what the user used to have it at - } - setBrightness(current_level); - // If we are still higher than we need to be, request a lower state - for ( i = 0; i < kNumber_of_power_states; i++ ) { // figure out what state we should be in - if ( current_level <= max_brightness_level[i] ) { - break; - } - } - if ( pm_vars->myCurrentState > i ) { - changePowerStateToPriv(i); - } - } - - if ( powerStateOrdinal < pm_vars->myCurrentState ) { // lowering power - if (powerStateOrdinal == 0 ) { // going all the way off? - IOByteCount unused = 0; - localSendMiscCommand(kPMUpower1Cntl,1, &displayOff, &unused,NULL); // yes - current_level = max_brightness_level[powerStateOrdinal]; - } - else { - if ( current_level > max_brightness_level[powerStateOrdinal] ) { // no - current_level = max_brightness_level[powerStateOrdinal]; - setBrightness(current_level); - } - } - } - } - return IOPMAckImplied; -} - - -// ********************************************************************************** -// maxCapabilityForDomainState -// -// This simple device needs only power. If the power domain is supplying -// power, the display can go to its highest state. If there is no power -// it can only be in its lowest state, which is off. -// ********************************************************************************** -unsigned long AppleG3SeriesDisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) -{ - if ( domainState & IOPMPowerOn ) { - return kNumber_of_power_states-1; - } - return 0; -} - - -// ********************************************************************************** -// initialPowerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. -// ********************************************************************************** -unsigned long AppleG3SeriesDisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) -{ - long unsigned i; - - if ( domainState & IOPMPowerOn ) { // domain has power - for ( i = 0; i < kNumber_of_power_states; i++ ) { // find power state that has our current - if ( current_level <= max_brightness_level[i] ) { // brightness level - return i; - break; - } - } - } - return 0; // domain is down, so display is off -} - - -// ********************************************************************************** -// powerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. -// ********************************************************************************** -unsigned long AppleG3SeriesDisplay::powerStateForDomainState ( IOPMPowerFlags domainState ) -{ - long unsigned i; - - if ( domainState & IOPMPowerOn ) { // domain has power - for ( i = 0; i < kNumber_of_power_states; i++ ) { // find power state that has our current - if ( current_level <= max_brightness_level[i] ) { // brightness level - return i; - } - } - } - return 0; // domain is down, so display is off -} - - -// ********************************************************************************** -// upButtonHandler -// -// The display-brightness-up button just went down. -// We are running on a new thread made by the ADB Button driver -// ********************************************************************************** -void upButtonHandler(AppleG3SeriesDisplay * us ) -{ - ((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_up); -} - - -// ********************************************************************************** -// downButtonHandler -// -// The display-brightness-down button just went down. -// We are running on a new thread made by the ADB Button driver -// ********************************************************************************** -void downButtonHandler(AppleG3SeriesDisplay * us ) -{ - ((AppleG3SeriesDisplay *)us)->ourButtonHandler(kBrightness_down); -} - - -// ********************************************************************************** -// ourButtonHandler -// -// Alter the backlight brightness up or down by one increment. -// This involves a call to the PMU driver, which will block the thread. -// ********************************************************************************** -void AppleG3SeriesDisplay::ourButtonHandler ( unsigned int keycode ) -{ // If we are idle, ignore the button. - // The display will be made usable - if ( ! displayPMVars->displayIdle ) { // by the DisplayWrangler - switch (keycode) { - case kBrightness_up: // The brightness-up button has just been pressed - // We make sure the brightness is not above the maximum - // brightness level of our current power state. If it - // is too high, we ask the device to raise power. - if (current_level < max_brightness_level[pm_vars->myCurrentState] ) { - current_level++; - current_user_brightness = current_level; - setBrightness(current_level); - } - else { - if ( pm_vars->myCurrentState < (kNumber_of_power_states-1) ) { - current_user_brightness++; // increment user's desire - if ( changePowerStateToPriv(pm_vars->myCurrentState + 1) != IOPMNoErr ) { // request higher power - current_user_brightness--; // can't - } - } - } - break; - - case kBrightness_down: // The brightness-down button has just been pressed - // We lower the brightness, and if that takes us into a - // lower power state, we tell our parent about it. - if ( pm_vars->myCurrentState > 0 ) { // don't lower if in lowest (off) state - if ( current_level > 0 ) { - current_level--; - current_user_brightness = current_level; - setBrightness(current_level); - if (current_level <= max_brightness_level[pm_vars->myCurrentState - 1] ) { // if this takes us into the next lower state - changePowerStateToPriv(pm_vars->myCurrentState - 1); // request lower power - } - } - } - break; - } - } -} - - -// ********************************************************************************** -// setBrightness -// -// Instruct PMU to set the display brightness. -// This will block the thread while the command completes. -// ********************************************************************************** -void AppleG3SeriesDisplay::setBrightness ( long brightness ) -{ - IOByteCount unused = 0; - UInt8 setBrightnessBuffer; - - setBrightnessBuffer = (UInt8)rawTable[brightness]; - localSendMiscCommand(kPMUSetBrightness,1, &setBrightnessBuffer, &unused,NULL); -} diff --git a/iokit/Families/IOGraphics/DDCInfo.m b/iokit/Families/IOGraphics/DDCInfo.m deleted file mode 100644 index 8ba555c95..000000000 --- a/iokit/Families/IOGraphics/DDCInfo.m +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <driverkit/ppc/IOMacOSTypes.h> -#include "IOMacOSVideo.h" -#include <stdlib.h> - -struct TimingToEDID { - UInt32 timingID; - UInt8 spare; - UInt8 establishedBit; - UInt16 standardTiming; -}; -typedef struct TimingToEDID TimingToEDID; - -#define MAKESTD(h,a,r) ( (((h/8)-31)<<8) | (a<<6) | (r-60) ) - -static const TimingToEDID timingToEDID[] = { - { timingApple_512x384_60hz, 0, 0xff, MAKESTD( 512,1,60) }, - { timingApple_640x480_67hz, 0, 0x04, MAKESTD( 640,1,67) }, - { timingVESA_640x480_60hz, 0, 0x05, MAKESTD( 640,1,60) }, - { timingVESA_640x480_72hz , 0, 0x03, MAKESTD( 640,1,72) }, - { timingVESA_640x480_75hz, 0, 0x02, MAKESTD( 640,1,75) }, - { timingVESA_640x480_85hz, 0, 0xff, MAKESTD( 640,1,85) }, - { timingApple_832x624_75hz, 0, 0x0d, MAKESTD( 832,1,75) }, - { timingVESA_800x600_56hz, 0, 0x01, MAKESTD( 800,1,56) }, - { timingVESA_800x600_60hz, 0, 0x00, MAKESTD( 800,1,60) }, - { timingVESA_800x600_72hz, 0, 0x0f, MAKESTD( 800,1,72) }, - { timingVESA_800x600_75hz, 0, 0x0e, MAKESTD( 800,1,75) }, - { timingVESA_800x600_85hz, 0, 0xff, MAKESTD( 800,1,85) }, - { timingVESA_1024x768_60hz, 0, 0x0b, MAKESTD( 1024,1,60) }, - { timingVESA_1024x768_70hz, 0, 0x0a, MAKESTD( 1024,1,70) }, - { timingVESA_1024x768_75hz, 0, 0x09, MAKESTD( 1024,1,75) }, - { timingVESA_1024x768_85hz, 0, 0xff, MAKESTD( 1024,1,85) }, - { timingApple_1024x768_75hz, 0, 0x09, MAKESTD( 1024,1,75) }, - { timingApple_1152x870_75hz, 0, 0x17, MAKESTD( 0000,0,00) }, - { timingVESA_1280x960_75hz, 0, 0xff, MAKESTD( 1280,1,75) }, - { timingVESA_1280x1024_60hz, 0, 0xff, MAKESTD( 1280,2,60) }, - { timingVESA_1280x1024_75hz, 0, 0x08, MAKESTD( 1280,2,75) }, - { timingVESA_1280x1024_85hz, 0, 0xff, MAKESTD( 1280,2,85) }, - { timingVESA_1600x1200_60hz, 0, 0xff, MAKESTD( 1600,1,60) }, - { timingVESA_1600x1200_65hz, 0, 0xff, MAKESTD( 1600,1,65) }, - { timingVESA_1600x1200_70hz, 0, 0xff, MAKESTD( 1600,1,70) }, - { timingVESA_1600x1200_75hz, 0, 0xff, MAKESTD( 1600,1,75) }, - { timingVESA_1600x1200_80hz, 0, 0xff, MAKESTD( 1600,1,80) } -}; - - -void main( void ) -{ - const TimingToEDID * lookTiming; - - lookTiming = timingToEDID; - while( lookTiming < (timingToEDID + sizeof( timingToEDID) / sizeof( TimingToEDID))) { - - printf("%d 0x%x ", lookTiming->timingID, - *((unsigned int *)&lookTiming->spare) ); - lookTiming++; - } - printf("\n"); -} - diff --git a/iokit/Families/IOGraphics/IOBootFramebuffer.cpp b/iokit/Families/IOGraphics/IOBootFramebuffer.cpp deleted file mode 100644 index c9e4caad1..000000000 --- a/iokit/Families/IOGraphics/IOBootFramebuffer.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Boot video dumb frambuffer shim - */ - -#include "IOBootFramebuffer.h" - -enum { kTheDisplayMode = 10 }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOFramebuffer - -OSDefineMetaClassAndStructors(IOBootFramebuffer, IOFramebuffer) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOService * IOBootFramebuffer::probe( IOService * provider, - SInt32 * score ) -{ - PE_Video bootDisplay; - IOService * ret = 0; - IOReturn err; - - do { - - if( !provider->getProperty("AAPL,boot-display")) - continue; - - err = getPlatform()->getConsoleInfo( &bootDisplay ); - if( err || (bootDisplay.v_baseAddr == 0)) - continue; - - if (false == super::probe( provider, score )) - continue; - - *score = 0; - ret = this; // Success - - } while( false); - - return( ret); -} - - -const char * IOBootFramebuffer::getPixelFormats( void ) -{ - const char * ret; - PE_Video bootDisplay; - - getPlatform()->getConsoleInfo( &bootDisplay); - - switch( bootDisplay.v_depth) { - case 8: - default: - ret = IO8BitIndexedPixels; - break; - case 15: - case 16: - ret = IO16BitDirectPixels; - break; - case 24: - case 32: - ret = IO32BitDirectPixels; - break; - } - - return( ret); -} - -IOItemCount IOBootFramebuffer::getDisplayModeCount( void ) -{ - return( 1); -} - -IOReturn IOBootFramebuffer::getDisplayModes( - IODisplayModeID * allDisplayModes ) -{ - - *allDisplayModes = kTheDisplayMode; - return( kIOReturnSuccess); -} - -IOReturn IOBootFramebuffer::getInformationForDisplayMode( - IODisplayModeID /* displayMode */, - IODisplayModeInformation * info ) -{ - PE_Video bootDisplay; - - getPlatform()->getConsoleInfo( &bootDisplay); - - bzero( info, sizeof( *info)); - - info->maxDepthIndex = 0; - info->nominalWidth = bootDisplay.v_width; - info->nominalHeight = bootDisplay.v_height; - info->refreshRate = 75 << 16; - - return( kIOReturnSuccess); -} - -UInt64 IOBootFramebuffer::getPixelFormatsForDisplayMode( - IODisplayModeID /* displayMode */, IOIndex /* depth */ ) -{ - return( 1); -} - -IOReturn IOBootFramebuffer::getPixelInformation( - IODisplayModeID displayMode, IOIndex depth, - IOPixelAperture aperture, IOPixelInformation * info ) -{ - PE_Video bootDisplay; - - if( aperture || depth || (displayMode != kTheDisplayMode) ) - return( kIOReturnUnsupportedMode); - - getPlatform()->getConsoleInfo( &bootDisplay); - - bzero( info, sizeof( *info)); - - info->activeWidth = bootDisplay.v_width; - info->activeHeight = bootDisplay.v_height; - info->bytesPerRow = bootDisplay.v_rowBytes & 0x7fff; - info->bytesPerPlane = 0; - - switch( bootDisplay.v_depth ) { - case 8: - default: - strcpy(info->pixelFormat, IO8BitIndexedPixels ); - info->pixelType = kIOCLUTPixels; - info->componentMasks[0] = 0xff; - info->bitsPerPixel = 8; - info->componentCount = 1; - info->bitsPerComponent = 8; - break; - case 15: - case 16: - strcpy(info->pixelFormat, IO16BitDirectPixels ); - info->pixelType = kIORGBDirectPixels; - info->componentMasks[0] = 0x7c00; - info->componentMasks[1] = 0x03e0; - info->componentMasks[2] = 0x001f; - info->bitsPerPixel = 16; - info->componentCount = 3; - info->bitsPerComponent = 5; - break; - case 24: - case 32: - strcpy(info->pixelFormat, IO32BitDirectPixels ); - info->pixelType = kIORGBDirectPixels; - info->componentMasks[0] = 0x00ff0000; - info->componentMasks[1] = 0x0000ff00; - info->componentMasks[2] = 0x000000ff; - info->bitsPerPixel = 32; - info->componentCount = 3; - info->bitsPerComponent = 8; - break; - } - - return( kIOReturnSuccess); -} - -IOReturn IOBootFramebuffer::getCurrentDisplayMode( - IODisplayModeID * displayMode, IOIndex * depth ) -{ - if( displayMode) - *displayMode = kTheDisplayMode; - if( depth) - *depth = 0; - - return( kIOReturnSuccess); -} - -IODeviceMemory * IOBootFramebuffer::getApertureRange( IOPixelAperture aper ) -{ - IOReturn err; - IOPixelInformation info; - IOByteCount bytes; - PE_Video bootDisplay; - - getPlatform()->getConsoleInfo( &bootDisplay); - - err = getPixelInformation( kTheDisplayMode, 0, aper, - &info ); - if( err) - return( 0 ); - - bytes = (info.bytesPerRow * info.activeHeight) + 128; - - return( IODeviceMemory::withRange( bootDisplay.v_baseAddr, bytes )); -} - -bool IOBootFramebuffer::isConsoleDevice( void ) -{ - return( (0 != getProvider()->getProperty("AAPL,boot-display")) ); -} - -IOReturn IOBootFramebuffer::setGammaTable( UInt32 channelCount, - UInt32 dataCount, UInt32 dataWidth, void * data ) -{ - return( kIOReturnSuccess ); -} - -IOReturn IOBootFramebuffer::setCLUTWithEntries( - IOColorEntry * colors, UInt32 index, UInt32 numEntries, - IOOptionBits options ) -{ - return( kIOReturnSuccess ); -} diff --git a/iokit/Families/IOGraphics/IOBootFramebuffer.h b/iokit/Families/IOGraphics/IOBootFramebuffer.h deleted file mode 100644 index c2a92c1c9..000000000 --- a/iokit/Families/IOGraphics/IOBootFramebuffer.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - */ - - -#ifndef _IOKIT_IOBOOTFRAMEBUFFER_H -#define _IOKIT_IOBOOTFRAMEBUFFER_H - -#include <IOKit/graphics/IOFramebuffer.h> -#include <IOKit/IOPlatformExpert.h> - - -class IOBootFramebuffer : public IOFramebuffer -{ - OSDeclareDefaultStructors(IOBootFramebuffer) - -public: - - virtual IOService * probe( IOService * provider, - SInt32 * score ); - -// virtual bool start( IOService * provider ); - - virtual const char * getPixelFormats( void ); - - virtual IOItemCount getDisplayModeCount( void ); - - virtual IOReturn getDisplayModes( IODisplayModeID * allDisplayModes ); - - virtual IOReturn getInformationForDisplayMode( IODisplayModeID displayMode, - IODisplayModeInformation * info ); - - virtual UInt64 getPixelFormatsForDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - - virtual IOReturn getPixelInformation( - IODisplayModeID displayMode, IOIndex depth, - IOPixelAperture aperture, IOPixelInformation * pixelInfo ); - - virtual IOReturn getCurrentDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ); - - virtual IODeviceMemory * getApertureRange( IOPixelAperture aperture ); - - virtual bool isConsoleDevice( void ); - - virtual IOReturn setCLUTWithEntries( IOColorEntry * colors, UInt32 index, - UInt32 numEntries, IOOptionBits options ); - - virtual IOReturn setGammaTable( UInt32 channelCount, UInt32 dataCount, - UInt32 dataWidth, void * data ); -}; - -#endif /* ! _IOKIT_IOBOOTFRAMEBUFFER_H */ - diff --git a/iokit/Families/IOGraphics/IOCursorBlits.h b/iokit/Families/IOGraphics/IOCursorBlits.h deleted file mode 100644 index 9f31b4f77..000000000 --- a/iokit/Families/IOGraphics/IOCursorBlits.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#define RBMASK 0xF0F0 /* Short, or 16 bit format */ -#define GAMASK 0x0F0F /* Short, or 16 bit format */ -#define AMASK 0x000F /* Short, or 16 bit format */ - -#if 1 -#define short34to35WithGamma(x) \ - ( (((x) & 0xf000) >> 1) \ - | (((x) & 0x0f00) >> 2) \ - | (((x) & 0x00f0) >> 3) \ - | (((x) & 0x8000) >> 5) \ - | (((x) & 0x0800) >> 6) \ - | (((x) & 0x0080) >> 7) ) - -#define short35to34WithGamma(x) \ - ( 0x000F \ - | (((x) & 0x001e) << 3) \ - | (((x) & 0x03c0) << 2) \ - | (((x) & 0x7800) << 1) ) -#else -#define short34to35WithGamma(x) \ - ( (_bm34To35SampleTable[((x) & 0x00F0) >> 4]) \ - | (_bm34To35SampleTable[((x) & 0x0F00) >> 8] << 5) \ - | (_bm34To35SampleTable[(x) >> 12] << 10) ) - -#define short35to34WithGamma(x) \ - ( 0x000F \ - | (_bm35To34SampleTable[x & 0x001F] << 4) \ - | (_bm35To34SampleTable[(x & 0x03E0) >> 5] << 8) \ - | (_bm35To34SampleTable[(x & 0x7C00) >> 10] << 12) ) -#endif - -void IOFramebuffer::StdFBDisplayCursor555( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned short *cursPtr; - volatile unsigned short *savePtr; - unsigned short s, d, f; - unsigned char *_bm34To35SampleTable; - unsigned char *_bm35To34SampleTable; - - savePtr = (volatile unsigned short *) inst->cursorSave; - cursPtr = (volatile unsigned short *) inst->cursorImages[ shmem->frame ]; - cursPtr += cursStart; - - _bm34To35SampleTable = inst->colorConvert.t._bm34To35SampleTable; - _bm35To34SampleTable = inst->colorConvert.t._bm35To34SampleTable; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) { - d = *savePtr++ = *vramPtr; - if ( (s = *cursPtr++) == 0 ) - { /* Transparent black area. Leave dst as is. */ - ++vramPtr; - continue; - } - if ( (f = (~s) & (unsigned int)AMASK) == 0 ) - { /* Opaque cursor pixel. Mark it. */ - *vramPtr++ = short34to35WithGamma(s); - continue; - } - if ((f == AMASK)) - { /* Transparent non black cursor pixel. xor it. */ - *vramPtr++ = d ^ short34to35WithGamma(s); - continue; - } - /* Alpha is not 0 or 1.0. Sover the cursor. */ - d = short35to34WithGamma(d); - d = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK) - | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK)); - *vramPtr++ = short34to35WithGamma(d); - } - cursPtr += cursRow; /* starting point of next cursor line */ - vramPtr += vramRow; /* starting point of next screen line */ - } -} - -void IOFramebuffer::StdFBDisplayCursor444( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned short *savePtr; /* saved screen data pointer */ - volatile unsigned short *cursPtr; - unsigned short s, d, f; - - savePtr = (volatile unsigned short *) inst->cursorSave; - cursPtr = (volatile unsigned short *) inst->cursorImages[ shmem->frame ]; - cursPtr += cursStart; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) { - d = *savePtr++ = *vramPtr; - if ( (s = *cursPtr++) == 0 ) - { /* Transparent black area. Leave dst as is. */ - ++vramPtr; - continue; - } - if ( (f = (~s) & (unsigned int)AMASK) == 0 ) - { /* Opaque cursor pixel. Mark it. */ - *vramPtr++ = s; - continue; - } - if ((f == AMASK)) - { /* Transparent non black cursor pixel. xor it. */ - *vramPtr++ = d ^ s; - continue; - } - /* Alpha is not 0 or 1.0. Sover the cursor. */ - *vramPtr++ = s + (((((d & RBMASK)>>4)*f + GAMASK) & RBMASK) - | ((((d & GAMASK)*f+GAMASK)>>4) & GAMASK)); - } - cursPtr += cursRow; /* starting point of next cursor line */ - vramPtr += vramRow; /* starting point of next screen line */ - } -} - -static inline unsigned int MUL32(unsigned int a, unsigned int b) -{ - unsigned int v, w; - - v = ((a & 0xff00ff00) >> 8) * b; - v += ((v & 0xff00ff00) >> 8) + 0x00010001; - w = (a & 0x00ff00ff) * b; - w += ((w & 0xff00ff00) >> 8) + 0x00010001; - - return (v & 0xff00ff00) | ((w >> 8) & 0x00ff00ff); -} - -static inline unsigned char map32to256( unsigned char *directToLogical, unsigned int s) -{ - unsigned char logicalValue; - - if ((s ^ (s>>8)) & 0x00ffff00) { - logicalValue = directToLogical[(s>>24) + 0] + - directToLogical[((s>>16)&0xff) + 256] + - directToLogical[((s>>8)&0xff) + 512]; - } else { - logicalValue = directToLogical[(s>>24) + 768]; - } - // final conversion to actual palette - return( directToLogical[ logicalValue + 1024 ]); -} - -void IOFramebuffer::StdFBDisplayCursor8P( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned char *savePtr; /* saved screen data pointer */ - volatile unsigned char *cursPtr; - unsigned char dst, src, alpha, white; - unsigned int rgb32val; - volatile unsigned char *maskPtr; /* cursor mask pointer */ - unsigned int *_bm256To38SampleTable - = inst->colorConvert.t._bm256To38SampleTable; - unsigned char *_bm38To256SampleTable - = inst->colorConvert.t._bm38To256SampleTable; - - savePtr = (volatile unsigned char *) inst->cursorSave; - cursPtr = (volatile unsigned char *) inst->cursorImages[ shmem->frame ]; - maskPtr = (volatile unsigned char *) inst->cursorMasks[ shmem->frame ]; - cursPtr += cursStart; - maskPtr += cursStart; - - white = inst->white; - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; savePtr++,maskPtr++,cursPtr++,vramPtr++) { - dst = *savePtr = *vramPtr; - src = *cursPtr; - if ((alpha = *maskPtr)) { - if ((alpha = ~alpha)) { - rgb32val = _bm256To38SampleTable[dst]; - rgb32val = (_bm256To38SampleTable[src] & ~0xff) + - MUL32(rgb32val, alpha); - *vramPtr = map32to256(_bm38To256SampleTable, rgb32val); - } else - *vramPtr = src; - } else if (src == white) - *vramPtr = map32to256(_bm38To256SampleTable, - _bm256To38SampleTable[dst] ^ 0xffffffff); - } - cursPtr += cursRow; /* starting point of next cursor line */ - maskPtr += cursRow; - vramPtr += vramRow; /* starting point of next screen line */ - } -} - - -void IOFramebuffer::StdFBDisplayCursor8G( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned char *savePtr; /* saved screen data pointer */ - unsigned short s, d, a; - volatile unsigned char *cursPtr; - volatile unsigned char *maskPtr; /* cursor mask pointer */ - - savePtr = (volatile unsigned char *) inst->cursorSave; - cursPtr = (volatile unsigned char *) inst->cursorImages[ shmem->frame ]; - maskPtr = (volatile unsigned char *) inst->cursorMasks[ shmem->frame ]; - cursPtr += cursStart; - maskPtr += cursStart; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) { - int t; - d = *savePtr++ = *vramPtr; - s = *cursPtr++; - a = *maskPtr++; - if (a) { - t = d * (255 - *maskPtr++); - *vramPtr = s + ((t + (t >> 8) + 1) >> 8); - } else if (s) - *vramPtr = d ^ s; - vramPtr++; - } - cursPtr += cursRow; /* starting point of next cursor line */ - maskPtr += cursRow; - vramPtr += vramRow; /* starting point of next screen line */ - } -} - -void IOFramebuffer::StdFBDisplayCursor32Axxx( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned int *savePtr; /* saved screen data pointer */ - unsigned int s, d, f; - volatile unsigned int *cursPtr; - - savePtr = (volatile unsigned int *) inst->cursorSave; - cursPtr = (volatile unsigned int *) inst->cursorImages[ shmem->frame ]; - cursPtr += cursStart; - - /* Pixel format is Axxx */ - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) { - d = *savePtr++ = *vramPtr; - s = *cursPtr++; - f = s >> 24; - if (f) { - if (f == 0xff) // Opaque pixel - *vramPtr++ = s; - else { // SOVER the cursor pixel - s <<= 8; d <<= 8; /* Now pixels are xxxA */ - f ^= 0xFF; - d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00) - | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) & - 0x00FF00FF)); - *vramPtr++ = (d>>8) | 0xff000000; - } - } else if (s) { - // Transparent non black cursor pixel. xor it. - *vramPtr++ = d ^ s; - continue; - } else // Transparent cursor pixel - vramPtr++; - } - cursPtr += cursRow; /* starting point of next cursor line */ - vramPtr += vramRow; /* starting point of next screen line */ - } -} - -void IOFramebuffer::StdFBDisplayCursor32xxxA( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ) -{ - int i, j; - volatile unsigned int *savePtr; /* saved screen data pointer */ - unsigned int s, d, f; - volatile unsigned int *cursPtr; - - savePtr = (volatile unsigned int *) inst->cursorSave; - cursPtr = (volatile unsigned int *) inst->cursorImages[ shmem->frame ]; - cursPtr += cursStart; - - /* Pixel format is xxxA */ - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) { - d = *savePtr++ = *vramPtr; - s = *cursPtr++; - f = s & (unsigned int)0xFF; - if (f) { - if (f == 0xff) // Opaque pixel - *vramPtr++ = s; - else { // SOVER the cursor pixel - f ^= 0xFF; - d = s+(((((d&0xFF00FF00)>>8)*f+0x00FF00FF)&0xFF00FF00) - | ((((d & 0x00FF00FF)*f+0x00FF00FF)>>8) & - 0x00FF00FF)); - *vramPtr++ = d; - } - } else if (s) { - // Transparent non black cursor pixel. xor it. - *vramPtr++ = d ^ s; - continue; - } else // Transparent cursor pixel - vramPtr++; - } - cursPtr += cursRow; /* starting point of next cursor line */ - vramPtr += vramRow; /* starting point of next screen line */ - } -} - -void IOFramebuffer::StdFBRemoveCursor16( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int vramRow, - int width, - int height ) -{ - int i, j; - volatile unsigned short *savePtr; - - savePtr = (volatile unsigned short *) inst->cursorSave; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) - *vramPtr++ = *savePtr++; - vramPtr += vramRow; - } -} - -void IOFramebuffer::StdFBRemoveCursor8( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int vramRow, - int width, - int height ) -{ - int i, j; - volatile unsigned char *savePtr; - - savePtr = (volatile unsigned char *) inst->cursorSave; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) - *vramPtr++ = *savePtr++; - vramPtr += vramRow; - } -} - -void IOFramebuffer::StdFBRemoveCursor32( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int vramRow, - int width, - int height ) -{ - int i, j; - volatile unsigned int *savePtr; - - savePtr = (volatile unsigned int *) inst->cursorSave; - - for (i = height; --i >= 0; ) { - for (j = width; --j >= 0; ) - *vramPtr++ = *savePtr++; - vramPtr += vramRow; - } -} diff --git a/iokit/Families/IOGraphics/IODisplay.cpp b/iokit/Families/IOGraphics/IODisplay.cpp deleted file mode 100644 index 8bcf2fdd9..000000000 --- a/iokit/Families/IOGraphics/IODisplay.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 18 May 98 - make loadable. - * sdouglas 23 Jul 98 - start IOKit - * sdouglas 08 Dec 98 - start cpp - */ - -#include <libkern/OSAtomic.h> -#include <IOKit/graphics/IODisplay.h> -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -const OSSymbol * gIODisplayParametersKey; -const OSSymbol * gIODisplayGUIDKey; - -const OSSymbol * gIODisplayValueKey; -const OSSymbol * gIODisplayMinValueKey; -const OSSymbol * gIODisplayMaxValueKey; - -const OSSymbol * gIODisplayContrastKey; -const OSSymbol * gIODisplayBrightnessKey; -const OSSymbol * gIODisplayHorizontalPositionKey; -const OSSymbol * gIODisplayHorizontalSizeKey; -const OSSymbol * gIODisplayVerticalPositionKey; -const OSSymbol * gIODisplayVerticalSizeKey; -const OSSymbol * gIODisplayTrapezoidKey; -const OSSymbol * gIODisplayPincushionKey; -const OSSymbol * gIODisplayParallelogramKey; -const OSSymbol * gIODisplayRotationKey; - -const OSSymbol * gIODisplayParametersCommitKey; -const OSSymbol * gIODisplayParametersDefaultKey; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOService - -OSDefineMetaClass( IODisplay, IOService ) -OSDefineAbstractStructors( IODisplay, IOService ) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -void IODisplay::initialize( void ) -{ - gIODisplayParametersKey = OSSymbol::withCStringNoCopy( - kIODisplayParametersKey ); - gIODisplayGUIDKey = OSSymbol::withCStringNoCopy( - kIODisplayGUIDKey ); - gIODisplayValueKey = OSSymbol::withCStringNoCopy( - kIODisplayValueKey ); - gIODisplayMinValueKey = OSSymbol::withCStringNoCopy( - kIODisplayMinValueKey ); - gIODisplayMaxValueKey = OSSymbol::withCStringNoCopy( - kIODisplayMaxValueKey ); - gIODisplayContrastKey = OSSymbol::withCStringNoCopy( - kIODisplayContrastKey ); - gIODisplayBrightnessKey = OSSymbol::withCStringNoCopy( - kIODisplayBrightnessKey ); - gIODisplayHorizontalPositionKey = OSSymbol::withCStringNoCopy( - kIODisplayHorizontalPositionKey ); - gIODisplayHorizontalSizeKey = OSSymbol::withCStringNoCopy( - kIODisplayHorizontalSizeKey ); - gIODisplayVerticalPositionKey = OSSymbol::withCStringNoCopy( - kIODisplayVerticalPositionKey ); - gIODisplayVerticalSizeKey = OSSymbol::withCStringNoCopy( - kIODisplayVerticalSizeKey ); - gIODisplayTrapezoidKey = OSSymbol::withCStringNoCopy( - kIODisplayTrapezoidKey ); - gIODisplayPincushionKey = OSSymbol::withCStringNoCopy( - kIODisplayPincushionKey ); - gIODisplayParallelogramKey = OSSymbol::withCStringNoCopy( - kIODisplayParallelogramKey ); - gIODisplayRotationKey = OSSymbol::withCStringNoCopy( - kIODisplayRotationKey ); - - gIODisplayParametersCommitKey = OSSymbol::withCStringNoCopy( - kIODisplayParametersCommitKey ); - gIODisplayParametersDefaultKey = OSSymbol::withCStringNoCopy( - kIODisplayParametersDefaultKey ); -} - -IOService * IODisplay::probe( IOService * provider, - SInt32 * score ) -{ - connection = OSDynamicCast(IODisplayConnect, provider); - - return( this ); -} - -IODisplayConnect * IODisplay::getConnection( void ) -{ - return( connection ); -} - - -IOReturn IODisplay::getGammaTableByIndex( - UInt32 * /* channelCount */, UInt32 * /* dataCount */, - UInt32 * /* dataWidth */, void ** /* data */ ) -{ - return( kIOReturnUnsupported); -} - - -bool IODisplay::start( IOService * provider ) -{ - if ( super::start(provider) ) { - if ( connection != NULL ) { - displayPMVars = (DisplayPMVars *)IOMalloc(sizeof(DisplayPMVars)); // make space for our variables - assert( displayPMVars ); - displayPMVars->displayIdle = false; // initialize some - initForPM(provider); // initialize power management of the device - registerService(); - } - return true; - } - return false; -} - -IOReturn IODisplay::setProperties( OSObject * properties ) -{ - IOService * handler; - OSDictionary * dict; - OSDictionary * dict2; - - dict = OSDynamicCast( OSDictionary, properties); - if( !dict) - return( kIOReturnUnsupported ); - - dict2 = OSDynamicCast( OSDictionary, dict->getObject(gIODisplayParametersKey)); - if( dict2) - dict = dict2; - - handler = getClientWithCategory(gIODisplayParametersKey); - if( !handler) - return( kIOReturnUnsupported ); - - return( handler->setProperties( dict ) ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* -This is the power-controlling driver for a display. It also acts as an agent of the policy-maker for display power - which is the DisplayWrangler. The Display Wrangler calls here to lower power by one state when it senses - no user activity. It also calls here to make the display usable after it has been idled down, and it also calls - here to make the display barely usable if it senses a power emergency (e.g. low battery). - - This driver assumes a video display, and it calls the framebuffer driver to control the sync signals. Non-video - display drivers (e.g. flat panels) subclass IODisplay and override this and other appropriate methods. - */ - -static IOPMPowerState ourPowerStates[kIODisplayMaxPowerStates] = { - {1,0,0,0,0,0,0,0,0,0,0,0}, -// {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, -// {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable+IOPMMaxPerformance,0,IOPMPowerOn,0,0,0,0,0,0,0,0} -}; - - -void IODisplay::initForPM ( IOService * provider ) -{ - UInt32 capabilities = 0; - unsigned long number_of_power_states; - UInt32 currentSyncs = 0; - IOReturn err; - - displayPMVars->connectIndex = connection->getConnection(); // find out our index in the nub - - // what are the sync-controlling capabilities of the framebuffer? - err = connection->getAttributeForConnection( displayPMVars->connectIndex, - kConnectionSyncEnable, &capabilities ); - - // find out current state of sync lines - err = connection->getAttributeForConnection( displayPMVars->connectIndex, - kConnectionSyncFlags, ¤tSyncs ); - - displayPMVars->currentSyncs = currentSyncs; - displayPMVars->powerControllable = true; - - if ( (capabilities & kIOHSyncDisable) && - (capabilities & kIOVSyncDisable) && - !(capabilities & kIONoSeparateSyncControl ) ) { // four power states - number_of_power_states = 4; - displayPMVars->syncControls[0] = 0 | kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable; - displayPMVars->syncControls[1] = 0 | kIOVSyncDisable | kIOCSyncDisable; - displayPMVars->syncControls[2] = 0 | kIOHSyncDisable | kIOCSyncDisable; - displayPMVars->syncControls[3] = 0; - displayPMVars->syncMask = capabilities & (kIOHSyncDisable | kIOVSyncDisable | kIOCSyncDisable); - } - else { - if ( capabilities & kIOCSyncDisable ) { // two power states - number_of_power_states = 2; - ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags; - displayPMVars->syncControls[0] = 0 | kIOCSyncDisable; - displayPMVars->syncControls[1] = 0; - displayPMVars->syncMask = 0 | kIOCSyncDisable; - } - else { // two power states and not controllable - number_of_power_states = 2; - ourPowerStates[1].capabilityFlags = ourPowerStates[3].capabilityFlags; - ourPowerStates[0].capabilityFlags |= IOPMNotAttainable; - ourPowerStates[1].capabilityFlags |= IOPMNotAttainable; - displayPMVars->syncControls[0] = displayPMVars->currentSyncs; - displayPMVars->syncControls[1] = displayPMVars->currentSyncs; - displayPMVars->syncMask = displayPMVars->currentSyncs; - displayPMVars->powerControllable = false; - } - } - - PMinit(); // initialize superclass variables - provider->joinPMtree(this); // attach into the power management hierarchy - - registerPowerDriver(this,ourPowerStates,number_of_power_states); // register ourselves with policy-maker (us) - -} - - -//********************************************************************************* -// registerPowerDriver -// -// We intercept this call to our superclass just to snoop early on -// the number of power states. -//********************************************************************************* - -IOReturn IODisplay::registerPowerDriver ( IOService* x, IOPMPowerState*y, unsigned long numberOfStates ) -{ - displayPMVars->max_display_state = numberOfStates - 1; - return super::registerPowerDriver(x,y,numberOfStates); -} - - -//********************************************************************************* -// setAggressiveness -// -// We are informed by our power domain parent of a new level of "power management -// aggressiveness". Our only interest is if it implies a power management -// emergency, in which case we keep the display brightness low. -//********************************************************************************* - -IOReturn IODisplay::setAggressiveness ( unsigned long type, unsigned long newLevel ) -{ - unsigned long i; - - if ( type == kPMGeneralAggressiveness ) { - if ( newLevel >= kIOPowerEmergencyLevel ) { // emergency level - for ( i = 0; i < pm_vars->theNumberOfPowerStates; i++ ) { // find lowest usable state - if ( pm_vars->thePowerStates[i].capabilityFlags & IOPMDeviceUsable ) { - break; - } - } - displayPMVars->max_display_state = i; - if ( pm_vars->myCurrentState > i ) { // if we are currently above that, - changePowerStateToPriv(i); // drop to emergency level - } - } - else { // not emergency level - if ( pm_vars->aggressiveness >= kIOPowerEmergencyLevel ) { // but it was emergency level - displayPMVars->max_display_state = pm_vars->theNumberOfPowerStates - 1; - if ( ! displayPMVars->displayIdle ) { - changePowerStateToPriv(displayPMVars->max_display_state); // return to normal usable level - } - } - } - } - super::setAggressiveness(type, newLevel); - return IOPMNoErr; -} - - -// ********************************************************************************** -// dropOneLevel -// -// Called by the display wrangler when it decides there hasn't been user -// activity for a while. We drop one power level. This can be called by the -// display wrangler before we have been completely initialized. -// ********************************************************************************** -void IODisplay::dropOneLevel ( void ) -{ - if ( initialized && displayPMVars->powerControllable) { - displayPMVars->displayIdle = true; - if ( pm_vars != NULL ) { - if ( pm_vars->myCurrentState > 0 ) { - changePowerStateToPriv(pm_vars->myCurrentState - 1); // drop a level - } - else { - changePowerStateToPriv(0); // this may rescind previous request for domain power - } - } - } -} - - -//********************************************************************************* -// makeDisplayUsable -// -// The DisplayWrangler has sensed user activity after we have idled the -// display and wants us to make it usable again. We are running on its -// workloop thread. This can be called before we are completely -// initialized. -//********************************************************************************* -void IODisplay::makeDisplayUsable ( void ) -{ - if ( initialized && displayPMVars->powerControllable) { - displayPMVars->displayIdle = false; - if ( pm_vars != NULL ) { - changePowerStateToPriv(displayPMVars->max_display_state); - } - } -} - - -// ********************************************************************************** -// setPowerState -// -// Called by the superclass to change the display power state. -// ********************************************************************************** -IOReturn IODisplay::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ) -{ - UInt32 flags; - if( initialized) { - flags =(displayPMVars->syncControls[powerStateOrdinal])<<8; - flags |= displayPMVars->syncMask; - displayPMVars->currentSyncs = displayPMVars->syncControls[powerStateOrdinal]; - connection->setAttributeForConnection( displayPMVars->connectIndex, kConnectionSyncEnable, flags ); - } - return IOPMAckImplied; -} - - -// ********************************************************************************** -// maxCapabilityForDomainState -// -// This simple device needs only power. If the power domain is supplying -// power, the display can go to its highest state. If there is no power -// it can only be in its lowest state, which is off. -// ********************************************************************************** -unsigned long IODisplay::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) -{ - if ( domainState & IOPMPowerOn ) { - return pm_vars->theNumberOfPowerStates-1; - } - else { - return 0; - } -} - - -// ********************************************************************************** -// initialPowerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. In that case ask the ndrv -// what our current state is. If domain power is off, we can attain -// only our lowest state, which is off. -// ********************************************************************************** -unsigned long IODisplay::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) -{ - long unsigned i; - - if ( domainState & IOPMPowerOn ) { // domain has power - for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { // compare to our table to find current power state - if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask) - == (displayPMVars->currentSyncs & displayPMVars->syncMask) ) { - break; - } - } - return i; - } - else { - return 0; // domain is down, so display is off - } -} - - -// ********************************************************************************** -// powerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. In that case ask the ndrv -// what our current state is. If domain power is off, we can attain -// only our lowest state, which is off. -// ********************************************************************************** -unsigned long IODisplay::powerStateForDomainState ( IOPMPowerFlags domainState ) -{ - long unsigned i; - - if ( domainState & IOPMPowerOn ) { // domain has power - for ( i = pm_vars->theNumberOfPowerStates-1; i > 0; i-- ) { // compare to our table to find current power state - if ( (displayPMVars->syncControls[i] & displayPMVars->syncMask) - == (displayPMVars->currentSyncs & displayPMVars->syncMask) ) { - break; - } - } - return i; - } - else { - return 0; // domain is down, so display is off - } -} - - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IODisplay - -OSDefineMetaClassAndStructors(AppleSenseDisplay, IODisplay) - - -IOService * AppleSenseDisplay::probe( IOService * provider, - SInt32 * score ) -{ - IODisplayConnect * connect; - IOFramebuffer * framebuffer; - IOService * ret = 0; - UInt32 sense, extSense; - UInt32 senseType, displayType; - - do { - - if( 0 == super::probe( provider, score )) - continue; - - connect = getConnection(); - if( !connect) - continue; - - framebuffer = connect->getFramebuffer(); - assert( framebuffer ); - - if( kIOReturnSuccess != framebuffer->getAttributeForConnection( - connect->getConnection(), - kConnectionSupportsAppleSense, NULL )) - continue; - - ret = this; - - if( kIOReturnSuccess != framebuffer->getAppleSense( - connect->getConnection(), - &senseType, &sense, &extSense, &displayType )) - continue; - sense = ((sense & 0xff) << 8) | (extSense & 0xff); - setProperty( kDisplayProductID, sense, 32); - setProperty( kDisplayVendorID, kDisplayVendorIDUnknown, 32); - setProperty( "AppleDisplayType", displayType, 32); - - } while( false); - - return( ret ); -} - -IOReturn AppleSenseDisplay::getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ) -{ - IOFramebuffer * framebuffer; - IODisplayConnect * connect; - - connect = getConnection(); - framebuffer = connect->getFramebuffer(); - - return( framebuffer->connectFlags( - connect->getConnection(), - mode, flags )); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - - -#undef super -#define super IODisplay - -OSDefineMetaClassAndStructors(AppleNoSenseDisplay, IODisplay) - - -IOReturn AppleNoSenseDisplay::getConnectFlagsForDisplayMode( - IODisplayModeID /* mode */, UInt32 * flags) -{ - *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag; - - setProperty( kDisplayProductID, kDisplayProductIDGeneric, 32); - setProperty( kDisplayVendorID, kDisplayVendorIDUnknown, 32); - - return( kIOReturnSuccess ); -} - - diff --git a/iokit/Families/IOGraphics/IODisplayWrangler.cpp b/iokit/Families/IOGraphics/IODisplayWrangler.cpp deleted file mode 100644 index 01502cede..000000000 --- a/iokit/Families/IOGraphics/IODisplayWrangler.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 18 Mar 99 - first checked in. - */ - - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOPlatformExpert.h> - -#include "IODisplayWrangler.h" - -bool wranglerHasRoot( OSObject * us, void *, IOService * yourDevice ); - -#define DODEFAULTMODE 0 - -#if DODEFAULTMODE -enum { - kAquaMinWidth = 800, - kAquaMinHeight = 600 -}; -#endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// tiddly nub - -#undef super -#define super IOService - -OSDefineMetaClassAndStructors(IODisplayConnect, IOService) - -bool IODisplayConnect::initWithConnection( IOIndex _connection ) -{ - char name[ 12 ]; - - if( !super::init()) - return( false); - - connection = _connection; - - sprintf( name, "display%ld", connection); - - setName( name); - - return( true); -} - -IOFramebuffer * IODisplayConnect::getFramebuffer( void ) -{ - return( (IOFramebuffer *) getProvider()); -} - -IOIndex IODisplayConnect::getConnection( void ) -{ - return( connection); -} - -IOReturn IODisplayConnect::getAttributeForConnection( IOIndex connectIndex, IOSelect selector, UInt32 * value ) -{ - return ((IOFramebuffer *) getProvider())->getAttributeForConnection( connectIndex, selector, value ); -} - -IOReturn IODisplayConnect::setAttributeForConnection( IOIndex connectIndex, IOSelect selector, UInt32 info ) -{ - return ((IOFramebuffer *) getProvider())->setAttributeForConnection( connectIndex, selector, info ); -} - - -//********************************************************************************* -// joinPMtree -// -// The policy-maker in the display driver calls here when initializing. -// We attach it into the power management hierarchy as a child of our -// frame buffer. -//********************************************************************************* -void IODisplayConnect::joinPMtree ( IOService * driver ) -{ - getProvider()->addPowerChild(driver); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOService -OSDefineMetaClassAndStructors(IODisplayWrangler, IOService); - -IODisplayWrangler * gIODisplayWrangler; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IODisplayWrangler::start( IOService * provider ) -{ - OSObject * notify; - - if( !super::start( provider)) - return( false); - - assert( gIODisplayWrangler == 0 ); - gIODisplayWrangler = this; - - fMatchingLock = IOLockAlloc(); - fFramebuffers = OSSet::withCapacity( 1 ); - fDisplays = OSSet::withCapacity( 1 ); - - assert( fMatchingLock && fFramebuffers && fDisplays ); - - notify = addNotification( gIOPublishNotification, - serviceMatching("IODisplay"), _displayHandler, - this, fDisplays ); - assert( notify ); - - notify = addNotification( gIOPublishNotification, - serviceMatching("IODisplayConnect"), _displayConnectHandler, - this, 0, 50000 ); - assert( notify ); - - rootDomain = NULL; - addNotification( gIOPublishNotification,serviceMatching("IOPMrootDomain"), // look for the Root Domain - (IOServiceNotificationHandler)wranglerHasRoot, this, 0 ); - - // initialize power managment - gIODisplayWrangler->initForPM(); - // set default screen-dim timeout - gIODisplayWrangler->setAggressiveness ( kPMMinutesToDim, 30 ); - - return( true ); -} - - -bool wranglerHasRoot( OSObject * us, void *, IOService * yourDevice ) -{ - if ( yourDevice != NULL ) { - ((IODisplayWrangler *)us)->rootDomain = yourDevice; - } - return true; -} - - -bool IODisplayWrangler::_displayHandler( void * target, void * ref, - IOService * newService ) -{ - - return( ((IODisplayWrangler *)target)->displayHandler( (OSSet *) ref, - (IODisplay *) newService )); -} - -bool IODisplayWrangler::_displayConnectHandler( void * target, void * ref, - IOService * newService ) -{ - return( ((IODisplayWrangler *)target)->displayConnectHandler( ref, - (IODisplayConnect *) newService )); -} - -bool IODisplayWrangler::displayHandler( OSSet * set, - IODisplay * newDisplay ) -{ - assert( OSDynamicCast( IODisplay, newDisplay )); - - IOTakeLock( fMatchingLock ); - - set->setObject( newDisplay ); - - IOUnlock( fMatchingLock ); - - return( true ); -} - -bool IODisplayWrangler::displayConnectHandler( void * /* ref */, - IODisplayConnect * connect ) -{ - SInt32 score = 50000; - OSIterator * iter; - IODisplay * display; - bool found = false; - - assert( OSDynamicCast( IODisplayConnect, connect )); - - IOTakeLock( fMatchingLock ); - - iter = OSCollectionIterator::withCollection( fDisplays ); - if( iter) { - while( !found && (display = (IODisplay *) iter->getNextObject())) { - if( display->getConnection()) - continue; - - do { - if( !display->attach( connect )) - continue; - found = ((display->probe( connect, &score )) - && (display->start( connect ))); - if( !found) - display->detach( connect ); - } while( false); - } - iter->release(); - } - - IOUnlock( fMatchingLock ); - - return( true); -} - -IOReturn IODisplayWrangler::clientStart( IOFramebuffer * fb ) -{ - IOReturn err = kIOReturnSuccess; - -// IOTakeLock( fFBLock ); - - if( gIODisplayWrangler && - gIODisplayWrangler->fFramebuffers->setObject( fb )) { - - // framebuffer not yet done - - err = fb->open(); - if( kIOReturnSuccess == err) { - gIODisplayWrangler->makeDisplayConnects( fb ); - gIODisplayWrangler->findStartupMode( fb ); - } - // try to open it next time - // else gIODisplayWrangler->fFramebuffers->removeObject( fb ); - } - -// IOUnlock( fFBLock ); - - return( err ); -} - -bool IODisplayWrangler::makeDisplayConnects( IOFramebuffer * fb ) -{ - IODisplayConnect * connect; - IOItemCount i; - - for( i = 0; i < fb->getConnectionCount(); i++) { - - connect = new IODisplayConnect; - if( 0 == connect) - continue; - - if( (connect->initWithConnection( i )) - && (connect->attach( fb ))) { - - connect->registerService( kIOServiceSynchronous ); - } - connect->release(); - } - - return( true ); -} - -IODisplayConnect * IODisplayWrangler::getDisplayConnect( - IOFramebuffer * fb, IOIndex connect ) -{ - OSIterator * iter; - OSObject * next; - IODisplayConnect * connection = 0; - - iter = fb->getClientIterator(); - if( iter) { - while( (next = iter->getNextObject())) { - connection = OSDynamicCast( IODisplayConnect, next); - if( connection && (0 == (connect--))) - break; - } - iter->release(); - } - return( connection ); -} - - -IOReturn IODisplayWrangler::getConnectFlagsForDisplayMode( - IODisplayConnect * connect, - IODisplayModeID mode, UInt32 * flags ) -{ - IOReturn err = kIOReturnUnsupported; - IODisplay * display; - - display = OSDynamicCast( IODisplay, connect->getClient()); - if( display) - err = display->getConnectFlagsForDisplayMode( mode, flags ); - else { - kprintf("%s: no display\n", connect->getFramebuffer()->getName()); - err = connect->getFramebuffer()->connectFlags( - connect->getConnection(), mode, flags ); - } - - return( err ); -} - -IOReturn IODisplayWrangler::getFlagsForDisplayMode( - IOFramebuffer * fb, - IODisplayModeID mode, UInt32 * flags ) -{ - IODisplayConnect * connect; - - // should look at all connections - connect = gIODisplayWrangler->getDisplayConnect( fb, 0 ); - if( !connect) { - kprintf("%s: no display connect\n", fb->getName()); - return( kIOReturnUnsupported ); - } - - return( gIODisplayWrangler-> - getConnectFlagsForDisplayMode( connect, mode, flags )); -} - -IOReturn IODisplayWrangler::getDefaultMode( IOFramebuffer * fb, - IODisplayModeID * mode, IOIndex * depth ) -{ -#if DODEFAULTMODE - UInt32 thisFlags, bestFlags = 0; - IODisplayModeID thisMode, bestMode = 0; - IOIndex bestDepth; - UInt32 i; - IOReturn err; - IODisplayModeInformation info; - char arg[ 64 ]; - const char * param; - UInt32 lookWidth, lookHeight, lookRefresh, lookDepth; - static const char bitsToIndex[] = { 0, 0, 1, 1, 2 }; - UInt32 numModes; - IODisplayModeID * allModes; - bool foundForced; - bool killedDefault = false; - bool haveSubst = false; - - numModes = fb->getDisplayModeCount(); - allModes = IONew( IODisplayModeID, numModes ); - - if( NULL == allModes) - return( kIOReturnNoMemory); - err = fb->getDisplayModes( allModes ); - if( err) // leak - return( err ); - - if( PE_parse_boot_arg("dm", arg)) { - - param = arg; - lookWidth = strtol( param, (char **) ¶m, 0); - param++; - lookHeight = strtol( param, (char **) ¶m, 0); - param++; - lookRefresh = strtol( param, (char **) ¶m, 0); - param++; - lookDepth = strtol( param, (char **) ¶m, 0); - if( lookDepth == 15) - lookDepth = 16; - if( lookDepth > 32) - lookDepth = 32; - -kprintf("%s: Looking %dx%d@%d,%d\n", fb->getName(), lookWidth, lookHeight, - lookRefresh, lookDepth ); - - } else { - param = 0; - lookWidth = 1024; - lookHeight = 768; - lookRefresh = 75; - lookDepth = 16; - } - - bestDepth = bitsToIndex[ lookDepth / 8 ]; - - for( i = 0; i < numModes; i++) { - - thisMode = allModes[ i ]; - if( getFlagsForDisplayMode( fb, thisMode, &thisFlags)) - continue; - - // make sure it does 16/32 && requested mode - err = fb->getInformationForDisplayMode( thisMode, &info); - if( err) - continue; - if( 0 == info.maxDepthIndex) - continue; -#if 0 - kprintf("%d x %d @ %d = %x\n", info.nominalWidth, info.nominalHeight, - info.refreshRate >> 16, thisFlags); -#endif - - if( 0 == (thisFlags & kDisplayModeValidFlag)) - continue; - - foundForced = (param - && (info.nominalWidth == lookWidth) - && (info.nominalHeight == lookHeight) - && (((info.refreshRate + 0x8000) >> 16) == lookRefresh) ); - - if( (thisFlags & kDisplayModeDefaultFlag) - && ((info.nominalWidth < kAquaMinWidth) - || (info.nominalHeight < kAquaMinHeight)) ) { - - thisFlags &= ~kDisplayModeDefaultFlag; - killedDefault = true; - haveSubst = false; - - } else if( killedDefault - && (info.nominalWidth >= kAquaMinWidth) - && (info.nominalHeight >= kAquaMinHeight) ) { - - if( thisFlags & kDisplayModeSafeFlag) { - thisFlags |= kDisplayModeDefaultFlag; - killedDefault = false; - } else if( !haveSubst) { - thisFlags |= kDisplayModeDefaultFlag; - haveSubst = true; - } - } - - if( foundForced - || (thisFlags & kDisplayModeDefaultFlag) - || (((bestFlags & kDisplayModeDefaultFlag) == 0) - && (thisFlags & kDisplayModeSafeFlag)) ) { - - bestMode = thisMode; - bestFlags = thisFlags; - - bestDepth = bitsToIndex[ lookDepth / 8 ]; - if( bestDepth > info.maxDepthIndex) - bestDepth = info.maxDepthIndex; - - if( foundForced) - break; - } - } - - IODelete( allModes, IODisplayModeID, numModes ); - - if( bestMode) { - *mode = bestMode; - *depth = bestDepth; - return( kIOReturnSuccess); - } else -#endif /* DODEFAULTMODE */ - return( kIOReturnUnsupported); -} - -// Determine a startup mode given the framebuffer & displays - -IOReturn IODisplayWrangler::findStartupMode( IOFramebuffer * fb ) -{ - IODisplayModeID mode; - IOIndex depth; - IODisplayModeID startMode; - IOIndex startDepth; - IOReturn err; - - fb->getCurrentDisplayMode( &mode, &depth); - err = fb->getStartupDisplayMode( &startMode, &startDepth ); - if( err) { - startMode = mode; - startDepth = depth; - } - -#if DODEFAULTMODE - IODisplayModeInformation info; - UInt32 startFlags = 0; - - do { - err = getFlagsForDisplayMode( fb, startMode, &startFlags ); - if( err) - continue; - err = fb->getInformationForDisplayMode( startMode, &info); - if( err) - continue; - - if( (info.nominalWidth < kAquaMinWidth) - || (info.nominalHeight < kAquaMinHeight)) { - err = kIOReturnNoResources; - continue; - } - - if( startDepth == 2) - startDepth = 1; - - if( (startDepth == 0) && (info.maxDepthIndex > 0)) - startDepth = 1; - - } while( false ); - - if( err - || (startDepth == 0) - || ((startFlags & kDisplayModeValidFlag) - != kDisplayModeValidFlag) ) { - // look for default - err = getDefaultMode( fb, &startMode, &startDepth ); - } -#endif /* DODEFAULTMODE */ - if( (startMode != mode) || (startDepth != depth)) - fb->setDisplayMode( startMode, startDepth ); - - fb->setupForCurrentConfig(); - - return( kIOReturnSuccess ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define kNumber_of_power_states 5 - -static IOPMPowerState ourPowerStates[kNumber_of_power_states] = { - {1,0,0,0,0,0,0,0,0,0,0,0}, - {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, - {1,IOPMDeviceUsable,0,IOPMPowerOn,0,0,0,0,0,0,0,0} - -}; - - -/* - This is the Power Management policy-maker for the displays. It senses when the display is idle - and lowers power accordingly. It raises power back up when the display becomes un-idle. - - It senses idleness with a combination of an idle timer and the "activityTickle" method call. "activityTickle" - is called by objects which sense keyboard activity, mouse activity, or other button activity (display contrast, - display brightness, PCMCIA eject). The method sets a "displayInUse" flag. When the timer expires, - this flag is checked. If it is on, the display is judged "in use". The flag is cleared and the timer is restarted. - - If the flag is off when the timer expires, then there has been no user activity since the last timer - expiration, and the display is judged idle and its power is lowered. - - The period of the timer is a function of the current value of Power Management aggressiveness. As that factor - varies from 1 to 999, the timer period varies from 1004 seconds to 6 seconds. Above 1000, the system is in - a very aggressive power management condition, and the timer period is 5 seconds. (In this case, the display dims - between five and ten seconds after the last user activity). - - This driver calls the drivers for each display and has them move their display between various power states. - When the display is idle, its power is dropped state by state until it is in the lowest state. When it becomes un-idle - it is powered back up to the state where it was last being used. - - In times of very high power management aggressiveness, the display will not be operated above the lowest power - state which is marked "usable". - - When Power Management is turned off (aggressiveness = 0), the display is never judged idle and never dimmed. - - We register with Power Management only so that we can be informed of changes in the Power Management - aggressiveness factor. We don't really have a device with power states so we implement the absolute minimum. - The display drivers themselves are part of the Power Management hierarchy under their respective frame buffers. - - */ - - -// ********************************************************************************** -// initForPM -// -// ********************************************************************************** -void IODisplayWrangler::initForPM (void ) -{ - - PMinit(); // initialize superclass variables - - mins_to_dim = 0; - use_general_aggressiveness = false; - - pm_vars->thePlatform->PMRegisterDevice(0,this); // attach into the power management hierarchy - - registerPowerDriver(this,ourPowerStates,kNumber_of_power_states); // register ourselves with policy-maker (us) - - registerService(); // HID system is waiting for this - -} - - -//********************************************************************************* -// setAggressiveness -// -// We are informed by our power domain parent of a new level of "power management -// aggressiveness" which we use as a factor in our judgement of when we are idle. -// This change implies a change in our idle timer period, so restart that timer. -// timer. -//********************************************************************************* - -IOReturn IODisplayWrangler::setAggressiveness ( unsigned long type, unsigned long newLevel ) -{ - if ( type == kPMMinutesToDim ) { // minutes to dim received - if( newLevel == 0 ) { - if( pm_vars->myCurrentState < kNumber_of_power_states-1 ) { // pm turned off while idle? - makeDisplaysUsable(); // yes, bring displays up again - } - } - mins_to_dim = newLevel; - use_general_aggressiveness = false; - if ( pm_vars->aggressiveness < kIOPowerEmergencyLevel ) { // no, currently in emergency level? - setIdleTimerPeriod(newLevel*60); // no, set new timeout - } - } - if ( type == kPMGeneralAggressiveness ) { // general factor received - if ( newLevel >= kIOPowerEmergencyLevel ) { // emergency level? - setIdleTimerPeriod(5); // yes - } - else { - if ( pm_vars->aggressiveness >= kIOPowerEmergencyLevel ) { // no, coming out of emergency level? - if (use_general_aggressiveness ) { // yes, set new timer period - setIdleTimerPeriod(333-(newLevel/3)); - } - else { - setIdleTimerPeriod(mins_to_dim*60); - } - } - else { - if (use_general_aggressiveness ) { // no, maybe set period - setIdleTimerPeriod(333-(newLevel/3)); - } - } - } - } - super::setAggressiveness(type, newLevel); - return IOPMNoErr; -} - - -// ********************************************************************************** -// activityTickle -// -// This is called by the HID system and calls the superclass in turn. -// ********************************************************************************** - -bool IODisplayWrangler::activityTickle ( unsigned long, unsigned long ) -{ - if ( rootDomain != NULL ) { - rootDomain->activityTickle (kIOPMSubclassPolicy); - } - return super::activityTickle (kIOPMSuperclassPolicy1,kNumber_of_power_states-1 ); -} - - -// ********************************************************************************** -// setPowerState -// -// The vanilla policy-maker in the superclass is changing our power state. -// If it's down, inform the displays to lower one state, too. If it's up, -// the idle displays are made usable. -// ********************************************************************************** -IOReturn IODisplayWrangler::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ) -{ - if ( powerStateOrdinal == 0 ) { // system is going to sleep - return IOPMNoErr; - } - if ( powerStateOrdinal < pm_vars->myCurrentState ) { // HI is idle, drop power - idleDisplays(); - return IOPMNoErr; - } - if ( powerStateOrdinal == kNumber_of_power_states-1 ) { // there is activity, raise power - makeDisplaysUsable(); - return IOPMNoErr; - } - return IOPMNoErr; -} - - -// ********************************************************************************** -// makeDisplaysUsable -// -// ********************************************************************************** -void IODisplayWrangler::makeDisplaysUsable ( void ) -{ - OSIterator * iter; - IODisplay * display; - - IOTakeLock( fMatchingLock ); - - iter = OSCollectionIterator::withCollection( fDisplays ); - if( iter ) { - while( (display = (IODisplay *) iter->getNextObject()) ) { - display->makeDisplayUsable(); - } - iter->release(); - } - IOUnlock( fMatchingLock ); -} - - -// ********************************************************************************** -// idleDisplays -// -// ********************************************************************************** -void IODisplayWrangler::idleDisplays ( void ) -{ - OSIterator * iter; - IODisplay * display; - - IOTakeLock( fMatchingLock ); - - iter = OSCollectionIterator::withCollection( fDisplays ); - if( iter ) { - while( (display = (IODisplay *) iter->getNextObject()) ) { - display->dropOneLevel(); - } - iter->release(); - } - IOUnlock( fMatchingLock ); -} - - diff --git a/iokit/Families/IOGraphics/IODisplayWrangler.h b/iokit/Families/IOGraphics/IODisplayWrangler.h deleted file mode 100644 index 0237a62ab..000000000 --- a/iokit/Families/IOGraphics/IODisplayWrangler.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. - * - * - * HISTORY - * - */ - -#ifndef _IOKIT_IODISPLAYWRANGLER_H -#define _IOKIT_IODISPLAYWRANGLER_H - -#include <IOKit/IOService.h> -#include <IOKit/graphics/IOFramebuffer.h> -#include <IOKit/graphics/IODisplay.h> - -class IOWorkLoop; -class IOCommandQueue; - -class IODisplayWrangler : public IOService -{ - OSDeclareDefaultStructors( IODisplayWrangler ); - -private: - bool fOpen; - IOLock * fMatchingLock; - OSSet * fFramebuffers; - OSSet * fDisplays; - // true: we have informed displays to assume lowest usable state - bool emergency_informed; - // from control panel: number of idle minutes before dimming - unsigned long mins_to_dim; - // false: use mins_to_dim unless in emergency situation - bool use_general_aggressiveness; - - virtual void initForPM ( void ); - virtual IOReturn setAggressiveness ( unsigned long, unsigned long ); - virtual bool activityTickle ( unsigned long, unsigned long ); - virtual IOReturn setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice ); - virtual void makeDisplaysUsable ( void ); - virtual void idleDisplays ( void ); - - static bool _displayHandler( void * target, void * ref, - IOService * newService ); - static bool _displayConnectHandler( void * target, void * ref, - IOService * newService ); - - virtual bool displayHandler( OSSet * set, IODisplay * newDisplay); - virtual bool displayConnectHandler( void * ref, IODisplayConnect * connect); - - virtual bool makeDisplayConnects( IOFramebuffer * fb ); - - virtual IODisplayConnect * getDisplayConnect( - IOFramebuffer * fb, IOIndex connect ); - - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayConnect * connect, - IODisplayModeID mode, UInt32 * flags ); - - virtual IOReturn getDefaultMode( IOFramebuffer * fb, - IODisplayModeID * mode, IOIndex * depth ); - - virtual IOReturn findStartupMode( IOFramebuffer * fb ); - -public: - - IOService * rootDomain; // points to Root Power Domain - - virtual bool start(IOService * provider); - - static IOReturn clientStart( IOFramebuffer * fb ); - - static IOReturn getFlagsForDisplayMode( - IOFramebuffer * fb, - IODisplayModeID mode, UInt32 * flags ); - -}; - -#endif /* _IOKIT_IODISPLAYWRANGLER_H */ diff --git a/iokit/Families/IOGraphics/IOFramebuffer.cpp b/iokit/Families/IOGraphics/IOFramebuffer.cpp deleted file mode 100644 index 73977c788..000000000 --- a/iokit/Families/IOGraphics/IOFramebuffer.cpp +++ /dev/null @@ -1,1847 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * 01 Sep 92 Portions from Joe Pasqua, Created. - */ - - -#include <IOKit/IOLib.h> -#include <libkern/c++/OSContainers.h> - -#include <IOKit/IOWorkLoop.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/IOPlatformExpert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> - -#define IOFRAMEBUFFER_PRIVATE -#include <IOKit/graphics/IOFramebuffer.h> -#include <IOKit/graphics/IODisplay.h> - -#include "IOFramebufferUserClient.h" -#include "IODisplayWrangler.h" -#include "IOFramebufferReallyPrivate.h" -#include <IOKit/pwr_mgt/RootDomain.h> - -#include <string.h> -#include <IOKit/assert.h> -#include <sys/kdebug.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOGraphicsDevice - -OSDefineMetaClass( IOFramebuffer, IOGraphicsDevice ) -OSDefineAbstractStructors( IOFramebuffer, IOGraphicsDevice ) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define GetShmem(instance) ((StdFBShmem_t *)(instance->priv)) - -#define CLEARSEMA(shmem) ev_unlock(&shmem->cursorSema) -#define SETSEMA(shmem) \ - if (!ev_try_lock(&shmem->cursorSema)) return; -#define TOUCHBOUNDS(one, two) \ - (((one.minx < two.maxx) && (two.minx < one.maxx)) && \ - ((one.miny < two.maxy) && (two.miny < one.maxy))) - -/* - * Cursor rendering - */ - -#include "IOCursorBlits.h" - -inline void IOFramebuffer::StdFBDisplayCursor( IOFramebuffer * inst ) -{ - StdFBShmem_t *shmem; - Bounds saveRect; - volatile unsigned char *vramPtr; /* screen data pointer */ - unsigned int cursStart; - unsigned int cursorWidth; - int width; - int height; - - shmem = GetShmem(inst); - saveRect = shmem->cursorRect; - /* Clip saveRect vertical within screen bounds */ - if (saveRect.miny < shmem->screenBounds.miny) - saveRect.miny = shmem->screenBounds.miny; - if (saveRect.maxy > shmem->screenBounds.maxy) - saveRect.maxy = shmem->screenBounds.maxy; - if (saveRect.minx < shmem->screenBounds.minx) - saveRect.minx = shmem->screenBounds.minx; - if (saveRect.maxx > shmem->screenBounds.maxx) - saveRect.maxx = shmem->screenBounds.maxx; - shmem->saveRect = saveRect; /* Remember save rect for RemoveCursor */ - - vramPtr = inst->frameBuffer + - (inst->rowBytes * (saveRect.miny - shmem->screenBounds.miny)) + - (inst->bytesPerPixel * (saveRect.minx - shmem->screenBounds.minx)); - - width = saveRect.maxx - saveRect.minx; - height = saveRect.maxy - saveRect.miny; - cursorWidth = shmem->cursorSize[shmem->frame].width; - - cursStart = (saveRect.miny - shmem->cursorRect.miny) * cursorWidth + - (saveRect.minx - shmem->cursorRect.minx); - - if( inst->cursorBlitProc) - inst->cursorBlitProc( inst, - (void *) shmem, - vramPtr, - cursStart, - inst->totalWidth - width, /* vramRow */ - cursorWidth - width, /* cursRow */ - width, - height); -} - -// Description: RemoveCursor erases the cursor by replacing the background -// image that was saved by the previous call to DisplayCursor. -// If the frame buffer is cacheable, flush at the end of the -// drawing operation. - -inline void IOFramebuffer::StdFBRemoveCursor( IOFramebuffer * inst ) -{ - StdFBShmem_t *shmem; - volatile unsigned char *vramPtr; /* screen data pointer */ - unsigned int vramRow; - int width; - int height; - - shmem = GetShmem(inst); - - vramRow = inst->totalWidth; /* Scanline width in pixels */ - - vramPtr = inst->frameBuffer + - (inst->rowBytes * (shmem->saveRect.miny - shmem->screenBounds.miny)) - + (inst->bytesPerPixel * - (shmem->saveRect.minx - shmem->screenBounds.minx)); - - width = shmem->saveRect.maxx - shmem->saveRect.minx; - height = shmem->saveRect.maxy - shmem->saveRect.miny; - vramRow -= width; - - if( inst->cursorRemoveProc) - inst->cursorRemoveProc( inst, (void *)shmem, - vramPtr, vramRow, width, height); -} - -inline void IOFramebuffer::RemoveCursor( IOFramebuffer * inst ) -{ - StdFBShmem_t * shmem = GetShmem(inst); - - if( shmem->hardwareCursorActive ) { - Point * hs; - - hs = &shmem->hotSpot[shmem->frame]; - inst->setCursorState( - shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, - shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, false ); - } else - StdFBRemoveCursor(inst); -} - -inline void IOFramebuffer::DisplayCursor( IOFramebuffer * inst ) -{ - Point * hs; - StdFBShmem_t * shmem = GetShmem(inst); - SInt32 x, y; - - hs = &shmem->hotSpot[shmem->frame]; - x = shmem->cursorLoc.x - hs->x; - y = shmem->cursorLoc.y - hs->y; - - if( shmem->hardwareCursorActive ) - inst->setCursorState( x - shmem->screenBounds.minx, - y - shmem->screenBounds.miny, true ); - else { - shmem->cursorRect.maxx = (shmem->cursorRect.minx = x) - + shmem->cursorSize[shmem->frame].width; - shmem->cursorRect.maxy = (shmem->cursorRect.miny = y) - + shmem->cursorSize[shmem->frame].height; - StdFBDisplayCursor(inst); - shmem->oldCursorRect = shmem->cursorRect; - } -} - -inline void IOFramebuffer::SysHideCursor( IOFramebuffer * inst ) -{ - if (!GetShmem(inst)->cursorShow++) - RemoveCursor(inst); -} - -inline void IOFramebuffer::SysShowCursor( IOFramebuffer * inst ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(inst); - - if (shmem->cursorShow) - if (!--(shmem->cursorShow)) - DisplayCursor(inst); -} - -inline void IOFramebuffer::CheckShield( IOFramebuffer * inst ) -{ - Point * hs; - int intersect; - Bounds tempRect; - StdFBShmem_t * shmem = GetShmem(inst); - - /* Calculate temp cursorRect */ - hs = &shmem->hotSpot[shmem->frame]; - tempRect.maxx = (tempRect.minx = (shmem->cursorLoc).x - hs->x) - + shmem->cursorSize[shmem->frame].width; - tempRect.maxy = (tempRect.miny = (shmem->cursorLoc).y - hs->y) - + shmem->cursorSize[shmem->frame].height; - - intersect = TOUCHBOUNDS(tempRect, shmem->shieldRect); - if (intersect != shmem->shielded) - (shmem->shielded = intersect) ? - SysHideCursor(inst) : SysShowCursor(inst); -} - -/** - ** external methods - **/ - -void IOFramebuffer::setupCursor( IOPixelInformation * info ) -{ - StdFBShmem_t * shmem = GetShmem(this); - volatile unsigned char * bits; - IOByteCount cursorImageBytes; - - rowBytes = info->bytesPerRow; - totalWidth = (rowBytes * 8) / info->bitsPerPixel; - bytesPerPixel = info->bitsPerPixel / 8; - frameBuffer = (volatile unsigned char *) vramMap->getVirtualAddress(); - - if( shmem) { - if( (shmem->screenBounds.maxx == shmem->screenBounds.minx) - || (shmem->screenBounds.maxy == shmem->screenBounds.miny)) { - // a default if no one calls IOFBSetBounds() - shmem->screenBounds.minx = 0; - shmem->screenBounds.miny = 0; - shmem->screenBounds.maxx = info->activeWidth; - shmem->screenBounds.maxy = info->activeHeight; - } - - cursorImageBytes = maxCursorSize.width * maxCursorSize.height - * bytesPerPixel; - bits = shmem->cursor; - for( int i = 0; i < kIOFBNumCursorFrames; i++ ) { - cursorImages[i] = bits; - bits += cursorImageBytes; - shmem->cursorSize[i] = maxCursorSize; - } - if( info->bitsPerPixel <= 8) { - for( int i = 0; i < kIOFBNumCursorFrames; i++ ) { - cursorMasks[i] = bits; - bits += cursorImageBytes; - } - } - cursorSave = bits; - } - - switch( info->bitsPerPixel) { - case 8: - if( colorConvert.t._bm256To38SampleTable - && colorConvert.t._bm38To256SampleTable) { - cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor8P; - cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor8; - } - break; - case 16: - if( colorConvert.t._bm34To35SampleTable - && colorConvert.t._bm35To34SampleTable) { - cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor555; - cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor16; - } - break; - case 32: - if( colorConvert.t._bm256To38SampleTable - && colorConvert.t._bm38To256SampleTable) { - cursorBlitProc = (CursorBlitProc) StdFBDisplayCursor32Axxx; - cursorRemoveProc = (CursorRemoveProc) StdFBRemoveCursor32; - } - break; - default: - IOLog("%s: can't do cursor at depth %ld\n", - getName(), info->bitsPerPixel); - cursorBlitProc = (CursorBlitProc) NULL; - cursorRemoveProc = (CursorRemoveProc) NULL; - break; - } -} - -void IOFramebuffer::stopCursor( void ) -{ - cursorBlitProc = (CursorBlitProc) NULL; - cursorRemoveProc = (CursorRemoveProc) NULL; -} - -IOReturn IOFramebuffer::createSharedCursor( - int shmemVersion, int maxWidth, int maxHeight ) -{ - StdFBShmem_t * shmem; - IOByteCount size, maxImageSize; - - kprintf("createSharedCursor vers = %d, %d x %d\n", - shmemVersion, maxWidth, maxHeight); - - if( shmemVersion != kIOFBCurrentShmemVersion) - return( kIOReturnUnsupported); - - shmemClientVersion = shmemVersion; - maxImageSize = (maxWidth * maxHeight * kIOFBMaxCursorDepth) / 8; - - size = sizeof( StdFBShmem_t) - + ((kIOFBNumCursorFrames + 1) * maxImageSize); - - if( !sharedCursor || (size != sharedCursor->getLength())) { - IOBufferMemoryDescriptor * newDesc; - - priv = 0; - newDesc = IOBufferMemoryDescriptor::withOptions( - kIODirectionNone | kIOMemoryKernelUserShared, size ); - if( !newDesc) - return( kIOReturnNoMemory ); - - if( sharedCursor) - sharedCursor->release(); - sharedCursor = newDesc; - } - shmem = (StdFBShmem_t *) sharedCursor->getBytesNoCopy(); - priv = shmem; - - // Init shared memory area - bzero( shmem, size ); - shmem->version = kIOFBCurrentShmemVersion; - shmem->structSize = size; - shmem->cursorShow = 1; - shmem->hardwareCursorCapable = haveHWCursor; - - maxCursorSize.width = maxWidth; - maxCursorSize.height = maxHeight; - - doSetup( false ); - - return( kIOReturnSuccess); -} - -IOReturn IOFramebuffer::setBoundingRect( Bounds * bounds ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - if( NULL == shmem) - return( kIOReturnUnsupported); - - shmem->screenBounds = *bounds; - - return( kIOReturnSuccess); -} - -/** - ** IOUserClient methods - **/ - -IOReturn IOFramebuffer::newUserClient( task_t owningTask, - void * security_id, - UInt32 type, - IOUserClient ** handler ) - -{ -#if 0 - static UInt8 data[] = { 0x00, 0x03, 0x04, 0x07, 0x08, 0x0b, 0x0c, 0x0f, - 0x10, 0x13, 0x14, 0x17, 0x18, 0x1b, 0x1c, 0x1f, - - 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, - 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, - 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, - 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f }; - colorConvert.t._bm34To35SampleTable = data; - colorConvert.t._bm35To34SampleTable = data + 16; -#endif - - IOReturn err = kIOReturnSuccess; - IOUserClient * newConnect = 0; - IOUserClient * theConnect = 0; - - switch( type ) { - - case kIOFBServerConnectType: - if( serverConnect) - err = kIOReturnExclusiveAccess; - else { - - if( isConsoleDevice()) - getPlatform()->setConsoleInfo( 0, kPEReleaseScreen); - - err = IODisplayWrangler::clientStart( this ); - if( kIOReturnSuccess == err) - newConnect = IOFramebufferUserClient::withTask(owningTask); - } - break; - - case kIOFBSharedConnectType: - if( sharedConnect) { - theConnect = sharedConnect; - theConnect->retain(); - } else if( serverConnect) - newConnect = IOFramebufferSharedUserClient::withTask(owningTask); - else - err = kIOReturnNotOpen; - break; - - case kIOFBEngineControllerConnectType: - case kIOFBEngineConnectType: - newConnect = IOGraphicsEngineClient::withTask(owningTask); - break; - - default: - err = kIOReturnBadArgument; - } - - if( newConnect) { - if( (false == newConnect->attach( this )) - || (false == newConnect->start( this ))) { - newConnect->detach( this ); - newConnect->release(); - } else - theConnect = newConnect; - } - - *handler = theConnect; - return( err ); -} - -IOReturn IOFramebuffer::extGetDisplayModeCount( IOItemCount * count ) -{ - *count = getDisplayModeCount(); - return( kIOReturnSuccess); -} - -IOReturn IOFramebuffer::extGetDisplayModes( IODisplayModeID * allModes, IOByteCount * size ) -{ - IOReturn err; - IOByteCount outSize; - - outSize = getDisplayModeCount() * sizeof( IODisplayModeID); - - if( *size < outSize) - return( kIOReturnBadArgument); - - *size = outSize; - err = getDisplayModes( allModes ); - - return( err); -} - -IOReturn IOFramebuffer::extGetVRAMMapOffset( IOPixelAperture /* aperture */, - IOByteCount * offset ) -{ - *offset = vramMapOffset; - - return( kIOReturnSuccess ); -} - -IOReturn IOFramebuffer::extSetBounds( Bounds * bounds ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - if( shmem) - shmem->screenBounds = *bounds; - - return( kIOReturnSuccess ); -} - -IOReturn IOFramebuffer::extValidateDetailedTiming( - void * description, void * outDescription, - IOByteCount inSize, IOByteCount * outSize ) -{ - IOReturn err; - - if( *outSize != inSize) - return( kIOReturnBadArgument ); - - err = validateDetailedTiming( description, inSize ); - - if( kIOReturnSuccess == err) - bcopy( description, outDescription, inSize ); - - return( err ); -} - - -IOReturn IOFramebuffer::extSetColorConvertTable( UInt32 select, - UInt8 * data, IOByteCount length ) -{ - static const IOByteCount checkLength[] = { - 16 * sizeof( UInt8), - 32 * sizeof( UInt8), - 256 * sizeof( UInt32), - 5 * 256 * sizeof( UInt8) }; - - UInt8 * table; - IODisplayModeID mode; - IOIndex depth; - IOPixelInformation info; - - if( select > 3) - return( kIOReturnBadArgument ); - - if( length != checkLength[select]) - return( kIOReturnBadArgument ); - - table = colorConvert.tables[select]; - if( 0 == table) { - table = (UInt8 *) IOMalloc( length ); - colorConvert.tables[select] = table; - } - if( !table) - return( kIOReturnNoMemory ); - - bcopy( data, table, length ); - if( select == 3) - white = data[data[255] + data[511] + data[767] + 1024]; - - if( (NULL == cursorBlitProc) - && colorConvert.tables[0] && colorConvert.tables[1] - && colorConvert.tables[2] && colorConvert.tables[3] - && vramMap - && (kIOReturnSuccess == getCurrentDisplayMode( &mode, &depth )) - && (kIOReturnSuccess == getPixelInformation( mode, depth, kIOFBSystemAperture, &info ))) - setupCursor( &info ); - - return( kIOReturnSuccess ); -} - -IOReturn IOFramebuffer::extSetCLUTWithEntries( UInt32 index, IOOptionBits options, - IOColorEntry * colors, IOByteCount inputCount ) -{ - IOReturn kr; - - kr = setCLUTWithEntries( colors, index, - inputCount / sizeof( IOColorEntry), - options ); - - return( kr ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// -// BEGIN: Implementation of the evScreen protocol -// - -void IOFramebuffer::hideCursor( void ) -{ - StdFBShmem_t *shmem = GetShmem(this); - - SETSEMA(shmem); - SysHideCursor(this); - CLEARSEMA(shmem); -} - -#if 0 -void IOFramebuffer::free() -{ - if( vblSemaphore) - semaphore_destroy(kernel_task, vblSemaphore); - super::free(); -} -#endif - -void IOFramebuffer::deferredMoveCursor( IOFramebuffer * inst ) -{ - StdFBShmem_t * shmem = GetShmem(inst); - IOReturn err = kIOReturnSuccess; - - if( shmem->hardwareCursorActive && (0 == shmem->frame) ) { - - if (shmem->cursorObscured) { - shmem->cursorObscured = 0; - if (shmem->cursorShow) - --shmem->cursorShow; - } - if (!shmem->cursorShow) { - Point * hs; - hs = &shmem->hotSpot[shmem->frame]; - err = inst->setCursorState( - shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, - shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, true ); - } - - } else { - - if (!shmem->cursorShow++) - RemoveCursor(inst); - if (shmem->cursorObscured) { - shmem->cursorObscured = 0; - if (shmem->cursorShow) - --shmem->cursorShow; - } - if (shmem->shieldFlag) CheckShield(inst); - if (shmem->cursorShow) - if (!--shmem->cursorShow) - DisplayCursor(inst); - - inst->flushCursor(); - } - inst->needCursorService = (kIOReturnBusy == err); -} - -void IOFramebuffer::moveCursor( Point * cursorLoc, int frame ) -{ - nextCursorLoc = *cursorLoc; - nextCursorFrame = frame; - needCursorService = true; - - StdFBShmem_t *shmem = GetShmem(this); - - SETSEMA(shmem); - - if( !haveVBLService) { - shmem->cursorLoc = *cursorLoc; - shmem->frame = frame; - deferredMoveCursor( this ); - } - - CLEARSEMA(shmem); -} - -void IOFramebuffer::handleVBL( IOFramebuffer * inst, void * ref ) -{ - StdFBShmem_t * shmem = GetShmem(inst); - AbsoluteTime now; - - if( !shmem) - return; - - clock_get_uptime( &now ); - shmem->vblDelta = now; - SUB_ABSOLUTETIME( &shmem->vblDelta, &shmem->vblTime ); - shmem->vblTime = now; - - KERNEL_DEBUG(0xc000030 | DBG_FUNC_NONE, - shmem->vblDelta.hi, shmem->vblDelta.lo, 0, 0, 0); - - if( inst->vblSemaphore) - semaphore_signal_all(inst->vblSemaphore); - - SETSEMA(shmem); - - if( inst->needCursorService) { - shmem->cursorLoc = inst->nextCursorLoc; - shmem->frame = inst->nextCursorFrame; - deferredMoveCursor( inst ); - } - - CLEARSEMA(shmem); -} - -void IOFramebuffer::showCursor( Point * cursorLoc, int frame ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - SETSEMA(shmem); - shmem->frame = frame; - shmem->hardwareCursorActive = hwCursorLoaded && (frame == 0); - shmem->cursorLoc = *cursorLoc; - if (shmem->shieldFlag) CheckShield(this); - SysShowCursor(this); - CLEARSEMA(shmem); -} - -void IOFramebuffer::resetCursor( void ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - hwCursorLoaded = false; - if( !shmem) - return; - hideCursor(); - shmem->hardwareCursorActive = false; - showCursor( &shmem->cursorLoc, shmem->frame ); -} - -void IOFramebuffer::getVBLTime( AbsoluteTime * time, AbsoluteTime * delta ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - if( shmem) { - *time = shmem->vblTime; - *delta = shmem->vblDelta; - } else - time->hi = time->lo = 0; -} - -void IOFramebuffer::getBoundingRect( Bounds ** bounds ) -{ - StdFBShmem_t *shmem; - - shmem = GetShmem(this); - if( NULL == shmem) - *bounds = NULL; - else - *bounds = &shmem->screenBounds; -} - -// -// END: Implementation of the evScreen protocol -// - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOFramebuffer::getNotificationSemaphore( - IOSelect interruptType, semaphore_t * semaphore ) -{ - kern_return_t kr; - semaphore_t sema; - - if( interruptType != kIOFBVBLInterruptType) - return( kIOReturnUnsupported ); - - if( !haveVBLService) - return( kIOReturnNoResources ); - - if( MACH_PORT_NULL == vblSemaphore) { - kr = semaphore_create(kernel_task, &sema, SYNC_POLICY_FIFO, 0); - if( kr == KERN_SUCCESS) - vblSemaphore = sema; - } else - kr = KERN_SUCCESS; - - if( kr == KERN_SUCCESS) - *semaphore = vblSemaphore; - - return( kr ); -} - -IOReturn IOFramebuffer::extSetCursorVisible( bool visible ) -{ - IOReturn err; - Point * hs; - StdFBShmem_t * shmem = GetShmem(this); - - if( shmem->hardwareCursorActive ) { - hs = &shmem->hotSpot[shmem->frame]; - err = setCursorState( - shmem->cursorLoc.x - hs->x - shmem->screenBounds.minx, - shmem->cursorLoc.y - hs->y - shmem->screenBounds.miny, - visible ); - } else - err = kIOReturnBadArgument; - - return( err ); -} - -IOReturn IOFramebuffer::extSetCursorPosition( SInt32 x, SInt32 y ) -{ - return( kIOReturnUnsupported ); -} - -IOReturn IOFramebuffer::extSetNewCursor( void * cursor, IOIndex frame, - IOOptionBits options ) -{ - StdFBShmem_t * shmem = GetShmem(this); - IOReturn err; - - if( cursor || options || frame) - err = kIOReturnBadArgument; - else { - - if( (shmem->cursorSize[frame].width > maxCursorSize.width) - || (shmem->cursorSize[frame].height > maxCursorSize.height)) - err = kIOReturnBadArgument; - - else if( haveHWCursor) - err = setCursorImage( (void *) frame ); - else - err = kIOReturnUnsupported; - } - - hwCursorLoaded = (kIOReturnSuccess == err); - shmem->hardwareCursorActive = hwCursorLoaded && (shmem->frame == 0); - - return( err ); -} - -bool IOFramebuffer::convertCursorImage( void * cursorImage, - IOHardwareCursorDescriptor * hwDesc, - IOHardwareCursorInfo * hwCursorInfo ) -{ - StdFBShmem_t * shmem = GetShmem(this); - UInt8 * dataOut = hwCursorInfo->hardwareCursorData; - IOColorEntry * clut = hwCursorInfo->colorMap; - UInt32 maxColors = hwDesc->numColors; - int frame = (int) cursorImage; - - volatile unsigned short * cursPtr16; - volatile unsigned int * cursPtr32; - SInt32 x, y; - UInt32 index, numColors = 0; - UInt16 alpha, red, green, blue; - UInt16 s16; - UInt32 s32; - UInt8 data = 0; - UInt8 pixel = 0; - bool ok = true; - - assert( frame < kIOFBNumCursorFrames ); - - if( bytesPerPixel == 4) { - cursPtr32 = (volatile unsigned int *) cursorImages[ frame ]; - cursPtr16 = 0; - } else if( bytesPerPixel == 2) { - cursPtr32 = 0; - cursPtr16 = (volatile unsigned short *) cursorImages[ frame ]; - } else - return( false ); - - x = shmem->cursorSize[frame].width; - y = shmem->cursorSize[frame].height; - - if( (x > (SInt32) hwDesc->width) || (y > (SInt32) hwDesc->height)) - return( false ); -#if 0 - hwCursorInfo->cursorWidth = x; - hwCursorInfo->cursorHeight = y; - while( (--y != -1) ) { - x = shmem->cursorSize[frame].width; - while( (--x != -1) ) { - - if( cursPtr32) { - s32 = *(cursPtr32++); - alpha = (s32 >> 28) & 0xf; - if( alpha && (alpha != 0xf)) - *(cursPtr32 - 1) = 0x00ffffff; - - } else { - s16 = *(cursPtr16++); - alpha = s16 & 0x000F; - if( alpha && (alpha != 0xf)) - *(cursPtr16 - 1) = 0xfff0; - } - } - } -#endif - - hwCursorInfo->cursorWidth = x; - hwCursorInfo->cursorHeight = y; - - while( ok && (--y != -1) ) { - x = shmem->cursorSize[frame].width; - while( ok && (--x != -1) ) { - - if( cursPtr32) { - s32 = *(cursPtr32++); - alpha = (s32 >> 28) & 0xf; - red = (s32 >> 16) & 0xff; - red |= (red << 8); - green = (s32 >> 8) & 0xff; - green |= (green << 8); - blue = (s32) & 0xff; - blue |= (blue << 8); - - } else { -#define RMASK16 0xF000 -#define GMASK16 0x0F00 -#define BMASK16 0x00F0 -#define AMASK16 0x000F - s16 = *(cursPtr16++); - alpha = s16 & AMASK16; - red = s16 & RMASK16; - red |= (red >> 4) | (red >> 8) | (red >> 12); - green = s16 & GMASK16; - green |= (green << 4) | (green >> 4) | (green >> 8); - blue = s16 & BMASK16; - blue |= (blue << 8) | (blue << 4) | (blue >> 4); - } - - if( alpha == 0 ) { - - if( 0 == (red | green | blue)) { - /* Transparent black area. Leave dst as is. */ - if( kTransparentEncodedPixel - & hwDesc->supportedSpecialEncodings) - pixel = hwDesc->specialEncodings[kTransparentEncoding]; - else - ok = false; - } else if (0xffff == (red & green & blue)) { - /* Transparent white area. Invert dst. */ - if( kInvertingEncodedPixel - & hwDesc->supportedSpecialEncodings) - pixel = hwDesc->specialEncodings[kInvertingEncoding]; - else - ok = false; - } else - ok = false; - - } else if( alpha == 0xf ) { - - /* Opaque cursor pixel. Mark it. */ - for( index = 0; index < numColors; index++ ) { - if( (red == clut[ index ].red) - && (green == clut[ index ].green) - && (blue == clut[ index ].blue) ) { - - pixel = clut[ index ].index; - break; - } - } - if( index == numColors) { - ok = (numColors < maxColors); - if( ok) { - pixel = hwDesc->colorEncodings[ numColors++ ]; - clut[ index ].red = red; - clut[ index ].green = green; - clut[ index ].blue = blue; - clut[ index ].index = pixel; - } - } - - } else { - /* Alpha is not 0 or 1.0. Sover the cursor. */ - ok = false; - break; - } - - data <<= hwDesc->bitDepth; - data |= pixel; - - if( 0 == (x & ((8 / hwDesc->bitDepth) - 1))) - *dataOut++ = data; - } /* x */ - } /* y */ - -// if( !ok) kprintf("Couldnt do a hw curs\n"); - - return( ok ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -void IOFramebuffer::initialize() -{ -#if 0 -static IOWorkLoop * gIOFramebufferWorkloop; -static IOLock * gIOFramebufferLock; - - gIOFramebufferLock = IOLockAlloc(); - - gIOFramebufferWorkloop = IOWorkLoop::workLoop(); - - assert( gIOFramebufferLock && gIOFramebufferWorkloop ); -#endif -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#if 0 -static bool serializeInfoCB( void * target, void * ref, OSSerialize * s ) -{ - return( ((IOFramebuffer *)target)->serializeInfo(s) ); -} -#endif - -static IOPMrootDomain * gIOPMRootDomain; - -bool IOFramebuffer::start( IOService * provider ) -{ - - if( ! super::start( provider)) - return( false ); - - userAccessRanges = OSArray::withCapacity( 1 ); - engineAccessRanges = OSArray::withCapacity( 1 ); - -#if 0 - OSSerializer * infoSerializer = OSSerializer::forTarget( (void *) this, &serializeInfoCB ); - if( !infoSerializer) - return( false ); - - setProperty( kIOFramebufferInfoKey, infoSerializer ); - infoSerializer->release(); - - - IOInterruptEventSource * eventSrc; - - eventSrc = IOInterruptEventSource::interruptEventSource( - this, autopollArrived); - if (!eventSrc || - kIOReturnSuccess != workLoop->addEventSource(eventSrc) ) { - kprintf("Start is bailing\n"); - return false; - } -#endif - - closed = true; - registerService(); - - // initialize superclass power management variables - PMinit(); - // attach into the power management hierarchy - provider->joinPMtree(this); - // clamp power on (the user client will change that when appropriate) -// makeUsable(); - - if( !gIOPMRootDomain) - gIOPMRootDomain = (IOPMrootDomain *) - IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane); - if( gIOPMRootDomain) - gIOPMRootDomain->registerInterestedDriver(this); - - return( true ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Apple standard 8-bit CLUT - -UInt8 appleClut8[ 256 * 3 ] = { -// 00 - 0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66, - 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC, - 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00, - 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66, -// 10 - 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC, - 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00, - 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66, - 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC, -// 20 - 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00, - 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66, - 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC, - 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00, -// 30 - 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66, - 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC, - 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00, - 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66, -// 40 - 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC, - 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00, - 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66, - 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC, -// 50 - 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00, - 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66, - 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC, - 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00, -// 60 - 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66, - 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC, - 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00, - 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66, -// 70 - 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC, - 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00, - 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66, - 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC, -// 80 - 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00, - 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66, - 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC, - 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00, -// 90 - 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66, - 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC, - 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00, - 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66, -// a0 - 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC, - 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00, - 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66, - 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC, -// b0 - 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00, - 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66, - 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC, - 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00, -// c0 - 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66, - 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC, - 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00, - 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66, -// d0 - 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC, - 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00, - 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00, - 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00, -// e0 - 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00, - 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00, - 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE, - 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88, -// f0 - 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22, - 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB, - 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55, - 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00 -}; - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifdef __ppc__ -extern -#endif -int killprint; -extern "C" { int kmputc( int c ); } - -IOReturn IOFramebuffer::setPowerState( unsigned long powerStateOrdinal, - IOService * whichDevice ) -{ - if( 0 == powerStateOrdinal ) { - if( isConsoleDevice()) - killprint = 1; - deliverFramebufferNotification( kIOFBNotifyWillSleep ); - - } else { - - if( isConsoleDevice()) { - killprint = 0; - kmputc( 033 ); - kmputc( 'c' ); - } - deliverFramebufferNotification( kIOFBNotifyDidWake ); - } - - return( IOPMAckImplied); -} - -IOReturn IOFramebuffer::beginSystemSleep( void * ackRef ) -{ - pmRef = ackRef; - powerOverrideOnPriv(); - changePowerStateToPriv(0); - - return( kIOReturnSuccess ); -} - -IOReturn IOFramebuffer::powerStateWillChangeTo( IOPMPowerFlags flags, - unsigned long, IOService * whatDevice ) -{ - if( (whatDevice == gIOPMRootDomain) && (IOPMPowerOn & flags)) - // end system sleep - powerOverrideOffPriv(); - - return( IOPMAckImplied ); -} - -IOReturn IOFramebuffer::powerStateDidChangeTo( IOPMPowerFlags flags, - unsigned long, IOService* whatDevice ) -{ - if( (whatDevice == this) && pmRef && (0 == (IOPMDeviceUsable & flags))) { - // root can proceed - acknowledgeSleepWakeNotification(pmRef); - pmRef = 0; - } - - return( IOPMAckImplied ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IODeviceMemory * IOFramebuffer::getVRAMRange( void ) -{ - return( getApertureRange( kIOFBSystemAperture )); -} - -void IOFramebuffer::close( void ) // called by the user client when -{ // the window server exits - -} - - - -IOReturn IOFramebuffer::open( void ) -{ - IOReturn err = kIOReturnSuccess; - UInt32 value; - - do { - if( opened) - continue; - - // tell the console if it's on this display, it's going away - if( isConsoleDevice()) - getPlatform()->setConsoleInfo( 0, kPEDisableScreen); - - deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange ); - - err = enableController(); - if( kIOReturnSuccess != err) { - deliverFramebufferNotification( kIOFBNotifyDisplayModeDidChange ); - continue; - } - err = registerForInterruptType( kIOFBVBLInterruptType, - (IOFBInterruptProc) &handleVBL, - this, priv, &vblInterrupt ); - haveVBLService = (err == kIOReturnSuccess ); - - err = getAttribute( kIOHardwareCursorAttribute, &value ); - haveHWCursor = ((err == kIOReturnSuccess) && value); - - err = kIOReturnSuccess; - opened = true; - - } while( false ); - - return( err ); -} - -IOReturn IOFramebuffer::setUserRanges( void ) -{ -#if 1 /* print ranges */ - - UInt32 i, numRanges; - IODeviceMemory * mem; - - numRanges = userAccessRanges->getCount(); - IOLog("%s: user ranges num:%ld", getName(), numRanges); - for( i = 0; i < numRanges; i++) { - mem = (IODeviceMemory *) userAccessRanges->getObject( i ); - if( 0 == mem) - continue; - IOLog(" start:%lx size:%lx", - mem->getPhysicalAddress(), mem->getLength() ); - } - IOLog("\n"); - -#endif - return( kIOReturnSuccess); -} - -IOReturn IOFramebuffer::setupForCurrentConfig( void ) -{ - return( doSetup( true )); -} - -IOReturn IOFramebuffer::doSetup( bool full ) -{ - IOReturn err; - IODisplayModeID mode; - IOIndex depth; - IOPixelInformation info; - IODisplayModeInformation dmInfo; - IODeviceMemory * mem; - IODeviceMemory * fbRange; - IOPhysicalAddress base; - PE_Video newConsole; - - err = getCurrentDisplayMode( &mode, &depth ); - if( err) - IOLog("%s: getCurrentDisplayMode %d\n", getName(), err); - - err = getPixelInformation( mode, depth, kIOFBSystemAperture, &info ); - if( err) - IOLog("%s: getPixelInformation %d\n", getName(), err); - - if( full && (clutValid == false) && (info.pixelType == kIOCLUTPixels)) { - - IOColorEntry * tempTable; - int i; - - tempTable = (IOColorEntry *) IOMalloc( 256 * sizeof( *tempTable)); - if( tempTable) { - - for( i = 0; i < 256; i++) { - if( currentMono) { - UInt32 lum; - - lum = 0x0101 * i; - tempTable[ i ].red = lum; - tempTable[ i ].green = lum; - tempTable[ i ].blue = lum; - } else { - tempTable[ i ].red = (appleClut8[ i * 3 + 0 ] << 8) - | appleClut8[ i * 3 + 0 ]; - tempTable[ i ].green = (appleClut8[ i * 3 + 1 ] << 8) - | appleClut8[ i * 3 + 1 ]; - tempTable[ i ].blue = (appleClut8[ i * 3 + 2 ] << 8) - | appleClut8[ i * 3 + 2 ]; - } - } - setCLUTWithEntries( tempTable, 0, 256, 1 * kSetCLUTImmediately ); - IOFree( tempTable, 256 * sizeof( *tempTable)); - } - clutValid = true; - } - - fbRange = getApertureRange( kIOFBSystemAperture ); - - if( full && fbRange) { - - userAccessRanges->removeObject( kIOFBSystemAperture ); - userAccessRanges->setObject( kIOFBSystemAperture, fbRange ); - err = setUserRanges(); - - base = fbRange->getPhysicalAddress(); - if( (mem = getVRAMRange())) { - vramMapOffset = base - mem->getPhysicalAddress(); - mem->release(); - } - - if( vramMap) - vramMap->release(); - vramMap = fbRange->map(); - assert( vramMap ); - if( vramMap) - base = vramMap->getVirtualAddress(); - - // console now available - if( info.activeWidth >= 128) { - newConsole.v_baseAddr = base; - newConsole.v_rowBytes = info.bytesPerRow; - newConsole.v_width = info.activeWidth; - newConsole.v_height = info.activeHeight; - newConsole.v_depth = info.bitsPerPixel; - // strcpy( consoleInfo->v_pixelFormat, "PPPPPPPP"); - getPlatform()->setConsoleInfo( &newConsole, kPEEnableScreen ); - } - - deliverFramebufferNotification( kIOFBNotifyDisplayModeDidChange, 0 ); - - (void) getInformationForDisplayMode( mode, &dmInfo ); - IOLog( "%s: using (%ldx%ld@%ldHz,%ld bpp)\n", getName(), - info.activeWidth, info.activeHeight, - (dmInfo.refreshRate + 0x8000) >> 16, info.bitsPerPixel ); - } - - if( fbRange) - fbRange->release(); - if( vramMap) - setupCursor( &info ); - - return( kIOReturnSuccess ); -} - -IOReturn IOFramebuffer::extSetDisplayMode( IODisplayModeID displayMode, - IOIndex depth ) -{ - IOReturn err; - - stopCursor(); - - if( isConsoleDevice()) - getPlatform()->setConsoleInfo( 0, kPEDisableScreen); - - deliverFramebufferNotification( kIOFBNotifyDisplayModeWillChange ); - - err = setDisplayMode( displayMode, depth ); - - clutValid = false; - - setupForCurrentConfig(); - - return( err ); -} - -IOReturn IOFramebuffer::extGetInformationForDisplayMode( - IODisplayModeID mode, IODisplayModeInformation * info ) -{ - UInt32 flags = 0; - IOReturn err; - IOTimingInformation timingInfo; - - err = getInformationForDisplayMode( mode, info ); - if( kIOReturnSuccess == err) { - err = IODisplayWrangler::getFlagsForDisplayMode( this, mode, &flags); - if( kIOReturnSuccess == err) { - info->flags &= ~kDisplayModeSafetyFlags; - info->flags |= flags; - } - if( kIOReturnSuccess == getTimingInfoForDisplayMode( mode, &timingInfo )) - info->reserved[0] = timingInfo.appleTimingID; - - } - - return( err ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOFramebuffer::setNumber( OSDictionary * dict, const char * key, - UInt32 value ) -{ - OSNumber * num; - bool ok; - - num = OSNumber::withNumber( value, 32 ); - if( !num) - return( false ); - - ok = dict->setObject( key, num ); - num->release(); - - return( ok ); -} - -bool IOFramebuffer::serializeInfo( OSSerialize * s ) -{ - IOReturn err; - IODisplayModeInformation info; - IOPixelInformation pixelInfo; - IODisplayModeID * modeIDs; - IOItemCount modeCount, modeNum, aperture; - IOIndex depthNum; - OSDictionary * infoDict; - OSDictionary * modeDict; - OSDictionary * pixelDict; - char keyBuf[12]; - bool ok = true; - - modeCount = getDisplayModeCount(); - modeIDs = IONew( IODisplayModeID, modeCount ); - if( !modeIDs) - return( false ); - - err = getDisplayModes( modeIDs ); - if( err) - return( false ); - - infoDict = OSDictionary::withCapacity( 10 ); - if( !infoDict) - return( false ); - - for( modeNum = 0; modeNum < modeCount; modeNum++ ) { - - err = getInformationForDisplayMode( modeIDs[ modeNum ], &info ); - if( err) - continue; - - modeDict = OSDictionary::withCapacity( 10 ); - if( !modeDict) - break; - - ok = setNumber( modeDict, kIOFBWidthKey, - info.nominalWidth ) - && setNumber( modeDict, kIOFBHeightKey, - info.nominalHeight ) - && setNumber( modeDict, kIOFBRefreshRateKey, - info.refreshRate ) - && setNumber( modeDict, kIOFBFlagsKey, - info.flags ); - if( !ok) - break; - - for( depthNum = 0; depthNum < info.maxDepthIndex; depthNum++ ) { - - for( aperture = 0; ; aperture++ ) { - - err = getPixelInformation( modeIDs[ modeNum ], depthNum, - aperture, &pixelInfo ); - if( err) - break; - - pixelDict = OSDictionary::withCapacity( 10 ); - if( !pixelDict) - continue; - - ok = setNumber( pixelDict, kIOFBBytesPerRowKey, - pixelInfo.bytesPerRow ) - && setNumber( pixelDict, kIOFBBytesPerPlaneKey, - pixelInfo.bytesPerPlane ) - && setNumber( pixelDict, kIOFBBitsPerPixelKey, - pixelInfo.bitsPerPixel ) - && setNumber( pixelDict, kIOFBComponentCountKey, - pixelInfo.componentCount ) - && setNumber( pixelDict, kIOFBBitsPerComponentKey, - pixelInfo.bitsPerComponent ) - && setNumber( pixelDict, kIOFBFlagsKey, - pixelInfo.flags ) - && setNumber( pixelDict, kIOFBWidthKey, - pixelInfo.activeWidth ) - && setNumber( pixelDict, kIOFBHeightKey, - pixelInfo.activeHeight ); - if( !ok) - break; - - sprintf( keyBuf, "%lx", depthNum + (aperture << 16) ); - modeDict->setObject( keyBuf, pixelDict ); - pixelDict->release(); - } - } - - sprintf( keyBuf, "%lx", modeIDs[ modeNum ] ); - infoDict->setObject( keyBuf, modeDict ); - modeDict->release(); - } - - IODelete( modeIDs, IODisplayModeID, modeCount ); - - ok &= infoDict->serialize( s ); - infoDict->release(); - - return( ok ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSDefineMetaClassAndStructors(_IOFramebufferNotifier, IONotifier) -#define LOCKNOTIFY() -#define UNLOCKNOTIFY() - -void _IOFramebufferNotifier::remove() -{ - LOCKNOTIFY(); - - if( whence) { - whence->removeObject( (OSObject *) this ); - whence = 0; - } - - fEnable = false; - - UNLOCKNOTIFY(); - - release(); -} - -bool _IOFramebufferNotifier::disable() -{ - bool ret; - - LOCKNOTIFY(); - ret = fEnable; - fEnable = false; - UNLOCKNOTIFY(); - - return( ret ); -} - -void _IOFramebufferNotifier::enable( bool was ) -{ - LOCKNOTIFY(); - fEnable = was; - UNLOCKNOTIFY(); -} - -IONotifier * IOFramebuffer::addFramebufferNotification( - IOFramebufferNotificationHandler handler, - OSObject * self, void * ref) -{ - _IOFramebufferNotifier * notify = 0; - - notify = new _IOFramebufferNotifier; - if( notify && !notify->init()) { - notify->release(); - notify = 0; - } - - if( notify) { - notify->handler = handler; - notify->self = self; - notify->ref = ref; - notify->fEnable = true; - - if( 0 == fbNotifications) - fbNotifications = OSSet::withCapacity(1); - - notify->whence = fbNotifications; - if( fbNotifications) - fbNotifications->setObject( notify ); - } - - return( notify ); -} - -IOReturn IOFramebuffer::deliverFramebufferNotification( - IOIndex event, void * info = 0 ) -{ - OSIterator * iter; - _IOFramebufferNotifier * notify; - IOReturn ret = kIOReturnSuccess; - IOReturn r; - - LOCKNOTIFY(); - - iter = OSCollectionIterator::withCollection( fbNotifications ); - - if( iter) { - while( (notify = (_IOFramebufferNotifier *) iter->getNextObject())) { - - if( notify->fEnable) { - r = (*notify->handler)( notify->self, notify->ref, this, - event, info ); - if( kIOReturnSuccess != ret) - ret = r; - } - } - iter->release(); - } - - UNLOCKNOTIFY(); - - return( ret ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// Some stubs - -IOReturn IOFramebuffer::enableController ( void ) -{ - return( kIOReturnSuccess ); -} - -bool IOFramebuffer::isConsoleDevice( void ) -{ - return( false ); -} - - // Set display mode and depth -IOReturn IOFramebuffer::setDisplayMode( IODisplayModeID /* displayMode */, - IOIndex /* depth */ ) -{ - return( kIOReturnUnsupported); -} - -// For pages -IOReturn IOFramebuffer::setApertureEnable( - IOPixelAperture /* aperture */, IOOptionBits /* enable */ ) -{ - return( kIOReturnUnsupported); -} - -// Display mode and depth for startup -IOReturn IOFramebuffer::setStartupDisplayMode( - IODisplayModeID /* displayMode */, IOIndex /* depth */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::getStartupDisplayMode( - IODisplayModeID * /* displayMode */, IOIndex * /* depth */ ) -{ - return( kIOReturnUnsupported); -} - -//// CLUTs - -IOReturn IOFramebuffer::setCLUTWithEntries( - IOColorEntry * /* colors */, UInt32 /* index */, - UInt32 /* numEntries */, IOOptionBits /* options */ ) -{ - return( kIOReturnUnsupported); -} - -//// Gamma - -IOReturn IOFramebuffer::setGammaTable( UInt32 /* channelCount */, - UInt32 /* dataCount */, UInt32 /* dataWidth */, void * /* data */ ) -{ - return( kIOReturnUnsupported); -} - -//// Controller attributes - -IOReturn IOFramebuffer::setAttribute( IOSelect /* attribute */, UInt32 /* value */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::getAttribute( IOSelect /* attribute */, - UInt32 * /* value */ ) -{ - return( kIOReturnUnsupported); -} - -//// Display mode timing information - -IOReturn IOFramebuffer::getTimingInfoForDisplayMode( - IODisplayModeID /* displayMode */, - IOTimingInformation * /* info */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::validateDetailedTiming( - void * description, IOByteCount descripSize ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::setDetailedTimings( OSArray * array ) -{ - return( kIOReturnUnsupported); -} - -//// Connections - -IOItemCount IOFramebuffer::getConnectionCount( void ) -{ - return( 1); -} - -IOReturn IOFramebuffer::setAttributeForConnection( IOIndex /* connectIndex */, - IOSelect /* attribute */, UInt32 /* value */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::getAttributeForConnection( IOIndex /* connectIndex */, - IOSelect /* attribute */, UInt32 * /* value */ ) -{ - return( kIOReturnUnsupported); -} - -//// HW Cursors - -IOReturn IOFramebuffer::setCursorImage( void * cursorImage ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible ) -{ - return( kIOReturnUnsupported); -} - -void IOFramebuffer::flushCursor( void ) -{ -} - -//// Interrupts - -IOReturn IOFramebuffer::registerForInterruptType( IOSelect interruptType, - IOFBInterruptProc proc, OSObject * target, void * ref, - void ** interruptRef ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::unregisterInterrupt( void * interruptRef ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::setInterruptState( void * interruptRef, UInt32 state ) -{ - return( kIOReturnUnsupported); -} - -// Apple sensing - -IOReturn IOFramebuffer::getAppleSense( - IOIndex /* connectIndex */, - UInt32 * /* senseType */, - UInt32 * /* primary */, - UInt32 * /* extended */, - UInt32 * /* displayType */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::connectFlags( IOIndex /* connectIndex */, - IODisplayModeID /* displayMode */, IOOptionBits * /* flags */ ) -{ - return( kIOReturnUnsupported); -} - -//// IOLowLevelDDCSense - -void IOFramebuffer::setDDCClock( IOIndex /* connectIndex */, UInt32 /* value */ ) -{ -} - -void IOFramebuffer::setDDCData( IOIndex /* connectIndex */, UInt32 /* value */ ) -{ -} - -bool IOFramebuffer::readDDCClock( IOIndex /* connectIndex */ ) -{ - return( false); -} - -bool IOFramebuffer::readDDCData( IOIndex /* connectIndex */ ) -{ - return( false); -} - -IOReturn IOFramebuffer::enableDDCRaster( bool /* enable */ ) -{ - return( kIOReturnUnsupported); -} - - -//// IOHighLevelDDCSense - -bool IOFramebuffer::hasDDCConnect( IOIndex /* connectIndex */ ) -{ - return( kIOReturnUnsupported); -} - -IOReturn IOFramebuffer::getDDCBlock( IOIndex /* connectIndex */, UInt32 /* blockNumber */, - IOSelect /* blockType */, IOOptionBits /* options */, - UInt8 * /* data */, IOByteCount * /* length */ ) -{ - return( kIOReturnUnsupported); -} - -OSMetaClassDefineReservedUnused(IOFramebuffer, 0); -OSMetaClassDefineReservedUnused(IOFramebuffer, 1); -OSMetaClassDefineReservedUnused(IOFramebuffer, 2); -OSMetaClassDefineReservedUnused(IOFramebuffer, 3); -OSMetaClassDefineReservedUnused(IOFramebuffer, 4); -OSMetaClassDefineReservedUnused(IOFramebuffer, 5); -OSMetaClassDefineReservedUnused(IOFramebuffer, 6); -OSMetaClassDefineReservedUnused(IOFramebuffer, 7); -OSMetaClassDefineReservedUnused(IOFramebuffer, 8); -OSMetaClassDefineReservedUnused(IOFramebuffer, 9); -OSMetaClassDefineReservedUnused(IOFramebuffer, 10); -OSMetaClassDefineReservedUnused(IOFramebuffer, 11); -OSMetaClassDefineReservedUnused(IOFramebuffer, 12); -OSMetaClassDefineReservedUnused(IOFramebuffer, 13); -OSMetaClassDefineReservedUnused(IOFramebuffer, 14); -OSMetaClassDefineReservedUnused(IOFramebuffer, 15); -OSMetaClassDefineReservedUnused(IOFramebuffer, 16); -OSMetaClassDefineReservedUnused(IOFramebuffer, 17); -OSMetaClassDefineReservedUnused(IOFramebuffer, 18); -OSMetaClassDefineReservedUnused(IOFramebuffer, 19); -OSMetaClassDefineReservedUnused(IOFramebuffer, 20); -OSMetaClassDefineReservedUnused(IOFramebuffer, 21); -OSMetaClassDefineReservedUnused(IOFramebuffer, 22); -OSMetaClassDefineReservedUnused(IOFramebuffer, 23); -OSMetaClassDefineReservedUnused(IOFramebuffer, 24); -OSMetaClassDefineReservedUnused(IOFramebuffer, 25); -OSMetaClassDefineReservedUnused(IOFramebuffer, 26); -OSMetaClassDefineReservedUnused(IOFramebuffer, 27); -OSMetaClassDefineReservedUnused(IOFramebuffer, 28); -OSMetaClassDefineReservedUnused(IOFramebuffer, 29); -OSMetaClassDefineReservedUnused(IOFramebuffer, 30); -OSMetaClassDefineReservedUnused(IOFramebuffer, 31); - diff --git a/iokit/Families/IOGraphics/IOFramebufferReallyPrivate.h b/iokit/Families/IOGraphics/IOFramebufferReallyPrivate.h deleted file mode 100644 index 5a58658ad..000000000 --- a/iokit/Families/IOGraphics/IOFramebufferReallyPrivate.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -class _IOFramebufferNotifier : public IONotifier -{ - friend IOFramebuffer; - - OSDeclareDefaultStructors(_IOFramebufferNotifier) - -public: - OSSet * whence; - - IOFramebufferNotificationHandler handler; - OSObject * self; - void * ref; - bool fEnable; - - virtual void remove(); - virtual bool disable(); - virtual void enable( bool was ); -}; diff --git a/iokit/Families/IOGraphics/IOFramebufferUserClient.cpp b/iokit/Families/IOGraphics/IOFramebufferUserClient.cpp deleted file mode 100644 index 3667cce8c..000000000 --- a/iokit/Families/IOGraphics/IOFramebufferUserClient.cpp +++ /dev/null @@ -1,801 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * 14 Aug 98 sdouglas created. - * 08 Dec 98 sdouglas cpp. - */ - -#define IOFRAMEBUFFER_PRIVATE -#include <IOKit/graphics/IOFramebufferShared.h> -#include <IOKit/pwr_mgt/RootDomain.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOMessage.h> -#include <libkern/c++/OSContainers.h> -#include <IOKit/IOBufferMemoryDescriptor.h> - -#include <IOKit/IOPlatformExpert.h> - -#include <IOKit/assert.h> - -#include "IOFramebufferUserClient.h" - -#include <IOKit/graphics/IOGraphicsEngine.h> - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOUserClient - -OSDefineMetaClassAndStructors(IOFramebufferUserClient, IOUserClient) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -static IOReturn myHandler(void *, void * , UInt32, IOService *, void *, unsigned int); -static IOLock * gSleepFramebuffersLock; -static OSOrderedSet * gSleepFramebuffers; -static UInt32 gWakeCount; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOFramebufferUserClient * IOFramebufferUserClient::withTask( task_t owningTask ) -{ - IOFramebufferUserClient * inst; - - if( 0 == gSleepFramebuffersLock) { - gSleepFramebuffersLock = IOLockAlloc(); - gSleepFramebuffers = OSOrderedSet::withCapacity(6); - assert( gSleepFramebuffersLock && gSleepFramebuffers ); - } - - inst = new IOFramebufferUserClient; - - if( inst && !inst->init()) { - inst->release(); - inst = 0; - } - - return( inst ); -} - -bool IOFramebufferUserClient::start( IOService * _owner ) -{ - static const IOExternalMethod methodTemplate[] = { -/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 0 }, -/* 1 */ { NULL, NULL, kIOUCScalarIStructO, 3, sizeof( IOPixelInformation) }, -/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 2 }, -/* 3 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 }, -/* 4 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 }, -/* 5 */ { NULL, NULL, kIOUCScalarIStructO, - 1, sizeof( IODisplayModeInformation) }, -/* 6 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 1 }, -/* 7 */ { NULL, NULL, kIOUCStructIStructO, 0, 0xffffffff }, -/* 8 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 1 }, -/* 9 */ { NULL, NULL, kIOUCStructIStructO, sizeof( Bounds), 0 }, -/* 10 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 0 }, -/* 11 */ { NULL, NULL, kIOUCScalarIStructI, 3, 0xffffffff }, -/* 12 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 13 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 0 }, -/* 14 */ { NULL, NULL, kIOUCScalarIScalarO, 0, 0 }, -/* 15 */ { NULL, NULL, kIOUCScalarIStructI, 1, 0xffffffff }, -/* 16 */ { NULL, NULL, kIOUCScalarIStructI, 2, 0xffffffff }, -/* 17 */ { NULL, NULL, kIOUCStructIStructO, 0xffffffff, 0xffffffff }, - - }; - - if( !super::start( _owner )) - return( false); - - owner = (IOFramebuffer *) _owner; - - assert( sizeof( methodTemplate) == sizeof( externals)); - bcopy( methodTemplate, externals, sizeof( externals )); - - externals[0].object = owner; - externals[0].func = (IOMethod) &IOFramebuffer::createSharedCursor; - - externals[1].object = owner; - externals[1].func = (IOMethod) &IOFramebuffer::getPixelInformation; - - externals[2].object = owner; - externals[2].func = (IOMethod) &IOFramebuffer::getCurrentDisplayMode; - - externals[3].object = owner; - externals[3].func = (IOMethod) &IOFramebuffer::setStartupDisplayMode; - - externals[4].object = owner; - externals[4].func = (IOMethod) &IOFramebuffer::extSetDisplayMode; - - externals[5].object = owner; - externals[5].func = - (IOMethod) &IOFramebuffer::extGetInformationForDisplayMode; - - externals[6].object = owner; - externals[6].func = (IOMethod) &IOFramebuffer::extGetDisplayModeCount; - - externals[7].object = owner; - externals[7].func = (IOMethod) &IOFramebuffer::extGetDisplayModes; - - externals[8].object = owner; - externals[8].func = (IOMethod) &IOFramebuffer::extGetVRAMMapOffset; - - externals[9].object = owner; - externals[9].func = (IOMethod) &IOFramebuffer::extSetBounds; - - externals[10].object = owner; - externals[10].func = (IOMethod) &IOFramebuffer::extSetNewCursor; - - externals[11].object = owner; - externals[11].func = (IOMethod) &IOFramebuffer::setGammaTable; - - externals[12].object = owner; - externals[12].func = (IOMethod) &IOFramebuffer::extSetCursorVisible; - - externals[13].object = owner; - externals[13].func = (IOMethod) &IOFramebuffer::extSetCursorPosition; - - externals[14].object = this; - externals[14].func = (IOMethod) &IOFramebufferUserClient::acknowledgeNotification; - - externals[15].object = owner; - externals[15].func = (IOMethod) &IOFramebuffer::extSetColorConvertTable; - - externals[16].object = owner; - externals[16].func = (IOMethod) &IOFramebuffer::extSetCLUTWithEntries; - - externals[17].object = owner; - externals[17].func = (IOMethod) &IOFramebuffer::extValidateDetailedTiming; - - - ackFrameBuffer = false; - ackRoot = false; - - owner->serverConnect = this; - - // register interest in sleep and wake - powerRootNotifier = registerSleepWakeInterest(myHandler, (void *) this); - // register interest in frame buffer - frameBufferNotifier = owner->registerInterest( gIOGeneralInterest, myHandler, this, 0 ); - return( true ); -} - - -IOReturn -IOFramebufferUserClient::acknowledgeNotification( void ) -{ - if( ackFrameBuffer ) { - ackFrameBuffer = false; - owner->allowPowerChange((unsigned long)PMrefcon); - } - if( ackRoot ) { - ackRoot = false; - owner->beginSystemSleep(PMrefcon); - } - - return IOPMNoErr; -} - - -// We have registered for notification of power state changes in the framebuffer and the system in general. -// We are notified here of such a change. "System" power changes refer to sleep/wake and power down/up. -// "Device" changes refer to the framebuffer. - -static IOReturn -myHandler(void * us, void *, UInt32 messageType, IOService *, void * params, unsigned int) -{ - kern_return_t r; - mach_msg_header_t *msgh; - IOFramebufferUserClient * self = (IOFramebufferUserClient *)us; - - switch (messageType) { - case kIOMessageSystemWillSleep: - if ( !(self->WSKnowsWeAreOff) ) { - msgh = (mach_msg_header_t *)(self->notificationMsg); - if( msgh && (self->WSnotificationPort) ) { - msgh->msgh_id = 0; - self->WSKnowsWeAreOff = true; - self->ackRoot = true; - r = mach_msg_send_from_kernel( msgh, msgh->msgh_size); - if( KERN_SUCCESS == r) { - // WS will ack within ten seconds - ((sleepWakeNote *)params)->returnValue = 10000000; - self->PMrefcon = ((sleepWakeNote *)params)->powerRef; - IOLockLock( gSleepFramebuffersLock ); - gSleepFramebuffers->setObject(self); - IOLockUnlock( gSleepFramebuffersLock ); - return kIOReturnSuccess; - } - } - } - self->ackRoot = false; - ((sleepWakeNote *)params)->returnValue = 0; - return kIOReturnSuccess; - - case kIOMessageDeviceWillPowerOff: - if ( !self->WSKnowsWeAreOff ) { - msgh = (mach_msg_header_t *)(self->notificationMsg); - if( msgh && (self->WSnotificationPort) ) { - msgh->msgh_id = 0; - self->WSKnowsWeAreOff = true; - self->ackFrameBuffer = true; - r = mach_msg_send_from_kernel( msgh, msgh->msgh_size); - if( KERN_SUCCESS == r) { - // WS will ack within ten seconds - ((sleepWakeNote *)params)->returnValue = 10000000; - self->PMrefcon = ((sleepWakeNote *)params)->powerRef; - IOLockLock( gSleepFramebuffersLock ); - gSleepFramebuffers->setObject(self); - IOLockUnlock( gSleepFramebuffersLock ); - return kIOReturnSuccess; - } - } - } - ((sleepWakeNote *)params)->returnValue = 0; - self->ackFrameBuffer = false; - return kIOReturnSuccess; - - case kIOMessageDeviceHasPoweredOn: - - IOLockLock( gSleepFramebuffersLock ); - gWakeCount++; - if( gWakeCount == gSleepFramebuffers->getCount()) { - while( (self = (IOFramebufferUserClient *) gSleepFramebuffers->getFirstObject())) { - if ( self->WSKnowsWeAreOff ) { - msgh = (mach_msg_header_t *)(self->notificationMsg); - if( msgh && (self->WSnotificationPort)) { - msgh->msgh_id = 1; - self->WSKnowsWeAreOff = false; - r = mach_msg_send_from_kernel( msgh, msgh->msgh_size); - } - } - gSleepFramebuffers->removeObject( self ); - } - gWakeCount = 0; - } - IOLockUnlock( gSleepFramebuffersLock ); - return kIOReturnSuccess; - } - return kIOReturnUnsupported; -} - -IOReturn IOFramebufferUserClient::registerNotificationPort( - mach_port_t port, - UInt32 type, - UInt32 refCon ) -{ - static mach_msg_header_t init_msg = { - // mach_msg_bits_t msgh_bits; - MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0), - // mach_msg_size_t msgh_size; - sizeof (mach_msg_header_t), - // mach_port_t msgh_remote_port; - MACH_PORT_NULL, - // mach_port_t msgh_local_port; - MACH_PORT_NULL, - // mach_msg_size_t msgh_reserved; - 0, - // mach_msg_id_t msgh_id; - 0 - }; - - if ( notificationMsg == NULL ) - notificationMsg = IOMalloc( sizeof (mach_msg_header_t) ); - // Initialize the power state change notification message. - *((mach_msg_header_t *)notificationMsg) = init_msg; - - ((mach_msg_header_t *)notificationMsg)->msgh_remote_port = port; - - WSnotificationPort = port; - WSKnowsWeAreOff = false; - return( kIOReturnSuccess); -} - -IOReturn IOFramebufferUserClient::getNotificationSemaphore( - UInt32 interruptType, semaphore_t * semaphore ) -{ - return( owner->getNotificationSemaphore(interruptType, semaphore) ); -} - -// The window server is going away. -// We disallow power down to prevent idle sleep while the console is running. -IOReturn IOFramebufferUserClient::clientClose( void ) -{ - owner->close(); - if( owner->isConsoleDevice()) - getPlatform()->setConsoleInfo( 0, kPEAcquireScreen); - - if( powerRootNotifier) { - powerRootNotifier->remove(); - powerRootNotifier = 0; - } - if( frameBufferNotifier) { - frameBufferNotifier->remove(); - frameBufferNotifier = 0; - } - if( notificationMsg) { - IOFree( notificationMsg, sizeof (mach_msg_header_t)); - notificationMsg = 0; - } - owner->serverConnect = 0; - WSnotificationPort = NULL; - detach( owner); - - return( kIOReturnSuccess); -} - -IOService * IOFramebufferUserClient::getService( void ) -{ - return( owner ); -} - -IOReturn IOFramebufferUserClient::clientMemoryForType( UInt32 type, - IOOptionBits * flags, IOMemoryDescriptor ** memory ) -{ - IOMemoryDescriptor * mem; - IOReturn err; - - switch( type) { - - case kIOFBCursorMemory: - mem = owner->sharedCursor; - mem->retain(); - break; - - case kIOFBVRAMMemory: - mem = owner->getVRAMRange(); - break; - - default: - mem = (IOMemoryDescriptor *) owner->userAccessRanges->getObject( type ); - mem->retain(); - break; - } - - *memory = mem; - if( mem) - err = kIOReturnSuccess; - else - err = kIOReturnBadArgument; - - return( err ); -} - -IOExternalMethod * IOFramebufferUserClient::getExternalMethodForIndex( UInt32 index ) -{ - if( index < (sizeof( externals) / sizeof( externals[0]))) - return( externals + index); - else - return( NULL); -} - -IOReturn IOFramebufferUserClient::setProperties( OSObject * properties ) -{ - OSDictionary * dict; - OSArray * array; - IOReturn kr = kIOReturnUnsupported; - - if( !(dict = OSDynamicCast( OSDictionary, properties))) - return( kIOReturnBadArgument); - - if( (array = OSDynamicCast(OSArray, - dict->getObject( kIOFBDetailedTimingsKey)))) - kr = owner->setDetailedTimings( array ); - else - kr = kIOReturnBadArgument; - - return( kr ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSDefineMetaClassAndStructors(IOGraphicsEngineClient, IOUserClient) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOGraphicsEngineClient * IOGraphicsEngineClient::withTask( task_t owningTask ) -{ - IOGraphicsEngineClient * inst; - - inst = new IOGraphicsEngineClient; - - if( inst && !inst->init()) { - inst->release(); - inst = 0; - } - if( inst) - inst->owningTask = owningTask; - - return( inst ); -} - -bool IOGraphicsEngineClient::start( IOService * _owner ) -{ - - static const IOExternalMethod methodTemplate[] = { -/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 1 }, -/* 1 */ { NULL, NULL, kIOUCScalarIScalarO, 2, 2 }, -/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 3, 2 }, -/* 3 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, - }; - - IOGraphicsEngineContext * mem; - IOByteCount size; - - if( !super::start( _owner )) - return( false); - - owner = (IOFramebuffer *) _owner; - agpDev = OSDynamicCast( IOAGPDevice, owner->getProvider()); - descriptors = OSArray::withCapacity( 1 ); - - bcopy( methodTemplate, externals, sizeof( methodTemplate )); - - externals[0].object = this; - externals[0].func = (IOMethod) &IOGraphicsEngineClient::addUserRange; - externals[1].object = this; - externals[1].func = (IOMethod) &IOGraphicsEngineClient::createAGPSpace; - externals[2].object = this; - externals[2].func = (IOMethod) &IOGraphicsEngineClient::commitAGPMemory; - externals[3].object = this; - externals[3].func = (IOMethod) &IOGraphicsEngineClient::releaseAGPMemory; - - if( 0 == owner->engineContext) { - - size = round_page( sizeof( IOGraphicsEngineContext)); - owner->engineContext = IOBufferMemoryDescriptor::withCapacity( - size, kIODirectionNone, false ); - if( !owner->engineContext) - return( kIOReturnNoMemory ); - owner->engineContext->setLength( size ); - - mem = (IOGraphicsEngineContext *) - owner->engineContext->getBytesNoCopy(); - memset((char *)mem, 0, size); - mem->version = kIOGraphicsEngineContextVersion; - mem->structSize = size; - } - - return( true ); -} - -void IOGraphicsEngineClient::free() -{ - if( descriptors) - descriptors->free(); - - if( agpDev && haveAGP) - agpDev->destroyAGPSpace(); - - super::free(); -} - -IOReturn IOGraphicsEngineClient::clientClose( void ) -{ - detach( owner ); - - return( kIOReturnSuccess); -} - -IOService * IOGraphicsEngineClient::getService( void ) -{ - return( owner ); -} - -IOReturn IOGraphicsEngineClient::clientMemoryForType( UInt32 type, - IOOptionBits * options, IOMemoryDescriptor ** memory ) -{ - IOMemoryDescriptor * mem; - - switch( type) { - case kIOGraphicsEngineContext: - mem = owner->engineContext; - break; - default: - mem = (IOMemoryDescriptor *) owner->engineAccessRanges->getObject( type ); - break; - } - - if( mem) { - mem->retain(); - *memory = mem; - return( kIOReturnSuccess); - } else - return( kIOReturnBadArgument); -} - -IOExternalMethod * IOGraphicsEngineClient::getExternalMethodForIndex( UInt32 index ) -{ - if( index < (sizeof( externals) / sizeof( externals[0]))) - return( externals + index); - else - return( NULL); -} - -IOReturn IOGraphicsEngineClient::addUserRange( vm_address_t start, - vm_size_t length, UInt32 apertureIndex, IOPhysicalAddress * phys ) -{ - IODeviceMemory * mem; - IOReturn err = kIOReturnSuccess; - OSArray * ranges; - int i; - IODeviceMemory * aperture - = owner->getProvider()->getDeviceMemoryWithIndex( apertureIndex ); - - if( 0 == aperture) - return( kIOReturnBadArgument ); - - ranges = owner->engineAccessRanges; - i = 0; - while( (mem = (IODeviceMemory *) ranges->getObject( i++ ))) { - if( (mem->getPhysicalAddress() == - (start + aperture->getPhysicalAddress())) - && (length <= mem->getLength()) ) - break; - } - - if( 0 == mem) { - mem = IODeviceMemory::withSubRange( - aperture, start, length ); - if( mem) { - owner->engineAccessRanges->setObject( mem ); - err = kIOReturnSuccess; - } else - err = kIOReturnNoResources; - } - - if( kIOReturnSuccess == err) - *phys = mem->getPhysicalAddress(); - - return( err ); -} - -IOReturn IOGraphicsEngineClient::createAGPSpace( IOOptionBits options, - IOPhysicalLength length, - IOPhysicalAddress * address, - IOPhysicalLength * lengthOut ) -{ - IOReturn err; - - if( !agpDev) - return( kIOReturnUnsupported ); - - *lengthOut = length; - err = agpDev->createAGPSpace( options, address, lengthOut ); - haveAGP = (kIOReturnSuccess == err); - - return( err ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class _IOGraphicsClientMemory : public OSObject { - OSDeclareDefaultStructors(_IOGraphicsClientMemory) -public: - IOMemoryDescriptor * memory; - IOAGPDevice * agpDev; - IOByteCount agpOffset; - - virtual bool init(); - virtual void free(); -}; - -OSDefineMetaClassAndStructors(_IOGraphicsClientMemory, OSObject) - -bool _IOGraphicsClientMemory::init() -{ - return( OSObject::init()); -} - -void _IOGraphicsClientMemory::free() -{ - if( memory) { - agpDev->getAGPRangeAllocator()->deallocate( agpOffset, - memory->getLength() ); - memory->complete(); - memory->release(); - } - - OSObject::free(); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOGraphicsEngineClient::commitAGPMemory( vm_address_t start, - vm_size_t length, IOOptionBits options, - void ** ref, IOByteCount * offset ) -{ - _IOGraphicsClientMemory * graphicsMem; - IORangeAllocator * rangeAllocator; - IOByteCount agpOffset; - IOReturn err = kIOReturnNoMemory; - bool ok; - - if( !agpDev) - return( kIOReturnUnsupported ); - if( (!start) || (!length)) - return( kIOReturnBadArgument ); - rangeAllocator = agpDev->getAGPRangeAllocator(); - if( !rangeAllocator) - return( kIOReturnUnsupported ); - - do { - graphicsMem = new _IOGraphicsClientMemory; - if( (!graphicsMem) || (!graphicsMem->init())) - continue; - - ok = rangeAllocator->allocate( length, (IORangeScalar *) &agpOffset ); - if( !ok) { - err = kIOReturnNoSpace; - continue; - } - - graphicsMem->agpDev = agpDev; - graphicsMem->agpOffset = agpOffset; - - graphicsMem->memory = IOMemoryDescriptor::withAddress( start, length, - kIODirectionOut, owningTask ); - if( !graphicsMem->memory) - continue; - - err = graphicsMem->memory->prepare(); - if( err != kIOReturnSuccess) - continue; - - err = agpDev->commitAGPMemory( graphicsMem->memory, agpOffset ); - if( err != kIOReturnSuccess) - continue; - - *ref = (void *) descriptors->getCount(); - *offset = agpOffset; - descriptors->setObject( graphicsMem ); - - } while( false ); - - if( graphicsMem) - graphicsMem->release(); - - if( (kIOReturnSuccess != err) && (!graphicsMem)) - rangeAllocator->deallocate( agpOffset, length ); - - return( err ); -} - -IOReturn IOGraphicsEngineClient::releaseAGPMemory( void * ref ) -{ - _IOGraphicsClientMemory * graphicsMem; - UInt32 index = (UInt32) ref; - - if( 0 == (graphicsMem = (_IOGraphicsClientMemory *) - descriptors->getObject( index ))) - return( kIOReturnBadArgument ); - - descriptors->removeObject( index ); - - return( kIOReturnSuccess ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSDefineMetaClassAndStructors(IOFramebufferSharedUserClient, IOUserClient) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOFramebufferSharedUserClient * IOFramebufferSharedUserClient::withTask( - task_t owningTask ) -{ - IOFramebufferSharedUserClient * inst; - - inst = new IOFramebufferSharedUserClient; - - if( inst && !inst->init()) { - inst->release(); - inst = 0; - } - - return( inst ); -} - -bool IOFramebufferSharedUserClient::start( IOService * _owner ) -{ - - static const IOExternalMethod methodTemplate[] = { - }; - - if( !super::start( _owner )) - return( false); - - owner = (IOFramebuffer *) _owner; - - bcopy( methodTemplate, externals, sizeof( methodTemplate )); - - return( true ); -} - -void IOFramebufferSharedUserClient::free( void ) -{ - retain(); retain(); - owner->sharedConnect = 0; - detach( owner); - super::free(); -} - -void IOFramebufferSharedUserClient::release() const -{ - super::release(2); -} - -IOReturn IOFramebufferSharedUserClient::clientClose( void ) -{ - return( kIOReturnSuccess); -} - -IOService * IOFramebufferSharedUserClient::getService( void ) -{ - return( owner ); -} - -IOReturn IOFramebufferSharedUserClient::clientMemoryForType( UInt32 type, - IOOptionBits * options, IOMemoryDescriptor ** memory ) -{ - IOMemoryDescriptor * mem = 0; - IOReturn err; - - switch( type) { - - case kIOFBCursorMemory: - mem = owner->sharedCursor; - mem->retain(); - *options = kIOMapReadOnly; - break; - - case kIOFBVRAMMemory: - mem = owner->getVRAMRange(); - break; - } - - *memory = mem; - if( mem) - err = kIOReturnSuccess; - else - err = kIOReturnBadArgument; - - return( err ); -} - -IOReturn IOFramebufferSharedUserClient::getNotificationSemaphore( - UInt32 interruptType, semaphore_t * semaphore ) -{ - return( owner->getNotificationSemaphore(interruptType, semaphore) ); -} - -IOExternalMethod * IOFramebufferSharedUserClient::getExternalMethodForIndex( UInt32 index ) -{ - if( index < (sizeof( externals) / sizeof( externals[0]))) - return( externals + index); - else - return( NULL); -} - diff --git a/iokit/Families/IOGraphics/IOFramebufferUserClient.h b/iokit/Families/IOGraphics/IOFramebufferUserClient.h deleted file mode 100644 index 78d5be5d5..000000000 --- a/iokit/Families/IOGraphics/IOFramebufferUserClient.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - */ - - -#ifndef _IOKIT_IOFRAMEBUFFERUSERCLIENT_H -#define _IOKIT_IOFRAMEBUFFERUSERCLIENT_H - -#include <IOKit/IOUserClient.h> -#include <IOKit/graphics/IOFramebuffer.h> -#include <IOKit/pci/IOAGPDevice.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class IOFramebufferUserClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOFramebufferUserClient) - -private: - - IONotifier * powerRootNotifier; - IONotifier * frameBufferNotifier; - - IOExternalMethod externals[ 18 ]; - - - -public: - - IOFramebuffer * owner; - mach_port_t WSnotificationPort; // how we tell window server of power changes - void * notificationMsg; // Msg to be sent to Window Server. - - bool WSKnowsWeAreOff; // true after informing WS that framebuffer is off - bool ackRoot; // true if we must ack the root domain - bool ackFrameBuffer; // true if we must ack the framebuffer - void * PMrefcon; // refcon to return to Power Management - - // IOUserClient methods - virtual IOReturn clientClose( void ); - - virtual IOService * getService( void ); - - virtual IOReturn clientMemoryForType( UInt32 type, - IOOptionBits * options, IOMemoryDescriptor ** memory ); - - virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ); - - virtual IOReturn registerNotificationPort( mach_port_t, UInt32, UInt32 ); - virtual IOReturn getNotificationSemaphore( UInt32 interruptType, - semaphore_t * semaphore ); - - // others - - static IOFramebufferUserClient * withTask( task_t owningTask ); - - virtual bool start( IOService * provider ); - virtual IOReturn setProperties( OSObject * properties ); - - virtual IOReturn acknowledgeNotification(void); - -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class IOGraphicsEngineClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOGraphicsEngineClient) - -private: - - IOFramebuffer * owner; - task_t owningTask; - IOAGPDevice * agpDev; - bool haveAGP; - OSArray * descriptors; - - IOExternalMethod externals[ 4 ]; - -public: - // IOUserClient methods - virtual IOReturn clientClose( void ); - virtual void free(); - - virtual IOService * getService( void ); - - virtual IOReturn clientMemoryForType( UInt32 type, - IOOptionBits * options, IOMemoryDescriptor ** memory ); - - virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ); - - // others - - static IOGraphicsEngineClient * withTask( task_t owningTask ); - virtual bool start( IOService * provider ); - - virtual IOReturn addUserRange( vm_address_t start, vm_size_t length, - UInt32 aperture, IOPhysicalAddress * phys ); - - virtual IOReturn createAGPSpace( IOOptionBits options, - IOPhysicalLength length, - IOPhysicalAddress * address, - IOPhysicalLength * lengthOut ); - - virtual IOReturn commitAGPMemory( vm_address_t start, - vm_size_t length, IOOptionBits options, - void ** ref, IOByteCount * offset ); - - virtual IOReturn releaseAGPMemory( void * ref ); - -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class IOFramebufferSharedUserClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOFramebufferSharedUserClient) - -private: - - IOFramebuffer * owner; - - IOExternalMethod externals[ 0 ]; - -public: - virtual void free(); - virtual void release() const; - - // IOUserClient methods - virtual IOReturn clientClose( void ); - - virtual IOService * getService( void ); - - virtual IOReturn clientMemoryForType( UInt32 type, - IOOptionBits * options, IOMemoryDescriptor ** memory ); - - virtual IOReturn getNotificationSemaphore( UInt32 notification_type, - semaphore_t * semaphore ); - - virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ); - - // others - static IOFramebufferSharedUserClient * withTask( task_t owningTask ); - virtual bool start( IOService * provider ); -}; - - -#endif /* ! _IOKIT_IOFRAMEBUFFERUSERCLIENT_H */ diff --git a/iokit/Families/IOGraphics/IOGraphicsDevice.cpp b/iokit/Families/IOGraphics/IOGraphicsDevice.cpp deleted file mode 100644 index 4718ec669..000000000 --- a/iokit/Families/IOGraphics/IOGraphicsDevice.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 30 Nov 98 sdouglas created. - */ - - -#include <IOKit/graphics/IOGraphicsDevice.h> -#include <libkern/c++/OSContainers.h> - -#include <IOKit/assert.h> - -#define super IOService - -OSDefineMetaClass( IOGraphicsDevice, IOService ) -OSDefineAbstractStructors( IOGraphicsDevice, IOService ) - diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCheckReport.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCheckReport.c deleted file mode 100644 index ca7be8202..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCheckReport.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDCheckReport.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (DF) David Ferguson - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB3> 1/2/01 DF Change length checking to check for the minimum size instead of - the "exact" size. - <USB2> 12/12/00 KH Correcting cast of void * - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDCheckReport - Check the Report ID, Type, and Length - * - * Input: - * reportType - The Specified Report Type - * ptPreparsedData - The Preparsed Data - * ptReportItem - The Report Item - * psReport - The Report - * iReportLength - The Report Length - * Output: - * Returns: - * kHIDSuccess, HidP_IncompatibleReportID, - * kHIDInvalidReportLengthErr, kHIDInvalidReportTypeErr - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDCheckReport(HIDReportType reportType, HIDPreparsedDataRef preparsedDataRef, - HIDReportItem *ptReportItem, void *report, UInt32 iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - int reportID, reportIndex; - int iExpectedLength; - Byte * psReport = (Byte *)report; -/* - * See if this is the correct Report ID -*/ - reportID = psReport[0]&0xFF; - if ((ptPreparsedData->reportCount > 1) - && (reportID != ptReportItem->globals.reportID)) - return kHIDIncompatibleReportErr; -/* - * See if this is the correct ReportType -*/ - if (reportType != ptReportItem->reportType) - return kHIDIncompatibleReportErr; -/* - * Check for the correct Length for the Type -*/ - reportIndex = ptReportItem->globals.reportIndex; - switch(reportType) - { - case kHIDInputReport: - iExpectedLength = (ptPreparsedData->reports[reportIndex].inputBitCount + 7)/8; - break; - case kHIDOutputReport: - iExpectedLength = (ptPreparsedData->reports[reportIndex].outputBitCount + 7)/8; - break; - case kHIDFeatureReport: - iExpectedLength = (ptPreparsedData->reports[reportIndex].featureBitCount + 7)/8; - break; - default: - return kHIDInvalidReportTypeErr; - } - if (iExpectedLength > iReportLength) - return kHIDInvalidReportLengthErr; - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCountDescriptorItems.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCountDescriptorItems.c deleted file mode 100644 index f3a6a12c3..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCountDescriptorItems.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDCountDescriptorItems.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -//#include <stdlib.h> - -/* - *------------------------------------------------------------------------------ - * - * HIDCountDescriptorItems - * - * Input: - * ptDescriptor - Descriptor Pointer Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDCountDescriptorItems(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - OSStatus iStatus; - ByteCount iSpaceRequired; - HIDItem *ptItem; - Byte *pMem; -/* - * Initialize Counters -*/ - int collectionCount = 1; - int reportItemCount = 0; - int iUsages = 0; - int iUsageRanges = 0; - int iStrings = 0; - int iStringRanges = 0; - int iDesigs = 0; - int iDesigRanges = 0; - int reportCount = 1; - int globalsNesting = 0; - int iMaxGlobalsNesting = 0; - int collectionNesting = 0; - int iMaxCollectionNesting = 0; -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Initialize the memory allocation pointer -*/ - ptPreparsedData->rawMemPtr = NULL; -/* - * Initialize the Descriptor Pointer Structure -*/ - ptDescriptor->index = 0; - ptItem = &ptDescriptor->item; -/* - * Count various items in the descriptor -*/ - while ((iStatus = HIDNextItem(ptDescriptor)) == kHIDSuccess) - { - switch (ptItem->itemType) - { - case kHIDTypeMain: - switch (ptItem->tag) - { - case kHIDTagCollection: - collectionCount++; - collectionNesting++; - if (collectionNesting > iMaxCollectionNesting) - iMaxCollectionNesting = collectionNesting; - break; - case kHIDTagEndCollection: - if (collectionNesting-- == 0) - return kHIDInvalidPreparsedDataErr; - break; - case kHIDTagInput: - case kHIDTagOutput: - case kHIDTagFeature: - reportItemCount++; - break; - } - break; - case kHIDTypeGlobal: - switch (ptItem->tag) - { - case kHIDTagReportID: - reportCount++; - break; - case kHIDTagPush: - globalsNesting++; - if (globalsNesting > iMaxGlobalsNesting) - iMaxGlobalsNesting = globalsNesting; - break; - case kHIDTagPop: - globalsNesting--; - if (globalsNesting < 0) - return kHIDInvalidPreparsedDataErr; - break; - } - break; - case kHIDTypeLocal: - switch (ptItem->tag) - { - case kHIDTagUsage: - iUsages++; - break; - case kHIDTagUsageMinimum: - case kHIDTagUsageMaximum: - iUsageRanges++; - break; - case kHIDTagStringIndex: - iStrings++; - break; - case kHIDTagStringMinimum: - case kHIDTagStringMaximum: - iStringRanges++; - break; - case kHIDTagDesignatorIndex: - iDesigs++; - break; - case kHIDTagDesignatorMinimum: - case kHIDTagDesignatorMaximum: - iDesigRanges++; - break; - } - } - } -/* - * Disallow malformed descriptors -*/ - if ((collectionNesting != 0) - || (collectionCount == 1) - || (reportItemCount == 0) - || ((iUsageRanges & 1) == 1) - || ((iStringRanges & 1) == 1) - || ((iDesigRanges & 1) == 1)) - return kHIDInvalidPreparsedDataErr; -/* - * Summarize the Indices and Ranges -*/ - iUsages += (iUsageRanges/2); - iStrings += (iStringRanges/2); - iDesigs += (iDesigRanges/2); -/* - * Calculate the space needed for the structures -*/ - iSpaceRequired = (sizeof(HIDCollection) * collectionCount) - + (sizeof(HIDReportItem) * reportItemCount) - + (sizeof(HIDReportSizes) * reportCount) - + (sizeof(HIDP_UsageItem) * iUsages) - + (sizeof(HIDStringItem) * iStrings) - + (sizeof(HIDDesignatorItem) * iDesigs) - + (sizeof(int) * iMaxCollectionNesting) - + (sizeof(HIDGlobalItems) * iMaxGlobalsNesting); - pMem = PoolAllocateResident(iSpaceRequired, kShouldClearMem); - - if (pMem == NULL) - return kHIDNotEnoughMemoryErr; - ptPreparsedData->rawMemPtr = pMem; - ptPreparsedData->numBytesAllocated = iSpaceRequired; -/* - * Allocate space to the various structures -*/ - ptPreparsedData->collections = (HIDCollection *) pMem; - ptPreparsedData->collectionCount = 0; - pMem += (sizeof(HIDCollection) * collectionCount); - ptPreparsedData->reportItems = (HIDReportItem *) pMem; - ptPreparsedData->reportItemCount = 0; - pMem += (sizeof(HIDReportItem) * reportItemCount); - ptPreparsedData->reports = (HIDReportSizes *) pMem; - ptPreparsedData->reportCount = 0; - pMem += (sizeof(HIDReportSizes) * reportCount); - ptPreparsedData->usageItems = (HIDP_UsageItem *) pMem; - ptPreparsedData->usageItemCount = 0; - pMem += (sizeof(HIDP_UsageItem) * iUsages); - ptPreparsedData->stringItems = (HIDStringItem *) pMem; - ptPreparsedData->stringItemCount = 0; - pMem += (sizeof(HIDStringItem) * iStrings); - ptPreparsedData->desigItems = (HIDDesignatorItem *) pMem; - ptPreparsedData->desigItemCount = 0; - pMem += (sizeof(HIDDesignatorItem) * iDesigs); - ptDescriptor->collectionStack = (SInt32 *) pMem; - ptDescriptor->collectionNesting = 0; - pMem += (sizeof(SInt32) * iMaxCollectionNesting); - ptDescriptor->globalsStack = (HIDGlobalItems *) pMem; - ptDescriptor->globalsNesting = 0; - if (iStatus == kHIDEndOfDescriptorErr) - return kHIDSuccess; - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonCaps.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonCaps.c deleted file mode 100644 index 53b910883..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonCaps.c +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetButtonCaps.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 4/21/00 KH Added HIDGetButtonCapabilities and - HIDGetSpecificButtonCapabilities that now allow users to find - HID report units and exponents. - <USB4> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB3> 5/3/99 BWS We were not setting isStringRange, isDesignatorRange, and - isAbsolute - <USB2> 3/7/99 BWS When range/notRange were made a union, we missed this case where - they were both being set indescriminately - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetSpecificButtonCaps - Get the binary values for a report type - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * buttonCaps - ButtonCaps Array - * piButtonCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piButtonCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetSpecificButtonCaps(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - HIDButtonCapsPtr buttonCaps, - UInt32 *piButtonCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDCollection *ptParent; - HIDReportItem *ptReportItem; - HIDP_UsageItem *ptUsageItem; - HIDStringItem *ptStringItem; - HIDDesignatorItem *ptDesignatorItem; - HIDP_UsageItem *ptFirstCollectionUsageItem; - HIDButtonCaps *ptCapability; - int iR, iU; - int parent; - int iReportItem, iUsageItem; - int iMaxCaps; - // There are 3 versions of HID Parser code all based on the same logic: OS 9 HID Library; - // OSX xnu; OSX IOKitUser. They should all be nearly the same logic. This version (xnu) - // is based on older OS 9 code. This version has added logic to maintain this startBit. - // I don't know why it is here, but believe if it is needed here, it would probably be - // needed in the other two implementations. Didn't have time to determine that at this - // time, so i'll leave this comment to remind me that we should reconcile the 3 versions. - UInt32 startBit; // Added esb 9-29-99 - /*If I remember correctly, it was an optimization. Each time you ask for - a specific value capability, it would search through the entire report - descriptor to find it (my recollection is kind of hazy on this part). - The start bit allowed somebody (client maybe) to cache the information - on where in the report a specific value resided and the use that later - when fetching that value. That way, you don't have to keep going - through the parse tree to find where a value exists. I don't remember - if the implementation was completed or if I even used it. -esb */ -/* - * Disallow Null Pointers -*/ - if ((buttonCaps == NULL) - || (piButtonCapsLength == NULL) - || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the buffer size -*/ - iMaxCaps = *piButtonCapsLength; - *piButtonCapsLength = 0; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; -/* - * Search only reports of the proper type -*/ - if ((ptReportItem->reportType == reportType) - && HIDIsButton(ptReportItem, preparsedDataRef)) - { - startBit = ptReportItem->startBit; -/* - * Search the usages -*/ - for (iU=0; iU<ptReportItem->usageItemCount; iU++) - { -/* - * Copy all usages if the usage above is zero - * or copy all that are "match" -*/ - iUsageItem = ptReportItem->firstUsageItem + iU; - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem]; - - // ¥¥ we assume there is a 1-1 corresponence between usage items, string items, and designator items - // ¥¥Êthis is not necessarily the case, but its better than nothing - ptStringItem = &ptPreparsedData->stringItems[ptReportItem->firstStringItem + iU]; - ptDesignatorItem = &ptPreparsedData->desigItems[ptReportItem->firstDesigItem + iU]; - - if (HIDUsageInRange(ptUsageItem,usagePage,usage)) - { -/* - * Only copy if there's room -*/ - if (*piButtonCapsLength >= iMaxCaps) - return kHIDBufferTooSmallErr; - ptCapability = &buttonCaps[(*piButtonCapsLength)++]; -/* - * Populate the Capability Structure -*/ - parent = ptReportItem->parent; - ptParent = &ptPreparsedData->collections[parent]; - ptFirstCollectionUsageItem - = &ptPreparsedData->usageItems[ptParent->firstUsageItem]; - ptCapability->collection = parent; - ptCapability->collectionUsagePage = ptParent->usagePage; - ptCapability->collectionUsage = ptFirstCollectionUsageItem->usage; - ptCapability->bitField = ptReportItem->dataModes; - ptCapability->reportID = ptReportItem->globals.reportID; - ptCapability->usagePage = ptUsageItem->usagePage; - - ptCapability->isStringRange = false; // ¥¥ todo: set this and stringMin,stringMax,stringIndex - ptCapability->isDesignatorRange = false; // ¥¥ todo: set this and designatorMin,designatorMax,designatorIndex - ptCapability->isAbsolute = !(ptReportItem->dataModes & kHIDDataRelative); - - ptCapability->isRange = ptUsageItem->isRange; - if (ptUsageItem->isRange) - { - ptCapability->u.range.usageMin = ptUsageItem->usageMinimum; - ptCapability->u.range.usageMax = ptUsageItem->usageMaximum; - } - else - ptCapability->u.notRange.usage = ptUsageItem->usage; - - // if there really are that many items - if (iU < ptReportItem->stringItemCount) - { - ptCapability->isStringRange = ptStringItem->isRange; - - if (ptStringItem->isRange) - { - ptCapability->u.range.stringMin = ptStringItem->minimum; - ptCapability->u.range.stringMax = ptStringItem->maximum; - } - else - ptCapability->u.notRange.stringIndex = ptStringItem->index; - } - // default, clear it - else - { - ptCapability->isStringRange = false; - ptCapability->u.notRange.stringIndex = 0; - } - - // if there really are that many items - if (iU < ptReportItem->desigItemCount) - { - ptCapability->isDesignatorRange = ptDesignatorItem->isRange; - - if (ptDesignatorItem->isRange) - { - ptCapability->u.range.designatorMin = ptDesignatorItem->minimum; - ptCapability->u.range.designatorMax = ptDesignatorItem->maximum; - } - else - ptCapability->u.notRange.designatorIndex = ptDesignatorItem->index; - } - // default, clear it - else - { - ptCapability->isDesignatorRange = false; - ptCapability->u.notRange.designatorIndex = 0; - } - ptCapability->startBit = startBit; - } - startBit += (ptReportItem->globals.reportSize * ptReportItem->globals.reportCount); - } - } - } - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDGetButtonCaps - Get the binary values for a report type - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * buttonCaps - ButtonCaps Array - * piButtonCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piButtonCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetButtonCaps(HIDReportType reportType, - HIDButtonCapsPtr buttonCaps, - UInt32 *piButtonCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - return HIDGetSpecificButtonCaps(reportType,0,0,0,buttonCaps, - piButtonCapsLength,preparsedDataRef); -} - - -/* - *------------------------------------------------------------------------------ - * - * HIDGetSpecificButtonCapabilities - Get the binary values for a report type - * This is the same as HIDGetSpecificButtonCaps, - * except that it takes a HIDButtonCapabilitiesPtr - * so it can return units and unitExponents. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * buttonCaps - ButtonCaps Array - * piButtonCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piButtonCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetSpecificButtonCapabilities(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - HIDButtonCapabilitiesPtr buttonCaps, - UInt32 *piButtonCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDCollection *ptParent; - HIDReportItem *ptReportItem; - HIDP_UsageItem *ptUsageItem; - HIDStringItem *ptStringItem; - HIDDesignatorItem *ptDesignatorItem; - HIDP_UsageItem *ptFirstCollectionUsageItem; - HIDButtonCapabilities *ptCapability; - int iR, iU; - int parent; - int iReportItem, iUsageItem; - int iMaxCaps; - // There are 3 versions of HID Parser code all based on the same logic: OS 9 HID Library; - // OSX xnu; OSX IOKitUser. They should all be nearly the same logic. This version (xnu) - // is based on older OS 9 code. This version has added logic to maintain this startBit. - // I don't know why it is here, but believe if it is needed here, it would probably be - // needed in the other two implementations. Didn't have time to determine that at this - // time, so i'll leave this comment to remind me that we should reconcile the 3 versions. - UInt32 startBit; -/* - * Disallow Null Pointers -*/ - if ((buttonCaps == NULL) - || (piButtonCapsLength == NULL) - || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the buffer size -*/ - iMaxCaps = *piButtonCapsLength; - *piButtonCapsLength = 0; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; -/* - * Search only reports of the proper type -*/ - if ((ptReportItem->reportType == reportType) - && HIDIsButton(ptReportItem, preparsedDataRef)) - { - startBit = ptReportItem->startBit; -/* - * Search the usages -*/ - for (iU=0; iU<ptReportItem->usageItemCount; iU++) - { -/* - * Copy all usages if the usage above is zero - * or copy all that are "match" -*/ - iUsageItem = ptReportItem->firstUsageItem + iU; - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem]; - - // ¥¥ we assume there is a 1-1 corresponence between usage items, string items, and designator items - // ¥¥Êthis is not necessarily the case, but its better than nothing - ptStringItem = &ptPreparsedData->stringItems[ptReportItem->firstStringItem + iU]; - ptDesignatorItem = &ptPreparsedData->desigItems[ptReportItem->firstDesigItem + iU]; - - if (HIDUsageInRange(ptUsageItem,usagePage,usage)) - { -/* - * Only copy if there's room -*/ - if (*piButtonCapsLength >= iMaxCaps) - return kHIDBufferTooSmallErr; - ptCapability = &buttonCaps[(*piButtonCapsLength)++]; -/* - * Populate the Capability Structure -*/ - parent = ptReportItem->parent; - ptParent = &ptPreparsedData->collections[parent]; - ptFirstCollectionUsageItem - = &ptPreparsedData->usageItems[ptParent->firstUsageItem]; - ptCapability->collection = parent; - ptCapability->collectionUsagePage = ptParent->usagePage; - ptCapability->collectionUsage = ptFirstCollectionUsageItem->usage; - ptCapability->bitField = ptReportItem->dataModes; - ptCapability->reportID = ptReportItem->globals.reportID; - ptCapability->usagePage = ptUsageItem->usagePage; - ptCapability->unitExponent = ptReportItem->globals.unitExponent; - ptCapability->units = ptReportItem->globals.units; -// ptCapability->reserved = 0; // for future OS 9 expansion - ptCapability->startBit = 0; // init esb added field. -// ptCapability->pbVersion = kHIDCurrentCapabilitiesPBVersion; - ptCapability->pbVersion = 2; - - ptCapability->isStringRange = false; // ¥¥ todo: set this and stringMin,stringMax,stringIndex - ptCapability->isDesignatorRange = false; // ¥¥ todo: set this and designatorMin,designatorMax,designatorIndex - ptCapability->isAbsolute = !(ptReportItem->dataModes & kHIDDataRelative); - - ptCapability->isRange = ptUsageItem->isRange; - if (ptUsageItem->isRange) - { - ptCapability->u.range.usageMin = ptUsageItem->usageMinimum; - ptCapability->u.range.usageMax = ptUsageItem->usageMaximum; - } - else - ptCapability->u.notRange.usage = ptUsageItem->usage; - - // if there really are that many items - if (iU < ptReportItem->stringItemCount) - { - ptCapability->isStringRange = ptStringItem->isRange; - - if (ptStringItem->isRange) - { - ptCapability->u.range.stringMin = ptStringItem->minimum; - ptCapability->u.range.stringMax = ptStringItem->maximum; - } - else - ptCapability->u.notRange.stringIndex = ptStringItem->index; - } - // default, clear it - else - { - ptCapability->isStringRange = false; - ptCapability->u.notRange.stringIndex = 0; - } - - // if there really are that many items - if (iU < ptReportItem->desigItemCount) - { - ptCapability->isDesignatorRange = ptDesignatorItem->isRange; - - if (ptDesignatorItem->isRange) - { - ptCapability->u.range.designatorMin = ptDesignatorItem->minimum; - ptCapability->u.range.designatorMax = ptDesignatorItem->maximum; - } - else - ptCapability->u.notRange.designatorIndex = ptDesignatorItem->index; - } - // default, clear it - else - { - ptCapability->isDesignatorRange = false; - ptCapability->u.notRange.designatorIndex = 0; - } - ptCapability->startBit = startBit; - } - startBit += (ptReportItem->globals.reportSize * ptReportItem->globals.reportCount); - } - } - } - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDGetButtonCapabilities - Get the binary values for a report type - * This is the same as HIDGetButtonCaps, - * except that it takes a HIDButtonCapabilitiesPtr - * so it can return units and unitExponents. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * buttonCaps - ButtonCaps Array - * piButtonCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piButtonCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetButtonCapabilities(HIDReportType reportType, - HIDButtonCapabilitiesPtr buttonCaps, - UInt32 *piButtonCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - return HIDGetSpecificButtonCapabilities(reportType,0,0,0,buttonCaps, - piButtonCapsLength,preparsedDataRef); -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtons.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtons.c deleted file mode 100644 index eec929e49..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtons.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetButtons.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB4> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB3> 4/7/99 BWS Add support for reversed report items - <USB2> 3/5/99 BWS [2311349] iteration broken, passing wrong value - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetButtons - Get the state of the buttons for a Page - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * piUsageList - Usages for pressed buttons - * piUsageListLength - Max entries in UsageList - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus -HIDGetButtons (HIDReportType reportType, - UInt32 iCollection, - HIDUsageAndPagePtr ptUsageList, - UInt32 * piUsageListLength, - HIDPreparsedDataRef preparsedDataRef, - void * psReport, - UInt32 iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - int iR, iE; - long iValue; - int iStart; - int iReportItem; - int iMaxUsages; - HIDUsageAndPage tUsageAndPage; - -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (ptUsageList == NULL) - || (piUsageListLength == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the UsageList size -*/ - iMaxUsages = *piUsageListLength; - *piUsageListLength = 0; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if ((ptReportItem->reportType == reportType) - && HIDIsButton(ptReportItem, preparsedDataRef)) - { -/* - * Save Arrays and Bitmaps -*/ - iStart = ptReportItem->startBit; - for (iE=0; iE<ptReportItem->globals.reportCount; iE++) - { - OSStatus status = noErr; - iValue = 0; - - if ((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray) - { - status = HIDGetData(psReport, iReportLength, iStart, ptReportItem->globals.reportSize, &iValue, false); - if (!status) - status = HIDPostProcessRIValue (ptReportItem, &iValue); - if (status) return status; - - iStart += ptReportItem->globals.reportSize; - HIDUsageAndPageFromIndex(preparsedDataRef,ptReportItem,ptReportItem->globals.logicalMinimum+iE,&tUsageAndPage); - if (*piUsageListLength >= iMaxUsages) - return kHIDBufferTooSmallErr; - ptUsageList[(*piUsageListLength)++] = tUsageAndPage; - } - else - { - status = HIDGetData(psReport, iReportLength, iStart, 1, &iValue, false); - if (!status) - status = HIDPostProcessRIValue (ptReportItem, &iValue); - if (status) return status; - - iStart++; - if (iValue != 0) - { - HIDUsageAndPageFromIndex(preparsedDataRef,ptReportItem,ptReportItem->globals.logicalMinimum+iE,&tUsageAndPage); - if (*piUsageListLength >= iMaxUsages) - return kHIDBufferTooSmallErr; - ptUsageList[(*piUsageListLength)++] = tUsageAndPage; - } - } - } - } - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c deleted file mode 100644 index a18361c64..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetButtonsOnPage.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB4> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB3> 5/26/99 BWS We are not checking the usage page for bitmapped buttons! This - caused the Wingman Extreme to get the tilt button on the user - page confused with the first button on the button page. - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetButtonsOnPage - Get the state of the buttons for a Page - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * piUsageList - Usages for pressed buttons - * piUsageListLength - Max entries in UsageList - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetButtonsOnPage(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage *piUsageList, - UInt32 *piUsageListLength, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - UInt32 iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDUsageAndPage tUsageAndPage; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR, iE; - long iValue; - int iStart; - int iMaxUsages; - int iReportItem; - Boolean bIncompatibleReport = false; - Boolean butNotReally = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (piUsageList == NULL) - || (piUsageListLength == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Save the size of the list -*/ - iMaxUsages = *piUsageListLength; - *piUsageListLength = 0; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsButton(ptReportItem, preparsedDataRef)) - { -/* - * This may be the proper data to get - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { - butNotReally = true; -/* - * Save Array Buttons -*/ - iStart = ptReportItem->startBit; - for (iE=0; iE<ptReportItem->globals.reportCount; iE++) - { - if ((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray) - { - iStatus = HIDGetData(psReport, iReportLength, iStart, - ptReportItem->globals.reportSize, - &iValue, false); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); - HIDUsageAndPageFromIndex(preparsedDataRef, - ptReportItem, - iValue-ptReportItem->globals.logicalMinimum, - &tUsageAndPage); - iStart += ptReportItem->globals.reportSize; - if (usagePage == tUsageAndPage.usagePage) - { - if (*piUsageListLength >= iMaxUsages) - return kHIDBufferTooSmallErr; - piUsageList[(*piUsageListLength)++] = iValue; - } - } -/* - * Save Bitmapped Buttons -*/ - else - { - iStatus = HIDGetData(psReport, iReportLength, iStart, 1, &iValue, false); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); - iStart++; - if (!iStatus && iValue != 0) - { - HIDUsageAndPageFromIndex(preparsedDataRef,ptReportItem,iE,&tUsageAndPage); - if (usagePage == tUsageAndPage.usagePage) - { - if (*piUsageListLength >= iMaxUsages) - return kHIDBufferTooSmallErr; - piUsageList[(*piUsageListLength)++] = tUsageAndPage.usage; - } - } - } - } - } - } - } -/* - * If nothing was returned then change the status -*/ - if (*piUsageListLength == 0) - { - // If any of the report items were not the right type, we have set the bIncompatibleReport flag. - // However, if any of the report items really were the correct type, we have done our job of checking - // and really didn't find a usage. Don't let the bIncompatibleReport flag wipe out our valid test. - if (bIncompatibleReport && !butNotReally) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCaps.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCaps.c deleted file mode 100644 index 32c2bb1c2..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCaps.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetCaps.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB3> 4/21/00 KH Added HIDGetCapabilities to be consistant with - HIDGetButtonCapabilities, HIDGetSpecificButtonCapabilities, - HIDGetValueCapabilities, and HIDGetSpecificValueCapabilities. - <USB2> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDP_GetCaps - * - * Input: - * ptPreparsedData - Pre-Parsed Data - * ptCapabilities - Pointer to caller-provided structure - * Output: - * ptCapabilities - Capabilities data - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetCaps(HIDPreparsedDataRef preparsedDataRef, HIDCapsPtr ptCapabilities) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - HIDReportSizes *ptReport; - int iFirstUsage; - int i; -/* - * Disallow Null Pointers -*/ - - if ((ptPreparsedData == NULL) || (ptCapabilities == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Copy the capabilities to the user - * Collection Capabilities -*/ - - ptCollection = &ptPreparsedData->collections[1]; - ptCapabilities->usagePage = ptCollection->usagePage; - iFirstUsage = ptCollection->firstUsageItem; - ptCapabilities->usage = ptPreparsedData->usageItems[iFirstUsage].usage; - ptCapabilities->numberCollectionNodes = ptPreparsedData->collectionCount; -/* - * Report Capabilities Summary -*/ - - ptCapabilities->inputReportByteLength = 0; - ptCapabilities->outputReportByteLength = 0; - ptCapabilities->featureReportByteLength = 0; - for (i=0; i<ptPreparsedData->reportCount; i++) - { - ptReport = &ptPreparsedData->reports[i]; - if (ptCapabilities->inputReportByteLength < ptReport->inputBitCount) - ptCapabilities->inputReportByteLength = ptReport->inputBitCount; - if (ptCapabilities->outputReportByteLength < ptReport->outputBitCount) - ptCapabilities->outputReportByteLength = ptReport->outputBitCount; - if (ptCapabilities->featureReportByteLength < ptReport->featureBitCount) - ptCapabilities->featureReportByteLength = ptReport->featureBitCount; - } - ptCapabilities->inputReportByteLength = (ptCapabilities->inputReportByteLength + 7) /8; - ptCapabilities->outputReportByteLength = (ptCapabilities->outputReportByteLength + 7)/8; - ptCapabilities->featureReportByteLength = (ptCapabilities->featureReportByteLength + 7)/8; -/* - * Sum the capabilities types -*/ - - ptCapabilities->numberInputButtonCaps = 0; - ptCapabilities->numberInputValueCaps = 0; - ptCapabilities->numberOutputButtonCaps = 0; - ptCapabilities->numberOutputValueCaps = 0; - ptCapabilities->numberFeatureButtonCaps = 0; - ptCapabilities->numberFeatureValueCaps = 0; - for (i=0; i<ptPreparsedData->reportItemCount; i++) - { - ptReportItem = &ptPreparsedData->reportItems[i]; - switch (ptReportItem->reportType) - { - case kHIDInputReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberInputButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberInputValueCaps += ptReportItem->usageItemCount; - break; - case kHIDOutputReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberOutputButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberOutputValueCaps += ptReportItem->usageItemCount; - break; - case kHIDFeatureReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberFeatureButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberFeatureValueCaps += ptReportItem->usageItemCount; - break; - } - } - return kHIDSuccess; -} - - -/* - *------------------------------------------------------------------------------ - * - * HIDGetCapabilities This is exactly the same as HIDGetCaps. It does take a - * HIDCapabiitiesPtr instead of a HIDCapsPtr, but the structures - * of each are exactly the same. The only reason this call - * exists seperately is for uniformity of naming with - * HIDGetValueCapabilities, HIDGetSpecificButtonCapabilities, etc. - * - * Input: - * ptPreparsedData - Pre-Parsed Data - * ptCapabilities - Pointer to caller-provided structure - * Output: - * ptCapabilities - Capabilities data - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetCapabilities(HIDPreparsedDataRef preparsedDataRef, HIDCapabilitiesPtr ptCapabilities) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - HIDReportSizes *ptReport; - int iFirstUsage; - int i; -/* - * Disallow Null Pointers -*/ - - if ((ptPreparsedData == NULL) || (ptCapabilities == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Copy the capabilities to the user - * Collection Capabilities -*/ - - ptCollection = &ptPreparsedData->collections[1]; - ptCapabilities->usagePage = ptCollection->usagePage; - iFirstUsage = ptCollection->firstUsageItem; - ptCapabilities->usage = ptPreparsedData->usageItems[iFirstUsage].usage; - ptCapabilities->numberCollectionNodes = ptPreparsedData->collectionCount; -/* - * Report Capabilities Summary -*/ - - ptCapabilities->inputReportByteLength = 0; - ptCapabilities->outputReportByteLength = 0; - ptCapabilities->featureReportByteLength = 0; - for (i=0; i<ptPreparsedData->reportCount; i++) - { - ptReport = &ptPreparsedData->reports[i]; - if (ptCapabilities->inputReportByteLength < ptReport->inputBitCount) - ptCapabilities->inputReportByteLength = ptReport->inputBitCount; - if (ptCapabilities->outputReportByteLength < ptReport->outputBitCount) - ptCapabilities->outputReportByteLength = ptReport->outputBitCount; - if (ptCapabilities->featureReportByteLength < ptReport->featureBitCount) - ptCapabilities->featureReportByteLength = ptReport->featureBitCount; - } - ptCapabilities->inputReportByteLength = (ptCapabilities->inputReportByteLength + 7) /8; - ptCapabilities->outputReportByteLength = (ptCapabilities->outputReportByteLength + 7)/8; - ptCapabilities->featureReportByteLength = (ptCapabilities->featureReportByteLength + 7)/8; -/* - * Sum the capabilities types -*/ - - ptCapabilities->numberInputButtonCaps = 0; - ptCapabilities->numberInputValueCaps = 0; - ptCapabilities->numberOutputButtonCaps = 0; - ptCapabilities->numberOutputValueCaps = 0; - ptCapabilities->numberFeatureButtonCaps = 0; - ptCapabilities->numberFeatureValueCaps = 0; - for (i=0; i<ptPreparsedData->reportItemCount; i++) - { - ptReportItem = &ptPreparsedData->reportItems[i]; - switch (ptReportItem->reportType) - { - case kHIDInputReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberInputButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberInputValueCaps += ptReportItem->usageItemCount; - break; - case kHIDOutputReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberOutputButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberOutputValueCaps += ptReportItem->usageItemCount; - break; - case kHIDFeatureReport: - if (HIDIsButton(ptReportItem, preparsedDataRef)) - ptCapabilities->numberFeatureButtonCaps += ptReportItem->usageItemCount; - else if (HIDIsVariable(ptReportItem, preparsedDataRef)) - ptCapabilities->numberFeatureValueCaps += ptReportItem->usageItemCount; - break; - } - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCollectionNodes.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCollectionNodes.c deleted file mode 100644 index f824c7247..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCollectionNodes.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetCollectionNodes.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetCollectionNodes - Get the Collections Database - * - * Input: - * ptLinkCollectionNodes - Node Array provided by caller - * piLinkCollectionNodesLength - Maximum Nodes - * Output: - * piLinkCollectionNodesLength - Actual number of Nodes - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * HidP_NotEnoughRoom - More Nodes than space for them - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetCollectionNodes(HIDCollectionNodePtr ptLinkCollectionNodes, - UInt32 *piLinkCollectionNodesLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollectionNodePtr ptLink; - HIDCollection *ptCollection; - HIDP_UsageItem *ptFirstUsageItem; - int iMaxNodes; - int collectionCount; - int firstUsageItem; - int i; -/* - * Disallow Null Pointers -*/ - if ((ptLinkCollectionNodes == NULL) - || (piLinkCollectionNodesLength == NULL) - || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Remember the size of the output array -*/ - iMaxNodes = *piLinkCollectionNodesLength; - collectionCount = ptPreparsedData->collectionCount; - *piLinkCollectionNodesLength = collectionCount; -/* - * Report if there's not enough room -*/ - if (collectionCount > iMaxNodes) - return kHIDBufferTooSmallErr; -/* - * Copy the nodes -*/ - for (i=0; i<collectionCount; i++) - { - ptCollection = &ptPreparsedData->collections[i]; - ptLink = &ptLinkCollectionNodes[i]; - firstUsageItem = ptCollection->firstUsageItem; - ptFirstUsageItem = &ptPreparsedData->usageItems[firstUsageItem]; - ptLink->collectionUsage = ptFirstUsageItem->usage; - ptLink->collectionUsagePage = ptCollection->usagePage; - ptLink->parent = ptCollection->parent; - ptLink->numberOfChildren = ptCollection->children; - ptLink->nextSibling = ptCollection->nextSibling; - ptLink->firstChild = ptCollection->firstChild; - } -/* - * Report if there wasn't enough space -*/ - if (iMaxNodes < ptPreparsedData->collectionCount) - return kHIDBufferTooSmallErr; - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetData.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetData.c deleted file mode 100644 index 8f373b906..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetData.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetData.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB3> 12/12/00 KH Correct cast of void * - <USB2> 3/5/99 BWS [2311353] HIDGetData not masking properly, so not work at all - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetData - Get a single data item from a report - * - * Input: - * psReport - The report - * iReportLength - The length of the report - * iStart - Start Bit in report - * iSize - Number of Bits - * piValue - The place to write the data - * bSignExtend - Sign extend? - * Output: - * piValue - The data - * Returns: - * kHidP_Success - Success - * kHidP_NullPointer - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetData(void * report, UInt32 iReportLength, - UInt32 iStart, UInt32 iSize, SInt32 *piValue, - Boolean bSignExtend) -{ - Byte * psReport = (Byte *)report; - unsigned data; - unsigned iSignBit; - unsigned iExtendMask; - unsigned iStartByte = iStart/8; - unsigned startBit = iStart&7; - unsigned iLastBit = iStart + iSize - 1; - unsigned iLastByte = iLastBit/8; - int iCurrentByte; // needs to be signed, we terminate loop on -1 - unsigned iMask; - - // Check the parameters - if ((iSize == 0) || (iLastByte >= iReportLength) || (iLastByte < iStartByte)) - return kHIDBadParameterErr; - - // Pick up the data bytes backwards - data = 0; - for (iCurrentByte = iLastByte; iCurrentByte >= (int) iStartByte; iCurrentByte--) - { - data <<= 8; - - iMask = 0xff; // 1111 1111 initial mask - // if this is the 'last byte', then we need to mask off the top part of the byte - // to find the mask, we: find the position in this byte (lastBit % 8) - // then shift one to the left that many times plus one (to get one bit further) - // then subtract 1 to get all ones starting from the lastBit to the least signif bit - // ex: if iLastBit is 9, or iLastBit is 15, then we get: - // 1 7 (x % 8) - // 0000 0100 1 0000 0000 (1 << (x + 1)) - // 0000 0011 0 1111 1111 (x - 1) - if (iCurrentByte == iLastByte) - iMask = ((1 << (((unsigned) iLastBit % 8) + 1)) - 1); - - data |= (unsigned) psReport[iCurrentByte] & iMask; - } - - // Shift to the right to byte align the least significant bit - data >>= startBit; - - // Sign extend the report item - if (bSignExtend) - { - iSignBit = 1; - if (iSize > 1) - iSignBit <<= (iSize-1); - iExtendMask = (iSignBit << 1) - 1; - if ((data & iSignBit)==0) - data &= iExtendMask; - else - data |= ~iExtendMask; - } - - // Return the value - *piValue = (SInt32) data; - - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextButtonInfo.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextButtonInfo.c deleted file mode 100644 index 26adbec86..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextButtonInfo.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetNextButtonInfo.c - - Contains: HIDGetNextButtonInfo call for HID Library - - Version: 1.0d1 - - Copyright: © 2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: David Ferguson - - Other Contact: Keithen Hayenga - - Technology: technologies, usb - - Writers: - - (KH) Keithen Hayenga - - Change History (most recent first): - - <USB1> 2/14/00 KH first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetNextButtonInfo - Get report id and collection for a button. In keeping - * with USBGetNextInterface, we find the usage in the - * next collection, so that you can find usages that - * have the same usage and usage page. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * usage - The usage to get the information for - * collection - Starting Collection Criteria or zero - * preparsedDataRef - Pre-Parsed Data - * Output: - * collection - Final Collection Criteria or no change - * reportID - Report ID or no change - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetNextButtonInfo - (HIDReportType reportType, - HIDUsage usagePage, - HIDUsage usage, - UInt32 * collection, - UInt8 * reportID, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr)preparsedDataRef; - HIDReportItem *ptReportItem; - UInt32 iCollection; - UInt32 newCollection = 0xFFFFFFFF; - int iR; - UInt8 newReportID = 0; - OSStatus iStatus = kHIDUsageNotFoundErr; - - //Disallow Null Pointers - - if ((ptPreparsedData == NULL) || (collection == NULL) || (reportID == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; - - // The Collection must be in range - - iCollection = *collection; - // Umm... an unsigned number can never be less than 0! - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; - - // HIDGetNextButtonInfo is different from HIDGetButton in how it treats - // the collection parameter. HIDGetButton will only look at report items that - // are within the collection and can therefore limit it's searches to starting at - // ptPreparsedData->collections[iCollection]->firstReportItem and only check - // ptPreparsedData->collections[iCollection]->reportItemCount. Since we want to - // find the NEXT collection as well, we need to cycle through all of the reports. - - for (iR = 0; iR < ptPreparsedData->reportItemCount; iR++) - { - SInt32 minUsage; - SInt32 maxUsage; - HIDP_UsageItem thisUsage; - - ptReportItem = &ptPreparsedData->reportItems[iR]; - - thisUsage = ptPreparsedData->usageItems[ptReportItem->firstUsageItem]; - - if (thisUsage.isRange) - { - minUsage = thisUsage.usageMinimum; - maxUsage = thisUsage.usageMaximum; - } - else - { - minUsage = thisUsage.usage; - maxUsage = thisUsage.usage; - } - - if (ptReportItem->reportType == reportType && - (usagePage == 0 || ptReportItem->globals.usagePage == usagePage) && - (usage >= minUsage && usage <= maxUsage) && - ptReportItem->parent > iCollection && - HIDIsButton(ptReportItem, preparsedDataRef)) - { - if (ptReportItem->parent < newCollection) - { - newCollection = ptReportItem->parent; - newReportID = iR; - iStatus = noErr; - } - } - } - - if (iStatus == noErr) - { - *reportID = newReportID; - *collection = newCollection; - } - - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextUsageValueInfo.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextUsageValueInfo.c deleted file mode 100644 index 7393d967d..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextUsageValueInfo.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetNextUsageValueInfo.c - - Contains: HIDGetNextUsageValueInfo call for HID Library - - Version: 1.0d1 - - Copyright: © 2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: David Ferguson - - Other Contact: Keithen Hayenga - - Technology: technologies, usb - - Writers: - - (KH) Keithen Hayenga - - Change History (most recent first): - - <USB1> 2/14/00 KH first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetNextUsageValueInfo - Get report id and collection for a usage. In keeping - * with USBGetNextInterface, we find the usage in the - * next collection, so that you can find usages that - * have the same usage and usage page. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * usage - The usage to get the information for - * collection - Starting Collection Criteria or zero - * preparsedDataRef - Pre-Parsed Data - * Output: - * collection - Final Collection Criteria or no change - * reportID - Report ID or no change - * Returns: - * kHIDBadParameterErr when there are no more collections to search. - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetNextUsageValueInfo - (HIDReportType reportType, - HIDUsage usagePage, - HIDUsage usage, - UInt32 * collection, - UInt8 * reportID, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr)preparsedDataRef; - HIDReportItem *ptReportItem; - UInt32 iCollection; - UInt32 newCollection = 0xFFFFFFFF; - int iR; - UInt8 newReportID = 0; - OSStatus iStatus = kHIDUsageNotFoundErr; - - //Disallow Null Pointers - - if ((ptPreparsedData == NULL) || (collection == NULL) || (reportID == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; - - // The Collection must be in range - - iCollection = *collection; - // Umm... an unsigned number can never be less than 0! - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; - - // HIDGetNextUsageValueInfo is different from HIDGetUsageValue in how it treats - // the collection parameter. HIDGetUsageValue will only look at report items that - // are within the collection and can therefore limit it's searches to starting at - // ptPreparsedData->collections[iCollection]->firstReportItem and only check - // ptPreparsedData->collections[iCollection]->reportItemCount. Since we want to - // find the NEXT collection as well, we need to cycle through all of the reports. - - for (iR = 0; iR < ptPreparsedData->reportItemCount; iR++) - { - SInt32 minUsage; - SInt32 maxUsage; - HIDP_UsageItem thisUsage; - - ptReportItem = &ptPreparsedData->reportItems[iR]; - - thisUsage = ptPreparsedData->usageItems[ptReportItem->firstUsageItem]; - - if (thisUsage.isRange) - { - minUsage = thisUsage.usageMinimum; - maxUsage = thisUsage.usageMaximum; - } - else - { - minUsage = thisUsage.usage; - maxUsage = thisUsage.usage; - } - - if (ptReportItem->reportType == reportType && - (usagePage == 0 || ptReportItem->globals.usagePage == usagePage) && - (usage >= minUsage && usage <= maxUsage) && - ptReportItem->parent > iCollection && - HIDIsVariable(ptReportItem, preparsedDataRef)) - { - if (ptReportItem->parent < newCollection) - { - newCollection = ptReportItem->parent; - newReportID = iR; - iStatus = noErr; - } - } - } - - if (iStatus == noErr) - { - *reportID = newReportID; - *collection = newCollection; - } - - return iStatus; -} - diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetReportLength.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetReportLength.c deleted file mode 100644 index 010dcf6df..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetReportLength.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetReportLength.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: David Ferguson - - Other Contact: Keithen Hayenga - - Technology: technologies, usb - - Writers: - - - Change History (most recent first): - -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetReportLength - Get the length of a report - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * reportID - Desired Report - * preparsedDataRef - opaque Pre-Parsed Data - * Output: - * reportLength - The length of the Report - * Returns: - * status kHIDNullPointerErr, kHIDInvalidPreparsedDataErr, - * kHIDUsageNotFoundErr - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetReportLength(HIDReportType reportType, - UInt8 reportID, - ByteCount * reportLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr)preparsedDataRef; - ByteCount dataLength = 0; - OSStatus iStatus = kHIDUsageNotFoundErr; - int iR; - - // Disallow Null Pointers. - - if (ptPreparsedData == NULL || reportLength == NULL) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; - - // Go through the Reports. - - for (iR = 0; iR < ptPreparsedData->reportCount; iR++) - { - if (ptPreparsedData->reports[iR].reportID == reportID) - { - switch(reportType) - { - case kHIDInputReport: - dataLength = (ptPreparsedData->reports[iR].inputBitCount + 7)/8; - break; - case kHIDOutputReport: - dataLength = (ptPreparsedData->reports[iR].outputBitCount + 7)/8; - break; - case kHIDFeatureReport: - dataLength = (ptPreparsedData->reports[iR].featureBitCount + 7)/8; - break; - default: - return kHIDInvalidReportTypeErr; - } - break; - } - } - - // If the reportID > 0, there must be 1 byte for reportID, so total report must be > 1. - // (Would come into play if we had input report 3, but searched for ouput report 3 - // that didn't exist.) - - if ((reportID == 0) && (dataLength > 0) || dataLength > 1) - { - iStatus = noErr; - } - else - { - dataLength = 0; // Ignore report that had id, but no data. - } - - *reportLength = dataLength; - - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValue.c deleted file mode 100644 index 888b413d7..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValue.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetUsageValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetUsageValue - Get the value for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - The usage to get the value for - * piUsageValue - User-supplied place to put value - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetUsageValue - (HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - SInt32 * piUsageValue, - HIDPreparsedDataRef preparsedDataRef, - void * psReport, - ByteCount iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR; - SInt32 iValue; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (piUsageValue == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) - { -/* - * This may be the proper data to get - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { -/* - * Pick up the data -*/ - iStart = ptReportItem->startBit - + (ptReportItem->globals.reportSize * iUsageIndex); - iStatus = HIDGetData(psReport, iReportLength, iStart, - ptReportItem->globals.reportSize, &iValue, - ((ptReportItem->globals.logicalMinimum < 0) - ||(ptReportItem->globals.logicalMaximum < 0))); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); - *piUsageValue = iValue; - return iStatus; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDGetScaledUsageValue - Get the value for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * piValue - Pointer to usage Value - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetScaledUsageValue(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - SInt32 *piUsageValue, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - ByteCount iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR; - long iValue; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (piUsageValue == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) - { -/* - * This may be the proper data to get - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { -/* - * Pick up the data -*/ - iStart = ptReportItem->startBit - + (ptReportItem->globals.reportSize * iUsageIndex); - iStatus = HIDGetData(psReport, iReportLength, iStart, - ptReportItem->globals.reportSize, &iValue, - ((ptReportItem->globals.logicalMinimum < 0) - ||(ptReportItem->globals.logicalMaximum < 0))); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); - if (iStatus != kHIDSuccess) - return iStatus; -/* - * Try to scale the data -*/ - iStatus = HIDScaleUsageValueIn(ptReportItem,iValue,&iValue); - *piUsageValue = iValue; - return iStatus; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValueArray.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValueArray.c deleted file mode 100644 index 69d925f06..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValueArray.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetUsageValueArray.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDP_GetUsageValueArray - Get the values for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria - * iCollection - Collection Criteria or zero - * usage - usage Criteria - * psBuffer - Pointer to usage Buffer - * iByteLength - Length of usage Buffer - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetUsageValueArray(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - UInt8 *psUsageBuffer, - UInt32 iByteLength, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - UInt32 iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int i; - int iR; - long iValue; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - UInt32 iCount; - int byteCount; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (psUsageBuffer == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,&iCount)) - { -/* - * This may be the proper data to get - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { -/* - * Disallow single count variables - * Count is set by HasUsage -*/ - if (iCount <= 1) - return kHIDNotValueArrayErr; -/* - * Get the data -*/ - iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); - byteCount = (ptReportItem->globals.reportSize * iCount + 7)/8; - if (byteCount > iByteLength) - byteCount = iByteLength; - for (i=0; i<byteCount; i++) - { - iStatus = HIDGetData(psReport, iReportLength, iStart, 8, &iValue, - ((ptReportItem->globals.logicalMinimum < 0) - ||(ptReportItem->globals.logicalMaximum < 0))); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &iValue); - if (iStatus != kHIDSuccess) - return iStatus; - *psUsageBuffer++ = (char) iValue; - iStart += 8; - } - return kHIDSuccess; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetValueCaps.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetValueCaps.c deleted file mode 100644 index 1af6f7467..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetValueCaps.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDGetValueCaps.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB8> 12/12/00 KH range count off by 1. - <USB7> 4/21/00 KH Added HIDGetValueCapabilities and - HIDGetSpecificValueCapabilities that now allow users to find HID - report units and exponents. - <USB6> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB5> 5/3/99 BWS Fix typo - <USB4> 5/3/99 BWS We were not setting isStringRange, isDesignatorRange, and - isAbsolute - <USB3> 3/7/99 BWS When range/notRange were made a union, we missed this case where - they were both being set indescriminately - <USB2> 3/7/99 BWS [2311411] Had added missing fields to caps structure, but they - were not being filled in - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDGetSpecificValueCaps - Get the binary values for a report type - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * valueCaps - ValueCaps Array - * piValueCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piValueCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetSpecificValueCaps(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - HIDValueCapsPtr valueCaps, - UInt32 *piValueCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDCollection *ptParent; - HIDReportItem *ptReportItem; - HIDP_UsageItem *ptUsageItem; - HIDStringItem *ptStringItem; - HIDDesignatorItem *ptDesignatorItem; - HIDP_UsageItem *ptFirstCollectionUsageItem; - HIDValueCaps *ptCapability; - int iR, iU; - int parent; - int iReportItem, iUsageItem; - int iMaxCaps; - UInt32 iCount; - // There are 3 versions of HID Parser code all based on the same logic: OS 9 HID Library; - // OSX xnu; OSX IOKitUser. They should all be nearly the same logic. This version (xnu) - // is based on older OS 9 code. This version has added logic to maintain this startBit. - // I don't know why it is here, but believe if it is needed here, it would probably be - // needed in the other two implementations. Didn't have time to determine that at this - // time, so i'll leave this comment to remind me that we should reconcile the 3 versions. - UInt32 startBit; // Added esb 9-29-99 - /*If I remember correctly, it was an optimization. Each time you ask for - a specific value capability, it would search through the entire report - descriptor to find it (my recollection is kind of hazy on this part). - The start bit allowed somebody (client maybe) to cache the information - on where in the report a specific value resided and the use that later - when fetching that value. That way, you don't have to keep going - through the parse tree to find where a value exists. I don't remember - if the implementation was completed or if I even used it. -esb */ -/* - * Disallow Null Pointers -*/ - if ((valueCaps == NULL) - || (piValueCapsLength == NULL) - || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the buffer size -*/ - iMaxCaps = *piValueCapsLength; - *piValueCapsLength = 0; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; -/* - * Search only reports of the proper type -*/ - if ((ptReportItem->reportType == reportType) - && ((ptReportItem->globals.usagePage == usagePage) - || (usagePage == 0)) - && HIDIsVariable(ptReportItem, preparsedDataRef)) - { - startBit = ptReportItem->startBit; // Added esb 9-28-99 -/* - * Search the usages -*/ - for (iU=0; iU<ptReportItem->usageItemCount; iU++) - { -/* - * Copy all usages if the usage above is zero - * or copy all that "match" -*/ - iUsageItem = ptReportItem->firstUsageItem + iU; - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem]; - - // ¥¥ we assume there is a 1-1 corresponence between usage items, string items, and designator items - // ¥¥Êthis is not necessarily the case, but its better than nothing - ptStringItem = &ptPreparsedData->stringItems[ptReportItem->firstStringItem + iU]; - ptDesignatorItem = &ptPreparsedData->desigItems[ptReportItem->firstDesigItem + iU]; - - if (HIDUsageInRange(ptUsageItem,usagePage,usage)) - { -/* - * Only copy if there's room -*/ - if (*piValueCapsLength >= iMaxCaps) - return kHIDBufferTooSmallErr; - ptCapability = &valueCaps[(*piValueCapsLength)++]; -/* - * Populate the Capability Structure -*/ - parent = ptReportItem->parent; - ptParent = &ptPreparsedData->collections[parent]; - ptFirstCollectionUsageItem = &ptPreparsedData->usageItems[ptParent->firstUsageItem]; - ptCapability->collection = parent; - ptCapability->collectionUsagePage = ptParent->usagePage; - ptCapability->collectionUsage = ptFirstCollectionUsageItem->usage; - ptCapability->bitField = ptReportItem->dataModes; - ptCapability->reportID = ptReportItem->globals.reportID; - ptCapability->usagePage = ptUsageItem->usagePage; - - ptCapability->isAbsolute = !(ptReportItem->dataModes & kHIDDataRelative); - - ptCapability->isRange = ptUsageItem->isRange; - if (ptUsageItem->isRange) - { - ptCapability->u.range.usageMin = ptUsageItem->usageMinimum; - ptCapability->u.range.usageMax = ptUsageItem->usageMaximum; - } - else - ptCapability->u.notRange.usage = ptUsageItem->usage; - - // if there really are that many items - if (iU < ptReportItem->stringItemCount) - { - ptCapability->isStringRange = ptStringItem->isRange; - - if (ptStringItem->isRange) - { - ptCapability->u.range.stringMin = ptStringItem->minimum; - ptCapability->u.range.stringMax = ptStringItem->maximum; - } - else - ptCapability->u.notRange.stringIndex = ptStringItem->index; - } - // default, clear it - else - { - ptCapability->isStringRange = false; - ptCapability->u.notRange.stringIndex = 0; - } - - // if there really are that many items - if (iU < ptReportItem->desigItemCount) - { - ptCapability->isDesignatorRange = ptDesignatorItem->isRange; - - if (ptDesignatorItem->isRange) - { - ptCapability->u.range.designatorMin = ptDesignatorItem->minimum; - ptCapability->u.range.designatorMax = ptDesignatorItem->maximum; - } - else - ptCapability->u.notRange.designatorIndex = ptDesignatorItem->index; - } - // default, clear it - else - { - ptCapability->isDesignatorRange = false; - ptCapability->u.notRange.designatorIndex = 0; - } - - ptCapability->bitSize = ptReportItem->globals.reportSize; - - ptCapability->logicalMin = ptReportItem->globals.logicalMinimum; - ptCapability->logicalMax = ptReportItem->globals.logicalMaximum; - ptCapability->physicalMin = ptReportItem->globals.physicalMinimum; - ptCapability->physicalMax = ptReportItem->globals.physicalMaximum; - - if (ptUsageItem->isRange) - { - iCount = ptUsageItem->usageMaximum - ptUsageItem->usageMinimum; - if (iCount < 0) - iCount = -iCount; - iCount++; // Range count was off by one. - } - else - // If we're not in a range, then there should be just one usage. - // Why do we have to call this function to determine that? Are we checking - // that there is that usage before we decide if usage count is 0 or 1? - // But haven't we already verified that we have this usage by the time we - // got here? - HIDHasUsage(preparsedDataRef,ptReportItem, - ptUsageItem->usagePage,ptUsageItem->usage, - NULL,&iCount); - ptCapability->reportCount = iCount; - ptCapability->startBit = startBit; - startBit += (ptCapability->bitSize * ptCapability->reportCount); - } - } - } - } - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDGetValueCaps - Get the binary values for a report type - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * valueCaps - ValueCaps Array - * piValueCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piValueCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetValueCaps(HIDReportType reportType, - HIDValueCapsPtr valueCaps, - UInt32 *piValueCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - return HIDGetSpecificValueCaps(reportType,0,0,0,valueCaps, - piValueCapsLength,preparsedDataRef); -} - - -/* - *------------------------------------------------------------------------------ - * - * HIDGetSpecificValueCapabilities - Get the binary values for a report type - * This is the same as HIDGetSpecificValueCaps, - * except that it takes a HIDValueCapabilitiesPtr - * so it can return units and unitExponents. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * valueCaps - ValueCaps Array - * piValueCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piValueCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetSpecificValueCapabilities(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - HIDValueCapabilitiesPtr valueCaps, - UInt32 *piValueCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDCollection *ptParent; - HIDReportItem *ptReportItem; - HIDP_UsageItem *ptUsageItem; - HIDStringItem *ptStringItem; - HIDDesignatorItem *ptDesignatorItem; - HIDP_UsageItem *ptFirstCollectionUsageItem; - HIDValueCapabilities *ptCapability; - int iR, iU; - int parent; - int iReportItem, iUsageItem; - int iMaxCaps; - UInt32 iCount; - // There are 3 versions of HID Parser code all based on the same logic: OS 9 HID Library; - // OSX xnu; OSX IOKitUser. They should all be nearly the same logic. This version (xnu) - // is based on older OS 9 code. This version has added logic to maintain this startBit. - // I don't know why it is here, but believe if it is needed here, it would probably be - // needed in the other two implementations. Didn't have time to determine that at this - // time, so i'll leave this comment to remind me that we should reconcile the 3 versions. - UInt32 startBit; // Carried esb's logic down here when we added HIDGetSpecificValueCapabilities(). -/* - * Disallow Null Pointers -*/ - if ((valueCaps == NULL) - || (piValueCapsLength == NULL) - || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the buffer size -*/ - iMaxCaps = *piValueCapsLength; - *piValueCapsLength = 0; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; -/* - * Search only reports of the proper type -*/ - if ((ptReportItem->reportType == reportType) - && ((ptReportItem->globals.usagePage == usagePage) - || (usagePage == 0)) - && HIDIsVariable(ptReportItem, preparsedDataRef)) - { - startBit = ptReportItem->startBit; // Same logic as Added esb 9-28-99 -/* - * Search the usages -*/ - for (iU=0; iU<ptReportItem->usageItemCount; iU++) - { -/* - * Copy all usages if the usage above is zero - * or copy all that "match" -*/ - iUsageItem = ptReportItem->firstUsageItem + iU; - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem]; - - // ¥¥ we assume there is a 1-1 corresponence between usage items, string items, and designator items - // ¥¥Êthis is not necessarily the case, but its better than nothing - ptStringItem = &ptPreparsedData->stringItems[ptReportItem->firstStringItem + iU]; - ptDesignatorItem = &ptPreparsedData->desigItems[ptReportItem->firstDesigItem + iU]; - - if (HIDUsageInRange(ptUsageItem,usagePage,usage)) - { -/* - * Only copy if there's room -*/ - if (*piValueCapsLength >= iMaxCaps) - return kHIDBufferTooSmallErr; - ptCapability = &valueCaps[(*piValueCapsLength)++]; - -/* - * Populate the Capability Structure -*/ - parent = ptReportItem->parent; - ptParent = &ptPreparsedData->collections[parent]; - ptFirstCollectionUsageItem = &ptPreparsedData->usageItems[ptParent->firstUsageItem]; - ptCapability->collection = parent; - ptCapability->collectionUsagePage = ptParent->usagePage; - ptCapability->collectionUsage = ptFirstCollectionUsageItem->usage; - ptCapability->bitField = ptReportItem->dataModes; - ptCapability->reportID = ptReportItem->globals.reportID; - ptCapability->usagePage = ptUsageItem->usagePage; - ptCapability->unitExponent = ptReportItem->globals.unitExponent; - ptCapability->units = ptReportItem->globals.units; -// ptCapability->reserved = 0; // for future OS 9 expansion - ptCapability->startBit = 0; // init esb added field. -// ptCapability->pbVersion = kHIDCurrentCapabilitiesPBVersion; - ptCapability->pbVersion = 2; - - ptCapability->isAbsolute = !(ptReportItem->dataModes & kHIDDataRelative); - - ptCapability->isRange = ptUsageItem->isRange; - if (ptUsageItem->isRange) - { - ptCapability->u.range.usageMin = ptUsageItem->usageMinimum; - ptCapability->u.range.usageMax = ptUsageItem->usageMaximum; - } - else - ptCapability->u.notRange.usage = ptUsageItem->usage; - - // if there really are that many items - if (iU < ptReportItem->stringItemCount) - { - ptCapability->isStringRange = ptStringItem->isRange; - - if (ptStringItem->isRange) - { - ptCapability->u.range.stringMin = ptStringItem->minimum; - ptCapability->u.range.stringMax = ptStringItem->maximum; - } - else - ptCapability->u.notRange.stringIndex = ptStringItem->index; - } - // default, clear it - else - { - ptCapability->isStringRange = false; - ptCapability->u.notRange.stringIndex = 0; - } - - // if there really are that many items - if (iU < ptReportItem->desigItemCount) - { - ptCapability->isDesignatorRange = ptDesignatorItem->isRange; - - if (ptDesignatorItem->isRange) - { - ptCapability->u.range.designatorMin = ptDesignatorItem->minimum; - ptCapability->u.range.designatorMax = ptDesignatorItem->maximum; - } - else - ptCapability->u.notRange.designatorIndex = ptDesignatorItem->index; - } - // default, clear it - else - { - ptCapability->isDesignatorRange = false; - ptCapability->u.notRange.designatorIndex = 0; - } - - ptCapability->bitSize = ptReportItem->globals.reportSize; - - ptCapability->logicalMin = ptReportItem->globals.logicalMinimum; - ptCapability->logicalMax = ptReportItem->globals.logicalMaximum; - ptCapability->physicalMin = ptReportItem->globals.physicalMinimum; - ptCapability->physicalMax = ptReportItem->globals.physicalMaximum; - - if (ptUsageItem->isRange) - { - iCount = ptUsageItem->usageMaximum - ptUsageItem->usageMinimum; - if (iCount < 0) - iCount = -iCount; - iCount++; // Range count was off by one. - } - else - HIDHasUsage(preparsedDataRef,ptReportItem, - ptUsageItem->usagePage,ptUsageItem->usage, - NULL,&iCount); - ptCapability->reportCount = iCount; - ptCapability->startBit = startBit; // more of same logic. - startBit += (ptCapability->bitSize * ptCapability->reportCount); - } - } - } - } - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDGetValueCapabilities - Get the binary values for a report type - * This is the same as HIDGetValueCaps, - * except that it takes a HIDValueCapabilitiesPtr - * so it can return units and unitExponents. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * valueCaps - ValueCaps Array - * piValueCapsLength - Maximum Entries - * ptPreparsedData - Pre-Parsed Data - * Output: - * piValueCapsLength - Entries Populated - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDGetValueCapabilities(HIDReportType reportType, - HIDValueCapabilitiesPtr valueCaps, - UInt32 *piValueCapsLength, - HIDPreparsedDataRef preparsedDataRef) -{ - return HIDGetSpecificValueCapabilities(reportType,0,0,0,valueCaps, - piValueCapsLength,preparsedDataRef); -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDHasUsage.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDHasUsage.c deleted file mode 100644 index 97a48ab14..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDHasUsage.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDHasUsage.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB2> 12/12/00 KH range count off by 1. - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HidP_UsageFromIndex - * - * Input: - * ptPreparsedData - The Preparsed Data - * ptReportItem - The Report Item - * usagePage - The usage Page to find - * usage - The usage to find - * piIndex(optional) - The usage Index pointer (Can be used to tell - * which bits in an array correspond to that usage.) - * piCount(optional) - The usage Count pointer (Can be used to tell - * how many items will be in a report.) - * Output: - * piIndex - The usage Index - * Returns: - * The usage - * - *------------------------------------------------------------------------------ -*/ -Boolean HIDHasUsage (HIDPreparsedDataRef preparsedDataRef, - HIDReportItem *ptReportItem, - HIDUsage usagePage, HIDUsage usage, - UInt32 *piIndex, UInt32 *piCount) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - int iUsageItem; - UInt32 iUsageIndex; - int iUsages; - int i; - UInt32 iCountsLeft; - HIDP_UsageItem *ptUsageItem; - Boolean bOnPage; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (ptReportItem == NULL)) - return 0; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return 0; -/* - * Look through the usage Items for this usage -*/ - iUsageItem = ptReportItem->firstUsageItem; - iUsageIndex = 0; - for (i=0; i<ptReportItem->usageItemCount; i++) - { -/* - * Each usage Item is either a usage or a usage range -*/ - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem++]; - bOnPage = ((usagePage == 0) || (usagePage == ptUsageItem->usagePage)); - if (ptUsageItem->isRange) - { -/* - * For usage Ranges - * If the index is in the range - * then return the usage - * Otherwise adjust the index by the size of the range -*/ - if ((usage >= ptUsageItem->usageMinimum) - && (usage <= ptUsageItem->usageMaximum)) - { - if (piIndex != NULL) - *piIndex = iUsageIndex + (ptUsageItem->usageMinimum - usage); -/* - * If this usage is the last one for this ReportItem - * then it gets all of the remaining reportCount -*/ - if (piCount != NULL) - { - // piCount is going to be used to find which element in a button array is - // the one that returns the value for that usage. - if (((i+1) == ptReportItem->usageItemCount) - && (usage == ptUsageItem->usageMaximum)) - { - // Hmm, the same logic in the non-range case below was wrong. But things - // seem to be working for finding buttons, so i am not changing it here. - // However, we have made some changes to range calculations that may no - // longer require that -1 here either. Heads up! - iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex - 1; - if (iCountsLeft > 1) - *piCount = iCountsLeft; - else - *piCount = 1; - } - else - *piCount = 1; - } - if (bOnPage) - return true; - } - iUsages = ptUsageItem->usageMaximum - ptUsageItem->usageMinimum; - if (iUsages < 0) - iUsages = -iUsages; - iUsages++; // Add off by one adjustment AFTER sign correction. - iUsageIndex += iUsages; - } - else - { -/* - * For Usages - * If the index is zero - * then return this usage - * Otherwise one less to index through -*/ - if (usage == ptUsageItem->usage) - { - if (piIndex != NULL) - *piIndex = iUsageIndex; - if (piCount != NULL) - { - if ((i+1) == ptReportItem->usageItemCount) - { - // Keithen does not understand the logic of iCountsLeft. - // In Radar #2579612 we come through here for HIDGetUsageValueArray - // and HIDGetSpecificValueCaps. In both cases piCount that is returned - // should be the reportCount without the -1. -// iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex - 1; - iCountsLeft = ptReportItem->globals.reportCount - iUsageIndex; - if (iCountsLeft > 1) - *piCount = iCountsLeft; - else - *piCount = 1; - } - else - *piCount = 1; - } - if (bOnPage) - return true; - } - iUsageIndex++; - } - } - return false; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDInitReport.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDInitReport.c deleted file mode 100644 index 54fdda491..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDInitReport.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDInitReport.c - - Contains: HIDInitReport call for HID Library - - Version: 1.0d1 - - Copyright: © 2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: David Ferguson - - Other Contact: Keithen Hayenga - - Technology: technologies, usb - - Writers: - - - Change History (most recent first): - -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDInitReport - Initialize report to have report ID and, if possible, null values - * so that setting any one value will not inadvertantly change - * other items in the same report to 0. - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * reportID - Report ID - * preparsedDataRef - Pre-Parsed Data - * report - An HID Report - * reportLength - The length of the Report - * Output: - * report - Initialized HID Report - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDInitReport - (HIDReportType reportType, - UInt8 reportID, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDReportItem * ptReportItem; - ByteCount minLength; - UInt8 * iPtr; - int iR; - OSStatus iStatus = kHIDSuccess; - - //Disallow Null Pointers - - if ((ptPreparsedData == NULL) || (report == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; - if (reportLength == 0) - return kHIDReportSizeZeroErr; - - // Report length must also be great enough to hold report. - HIDGetReportLength(reportType, reportID, &minLength, preparsedDataRef); - // I know that HIDGetReportLength repeats the first tests above, but it - // was easier to duplicate that logic than build test cases for the other - // errors that could be returned by HIDGetReportLength that i don't care - // about. - - if (reportLength < minLength) - return kHIDInvalidReportLengthErr; - - // First byte of report must be reportID. Unless it is report ID 0; - // in which case 0 is just the first byte of the following initialization. - - iPtr = (UInt8 *)report; - *iPtr++ = reportID; - - // Default initialization is to zero out all values. - - for (iR = 1; iR < reportLength; iR++) - { - *iPtr++ = 0; - } - - // Search through all report items to see if they belong in this report. - - for (iR = 0; iR < ptPreparsedData->reportItemCount; iR++) - { - ptReportItem = &ptPreparsedData->reportItems[iR]; - - if (ptReportItem->reportType == reportType && - ptReportItem->globals.reportID == reportID) - { - // Is there a null value for this item? - SInt32 nullValue; - SInt32 bitwiseMax; - SInt32 bitwiseMin; - SInt32 bitSize; - Boolean isSigned; - - // The HID spec "highly encourages" 0 to be a null value, so test - // for it first. - - if ( 0 < ptReportItem->globals.logicalMinimum || - 0 > ptReportItem->globals.logicalMaximum) - continue; // Default initialization was good enough. - - nullValue = 0; // We can test if this changes below. - - // Determine the maximum and minimum signed numbers that will fit into this - // item and then see if they are outside the bounds of what the descriptor - // says are the allowed min and max. - // What the possible ranges are depends upon if the device is accepting - // signed or unsigned numbers. I haven't noticed that information in the - // preparsed data, so i'll take an educated guess. If logicalMinimum is - // less than 0 it must be using signed numbers. Conversly, logicalMaximum - // using the high order bit of it's bitfield would indicate unsigned. In - // case of a tie, we'll say signed since that agrees with the SInt32 that - // logicalMinimum and logicalMaximum are stored in. - - // The mininimum 8 bit value would be 0x80 (-128). To be -128 in UInt32 = 0xFFFFFF80. - // This just happens to also set the high order bit that we need to test in the - // maximum value using the high order bit, such as 64, 0x80. - bitSize = ptReportItem->globals.reportSize; - bitwiseMin = -1 << (bitSize - 1); - - // Logical max should not have any bit set higher than the high order bit of our - // size, so anding with 0xFFFFFF80 should only test field's high order bit. - isSigned = (ptReportItem->globals.logicalMinimum < 0) || - !(ptReportItem->globals.logicalMaximum & bitwiseMin); - - // If signed, we test from 0x80 to 0x7F. If not, 0x00 to 0xFF. - if (isSigned) - { - --bitSize; // Don't let max value flow into sign bit. - } - else - { - bitwiseMin = 0; - } - - // Our compare uses SInt32, so even for unsigned values, we can't let them - // overflow into real sign bit. (So 0x80000000 is not a legal HID positive number.) - if (bitSize >= 32) bitSize = 31; - - // The theory behind this greatly simplified set of compares. 1. I was worried about - // the case of a 4 bit field with a max = 4 and a min = -2. Then if i chose a value - // of 7 for my bitwise max, it could also be -1 for min, which would make it a null - // positive value, but a legal negative one. But while HID specs say a field can be - // either a signed or unsigned value, i don't see how it can be both, so i haven't - // allowed for such a situation. 2. I originally built logic that tested for signed - // or unsigned fields as above, but had seperate logic based on what would happen - // after that. I have resolved that logic down to the main part below and the only - // exceptions i had are now filtered out into the 2 lines of "if (signed)" etc. above. - - bitwiseMax = (1<<bitSize) - 1; - - if (bitwiseMax > ptReportItem->globals.logicalMaximum) - { - nullValue = bitwiseMax; - } - else - { - if (bitwiseMin < ptReportItem->globals.logicalMinimum) - { - nullValue = bitwiseMin; - } - } - - // If we found a null value, store it into the proper place in the report. - - if (nullValue != 0) - { - // Write out the data. - SInt32 iStart; - int lR; - OSStatus tempStatus; - - HIDPreProcessRIValue(ptReportItem, &nullValue); - - // For a reportItem, there can be multiple identical usages. - for (lR = 0; lR < ptReportItem->usageItemCount; lR++) - { - iStart = ptReportItem->startBit - + (ptReportItem->globals.reportSize * lR); - tempStatus = HIDPutData(report, reportLength, iStart, - ptReportItem->globals.reportSize, nullValue); - if (tempStatus) - iStatus = tempStatus; // Pass on any bad news. - } - } - } // == reportID - } // reportItemCount - - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDIsButtonOrValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDIsButtonOrValue.c deleted file mode 100644 index 5855ef1a6..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDIsButtonOrValue.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDIsButtonOrValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. - <USB2> 3/5/99 BWS [2311366] HIDIsButton should screen out constants (at least - until other functions, like HIDGetButtons, are fixed to be able - to properly skip constants) - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *----------------------------------------------------------------------------- - * - * HIDIsButton - Is the data button(s)? - * - * Input: - * ptReportItem - Input/Output/Feature - * Output: - * Returns: - * Boolean - * - *----------------------------------------------------------------------------- -*/ -Boolean HIDIsButton(HIDReportItem *ptReportItem, HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - -/* - * Disallow Null Pointers -*/ - if (ptReportItem==NULL) - return false; -/* - * Remove items that are constant and have no usage - */ - if ((ptReportItem->dataModes & kHIDDataConstantBit) == kHIDDataConstant) - { - // if has no usages, then bit filler - if (ptReportItem->usageItemCount == 0) - return false; - - // also check to see if there is a usage, but it is zero - - // if the first usage item is range, then check that one - // (we will not worry about report items with multiple zero usages, - // as I dont think that is a case that makes sense) - if (ptReportItem->firstUsageItem < ptPreparsedData->usageItemCount) - { - HIDP_UsageItem * ptUsageItem = &ptPreparsedData->usageItems[ptReportItem->firstUsageItem]; - - // if it is a range usage, with both zero usages - if ((ptUsageItem->isRange && ptUsageItem->usageMinimum == 0 && ptUsageItem->usageMaximum == 0) && - // or not a range, and zero usage - (!ptUsageItem->isRange && ptUsageItem->usage == 0)) - // then this is bit filler - return false; - } - } - -/* - * Arrays and 1-bit Variables -*/ - return (((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray) - || (ptReportItem->globals.reportSize == 1)); -} - -/* - *----------------------------------------------------------------------------- - * - * HIDIsVariable - Is the data variable(s)? - * - * Input: - * ptReportItem - Input/Output/Feature - * Output: - * Returns: - * Boolean - * - *----------------------------------------------------------------------------- -*/ -Boolean HIDIsVariable(HIDReportItem *ptReportItem, HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - -/* - * Disallow Null Pointers -*/ - if (ptReportItem==NULL) - return false; - -/* - * Remove items that are constant and have no usage - */ - if ((ptReportItem->dataModes & kHIDDataConstantBit) == kHIDDataConstant) - { - // if has no usages, then bit filler - if (ptReportItem->usageItemCount == 0) - return false; - - // also check to see if there is a usage, but it is zero - - // if the first usage item is range, then check that one - // (we will not worry about report items with multiple zero usages, - // as I dont think that is a case that makes sense) - if (ptReportItem->firstUsageItem < ptPreparsedData->usageItemCount) - { - HIDP_UsageItem * ptUsageItem = &ptPreparsedData->usageItems[ptReportItem->firstUsageItem]; - - // if it is a range usage, with both zero usages - if ((ptUsageItem->isRange && ptUsageItem->usageMinimum == 0 && ptUsageItem->usageMaximum == 0) && - // or not a range, and zero usage - (!ptUsageItem->isRange && ptUsageItem->usage == 0)) - // then this is bit filler - return false; - } - } - -/* - * Multi-bit Variables -*/ - return (((ptReportItem->dataModes & kHIDDataArrayBit) != kHIDDataArray) - && (ptReportItem->globals.reportSize != 1)); -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDLib.h b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDLib.h deleted file mode 100644 index b727e76d5..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDLib.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDLib.h - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#ifndef __HIDLib__ -#define __HIDLib__ - -#include "HIDPriv.h" - -#define kShouldClearMem true - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Library definitions */ -/* */ -/*------------------------------------------------------------------------------*/ - -/* And now our extern procedures that are not external entry points in our shared library */ - -struct HIDReportDescriptor -{ - Byte * descriptor; - ByteCount descriptorLength; - UInt32 index; - SInt32 * collectionStack; - SInt32 collectionNesting; - HIDGlobalItems * globalsStack; - SInt32 globalsNesting; - HIDItem item; - SInt32 firstUsageItem; - SInt32 firstStringItem; - SInt32 firstDesigItem; - SInt32 parent; - SInt32 sibling; - HIDGlobalItems globals; - Boolean haveUsageMin; - Boolean haveUsageMax; - SInt32 rangeUsagePage; - SInt32 usageMinimum; - SInt32 usageMaximum; - Boolean haveStringMin; - Boolean haveStringMax; - SInt32 stringMinimum; - SInt32 stringMaximum; - Boolean haveDesigMin; - Boolean haveDesigMax; - SInt32 desigMinimum; - SInt32 desigMaximum; -}; -typedef struct HIDReportDescriptor HIDReportDescriptor; - -/* And now our extern procedures that are not external entry points in our shared library */ - -extern OSStatus -HIDCountDescriptorItems (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDNextItem (HIDReportDescriptor * reportDescriptor); - -extern OSStatus -HIDParseDescriptor (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessCollection (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessEndCollection (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessGlobalItem (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessLocalItem (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessMainItem (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -extern OSStatus -HIDProcessReportItem (HIDReportDescriptor * reportDescriptor, - HIDPreparsedDataPtr preparsedData); - -#endif diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDMaxUsageListLength.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDMaxUsageListLength.c deleted file mode 100644 index 9568e0a27..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDMaxUsageListLength.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDMaxUsageListLength.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 3/6/99 BWS Eliminate warning - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDMaxUsageListLength - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * ptPreparsedData - Pre-Parsed Data - * Output: - * Returns: length of list - * - *------------------------------------------------------------------------------ -*/ -UInt32 -HIDMaxUsageListLength (HIDReportType reportType, - HIDUsage usagePage, - HIDPreparsedDataRef preparsedDataRef) -{ -#pragma unused(usagePage) // not used, see comment below - - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDReportItem *ptReportItem; - int iButtons; - int i; - - -/* - * Disallow Null Pointers -*/ - if (ptPreparsedData == NULL) - return 0; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Go through the ReportItems - * Filter on ReportType - * Sum the button counts - * - * NOTE: A more precise value for the maximum list length - * may be obtained by filtering out the usages that - * are not on the specified usage page. Most of - * the time the number returned below is the same - * as that returned by filtering usages. It is - * never smaller. The tradeoff is sometimes wasting - * a few words of RAM in exchange for speed. -*/ - iButtons = 0; - for (i=0; i<ptPreparsedData->reportItemCount; i++) - { - ptReportItem = &ptPreparsedData->reportItems[i]; - if ((ptReportItem->reportType == reportType) - && HIDIsButton(ptReportItem, preparsedDataRef)) - iButtons += ptReportItem->globals.reportCount; - } - return iButtons; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDNextItem.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDNextItem.c deleted file mode 100644 index 59091afe6..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDNextItem.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDNextItem.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (DF) David Ferguson - (JRH) Rhoads Hollowell - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB4> 11/3/99 DF And now I get to add the code to actually fix the checkin below. - <USB3> 11/1/99 BWS Fix long item calc error, fix by Dave Ferguson - <USB2> 6/1/99 JRH Get rid of an uninitialized variable warning. It turns out that - with the code flow it was never being used before being - initialized, but the compiler was complaining. - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *----------------------------------------------------------------------------- - * - * HIDNextItem - Get the Next Item - * - * Input: - * ptDescriptor - Descriptor Structure - * Output: - * ptItem - Caller-provided Item Structure - * Returns: - * kHIDSuccess - Success - * kHIDEndOfDescriptorErr - End of the HID Report Descriptor - * - *----------------------------------------------------------------------------- -*/ -OSStatus HIDNextItem(HIDReportDescriptor *ptDescriptor) -{ - HIDItem *ptItem; - unsigned char iHeader; - unsigned char *psD; - int i; - int iLength; - UInt32 *piX; - int iSize; - int iByte = 0; -/* - * Disallow Null Pointers -*/ - if (ptDescriptor==NULL) - return kHIDNullPointerErr; -/* - * Use local pointers -*/ - ptItem = &ptDescriptor->item; - psD = ptDescriptor->descriptor; - piX = &ptDescriptor->index; - iLength = ptDescriptor->descriptorLength; -/* - * Don't go past the end of the buffer -*/ - if (*piX >= iLength) - return kHIDEndOfDescriptorErr; -/* - * Get the header byte -*/ - iHeader = psD[(*piX)++]; -/* - * Don't go past the end of the buffer -*/ - if (*piX > iLength) - return kHIDEndOfDescriptorErr; - ptItem->itemType = iHeader; - ptItem->itemType &= kHIDItemTypeMask; - ptItem->itemType >>= kHIDItemTypeShift; -/* - * Long Item Header - * Skip Long Items! -*/ - if (iHeader==kHIDLongItemHeader) - { - iSize = psD[(*piX)++]; - ptItem->tag = *piX++; - } -/* - * Short Item Header -*/ - else - { - iSize = iHeader; - iSize &= kHIDItemSizeMask; - if (iSize==3) - iSize = 4; - ptItem->byteCount = iSize; - ptItem->tag = iHeader; - ptItem->tag &= kHIDItemTagMask; - ptItem->tag >>= kHIDItemTagShift; - } -/* - * Don't go past the end of the buffer -*/ - if ((*piX + iSize) > iLength) - return kHIDEndOfDescriptorErr; -/* - * Pick up the data -*/ - ptItem->unsignedValue = 0; - if (iSize==0) - { - ptItem->signedValue = 0; - return kHIDSuccess; - } -/* - * Get the data bytes -*/ - for (i = 0; i < iSize; i++) - { - iByte = psD[(*piX)++]; - ptItem->unsignedValue |= (iByte << (i*8)); - } -/* - * Keep one value unsigned -*/ - ptItem->signedValue = ptItem->unsignedValue; -/* - * Sign extend one value -*/ - if ((iByte & 0x80) != 0) - { - while (i < sizeof(int)) - ptItem->signedValue |= (0xFF << ((i++)*8)); - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDOpenCloseDescriptor.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDOpenCloseDescriptor.c deleted file mode 100644 index a52667e04..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDOpenCloseDescriptor.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDOpenCloseDescriptor.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB2> 3/17/99 BWS [2314839] Added flags field to HIDPreparsedData which is set in - new parameter to HIDOpenReportDescriptor - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -//#include <stdlib.h> - -/* - *------------------------------------------------------------------------------ - * - * HIDCloseReportDescriptor - Close the Descriptor - * - * Input: - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDCloseReportDescriptor(HIDPreparsedDataRef preparsedDataRef) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - OSStatus iStatus; -/* - * Disallow NULL Pointers -*/ - if (ptPreparsedData == NULL) - return kHIDNullPointerErr; -/* - * If it's marked closed then don't do anything -*/ - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Free any memory that was allocated -*/ - if (ptPreparsedData->rawMemPtr != NULL) - { - PoolDeallocate (ptPreparsedData->rawMemPtr, ptPreparsedData->numBytesAllocated); - ptPreparsedData->rawMemPtr = NULL; - } -/* - * Mark closed -*/ - ptPreparsedData->hidTypeIfValid = 0; -/* - * Deallocate the preparsed data -*/ - iStatus = PoolDeallocate (ptPreparsedData, sizeof(HIDPreparsedData)); - - return iStatus; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDOpenReportDescriptor - Initialize the HID Parser - * - * Input: - * psHidReportDescriptor - The HID Report Descriptor (String) - * descriptorLength - Length of the Descriptor in bytes - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus -HIDOpenReportDescriptor (void * hidReportDescriptor, - UInt32 descriptorLength, - HIDPreparsedDataRef * preparsedDataRef, - UInt32 flags) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - OSStatus iStatus; - HIDReportDescriptor tDescriptor; - -/* - * Disallow NULL Pointers -*/ - if ((hidReportDescriptor == NULL) || (preparsedDataRef == NULL)) - return kHIDNullPointerErr; - -/* - * Initialize the return result, and allocate space for preparsed data -*/ - *preparsedDataRef = NULL; - - ptPreparsedData = PoolAllocateResident (sizeof (HIDPreparsedData), kShouldClearMem); - -/* - * Make sure we got the memory -*/ - if (ptPreparsedData == NULL) - return kHIDNotEnoughMemoryErr; - -/* - * Copy the flags field -*/ - ptPreparsedData->flags = flags; -/* - * Initialize the memory allocation pointer -*/ - ptPreparsedData->rawMemPtr = NULL; -/* - * Set up the descriptor structure -*/ - tDescriptor.descriptor = hidReportDescriptor; - tDescriptor.descriptorLength = descriptorLength; -/* - * Count various items in the descriptor - * allocate space within the PreparsedData structure - * and initialize the counters there -*/ - iStatus = HIDCountDescriptorItems(&tDescriptor,ptPreparsedData); - if (iStatus != kHIDSuccess) - return iStatus; -/* - * Parse the Descriptor - * filling in the structures in the PreparsedData structure -*/ - iStatus = HIDParseDescriptor(&tDescriptor,ptPreparsedData); -/* - * Mark the PreparsedData initialized, maybe -*/ - if (iStatus == kHIDSuccess && ptPreparsedData->rawMemPtr != NULL) - { - ptPreparsedData->hidTypeIfValid = kHIDOSType; - *preparsedDataRef = (HIDPreparsedDataRef) ptPreparsedData; - } - else // something failed, deallocate everything, and make sure we return an error - { - if (ptPreparsedData->rawMemPtr != NULL) - PoolDeallocate (ptPreparsedData->rawMemPtr, ptPreparsedData->numBytesAllocated); - - PoolDeallocate (ptPreparsedData, sizeof(HIDPreparsedData)); - - if (iStatus == kHIDSuccess) - iStatus = kHIDNotEnoughMemoryErr; - } - - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDParseDescriptor.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDParseDescriptor.c deleted file mode 100644 index 8de229a6c..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDParseDescriptor.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDParseDescriptor.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -//#include <stdio.h> -/* - *------------------------------------------------------------------------------ - * - * HIDParseDescriptor - Fill in the PreparsedData structures - * - * Input: - * ptDescriptor - Descriptor Pointer Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - * NOTE: HIDCountDescriptorItems MUST have been called to set up the - * array pointers in the HIDPreparsedData structure! - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDParseDescriptor(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - OSStatus iStatus; - HIDItem *ptItem; - HIDCollection *ptCollection; - HIDReportSizes *ptReport; -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Initialize Counters -*/ - ptPreparsedData->collectionCount = 1; - ptPreparsedData->reportItemCount = 0; - ptPreparsedData->reportCount = 1; - ptPreparsedData->usageItemCount = 0; - ptPreparsedData->stringItemCount = 0; - ptPreparsedData->desigItemCount = 0; -/* - * Initialize the Descriptor Data -*/ - ptDescriptor->index = 0; - ptDescriptor->collectionNesting = 0; - ptDescriptor->globalsNesting = 0; - ptDescriptor->firstUsageItem = 0; - ptDescriptor->firstStringItem = 0; - ptDescriptor->firstDesigItem = 0; - ptDescriptor->parent = 0; - ptDescriptor->sibling = 0; - ptDescriptor->globals.usagePage = 0; - ptDescriptor->globals.logicalMinimum = 0; - ptDescriptor->globals.logicalMaximum = 0; - ptDescriptor->globals.physicalMinimum = 0; - ptDescriptor->globals.physicalMaximum = 0; - ptDescriptor->globals.unitExponent = 0; - ptDescriptor->globals.units = 0; - ptDescriptor->globals.reportSize = 0; - ptDescriptor->globals.reportID = 0; - ptDescriptor->globals.reportCount = 0; - ptDescriptor->globals.reportIndex = 0; - ptDescriptor->haveUsageMin = false; - ptDescriptor->haveUsageMax = false; - ptDescriptor->haveStringMin = false; - ptDescriptor->haveStringMax = false; - ptDescriptor->haveDesigMin = false; - ptDescriptor->haveDesigMax = false; - ptItem = &ptDescriptor->item; -/* - * Initialize the virtual collection -*/ - ptCollection = ptPreparsedData->collections; - ptCollection->data = 0; - ptCollection->usagePage = 0; - ptCollection->firstUsageItem = 0; - ptCollection->usageItemCount = 0; - ptCollection->firstReportItem = 0; - ptCollection->reportItemCount = 0; - ptCollection->parent = 0; - ptCollection->children = 0; - ptCollection->firstChild = 0; - ptCollection->nextSibling = 0; -/* - * Initialize the default report -*/ - ptReport = ptPreparsedData->reports; - ptReport->reportID = 0; - ptReport->inputBitCount = 0; - ptReport->outputBitCount = 0; - ptReport->featureBitCount = 0; - -/* - * Parse the Descriptor -*/ - while ((iStatus = HIDNextItem(ptDescriptor)) == kHIDSuccess) - { - switch (ptItem->itemType) - { - case kHIDTypeMain: - iStatus = HIDProcessMainItem(ptDescriptor,ptPreparsedData); - break; - case kHIDTypeGlobal: - iStatus = HIDProcessGlobalItem(ptDescriptor,ptPreparsedData); - break; - case kHIDTypeLocal: - iStatus = HIDProcessLocalItem(ptDescriptor,ptPreparsedData); - break; - } - if (iStatus != kHIDSuccess) - return iStatus; - } - if (iStatus == kHIDEndOfDescriptorErr) - iStatus = kHIDSuccess; -/* - * Update the virtual collection -*/ - ptCollection = ptPreparsedData->collections; - ptCollection->reportItemCount = ptPreparsedData->reportItemCount; -/* - * Mark the PreparsedData initialized -*/ - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPostProcessRIValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPostProcessRIValue.c deleted file mode 100644 index 32c7ca22f..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPostProcessRIValue.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDPostProcessRIValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 4/7/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDPostProcessRIValue - performs any post-processing necessary for data - * retrieved _from_ a report for the specified report - * item. Currently, the only post-processing done - * is reversing when appropriate - * - * Input: - * reportItem - The report item - * value - the value, from HIDGetData - * Output: - * value - The processed value - * Returns: - * kHIDSuccess - Success - * - *------------------------------------------------------------------------------ -*/ - -OSStatus HIDPostProcessRIValue (HIDReportItem * reportItem, - SInt32 * value) -{ - - // if isReversed, returnValue = ((min - returnValue) + max) - if (reportItem->flags & kHIDReportItemFlag_Reversed) - *value = ((reportItem->globals.logicalMinimum - (*value)) + - reportItem->globals.logicalMaximum); - - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDPreProcessRIValue - performs any pre-processing necessary for data - * ouput _to_ a report for the specified report - * item. Currently, the only pre-processing done - * is reversing when appropriate - * - * Input: - * reportItem - The report item - * value - the value, destined for HIDPutData - * Output: - * value - The processed value - * Returns: - * kHIDSuccess - Success - * - *------------------------------------------------------------------------------ -*/ - -OSStatus HIDPreProcessRIValue (HIDReportItem * reportItem, - SInt32 * value) -{ - - // if isReversed, returnValue = ((min - returnValue) + max) - if (reportItem->flags & kHIDReportItemFlag_Reversed) - *value = ((reportItem->globals.logicalMinimum - (*value)) + - reportItem->globals.logicalMaximum); - - return kHIDSuccess; -} - - diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPriv.h b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPriv.h deleted file mode 100644 index 3db02ab6b..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPriv.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef __HIDPriv__ -#define __HIDPriv__ - -/* - File: HIDPriv.i - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <5> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <4> 4/7/99 BWS Add flags to report items (for reverse) - <3> 3/19/99 BWS Build stub library - <2> 3/17/99 BWS [2314839] Add flags field to HIDPreparsedData, is set in - HIDOpenReportDescriptor - <1> 3/5/99 BWS first checked in -*/ - -#include "MacTypes.h" -#include <IOKit/hidsystem/IOHIDDescriptorParser.h> - -/* the following constants are from the USB HID Specification (www.usb.org)*/ - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Header */ -/* */ -/* --------------------------------------------------------- */ -/* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ -/* | Tag | Type | Size | */ -/* --------------------------------------------------------- */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDItemSizeMask = 0x03, - kHIDItemTagMask = 0xF0, - kHIDItemTagShift = 4, - kHIDItemTypeMask = 0x0C, - kHIDItemTypeShift = 2, - kHIDLongItemHeader = 0xFE -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Item Type Definitions */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDTypeMain = 0, - kHIDTypeGlobal = 1, - kHIDTypeLocal = 2, - kHIDTypeLong = 3 -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Item Tag Definitions - Main Items */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDTagInput = 8, - kHIDTagOutput = 9, - kHIDTagCollection = 0x0A, - kHIDTagFeature = 0x0B, - kHIDTagEndCollection = 0x0C -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Item Tag Definitions - Globals */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDTagUsagePage = 0, - kHIDTagLogicalMinimum = 1, - kHIDTagLogicalMaximum = 2, - kHIDTagPhysicalMinimum = 3, - kHIDTagPhysicalMaximum = 4, - kHIDTagUnitExponent = 5, - kHIDTagUnit = 6, - kHIDTagReportSize = 7, - kHIDTagReportID = 8, - kHIDTagReportCount = 9, - kHIDTagPush = 0x0A, - kHIDTagPop = 0x0B -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Item Tag Definitions - Locals */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDTagUsage = 0, - kHIDTagUsageMinimum = 1, - kHIDTagUsageMaximum = 2, - kHIDTagDesignatorIndex = 3, - kHIDTagDesignatorMinimum = 4, - kHIDTagDesignatorMaximum = 5, - kHIDTagStringIndex = 7, - kHIDTagStringMinimum = 8, - kHIDTagStringMaximum = 9, - kHIDTagSetDelimiter = 0x0A -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Main Item Header Bit Definitions */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDDataBufferedBytes = 0x0100, - kHIDDataVolatileBit = 0x80, - kHIDDataVolatile = 0x80, - kHIDDataNullStateBit = 0x40, - kHIDDataNullState = 0x40, - kHIDDataNoPreferredBit = 0x20, - kHIDDataNoPreferred = 0x20, - kHIDDataNonlinearBit = 0x10, - kHIDDataNonlinear = 0x10, - kHIDDataWrapBit = 0x08, - kHIDDataWrap = 0x08, - kHIDDataRelativeBit = 0x04, - kHIDDataRelative = 0x04, - kHIDDataAbsolute = 0x00, - kHIDDataVariableBit = 0x02, - kHIDDataVariable = 0x02, - kHIDDataArrayBit = 0x02, - kHIDDataArray = 0x00, - kHIDDataConstantBit = 0x01, - kHIDDataConstant = 0x01 -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HID Collection Data Definitions */ -/* */ -/*------------------------------------------------------------------------------*/ -enum { - kHIDPhysicalCollection = 0x00, - kHIDApplicationCollection = 0x01 -}; - -/*------------------------------------------------------------------------------*/ -/* */ -/* HIDLibrary private defs */ -/* */ -/*------------------------------------------------------------------------------*/ - -enum -{ - kHIDOSType = 'hid ' -}; - -struct HIDItem -{ - ByteCount byteCount; - SInt32 itemType; - SInt32 tag; - SInt32 signedValue; - UInt32 unsignedValue; -}; -typedef struct HIDItem HIDItem; - -struct HIDGlobalItems -{ - HIDUsage usagePage; - SInt32 logicalMinimum; - SInt32 logicalMaximum; - SInt32 physicalMinimum; - SInt32 physicalMaximum; - SInt32 unitExponent; - SInt32 units; - ByteCount reportSize; - SInt32 reportID; - SInt32 reportCount; - SInt32 reportIndex; -}; -typedef struct HIDGlobalItems HIDGlobalItems; - -struct HIDReportSizes -{ - SInt32 reportID; - SInt32 inputBitCount; - SInt32 outputBitCount; - SInt32 featureBitCount; -}; -typedef struct HIDReportSizes HIDReportSizes; - -struct HIDCollection -{ - SInt32 data; - SInt32 usagePage; - SInt32 firstUsageItem; - SInt32 usageItemCount; - SInt32 firstReportItem; - SInt32 reportItemCount; - SInt32 parent; - SInt32 children; - SInt32 firstChild; - SInt32 nextSibling; -}; -typedef struct HIDCollection HIDCollection; - -enum -{ - kHIDReportItemFlag_Reversed = 0x00000001 -}; - -struct HIDReportItem -{ - UInt32 reportType; - HIDGlobalItems globals; - SInt32 startBit; - SInt32 parent; - SInt32 dataModes; - SInt32 firstUsageItem; - SInt32 usageItemCount; - SInt32 firstStringItem; - SInt32 stringItemCount; - SInt32 firstDesigItem; - SInt32 desigItemCount; - UInt32 flags; -}; -typedef struct HIDReportItem HIDReportItem; - -struct HIDP_UsageItem -{ - Boolean isRange; - Boolean reserved; - HIDUsage usagePage; - HIDUsage usage; - SInt32 usageMinimum; - SInt32 usageMaximum; -}; -typedef struct HIDP_UsageItem HIDP_UsageItem; - -struct HIDStringItem -{ - Boolean isRange; - Boolean reserved; - SInt32 index; - SInt32 minimum; - SInt32 maximum; -}; -typedef struct HIDStringItem HIDStringItem; -typedef HIDStringItem HIDDesignatorItem; - -struct HIDPreparsedData -{ - OSType hidTypeIfValid; - HIDCollection * collections; - UInt32 collectionCount; - HIDReportItem * reportItems; - UInt32 reportItemCount; - HIDReportSizes * reports; - UInt32 reportCount; - HIDP_UsageItem * usageItems; - UInt32 usageItemCount; - HIDStringItem * stringItems; - UInt32 stringItemCount; - HIDDesignatorItem * desigItems; - UInt32 desigItemCount; - UInt8 * rawMemPtr; - UInt32 flags; - ByteCount numBytesAllocated; -}; -typedef struct HIDPreparsedData HIDPreparsedData; -typedef HIDPreparsedData * HIDPreparsedDataPtr; - -extern -OSStatus -HIDCheckReport (HIDReportType reportType, - HIDPreparsedDataRef preparsedDataRef, - HIDReportItem * reportItem, - void * report, - ByteCount reportLength); - - -extern -OSStatus -HIDGetData (void * report, - ByteCount reportLength, - UInt32 start, - UInt32 size, - SInt32 * value, - Boolean signExtend); - -extern -OSStatus -HIDPostProcessRIValue (HIDReportItem * reportItem, - SInt32 * value); - -extern -OSStatus -HIDPreProcessRIValue (HIDReportItem * reportItem, - SInt32 * value); - -extern -Boolean -HIDHasUsage (HIDPreparsedDataRef preparsedDataRef, - HIDReportItem * reportItem, - HIDUsage usagePage, - HIDUsage usage, - UInt32 * usageIndex, - UInt32 * count); - -extern -Boolean -HIDIsButton (HIDReportItem * reportItem, - HIDPreparsedDataRef preparsedDataRef); - -extern -Boolean -HIDIsVariable (HIDReportItem * reportItem, - HIDPreparsedDataRef preparsedDataRef); - -extern -OSStatus -HIDPutData (void * report, - ByteCount reportLength, - UInt32 start, - UInt32 size, - SInt32 value); - -extern -OSStatus -HIDScaleUsageValueIn (HIDReportItem * reportItem, - UInt32 value, - SInt32 * scaledValue); - -extern -OSStatus -HIDScaleUsageValueOut (HIDReportItem * reportItem, - UInt32 value, - SInt32 * scaledValue); - -extern -void -HIDUsageAndPageFromIndex (HIDPreparsedDataRef preparsedDataRef, - HIDReportItem * reportItem, - UInt32 index, - HIDUsageAndPage * usageAndPage); - -extern -Boolean -HIDUsageInRange (HIDP_UsageItem * usageItem, - HIDUsage usagePage, - HIDUsage usage); - -#endif diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessCollection.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessCollection.c deleted file mode 100644 index 93e1b18ad..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessCollection.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDProcessCollection.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessCollection - Process a Collection MainItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessCollection(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - HIDCollection *collections; - HIDCollection *ptCollection; - int parent; - int iCollection; -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Initialize the new Collection Structure -*/ - iCollection = ptPreparsedData->collectionCount++; - collections = ptPreparsedData->collections; - ptCollection = &collections[iCollection]; - ptCollection->data = ptDescriptor->item.unsignedValue; - ptCollection->firstUsageItem = ptDescriptor->firstUsageItem; - ptCollection->usageItemCount = ptPreparsedData->usageItemCount - ptDescriptor->firstUsageItem; - ptDescriptor->firstUsageItem = ptPreparsedData->usageItemCount; - ptCollection->children = 0; - ptCollection->nextSibling = ptDescriptor->sibling; - ptDescriptor->sibling = 0; - ptCollection->firstChild = 0; - ptCollection->usagePage = ptDescriptor->globals.usagePage; - ptCollection->firstReportItem = ptPreparsedData->reportItemCount; -/* - * Set up the relationship with the parent Collection -*/ - parent = ptDescriptor->parent; - ptCollection->parent = parent; - collections[parent].firstChild = iCollection; - collections[parent].children++; - ptDescriptor->parent = iCollection; -/* - * Save the parent Collection Information on the stack -*/ - ptDescriptor->collectionStack[ptDescriptor->collectionNesting++] = parent; - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessEndCollection - Process an EndCollection MainItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessEndCollection(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - HIDCollection *ptCollection; - int iCollection; -/* - * Remember the number of ReportItem MainItems in this Collection -*/ - ptCollection = &ptPreparsedData->collections[ptDescriptor->parent]; - ptCollection->reportItemCount = ptPreparsedData->reportItemCount - ptCollection->firstReportItem; -/* - * Restore the parent Collection Data -*/ - iCollection = ptDescriptor->collectionStack[--ptDescriptor->collectionNesting]; - ptDescriptor->sibling = ptDescriptor->parent; - ptDescriptor->parent = iCollection; - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessGlobalItem.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessGlobalItem.c deleted file mode 100644 index 5764b6141..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessGlobalItem.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDProcessGlobalItem.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (DF) David Ferguson - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB2> 10/18/99 DF Lets try not reporting an error with zero report count - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessGlobalItem - Process a GlobalItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessGlobalItem(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - HIDReportSizes *ptReport; - HIDGlobalItems *ptGlobals; - HIDItem *ptItem; - int reportIndex; -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Process by tag -*/ - ptItem = &ptDescriptor->item; - ptGlobals = &ptDescriptor->globals; - switch (ptItem->tag) - { -/* - * usage Page -*/ - case kHIDTagUsagePage: - if (ptItem->unsignedValue == 0) - return kHIDUsagePageZeroErr; - ptGlobals->usagePage = ptItem->unsignedValue; - break; -/* - * Logical Minimum -*/ - case kHIDTagLogicalMinimum: - ptGlobals->logicalMinimum = ptItem->signedValue; - break; -/* - * Logical Maximum -*/ - case kHIDTagLogicalMaximum: - ptGlobals->logicalMaximum = ptItem->signedValue; - break; -/* - * Physical Minimum -*/ - case kHIDTagPhysicalMinimum: - ptGlobals->physicalMinimum = ptItem->signedValue; - break; -/* - * Physical Maximum -*/ - case kHIDTagPhysicalMaximum: - ptGlobals->physicalMaximum = ptItem->signedValue; - break; -/* - * Unit Exponent -*/ - case kHIDTagUnitExponent: - ptGlobals->unitExponent = ptItem->signedValue; - break; -/* - * Unit -*/ - case kHIDTagUnit: - ptGlobals->units = ptItem->unsignedValue; - break; -/* - * Report Size in Bits -*/ - case kHIDTagReportSize: - ptGlobals->reportSize = ptItem->unsignedValue; - if (ptGlobals->reportSize == 0) - return kHIDReportSizeZeroErr; - break; -/* - * Report ID -*/ - case kHIDTagReportID: - if (ptItem->unsignedValue == 0) - return kHIDReportIDZeroErr; -/* - * Look for the Report ID in the table -*/ - reportIndex = 0; - while ((reportIndex < ptPreparsedData->reportCount) - && (ptPreparsedData->reports[reportIndex].reportID != ptItem->unsignedValue)) - reportIndex++; -/* - * Initialize the entry if it's new and there's room for it - * Start with 8 bits for the Report ID -*/ - if (reportIndex == ptPreparsedData->reportCount) - { - ptReport = &ptPreparsedData->reports[ptPreparsedData->reportCount++]; - ptReport->reportID = ptItem->unsignedValue; - ptReport->inputBitCount = 8; - ptReport->outputBitCount = 8; - ptReport->featureBitCount = 8; - } -/* - * Remember which report is being processed -*/ - ptGlobals->reportID = ptItem->unsignedValue; - ptGlobals->reportIndex = reportIndex; - break; -/* - * Report Count -*/ - case kHIDTagReportCount: -#if 0 - // some device actually have a report count of zero specified. we must allow it! - if (ptItem->unsignedValue == 0) - return kHIDReportCountZeroErr; -#endif - ptGlobals->reportCount = ptItem->unsignedValue; - break; -/* - * Push Globals -*/ - case kHIDTagPush: - ptDescriptor->globalsStack[ptDescriptor->globalsNesting++] = ptDescriptor->globals; - break; -/* - * Pop Globals -*/ - case kHIDTagPop: - ptDescriptor->globals = ptDescriptor->globalsStack[--ptDescriptor->globalsNesting]; - break; - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c deleted file mode 100644 index c67f05a24..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDProcessLocalItem.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessLocalItem - Process a LocalItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessLocalItem(HIDReportDescriptor *ptDescriptor, - HIDPreparsedDataPtr ptPreparsedData) -{ - HIDDesignatorItem *ptDesignatorItem; - HIDStringItem *ptStringItem; - HIDP_UsageItem *ptUsageItem; - HIDItem *ptItem; -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Process the LocalItem by tag -*/ - ptItem = &ptDescriptor->item; - switch (ptItem->tag) - { -/* - * Note that Tag = usage Item may represent either - * a UsagePair with the usagePage implied, or - * a UsagePair defined by an extended usage - * If a Tag = usage Item has 1 or 2 bytes of data - * then the current usagePage is used - * If a Tag = usage Item has 4 bytes of data - * then the high order bytes are the usagePage - * - * Note that the Microsoft HID Parser uses the last - * usagePage defined before the MainItem with which - * the usage is associated rather than the current - * usagePage. The method used here is more generic - * although multiple UsagePages for a MainItem are - * unlikely due to the MS limitation. -*/ - case kHIDTagUsage: - ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; - ptUsageItem->isRange = false; - if (ptItem->byteCount == 4) - { - ptUsageItem->usagePage = ptItem->unsignedValue>>16; - ptUsageItem->usage = ptItem->unsignedValue&0xFFFFL; - } - else - { - ptUsageItem->usagePage = ptDescriptor->globals.usagePage; - ptUsageItem->usage = ptItem->unsignedValue; - } - break; -/* - * Note that Tag = usage Minimum Item may represent either - * a UsagePair with the usagePage implied, or - * a UsagePair defined by an extended usage - * If a Tag = usage Item has 1 or 2 bytes of data - * then the current usagePage is used - * If a Tag = usage Item has 4 bytes of data - * then the high order bytes are the usagePage -*/ - case kHIDTagUsageMinimum: - if (ptDescriptor->haveUsageMax) - { - ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; - ptUsageItem->isRange = true; - if (ptItem->byteCount == 4) - { - ptUsageItem->usagePage = ptItem->unsignedValue>>16; - ptUsageItem->usageMinimum = ptItem->unsignedValue&0xFFFFL; - } - else - { - ptUsageItem->usagePage = ptDescriptor->globals.usagePage; - ptUsageItem->usageMinimum = ptItem->unsignedValue; - } - if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage) - return kHIDInvalidRangePageErr; - ptUsageItem->usageMaximum = ptDescriptor->usageMaximum; - if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum) - return kHIDInvertedUsageRangeErr; - ptDescriptor->haveUsageMax = false; - ptDescriptor->haveUsageMin = false; - } - else - { - if (ptItem->byteCount == 4) - { - ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16; - ptDescriptor->usageMinimum = ptItem->unsignedValue&0xFFFFL; - } - else - { - ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage; - ptDescriptor->usageMinimum = ptItem->unsignedValue; - } - ptDescriptor->haveUsageMin = true; - } - break; -/* - * Note that Tag = usage Maximum Item may represent either - * a UsagePair with the usagePage implied, or - * a UsagePair defined by an extended usage - * If a Tag = usage Item has 1 or 2 bytes of data - * then the current usagePage is used - * If a Tag = usage Item has 4 bytes of data - * then the high order bytes are the usagePage -*/ - case kHIDTagUsageMaximum: - if (ptDescriptor->haveUsageMin) - { - ptUsageItem = &ptPreparsedData->usageItems[ptPreparsedData->usageItemCount++]; - ptUsageItem->isRange = true; - if (ptItem->byteCount == 4) - { - ptUsageItem->usagePage = ptItem->unsignedValue>>16; - ptUsageItem->usageMaximum = ptItem->unsignedValue&0xFFFFL; - } - else - { - ptUsageItem->usagePage = ptDescriptor->globals.usagePage; - ptUsageItem->usageMaximum = ptItem->unsignedValue; - } - if (ptUsageItem->usagePage != ptDescriptor->rangeUsagePage) - return kHIDInvalidRangePageErr; - ptUsageItem->usageMinimum = ptDescriptor->usageMinimum; - if (ptUsageItem->usageMaximum < ptUsageItem->usageMinimum) - return kHIDInvertedUsageRangeErr; - ptDescriptor->haveUsageMax = false; - ptDescriptor->haveUsageMin = false; - } - else - { - if (ptItem->byteCount == 4) - { - ptDescriptor->rangeUsagePage = ptItem->unsignedValue>>16; - ptDescriptor->usageMaximum = ptItem->unsignedValue&0xFFFFL; - } - else - { - ptDescriptor->rangeUsagePage = ptDescriptor->globals.usagePage; - ptDescriptor->usageMaximum = ptItem->unsignedValue; - } - ptDescriptor->haveUsageMax = true; - } - break; -/* - * Designators -*/ - case kHIDTagDesignatorIndex: - ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; - ptDesignatorItem->isRange = false; - ptDesignatorItem->index = ptItem->unsignedValue; - break; - case kHIDTagDesignatorMinimum: - if (ptDescriptor->haveDesigMax) - { - ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; - ptDesignatorItem->isRange = true; - ptDesignatorItem->minimum = ptItem->unsignedValue; - ptDesignatorItem->maximum = ptDescriptor->desigMaximum; - ptDescriptor->haveDesigMin = false; - ptDescriptor->haveDesigMax = false; - } - else - { - ptDescriptor->desigMinimum = ptItem->unsignedValue; - ptDescriptor->haveDesigMin = true; - } - break; - case kHIDTagDesignatorMaximum: - if (ptDescriptor->haveDesigMin) - { - ptDesignatorItem = &ptPreparsedData->desigItems[ptPreparsedData->desigItemCount++]; - ptDesignatorItem->isRange = true; - ptDesignatorItem->maximum = ptItem->unsignedValue; - ptDesignatorItem->minimum = ptDescriptor->desigMinimum; - ptDescriptor->haveDesigMin = false; - ptDescriptor->haveDesigMax = false; - } - else - { - ptDescriptor->desigMaximum = ptItem->unsignedValue; - ptDescriptor->haveDesigMax = true; - } - break; -/* - * Strings -*/ - case kHIDTagStringIndex: - ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; - ptStringItem->isRange = false; - ptStringItem->index = ptItem->unsignedValue; - break; - case kHIDTagStringMinimum: - if (ptDescriptor->haveStringMax) - { - ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; - ptStringItem->isRange = true; - ptStringItem->minimum = ptItem->unsignedValue; - ptStringItem->maximum = ptDescriptor->stringMaximum; - ptDescriptor->haveStringMin = false; - ptDescriptor->haveStringMax = false; - } - else - { - ptDescriptor->stringMinimum = ptItem->unsignedValue; - ptDescriptor->haveStringMin = true; - } - break; - case kHIDTagStringMaximum: - if (ptDescriptor->haveStringMin) - { - ptStringItem = &ptPreparsedData->stringItems[ptPreparsedData->stringItemCount++]; - ptStringItem->isRange = true; - ptStringItem->maximum = ptItem->unsignedValue; - ptStringItem->minimum = ptDescriptor->stringMinimum; - ptDescriptor->haveStringMin = false; - ptDescriptor->haveStringMax = false; - } - else - { - ptDescriptor->stringMaximum = ptItem->unsignedValue; - ptDescriptor->haveStringMax = true; - } - break; -/* - * Delimiters (are not processed) -*/ - case kHIDTagSetDelimiter: - break; - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessMainItem.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessMainItem.c deleted file mode 100644 index 2bc2cd36c..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessMainItem.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDProcessMainItem.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessMainItem - Process a MainItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessMainItem(HIDReportDescriptor *ptDescriptor, - HIDPreparsedDataPtr ptPreparsedData) -{ - OSStatus iStatus = kHIDSuccess; - -/* - * Disallow NULL Pointers -*/ - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Process by MainItem Tag -*/ - switch (ptDescriptor->item.tag) - { - case kHIDTagCollection: - iStatus = HIDProcessCollection(ptDescriptor,ptPreparsedData); - break; - case kHIDTagEndCollection: - iStatus = HIDProcessEndCollection(ptDescriptor,ptPreparsedData); - break; - case kHIDTagInput: - case kHIDTagOutput: - case kHIDTagFeature: - iStatus = HIDProcessReportItem(ptDescriptor,ptPreparsedData); - break; - } - return iStatus; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c deleted file mode 100644 index 7d81b9ecc..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDProcessReportItem.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (DF) David Ferguson - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB10> 1/11/00 KH Tweaking last fix. For logical maximum, limit shifting into the - sign bit only for report sizes of 32 bits or greater. - <USB9> 1/10/00 DF re-do last change (better fix). - <USB8> 1/10/00 DF do proper logical range test for 32-bit report items. - <USB7> 4/7/99 BWS Add support for reversed report items - <USB6> 3/20/99 BWS Oops, strict error checking does not work if there is no error. - We should only return error if it is not noErr - <USB5> 3/17/99 BWS [2314839] Added flags field to HIDPreparsedData which is set in - new parameter to HIDOpenReportDescriptor. We check the - StrictErrorCheck bit to determine whether we return errors or - just try to work around problems we find - <USB4> 3/7/99 BWS [2311413] Do not error check min/max ranges for constants - <USB3> 3/7/99 BWS [2311412] We need to handle the cases where physical min/max is - either (0/0) which is valid according to the spec, and means to - use the logical min/max, and the invalid case, that some devices - exibit, which has (0/-1) which we will treat the same, - <USB2> 3/5/99 BWS [2311359] HIDProcessReportItem does not initialize startBit - field of HIDReportItem! - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDProcessReportItem - Process a Report Item MainItem - * - * Input: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Output: - * ptDescriptor - The Descriptor Structure - * ptPreparsedData - The PreParsedData Structure - * Returns: - * kHIDSuccess - Success - * kHIDNullPointerErr - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDProcessReportItem(HIDReportDescriptor *ptDescriptor, HIDPreparsedDataPtr ptPreparsedData) -{ - OSStatus error = noErr; - HIDReportItem *ptReportItem; - HIDReportSizes *ptReport; - int iBits; -/* - * Disallow NULL Pointers -*/ - - if ((ptDescriptor == NULL) || (ptPreparsedData == NULL)) - return kHIDNullPointerErr; -/* - * Begin to initialize the new Report Item structure -*/ - - ptReportItem = &ptPreparsedData->reportItems[ptPreparsedData->reportItemCount++]; - ptReportItem->dataModes = ptDescriptor->item.unsignedValue; - ptReportItem->globals = ptDescriptor->globals; - ptReportItem->flags = 0; - -/* - * Reality Check on the Report Main Item -*/ - // Don't check ranges for constants (MS Sidewinder, for one, does not reset) - //if (!(ptReportItem->dataModes & kHIDDataConstantBit)) // don't think we need this anymore - { - // Determine the maximum signed value for a given report size. - // (Don't allow shifting into sign bit.) - SInt32 posSize = (ptReportItem->globals.reportSize >= 32) ? - 31 : ptReportItem->globals.reportSize; - SInt32 realMax = (1<<posSize) - 1; - - if (ptReportItem->globals.logicalMinimum > realMax) - { - error = kHIDBadLogicalMinimumErr; - ptReportItem->globals.logicalMinimum = 0; - } - if (ptReportItem->globals.logicalMaximum > realMax) - { - if (error == noErr) - error = kHIDBadLogicalMaximumErr; - ptReportItem->globals.logicalMaximum = realMax; - } - if (ptReportItem->globals.logicalMinimum > ptReportItem->globals.logicalMaximum) - { - SInt32 temp; - if (error == noErr) - error = kHIDInvertedLogicalRangeErr; - - // mark as a 'reversed' item - ptReportItem->flags |= kHIDReportItemFlag_Reversed; - - temp = ptReportItem->globals.logicalMaximum; - ptReportItem->globals.logicalMaximum = ptReportItem->globals.logicalMinimum; - ptReportItem->globals.logicalMinimum = temp; - } - } - - // check to see if we got half a range (we don't need to fix this, since 'isRange' will be false - if ((error == noErr) && (ptDescriptor->haveUsageMin || ptDescriptor->haveUsageMax)) - error = kHIDUnmatchedUsageRangeErr; - if ((error == noErr) && (ptDescriptor->haveStringMin || ptDescriptor->haveStringMax)) - error = kHIDUnmatchedStringRangeErr; - if ((error == noErr) && (ptDescriptor->haveDesigMin || ptDescriptor->haveDesigMax)) - error = kHIDUnmatchedDesignatorRangeErr; - - // if the physical min/max are out of wack, use the logical values - if (ptReportItem->globals.physicalMinimum >= ptReportItem->globals.physicalMaximum) - { - // equal to each other is not an error, just means to use the logical values - if ((error == noErr) && - (ptReportItem->globals.physicalMinimum > ptReportItem->globals.physicalMaximum)) - error = kHIDInvertedPhysicalRangeErr; - - ptReportItem->globals.physicalMinimum = ptReportItem->globals.logicalMinimum; - ptReportItem->globals.physicalMaximum = ptReportItem->globals.logicalMaximum; - } - - // if strict error checking is true, return any errors - if (error != noErr && ptPreparsedData->flags & kHIDFlag_StrictErrorChecking) - return error; - -/* - * Continue to initialize the new Report Item structure -*/ - - ptReportItem->parent = ptDescriptor->parent; - ptReportItem->firstUsageItem = ptDescriptor->firstUsageItem; - ptDescriptor->firstUsageItem = ptPreparsedData->usageItemCount; - ptReportItem->usageItemCount = ptPreparsedData->usageItemCount - ptReportItem->firstUsageItem; - ptReportItem->firstStringItem = ptDescriptor->firstStringItem; - ptDescriptor->firstStringItem = ptPreparsedData->stringItemCount; - ptReportItem->stringItemCount = ptPreparsedData->stringItemCount - ptReportItem->firstStringItem; - ptReportItem->firstDesigItem = ptDescriptor->firstDesigItem; - ptDescriptor->firstDesigItem = ptPreparsedData->desigItemCount; - ptReportItem->desigItemCount = ptPreparsedData->desigItemCount - ptReportItem->firstDesigItem; -/* - * Update the Report by the size of this item -*/ - - ptReport = &ptPreparsedData->reports[ptReportItem->globals.reportIndex]; - iBits = ptReportItem->globals.reportSize * ptReportItem->globals.reportCount; - switch (ptDescriptor->item.tag) - { - case kHIDTagFeature: - ptReportItem->reportType = kHIDFeatureReport; - ptReportItem->startBit = ptReport->featureBitCount; - ptReport->featureBitCount += iBits; - break; - case kHIDTagOutput: - ptReportItem->reportType = kHIDOutputReport; - ptReportItem->startBit = ptReport->outputBitCount; - ptReport->outputBitCount += iBits; - break; - case kHIDTagInput: - ptReportItem->reportType = kHIDInputReport; - ptReportItem->startBit = ptReport->inputBitCount; - ptReport->inputBitCount += iBits; - break; - default: - ptReportItem->reportType = kHIDUnknownReport; - ptReportItem->startBit = 0; - break; - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPutData.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPutData.c deleted file mode 100644 index 3eceaac1c..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPutData.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDPutData.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - (KH) Keithen Hayenga - - Change History (most recent first): - - <USB3> 12/12/00 KH Correcct cast of void * - <USB2> 11/11/99 KH Use shifted value when HIDSetUsageValue fills data into a report - field that spans multiple bytes. - <USB2> 11/10/99 KH Data that overflowed byte bounderies was lost because - we shifted initial value instead of value corrected for - starting bit location. - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -//#include <stdio.h> - -/* - *------------------------------------------------------------------------------ - * - * HIDPutData - Put a single data item to a report - * - * Input: - * psReport - The report - * iReportLength - The length of the report - * iStart - Start Bit in report - * iSize - Number of Bits - * iValue - The data - * Output: - * Returns: - * kHidP_Success - Success - * kHidP_NullPointer - Argument, Pointer was Null - * - *------------------------------------------------------------------------------ -*/ -OSStatus -HIDPutData (void * report, - ByteCount reportLength, - UInt32 start, - UInt32 size, - SInt32 value) -{ - Byte * psReport = (Byte *)report; - SInt32 data, iShiftedData; - UInt32 iStartByte, startBit; - UInt32 iLastByte, iLastBit; - UInt32 iStartMask, iLastMask; - UInt32 iDataMask; -/* - * Report - * Bit 28 27 26 25 24 | 23 22 21 20 19 18 17 16 | 15 14 13 12 11 10 09 ... - * Last Byte (3) | | Byte 2 | | Start Byte (1) - * Data x x x d d | d d d d d d d d | d d y y y y y - * Last Bit (1) / | | \ Start Bit (6) - * ... 1 1 1 0 0 | Intermediate | 0 0 1 1 1 1 1 ... - * Last Mask | Byte(s) | StartMask -*/ - iLastByte = (start + size - 1)/8; -/* - * Check the parameters -*/ - if ((start < 0) || (size <= 0) || (iLastByte >= reportLength)) - return kHIDBadParameterErr; - iLastBit = (start + size - 1)&7; - iLastMask = ~((1<<(iLastBit+1)) - 1); - iStartByte = start/8; - startBit = start&7; - iStartMask = (1<<startBit) - 1; -/* - * If the data is contained in one byte then - * handle it differently - * Mask off just the area where the new data goes - * Shift the data over to its new location - * Mask the data for its new location - * Or in the data -*/ - if (iStartByte == iLastByte) - { - data = psReport[iStartByte]; - iDataMask = iStartMask | iLastMask; - data &= iDataMask; - iShiftedData = value << startBit; - iShiftedData &= ~iDataMask; - data |= iShiftedData; - } -/* - * If the data is in more than one byte then - * Do the start byte first - * Mask off the bits where the new data goes - * Shift the new data over to the start of field - * Or the two together and store back out -*/ - else - { - data = psReport[iStartByte]; - data &= iStartMask; - iShiftedData = value << startBit; - data |= iShiftedData; - psReport[iStartByte] = (Byte) data; - iShiftedData >>= 8; -/* - * Store out an intermediate bytes -*/ - while (++iStartByte < iLastByte) - { - psReport[iStartByte] = (Byte) iShiftedData; - iShiftedData >>= 8; - } -/* - * Mask off the bits where the new data goes - * Mask off the bits in the new data where the old goes - * Or the two together and store back out -*/ - data = psReport[iLastByte]; - data &= iLastMask; - iShiftedData &= ~iLastMask; - data |= iShiftedData; - } -/* - * Store out the last or only Byte -*/ - psReport[iStartByte] = (Byte) data; - return kHIDSuccess; -} - diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDScaleUsageValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDScaleUsageValue.c deleted file mode 100644 index 842453e8e..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDScaleUsageValue.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDScaleUsageValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDScaleUsageValueIn - * - * Input: - * ptReportItem - The ReportItem in which the data resides - * iValue - The unscaled data - * piScaledValue - The scaled value - * Output: - * piScaledValue - The scaled value - * Returns: - * kHIDSuccess - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDScaleUsageValueIn (HIDReportItem *ptReportItem, UInt32 iValue, SInt32 *piScaledValue) -{ - long int lData; - long int lDeltaL; - long int lDeltaP; - long int lL, lP; - long int lScaledData; - long int lLMin, lLMax; -/* - * Disallow Null Pointers -*/ - if ((ptReportItem == NULL) || (piScaledValue == NULL)) - return kHIDNullPointerErr; -/* - * Convert the data to Long Integer -*/ - lData = iValue; -/* - * range check the Logical Value -*/ - lLMax = ptReportItem->globals.logicalMaximum; - lLMin = ptReportItem->globals.logicalMinimum; - if ((lData < lLMin) || (lData > lLMax)) - { - if ((ptReportItem->dataModes & kHIDDataNullStateBit) == kHIDDataNullState) - return kHIDNullStateErr; - return kHIDValueOutOfRangeErr; - } -/* - * (PhysicalValue - PhysicalMinimum)/(PhysicalMaximum - PhysicalMinimum) - * = (LogicalValue - LogicalMinimum)/(LogicalMaximum - LogicalMinimum) - * - * Calculate the ranges - * Zero ranges are invalid! - * lDeltaL = (LogicalMaximum - LogicalMinimum) - * lDeltaP = (PhysicalMaximum - PhysicalMinimum) -*/ - lDeltaL = lLMax - lLMin; - lDeltaP = ptReportItem->globals.physicalMaximum - ptReportItem->globals.physicalMinimum; - if ((lDeltaL == 0) || (lDeltaP == 0)) - return kHIDBadLogPhysValuesErr; -/* - * (PhysicalValue - PhysicalMinimum)/lDeltaP - * = (LogicalValue - LogicalMinimum)/lDeltaL - * lL = (LogicalValue - LogicalMinimum) -*/ - lL = lData - ptReportItem->globals.logicalMinimum; -/* - * (PhysicalValue - PhysicalMinimum)/lDeltaP = lL/lDeltaL - * (PhysicalValue - PhysicalMinimum) = (lDeltaP * lL)/lDeltaL - * lP = (PhysicalValue - PhysicalMinimum) = (lDeltaP * lL)/lDeltaL -*/ - lP = (lL* lDeltaP)/lDeltaL; -/* - * lP = (PhysicalValue - PhysicalMinimum) - * PhysicalValue = lP + PhysicalMinimum; -*/ - lScaledData = lP + ptReportItem->globals.physicalMinimum; - *piScaledValue = (int) lScaledData; - return kHIDSuccess; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDScaleUsageValueOut - * - * Input: - * ptReportItem - The ReportItem in which the data will go - * iValue - The unscaled data - * piScaledValue - The scaled value - * Output: - * piScaledValue - The scaled value - * Returns: - * kHIDSuccess - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDScaleUsageValueOut (HIDReportItem *ptReportItem, UInt32 iValue, SInt32 *piScaledValue) -{ - long int lData; - long int lDeltaL; - long int lDeltaP; - long int lL, lP; - long int lPMax, lPMin; -/* - * Convert the data to Long Integer -*/ - lData = iValue; -/* - * range check the Logical Value -*/ - lPMax = ptReportItem->globals.physicalMaximum; - lPMin = ptReportItem->globals.physicalMinimum; - if ((lData < lPMin) || (lData > lPMax)) - { - if ((ptReportItem->dataModes & kHIDDataNullStateBit) == kHIDDataNullState) - return kHIDNullStateErr; - return kHIDValueOutOfRangeErr; - } -/* - * (PhysicalValue - PhysicalMinimum)/(PhysicalMaximum - PhysicalMinimum) - * = (LogicalValue - LogicalMinimum)/(LogicalMaximum - LogicalMinimum) - * - * Calculate the ranges - * Zero ranges are invalid! - * lDeltaL = (LogicalMaximum - LogicalMinimum) - * lDeltaP = (PhysicalMaximum - PhysicalMinimum) -*/ - lDeltaL = ptReportItem->globals.logicalMaximum - ptReportItem->globals.logicalMinimum; - lDeltaP = ptReportItem->globals.physicalMaximum - ptReportItem->globals.physicalMinimum; - if ((lDeltaL == 0) || (lDeltaP == 0)) - return kHIDBadLogPhysValuesErr; -/* - * (PhysicalValue - PhysicalMinimum)/lDeltaP - * = (LogicalValue - LogicalMinimum)/lDeltaL - * lP = (PhysicalValue - PhysicalMinimum) -*/ - lP = lData - ptReportItem->globals.physicalMinimum; -/* - * (LogicalValue - LogicalMinimum)/lDeltaL = lP/lDeltaP - * (LogicalValue - LogicalMinimum)/lDeltaL = (lDeltaL * lP)/lDeltaP - * lL = (LogicalValue - LogicalMinimum) = (lDeltaL * lP)/lDeltaP -*/ - lL = (lP* lDeltaL)/lDeltaP; -/* - * lL = (LogicalValue - LogicalMinimum) - * LogicalValue = lL + LogicalMinimum; -*/ - lData = lL + ptReportItem->globals.logicalMinimum; - *piScaledValue = (int) lData; - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetButtons.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetButtons.c deleted file mode 100644 index b13e73685..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetButtons.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDSetButtons.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDSetButton - Set the state of a button for a Page - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - Usages for pressed button - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDSetButton (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR, iX; - SInt32 data; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - Boolean bIncompatibleReport = false; - Boolean butNotReally = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (report == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((collection < 0) || (collection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[collection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsButton(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) - { -/* - * This may be the proper data to get - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem,report,reportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { - butNotReally = true; -/* - * Save Arrays -*/ - if ((ptReportItem->dataModes & kHIDDataArrayBit) == kHIDDataArray) - { - for (iX=0; iX<ptReportItem->globals.reportCount; iX++) - { - iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iX); - iStatus = HIDGetData(report, reportLength, iStart, - ptReportItem->globals.reportSize, &data, true); - if (!iStatus) - iStatus = HIDPostProcessRIValue (ptReportItem, &data); - if (iStatus != kHIDSuccess) - return iStatus; - // if not already in the list, add it (is this code right??) - if (data == 0) - return HIDPutData(report, reportLength, iStart, - ptReportItem->globals.reportSize, - iUsageIndex + ptReportItem->globals.logicalMinimum); - } - return kHIDBufferTooSmallErr; - } -/* - * Save Bitmaps -*/ - else if (ptReportItem->globals.reportSize == 1) - { - iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); - // should we call HIDPreProcessRIValue here? - // we are passing '-1' as trhe value, is this right? Some hack to set the right bit to 1? - iStatus = HIDPutData(report, reportLength, iStart, ptReportItem->globals.reportSize, -1); - if (iStatus != kHIDSuccess) - return iStatus; - return kHIDSuccess; - } - } - } - } - // If any of the report items were not the right type, we have set the bIncompatibleReport flag. - // However, if any of the report items really were the correct type, we have done our job of checking - // and really didn't find a usage. Don't let the bIncompatibleReport flag wipe out our valid test. - if (bIncompatibleReport && !butNotReally) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDSetButtons - Set the state of the buttons for a Page - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * collection - Collection Criteria or zero - * piUsageList - Usages for pressed buttons - * piUsageListLength - Max entries in UsageList - * ptPreparsedData - Pre-Parsed Data - * report - An HID Report - * reportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus -HIDSetButtons (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage * usageList, - UInt32 * usageListSize, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - OSStatus iStatus; - int iUsages; - int usage; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (usageList == NULL) - || (usageListSize == NULL) - || (report == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * Save the usage List Length -*/ - iUsages = *usageListSize; -/* - * Write them out one at a time -*/ - for (usage=0; usage<iUsages; usage++) - { - *usageListSize = usage; - iStatus = HIDSetButton(reportType, usagePage, collection, - usageList[usage], preparsedDataRef, - report, reportLength); - if (iStatus != kHIDSuccess) - return iStatus; - } - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetScaledUsageValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetScaledUsageValue.c deleted file mode 100644 index 46fabf8f9..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetScaledUsageValue.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDSetScaledUsageValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDSetScaledUsageValue - Set the value for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * iValue - The usage Value - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDSetScaledUsageValue(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - SInt32 iUsageValue, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - ByteCount iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR; - SInt32 data; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if ((ptReportItem->reportType == reportType) - && HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) - { -/* - * This may be the proper place to write data - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem,psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { - iStatus = HIDScaleUsageValueOut(ptReportItem,iUsageValue,&data); - if (iStatus != kHIDSuccess) - return iStatus; - iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); - iStatus = HIDPreProcessRIValue (ptReportItem, &data); - iStatus = HIDPutData(psReport, iReportLength, iStart, ptReportItem->globals.reportSize, data); - if (iStatus != kHIDSuccess) - return iStatus; - return kHIDSuccess; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValue.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValue.c deleted file mode 100644 index 06a9e9438..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValue.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDSetUsageValue.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDSetUsageValue - Set the value for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria or zero - * iCollection - Collection Criteria or zero - * usage - usage Criteria or zero - * iValue - The usage Value - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDSetUsageValue(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - SInt32 iUsageValue, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - ByteCount iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int iR; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,NULL)) - { -/* - * This may be the proper place - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { -/* - * Write out the data -*/ - iStart = ptReportItem->startBit - + (ptReportItem->globals.reportSize * iUsageIndex); - iStatus = HIDPreProcessRIValue (ptReportItem, &iUsageValue); - iStatus = HIDPutData(psReport, iReportLength, iStart, - ptReportItem->globals.reportSize, iUsageValue); - if (iStatus != kHIDSuccess) - return iStatus; - return kHIDSuccess; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValueArray.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValueArray.c deleted file mode 100644 index 29c5ab2cc..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValueArray.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDSetUsageValueArray.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2001 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB5> 1/18/01 KH Fix for complex descriptors only needed for buttons. - <USB4> 3/24/00 KH Complex report descriptors could lead to reporting - kHIDUsageNotFoundErr's as kHIDIncompatibleReportErr's instead. - <USB3> 11/1/99 BWS [2405720] We need a better check for 'bit padding' items, - rather than just is constant. We will check to make sure the - item is constant, and has no usage, or zero usage. This means we - need to pass an additional parameter to some internal functions - <USB2> 4/7/99 BWS Add support for reversed report items - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDSetUsageValueArray - Set the values for a usage - * - * Input: - * reportType - HIDP_Input, HIDP_Output, HIDP_Feature - * usagePage - Page Criteria - * iCollection - Collection Criteria or zero - * usage - usage Criteria - * psBuffer - Pointer to usage Buffer - * iByteLength - Length of usage Buffer - * ptPreparsedData - Pre-Parsed Data - * psReport - An HID Report - * iReportLength - The length of the Report - * Output: - * piValue - Pointer to usage Value - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDSetUsageValueArray(HIDReportType reportType, - HIDUsage usagePage, - UInt32 iCollection, - HIDUsage usage, - UInt8 *psUsageBuffer, - UInt32 iByteLength, - HIDPreparsedDataRef preparsedDataRef, - void *psReport, - UInt32 iReportLength) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDCollection *ptCollection; - HIDReportItem *ptReportItem; - OSStatus iStatus; - int i; - int iR; - long iValue; - int iStart; - int iReportItem; - UInt32 iUsageIndex; - UInt32 iCount; - int byteCount; - Boolean bIncompatibleReport = false; -/* - * Disallow Null Pointers -*/ - if ((ptPreparsedData == NULL) - || (psUsageBuffer == NULL) - || (psReport == NULL)) - return kHIDNullPointerErr; - if (ptPreparsedData->hidTypeIfValid != kHIDOSType) - return kHIDInvalidPreparsedDataErr; -/* - * The Collection must be in range -*/ - if ((iCollection < 0) || (iCollection >= ptPreparsedData->collectionCount)) - return kHIDBadParameterErr; -/* - * Search only the scope of the Collection specified - * Go through the ReportItems - * Filter on ReportType and usagePage -*/ - ptCollection = &ptPreparsedData->collections[iCollection]; - for (iR=0; iR<ptCollection->reportItemCount; iR++) - { - iReportItem = ptCollection->firstReportItem + iR; - ptReportItem = &ptPreparsedData->reportItems[iReportItem]; - if (HIDIsVariable(ptReportItem, preparsedDataRef) - && HIDHasUsage(preparsedDataRef,ptReportItem,usagePage,usage,&iUsageIndex,&iCount)) - { -/* - * This may be the proper place - * Let's check for the proper Report ID, Type, and Length -*/ - iStatus = HIDCheckReport(reportType,preparsedDataRef,ptReportItem, - psReport,iReportLength); -/* - * The Report ID or Type may not match. - * This may not be an error (yet) -*/ - if (iStatus == kHIDIncompatibleReportErr) - bIncompatibleReport = true; - else if (iStatus != kHIDSuccess) - return iStatus; - else - { -/* - * Disallow single count variables - * Count is set by HasUsage -*/ - if (iCount <= 1) - return kHIDNotValueArrayErr; -/* - * Write out the data -*/ - iStart = ptReportItem->startBit + (ptReportItem->globals.reportSize * iUsageIndex); - byteCount = (ptReportItem->globals.reportSize * iCount + 7)/8; - if (byteCount > iByteLength) - byteCount = iByteLength; - for (i=0; i<byteCount; i++) - { - iValue = *psUsageBuffer++; - iStatus = HIDPreProcessRIValue (ptReportItem, &iValue); - iStatus = HIDPutData(psReport, iReportLength, iStart, 8, iValue); - if (iStatus != kHIDSuccess) - return iStatus; - iStart += 8; - } - return kHIDSuccess; - } - } - } - if (bIncompatibleReport) - return kHIDIncompatibleReportErr; - return kHIDUsageNotFoundErr; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageAndPageFromIndex.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageAndPageFromIndex.c deleted file mode 100644 index 9692f3219..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageAndPageFromIndex.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDUsageAndPageFromIndex.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (KH) Keithen Hayenga - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB2> 12/12/00 KH range count off by 1. - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDUsageAndPageFromIndex - * - * Input: - * ptPreparsedData - The Preparsed Data - * ptReportItem - The Report Item - * index - The usage Index - * ptUsageAndPage - The usage And Page - * Output: - * Returns: - * - *------------------------------------------------------------------------------ -*/ -void HIDUsageAndPageFromIndex (HIDPreparsedDataRef preparsedDataRef, - HIDReportItem *ptReportItem, UInt32 index, - HIDUsageAndPage *ptUsageAndPage) -{ - HIDPreparsedDataPtr ptPreparsedData = (HIDPreparsedDataPtr) preparsedDataRef; - HIDP_UsageItem *ptUsageItem = NULL; - int iUsageItem; - int iUsages; - int i; - -/* - * Disallow NULL Pointers -*/ - if ((ptUsageAndPage == NULL) || (ptReportItem == NULL) || (ptPreparsedData == NULL)) - { - ptUsageAndPage->usagePage = 0; - return; // kHIDNullPointerErr; - } - -/* - * Index through the usage Items for this ReportItem -*/ - iUsageItem = ptReportItem->firstUsageItem; - for (i=0; i<ptReportItem->usageItemCount; i++) - { -/* - * Each usage Item is either a usage or a usage range -*/ - ptUsageItem = &ptPreparsedData->usageItems[iUsageItem++]; - if (ptUsageItem->isRange) - { -/* - * For usage Ranges - * If the index is in the range - * then return the usage - * Otherwise adjust the index by the size of the range -*/ - iUsages = ptUsageItem->usageMaximum - ptUsageItem->usageMinimum; - if (iUsages < 0) - iUsages = -iUsages; - iUsages++; // Add off by one adjustment AFTER sign correction. - if (iUsages > index) - { - ptUsageAndPage->usagePage = ptUsageItem->usagePage; - ptUsageAndPage->usage = ptUsageItem->usageMinimum + index; - return; - } - index -= iUsages; - } - else - { -/* - * For Usages - * If the index is zero - * then return this usage - * Otherwise one less to index through -*/ - if (index-- == 0) - { - ptUsageAndPage->usagePage = ptUsageItem->usagePage; - ptUsageAndPage->usage = ptUsageItem->usage; - return; - } - } - } - if (ptUsageItem != NULL) - { - ptUsageAndPage->usagePage = ptUsageItem->usagePage; - if (ptUsageItem->isRange) - ptUsageAndPage->usage = ptUsageItem->usageMaximum; - else - ptUsageAndPage->usage = ptUsageItem->usage; - } -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageInRange.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageInRange.c deleted file mode 100644 index 2d975ecc0..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageInRange.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDUsageInRange.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * HIDUsageInRange - * - * Input: - * ptUsage - The usage/UsageRange Item - * usagePage - The usagePage of the Item - or zero - * usage - The usage of the Item - * Output: - * Returns: - * true - usagePage/usage is in usage/UsageRange - * false - usagePage/usage is not in usage/UsageRange - * - *------------------------------------------------------------------------------ -*/ -Boolean HIDUsageInRange (HIDP_UsageItem *ptUsage, HIDUsage usagePage, HIDUsage usage) -{ -/* - * Disallow Null Pointers -*/ - if (ptUsage == NULL) - return false; -/* - * Check for the proper Page, 0 means don't care -*/ - if ((usagePage != 0) && (ptUsage->usagePage != usagePage)) - return false; -/* - * usage = 0 means don't care -*/ - if (usage == 0) - return true; -/* - * The requested usage must match or be in the range -*/ - if (ptUsage->isRange) - { - if ((ptUsage->usageMinimum > usage) || (ptUsage->usageMaximum < usage)) - return false; - } - else - { - if (ptUsage->usage != usage) - return false; - } - return true; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageListDifference.c b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageListDifference.c deleted file mode 100644 index 87e3816a3..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageListDifference.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: HIDUsageListDifference.c - - Contains: xxx put contents here xxx - - Version: xxx put version here xxx - - Copyright: © 1999 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: xxx put dri here xxx - - Other Contact: xxx put other contact here xxx - - Technology: xxx put technology here xxx - - Writers: - - (BWS) Brent Schorsch - - Change History (most recent first): - - <USB1> 3/5/99 BWS first checked in -*/ - -#include "HIDLib.h" - -/* - *------------------------------------------------------------------------------ - * - * In - Is a usage in a UsageList? - * - * Input: - * piUsageList - usage List - * iUsageListLength - Max entries in usage Lists - * usage - The usage - * Output: - * Returns: true or false - * - *------------------------------------------------------------------------------ -*/ -static Boolean IsUsageInUsageList(HIDUsage *piUsageList, UInt32 iUsageListLength, HIDUsage usage) -{ - unsigned int i; - for (i = 0; i < iUsageListLength; i++) - if (piUsageList[i] == usage) - return true; - return false; -} - -/* - *------------------------------------------------------------------------------ - * - * HIDUsageListDifference - Return adds and drops given present and past - * - * Input: - * piPreviouUL - Previous usage List - * piCurrentUL - Current usage List - * piBreakUL - Break usage List - * piMakeUL - Make usage List - * iUsageListLength - Max entries in usage Lists - * Output: - * piBreakUL - Break usage List - * piMakeUL - Make usage List - * Returns: - * - *------------------------------------------------------------------------------ -*/ -OSStatus HIDUsageListDifference(HIDUsage *piPreviousUL, HIDUsage *piCurrentUL, HIDUsage *piBreakUL, HIDUsage *piMakeUL, UInt32 iUsageListLength) -{ - int i; - HIDUsage usage; - int iBreakLength=0; - int iMakeLength=0; - for (i = 0; i < iUsageListLength; i++) - { -/* - * If in Current but not Previous then it's a Make -*/ - usage = piCurrentUL[i]; - if ((usage != 0) && (!IsUsageInUsageList(piPreviousUL,iUsageListLength,usage)) - && (!IsUsageInUsageList(piMakeUL,iMakeLength,usage))) - piMakeUL[iMakeLength++] = usage; -/* - * If in Previous but not Current then it's a Break -*/ - usage = piPreviousUL[i]; - if ((usage != 0) && (!IsUsageInUsageList(piCurrentUL,iUsageListLength,usage)) - && (!IsUsageInUsageList(piBreakUL,iBreakLength,usage))) - piBreakUL[iBreakLength++] = usage; - } -/* - * Clear the rest of the usage Lists -*/ - while (iMakeLength < iUsageListLength) - piMakeUL[iMakeLength++] = 0; - while (iBreakLength < iUsageListLength) - piBreakUL[iBreakLength++] = 0; - return kHIDSuccess; -} diff --git a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/MacTypes.h b/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/MacTypes.h deleted file mode 100644 index 915d7fcbb..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDDescriptorParser/MacTypes.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef __HID_MACTYPES__ -#define __HID_MACTYPES__ - -#include <IOKit/IOTypes.h> -#include <IOKit/hidsystem/IOHIDDescriptorParser.h> - -extern void *PoolAllocateResident(vm_size_t size, unsigned char clear); -extern OSStatus PoolDeallocate(void *ptr, vm_size_t size); - -#endif /* __HID_MACTYPES__ */ diff --git a/iokit/Families/IOHIDSystem/IOHIDIO.cpp b/iokit/Families/IOHIDSystem/IOHIDIO.cpp deleted file mode 100644 index 7e59174c7..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDIO.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * EventIO.m - Event System MiG interface for driver control and status. - * - * HISTORY - * 2-April-92 Mike Paquette at NeXT - * Created. - */ - -#include <IOKit/system.h> - -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOHIDSystem.h> -#include <IOKit/hidsystem/IOHIDShared.h> - -#include <IOKit/hidsystem/ev_private.h> /* Per-machine configuration info */ - -/* - * Additional kernel API to drivers using the Event Driver - */ - int -EventCoalesceDisplayCmd( int cmd, int oldcmd ) -{ - static const char coalesce[4][4] = { - /* nop */ {EVNOP, EVHIDE, EVSHOW, EVMOVE}, - /* hide */ {EVHIDE, EVHIDE, EVNOP, EVSHOW}, - /* show */ {EVSHOW, EVNOP, EVSHOW, EVSHOW}, - /* move */ {EVMOVE, EVHIDE, EVSHOW, EVMOVE} - }; - if ( cmd < EVLEVEL ) // coalesce EVNOP thru EVMOVE only - cmd = coalesce[oldcmd & 3][cmd & 3]; - return cmd; -} - diff --git a/iokit/Families/IOHIDSystem/IOHIDSystem.cpp b/iokit/Families/IOHIDSystem/IOHIDSystem.cpp deleted file mode 100644 index 12f4599da..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDSystem.cpp +++ /dev/null @@ -1,2643 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * EventDriver.m - Event System module, ObjC implementation. - * - * The EventDriver is a pseudo-device driver. - * - * HISTORY - * 31-Mar-92 Mike Paquette at NeXT - * Created. - * 04-Aug-93 Erik Kay at NeXT - * minor API cleanup - * 12-Dec-00 bubba at Apple. - * Handle eject key cases on Pro Keyboard. -*/ - -#include <IOKit/system.h> -#include <IOKit/assert.h> - -#include <libkern/c++/OSContainers.h> -#include <libkern/c++/OSCollectionIterator.h> - -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/IOCommandQueue.h> -#include <IOKit/IOMessage.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHIDShared.h> -#include <IOKit/hidsystem/IOHIDSystem.h> -#include <IOKit/hidsystem/IOHIKeyboard.h> -#include <IOKit/hidsystem/IOHIPointing.h> -#include <IOKit/hidsystem/IOHIDParameter.h> - -#include <IOKit/hidsystem/ev_private.h> /* Per-machine configuration info */ -#include "IOHIDUserClient.h" - -#include <sys/kdebug.h> - -#ifdef __cplusplus - extern "C" - { - #include <UserNotification/KUNCUserNotifications.h> - } -#endif - -bool displayWranglerUp( OSObject *, void *, IOService * ); - -static IOHIDSystem * evInstance = 0; -MasterAudioFunctions *masterAudioFunctions = 0; - -#define xpr_ev_cursor(x, a, b, c, d, e) -#define PtInRect(ptp,rp) \ - ((ptp)->x >= (rp)->minx && (ptp)->x < (rp)->maxx && \ - (ptp)->y >= (rp)->miny && (ptp)->y < (rp)->maxy) - - - -static inline unsigned AbsoluteTimeToTick( AbsoluteTime * ts ) -{ - UInt64 nano; - absolutetime_to_nanoseconds(*ts, &nano); - return( nano >> 24 ); -} - -static inline void TickToAbsoluteTime( unsigned tick, AbsoluteTime * ts ) -{ - UInt64 nano = ((UInt64) tick) << 24; - nanoseconds_to_absolutetime(nano, ts); -} - -#define EV_NS_TO_TICK(ns) AbsoluteTimeToTick(ns) -#define EV_TICK_TO_NS(tick,ns) TickToAbsoluteTime(tick,ns) - - -#define super IOService -OSDefineMetaClassAndStructors(IOHIDSystem, IOService); - -/* Return the current instance of the EventDriver, or 0 if none. */ -IOHIDSystem * IOHIDSystem::instance() -{ - return evInstance; -} - -bool IOHIDSystem::init(OSDictionary * properties) -{ - if (!super::init(properties)) return false; - - /* - * Initialize minimal state. - */ - - driverLock = NULL; - kickConsumerLock = NULL; - evScreen = NULL; - timerES = 0; - cmdQ = 0; - workLoop = 0; - - return true; -} - -IOHIDSystem * IOHIDSystem::probe(IOService * provider, - SInt32 * score) -{ - if (!super::probe(provider,score)) return 0; - - return this; -} - -/* - * Perform reusable initialization actions here. - */ -IOWorkLoop * IOHIDSystem::getWorkLoop() const -{ - return workLoop; -} - -bool IOHIDSystem::start(IOService * provider) -{ - bool iWasStarted = false; - - do { - if (!super::start(provider)) break; - - evInstance = this; - - driverLock = IOLockAlloc(); // Event driver data protection lock - kickConsumerLock = IOLockAlloc(); - - /* A few details to be set up... */ - pointerLoc.x = INIT_CURSOR_X; - pointerLoc.y = INIT_CURSOR_Y; - - pointerDelta.x = 0; - pointerDelta.y = 0; - - evScreenSize = sizeof(EvScreen) * 6; // FIX - evScreen = (void *) IOMalloc(evScreenSize); - - if (!driverLock || - !kickConsumerLock || - !evScreenSize) break; - - IOLockInit(driverLock); - IOLockInit(kickConsumerLock); - bzero(evScreen, evScreenSize); - - /* - * Start up the work loop - */ - workLoop = IOWorkLoop::workLoop(); - cmdQ = IOCommandQueue::commandQueue - (this, (IOCommandQueueAction) &_doPerformInIOThread ); - timerES = IOTimerEventSource::timerEventSource - (this, (IOTimerEventSource::Action) &_periodicEvents ); - - if (!workLoop || !cmdQ || !timerES) - break; - - if ((workLoop->addEventSource(cmdQ) != kIOReturnSuccess) - || (workLoop->addEventSource(timerES) != kIOReturnSuccess)) - break; - - publishNotify = addNotification( - gIOPublishNotification, serviceMatching("IOHIDevice"), - (IOServiceNotificationHandler) &publishNotificationHandler, - this, 0 ); - - if (!publishNotify) break; - - /* - * IOHIDSystem serves both as a service and a nub (we lead a double - * life). Register ourselves as a nub to kick off matching. - */ - - registerService(); - - addNotification( gIOPublishNotification,serviceMatching("IODisplayWrangler"), // look for the display wrangler - (IOServiceNotificationHandler)displayWranglerUp, this, 0 ); - - iWasStarted = true; - } while(false); - - if (!iWasStarted) evInstance = 0; - - return iWasStarted; -} - -// ********************************************************************************** -// displayWranglerUp -// -// The Display Wrangler has appeared. We will be calling its -// activityTickle method when there is user activity. -// ********************************************************************************** -bool displayWranglerUp( OSObject * us, void * ref, IOService * yourDevice ) -{ - if ( yourDevice != NULL ) { - ((IOHIDSystem *)us)->displayManager = yourDevice; - ((IOHIDSystem *)us)->displayState = yourDevice->registerInterestedDriver((IOService *)us); - } - return true; -} - - -//********************************************************************************* -// powerStateDidChangeTo -// -// The display wrangler has changed state, so the displays have changed -// state, too. We save the new state. -//********************************************************************************* - -IOReturn IOHIDSystem::powerStateDidChangeTo ( IOPMPowerFlags theFlags, unsigned long, IOService*) -{ - displayState = theFlags; - return IOPMNoErr; -} - - - -bool IOHIDSystem::publishNotificationHandler( - IOHIDSystem * self, - void * /* ref */, - IOService * newService ) -{ - self->attach( newService ); - -// IOTakeLock( self->driverLock); - if( self->eventsOpen - && OSDynamicCast(IOHIDevice, newService)) { - self->registerEventSource((IOHIDevice *) newService); - } -// IOUnlock( self->driverLock); - - return true; -} - - -/* - * Free locally allocated resources, and then ourselves. - */ -void IOHIDSystem::free() -{ - /* Initiates a normal close if open & inited */ - if( driverLock) - evClose(); - - if (evScreen) IOFree( (void *)evScreen, evScreenSize ); - evScreen = (void *)0; - evScreenSize = 0; - - if (timerES) timerES->release(); - if (cmdQ) cmdQ->release(); - if (workLoop) workLoop->release(); - if (publishNotify) publishNotify->release(); - - /* Release locally allocated resources */ - if (kickConsumerLock) IOLockFree( kickConsumerLock); - if (driverLock) IOLockFree( driverLock); - - super::free(); -} - - - -/* - * Open the driver for business. This call must be made before - * any other calls to the Event driver. We can only be opened by - * one user at a time. - */ -IOReturn IOHIDSystem::evOpen(void) -{ - IOReturn r = kIOReturnSuccess; - - if ( evOpenCalled == true ) - { - r = kIOReturnBusy; - goto done; - } - evOpenCalled = true; - - if (!evInitialized) - { - evInitialized = true; - curBright = EV_SCREEN_MAX_BRIGHTNESS; // FIXME: Set from NVRAM? - curVolume = EV_AUDIO_MAX_VOLUME / 2; // FIXME: Set from NVRAM? - // Put code here that is to run on the first open ONLY. - } - -done: - return r; -} - -IOReturn IOHIDSystem::evClose(void) -{ - IOTakeLock( driverLock); - if ( evOpenCalled == false ) - { - IOUnlock( driverLock); - return kIOReturnBadArgument; - } - // Early close actions here - forceAutoDimState(false); - if( cursorEnabled) - hideCursor(); - cursorStarted = false; - cursorEnabled = false; - IOUnlock( driverLock); - - // Release the input devices. - detachEventSources(); - - // Tear down the shared memory area if set up -// if ( eventsOpen == true ) -// unmapEventShmem(eventPort); - - IOTakeLock( driverLock); - // Clear screens registry and related data - if ( evScreen != (void *)0 ) - { - screens = 0; - lastShmemPtr = (void *)0; - } - // Remove port notification for the eventPort and clear the port out - setEventPort(MACH_PORT_NULL); -// ipc_port_release_send(event_port); - - // Clear local state to shutdown - evOpenCalled = false; - eventsOpen = false; - - IOUnlock( driverLock); - - return kIOReturnSuccess; -} - -// -// Dispatch state to screens registered with the Event Driver -// Pending state changes for a device may be coalesced. -// -// -// On entry, the driverLock should be set. -// -void IOHIDSystem::evDispatch( - /* command */ EvCmd evcmd) -{ - Point p; - - if( !eventsOpen) - return; - - for( int i = 0; i < screens; i++ ) { - - EvScreen *esp = &((EvScreen*)evScreen)[i]; - - if ( esp->instance ) - { - p.x = evg->cursorLoc.x; // Copy from shmem. - p.y = evg->cursorLoc.y; - - bool onscreen = (0 != (cursorScreens & (1 << i))); - - switch ( evcmd ) - { - case EVMOVE: - if (onscreen) - esp->instance->moveCursor(&p, evg->frame); - break; - - case EVSHOW: - if (onscreen) - esp->instance->showCursor(&p, evg->frame); - break; - - case EVHIDE: - if (onscreen) - esp->instance->hideCursor(); - break; - - case EVLEVEL: - case EVNOP: - /* lets keep that compiler happy */ - break; - } - } - } -} - -// -// Dispatch mechanism for special key press. If a port has been registered, -// a message is built to be sent out to that port notifying that the key has -// changed state. A level in the range 0-64 is provided for convenience. -// -void IOHIDSystem::evSpecialKeyMsg(unsigned key, - /* direction */ unsigned dir, - /* flags */ unsigned f, - /* level */ unsigned l) -{ - mach_port_t dst_port; - struct evioSpecialKeyMsg *msg; - - static const struct evioSpecialKeyMsg init_msg = - { { MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, // mach3xxx, is the right? - MACH_MSG_TYPE_MAKE_SEND), // mach_msg_bits_t msgh_bits; - sizeof (struct evioSpecialKeyMsg), // mach_msg_size_t msgh_size; - MACH_PORT_NULL, // mach_port_t msgh_remote_port; - MACH_PORT_NULL, // mach_port_t msgh_local_port; - 0, // mach_msg_size_t msgh_reserved; - EV_SPECIAL_KEY_MSG_ID // mach_msg_id_t msgh_id; - }, - 0, /* key */ - 0, /* direction */ - 0, /* flags */ - 0 /* level */ - }; - - if ( (dst_port = specialKeyPort(key)) == MACH_PORT_NULL ) - return; - msg = (struct evioSpecialKeyMsg *) IOMalloc( - sizeof (struct evioSpecialKeyMsg) ); - if ( msg == NULL ) - return; - - // Initialize the message. - bcopy( &init_msg, msg, sizeof (struct evioSpecialKeyMsg) ); - msg->Head.msgh_remote_port = dst_port; - msg->key = key; - msg->direction = dir; - msg->flags = f; - msg->level = l; - - // Send the message out from the I/O thread. - sendWorkLoopCommand(this,(IOHIDAction)_performSpecialKeyMsg,(void*)msg); -} - -// -// Reset instance variables to their default state for mice/pointers -// -void IOHIDSystem::_resetMouseParameters() -{ - - IOTakeLock( driverLock); - if ( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - nanoseconds_to_absolutetime( EV_DCLICKTIME, &clickTimeThresh); - clickSpaceThresh.x = clickSpaceThresh.y = EV_DCLICKSPACE; - AbsoluteTime_to_scalar( &clickTime) = 0; - clickLoc.x = clickLoc.y = -EV_DCLICKSPACE; - clickState = 1; - nanoseconds_to_absolutetime( DAUTODIMPERIOD, &autoDimPeriod); - clock_get_uptime( &autoDimTime); - ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod); - dimmedBrightness = DDIMBRIGHTNESS; - - IOUnlock( driverLock); -} - -void IOHIDSystem::_resetKeyboardParameters() -{ -} - -/* - * Methods exported by the EventDriver. - * - * The screenRegister protocol is used by frame buffer drivers to register - * themselves with the Event Driver. These methods are called in response - * to a registerSelf or unregisterSelf message received from the Event - * Driver. - */ - -int IOHIDSystem::registerScreen(IOGraphicsDevice * instance, - /* bounds */ Bounds * bp) -{ - EvScreen *esp; - - if( (false == eventsOpen) || (0 == bp) ) - { - return -1; - } - - if ( lastShmemPtr == (void *)0 ) - lastShmemPtr = evs; - - /* shmemSize and bounds already set */ - esp = &((EvScreen*)evScreen)[screens]; - esp->instance = instance; - esp->bounds = bp; - // Update our idea of workSpace bounds - if ( bp->minx < workSpace.minx ) - workSpace.minx = bp->minx; - if ( bp->miny < workSpace.miny ) - workSpace.miny = bp->miny; - if ( bp->maxx < workSpace.maxx ) - workSpace.maxx = bp->maxx; - if ( esp->bounds->maxy < workSpace.maxy ) - workSpace.maxy = bp->maxy; - - return(SCREENTOKEN + screens++); -} - - -void IOHIDSystem::unregisterScreen(int index) -{ - index -= SCREENTOKEN; - - IOTakeLock( driverLock); - if ( eventsOpen == false || index < 0 || index >= screens ) - { - IOUnlock( driverLock); - return; - } - hideCursor(); - - // clear the state for the screen - ((EvScreen*)evScreen)[index].instance = 0; - // Put the cursor someplace reasonable if it was on the destroyed screen - cursorScreens &= ~(1 << index); - // This will jump the cursor back on screen - setCursorPosition((Point *)&evg->cursorLoc, true); - - showCursor(); - - IOUnlock( driverLock); -} - -/* Member of EventClient protocol - * - * Absolute position input devices and some specialized output devices - * may need to know the bounding rectangle for all attached displays. - * The following method returns a Bounds* for the workspace. Please note - * that the bounds are kept as signed values, and that on a multi-display - * system the minx and miny values may very well be negative. - */ -Bounds * IOHIDSystem::workspaceBounds() -{ - return &workSpace; -} - -IOReturn IOHIDSystem::createShmem(void* p1, void*, void*, void*, void*, void*) -{ // IOMethod - int shmemVersion = (int)p1; - IOByteCount size; - - if( shmemVersion != kIOHIDCurrentShmemVersion) - return( kIOReturnUnsupported); - - IOTakeLock( driverLock); - - if( 0 == globalMemory) { - - size = sizeof(EvOffsets) + sizeof(EvGlobals); - globalMemory = IOBufferMemoryDescriptor::withOptions( - kIODirectionNone | kIOMemoryKernelUserShared, size ); - - if( !globalMemory) { - IOUnlock( driverLock); - return( kIOReturnNoMemory ); - } - shmem_addr = (vm_offset_t) globalMemory->getBytesNoCopy(); - shmem_size = size; - } - - initShmem(); - IOUnlock( driverLock); - - return kIOReturnSuccess; -} - - -// Initialize the shared memory area. -// -// On entry, the driverLock should be set. -void IOHIDSystem::initShmem() -{ - int i; - EvOffsets *eop; - - /* top of sharedMem is EvOffsets structure */ - eop = (EvOffsets *) shmem_addr; - - bzero( (void*)shmem_addr, shmem_size); - - /* fill in EvOffsets structure */ - eop->evGlobalsOffset = sizeof(EvOffsets); - eop->evShmemOffset = eop->evGlobalsOffset + sizeof(EvGlobals); - - /* find pointers to start of globals and private shmem region */ - evg = (EvGlobals *)((char *)shmem_addr + eop->evGlobalsOffset); - evs = (void *)((char *)shmem_addr + eop->evShmemOffset); - - evg->version = kIOHIDCurrentShmemVersion; - evg->structSize = sizeof( EvGlobals); - - /* Set default wait cursor parameters */ - evg->waitCursorEnabled = TRUE; - evg->globalWaitCursorEnabled = TRUE; - evg->waitThreshold = (12 * EV_TICKS_PER_SEC) / 10; - clock_interval_to_absolutetime_interval(DefaultWCFrameRate, kNanosecondScale, - &waitFrameRate); - clock_interval_to_absolutetime_interval(DefaultWCSustain, kNanosecondScale, - &waitSustain); - AbsoluteTime_to_scalar(&waitSusTime) = 0; - AbsoluteTime_to_scalar(&waitFrameTime) = 0; - - EV_TICK_TO_NS(10,&periodicEventDelta); - - /* Set up low-level queues */ - lleqSize = LLEQSIZE; - for (i=lleqSize; --i != -1; ) { - evg->lleq[i].event.type = 0; - AbsoluteTime_to_scalar(&evg->lleq[i].event.time) = 0; - evg->lleq[i].event.flags = 0; - ev_init_lock(&evg->lleq[i].sema); - evg->lleq[i].next = i+1; - } - evg->LLELast = 0; - evg->lleq[lleqSize-1].next = 0; - evg->LLEHead = - evg->lleq[evg->LLELast].next; - evg->LLETail = - evg->lleq[evg->LLELast].next; - evg->buttons = 0; - evg->eNum = INITEVENTNUM; - evg->eventFlags = 0; - - AbsoluteTime ts; - unsigned tick; - clock_get_uptime( &ts); - tick = EV_NS_TO_TICK(&ts); - if ( tick == 0 ) - tick = 1; // No zero values allowed! - evg->VertRetraceClock = tick; - - evg->cursorLoc.x = pointerLoc.x; - evg->cursorLoc.y = pointerLoc.y; - evg->dontCoalesce = 0; - evg->dontWantCoalesce = 0; - evg->wantPressure = 0; - evg->wantPrecision = 0; - evg->mouseRectValid = 0; - evg->movedMask = 0; - ev_init_lock( &evg->cursorSema ); - ev_init_lock( &evg->waitCursorSema ); - // Set eventsOpen last to avoid race conditions. - eventsOpen = true; -} - -// -// Set the event port. The event port is both an ownership token -// and a live port we hold send rights on. The port is owned by our client, -// the WindowServer. We arrange to be notified on a port death so that -// we can tear down any active resources set up during this session. -// An argument of PORT_NULL will cause us to forget any port death -// notification that's set up. -// -// The driverLock should be held on entry. -// -void IOHIDSystem::setEventPort(mach_port_t port) -{ - static struct _eventMsg init_msg = { { - // mach_msg_bits_t msgh_bits; - MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND,0), - // mach_msg_size_t msgh_size; - sizeof (struct _eventMsg), - // mach_port_t msgh_remote_port; - MACH_PORT_NULL, - // mach_port_t msgh_local_port; - MACH_PORT_NULL, - // mach_msg_size_t msgh_reserved; - 0, - // mach_msg_id_t msgh_id; - 0 - } }; - - if ( eventMsg == NULL ) - eventMsg = IOMalloc( sizeof (struct _eventMsg) ); - eventPort = port; - // Initialize the events available message. - *((struct _eventMsg *)eventMsg) = init_msg; - - ((struct _eventMsg *)eventMsg)->h.msgh_remote_port = port; -} - -// -// Set the port to be used for a special key notification. This could be more -// robust about letting ports be set... -// -IOReturn IOHIDSystem::setSpecialKeyPort( - /* keyFlavor */ int special_key, - /* keyPort */ mach_port_t key_port) -{ - if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS ) - _specialKeyPort[special_key] = key_port; - return kIOReturnSuccess; -} - -mach_port_t IOHIDSystem::specialKeyPort(int special_key) -{ - if ( special_key >= 0 && special_key < NX_NUM_SCANNED_SPECIALKEYS ) - return _specialKeyPort[special_key]; - return MACH_PORT_NULL; -} - -// -// Helper functions for postEvent -// -static inline int myAbs(int a) { return(a > 0 ? a : -a); } - -short IOHIDSystem::getUniqueEventNum() -{ - while (++evg->eNum == NULLEVENTNUM) - ; /* sic */ - return(evg->eNum); -} - -// postEvent -// -// This routine actually places events in the event queue which is in -// the EvGlobals structure. It is called from all parts of the ev -// driver. -// -// On entry, the driverLock should be set. -// - -void IOHIDSystem::postEvent(int what, - /* at */ Point * location, - /* atTime */ AbsoluteTime ts, - /* withData */ NXEventData * myData) -{ - NXEQElement * theHead = (NXEQElement *) &evg->lleq[evg->LLEHead]; - NXEQElement * theLast = (NXEQElement *) &evg->lleq[evg->LLELast]; - NXEQElement * theTail = (NXEQElement *) &evg->lleq[evg->LLETail]; - int wereEvents; - unsigned theClock = EV_NS_TO_TICK(&ts); - - /* Some events affect screen dimming */ - if (EventCodeMask(what) & NX_UNDIMMASK) { - autoDimTime = ts; - ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod); - if (autoDimmed) - undoAutoDim(); - } - // Update the PS VertRetraceClock off of the timestamp if it looks sane - if ( theClock > (unsigned)evg->VertRetraceClock - && theClock < (unsigned)(evg->VertRetraceClock + (20 * EV_TICK_TIME)) ) - evg->VertRetraceClock = theClock; - - wereEvents = EventsInQueue(); - - xpr_ev_post("postEvent: what %d, X %d Y %d Q %d, needKick %d\n", - what,location->x,location->y, - EventsInQueue(), needToKickEventConsumer); - - if ((!evg->dontCoalesce) /* Coalescing enabled */ - && (theHead != theTail) - && (theLast->event.type == what) - && (EventCodeMask(what) & COALESCEEVENTMASK) - && ev_try_lock(&theLast->sema)) { - /* coalesce events */ - theLast->event.location.x = location->x; - theLast->event.location.y = location->y; - absolutetime_to_nanoseconds(ts, &theLast->event.time); - if (myData != NULL) - theLast->event.data = *myData; - ev_unlock(&theLast->sema); - } else if (theTail->next != evg->LLEHead) { - /* store event in tail */ - theTail->event.type = what; - theTail->event.location.x = location->x; - theTail->event.location.y = location->y; - theTail->event.flags = evg->eventFlags; - absolutetime_to_nanoseconds(ts, &theLast->event.time); - theTail->event.window = 0; - if (myData != NULL) - theTail->event.data = *myData; - switch(what) { - case NX_LMOUSEDOWN: - theTail->event.data.mouse.eventNum = - leftENum = getUniqueEventNum(); - break; - case NX_RMOUSEDOWN: - theTail->event.data.mouse.eventNum = - rightENum = getUniqueEventNum(); - break; - case NX_LMOUSEUP: - theTail->event.data.mouse.eventNum = leftENum; - leftENum = NULLEVENTNUM; - break; - case NX_RMOUSEUP: - theTail->event.data.mouse.eventNum = rightENum; - rightENum = NULLEVENTNUM; - break; - } - if (EventCodeMask(what) & PRESSUREEVENTMASK) { - theTail->event.data.mouse.pressure = lastPressure; - } - if (EventCodeMask(what) & MOUSEEVENTMASK) { /* Click state */ - AbsoluteTime delta = ts; - SUB_ABSOLUTETIME( &delta, &clickTime); - if ((CMP_ABSOLUTETIME(&delta, &clickTimeThresh) <= 0) - && (myAbs(location->x - clickLoc.x) <= clickSpaceThresh.x) - && (myAbs(location->y - clickLoc.y) <= clickSpaceThresh.y)) { - if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) { - clickTime = ts; - theTail->event.data.mouse.click = ++clickState; - } else { - theTail->event.data.mouse.click = clickState; - } - } else if ((what == NX_LMOUSEDOWN)||(what == NX_RMOUSEDOWN)) { - clickLoc = *location; - clickTime = ts; - clickState = 1; - theTail->event.data.mouse.click = clickState; - } else - theTail->event.data.mouse.click = 0; - } -#if PMON - pmon_log_event(PMON_SOURCE_EV, - KP_EV_POST_EVENT, - what, - evg->eventFlags, - theClock); -#endif - evg->LLETail = theTail->next; - evg->LLELast = theLast->next; - if ( ! wereEvents ) // Events available, so wake event consumer - kickEventConsumer(); - } - else - { - /* - * if queue is full, ignore event, too hard to take care of all cases - */ - IOLog("%s: postEvent LLEventQueue overflow.\n", getName()); - kickEventConsumer(); -#if PMON - pmon_log_event( PMON_SOURCE_EV, - KP_EV_QUEUE_FULL, - what, - evg->eventFlags, - theClock); -#endif - } -} - -/* - * - kickEventConsumer - * - * Try to send a message out to let the event consumer know that - * there are now events available for consumption. - */ - -void IOHIDSystem::kickEventConsumer() -{ - IOReturn err; - - IOTakeLock( kickConsumerLock); - xpr_ev_post("kickEventConsumer (need == %d)\n", - needToKickEventConsumer,2,3,4,5); - if ( needToKickEventConsumer == true ) - { - IOUnlock( kickConsumerLock); - return; // Request is already pending - } - needToKickEventConsumer = true; // Posting a request now - IOUnlock( kickConsumerLock); - - err = sendWorkLoopCommand(this, (IOHIDAction)_performKickEventConsumer, - NULL); - - if( err) - IOLog("%s: cmdQ fail %d\n", getName(), err); -} - -/* - * Event sources may need to use an I/O thread from time to time. - * Rather than have each instance running it's own thread, we provide - * a callback mechanism to let all the instances share a common Event I/O - * thread running in the IOTask space, and managed by the Event Driver. - */ - -IOReturn IOHIDSystem::sendWorkLoopCommand(OSObject * target, - IOHIDAction action, - void * data) -{ - kern_return_t err; - - err = cmdQ->enqueueCommand( /* sleep */ true, - /* field0 */ target, - /* field1 */ (void *) action, - /* field2 */ data ); - - return (err == KERN_SUCCESS) ? kIOReturnSuccess : kIOReturnNoMemory; -} - -/* - * The following methods are executed from the I/O thread only. - */ - -/* - * This routine is run within the I/O thread, on demand from the - * sendWorkLoopCommand method above. We attempt to dispatch a message - * to the specified selector and instance. - */ -void IOHIDSystem::_doPerformInIOThread(void* self, - void* target, /* IOCommandQueueAction */ - void* action, - void* data, - void* /* unused */) -{ - (*((IOHIDAction)action))((OSObject *)target, data); -} - -/* - * This is run in the I/O thread, to perform the actual message send operation. - */ - -void IOHIDSystem::_performSpecialKeyMsg(IOHIDSystem * self, - struct evioSpecialKeyMsg *msg) - /* IOHIDAction */ -{ - kern_return_t r; - - xpr_ev_post("_performSpecialKeyMsg 0x%x\n", msg,2,3,4,5); - - - /* FIXME: Don't block */ - r = mach_msg_send_from_kernel( &msg->Head, msg->Head.msgh_size); - - xpr_ev_post("_performSpecialKeyMsg: msg_send() == %d\n",r,2,3,4,5); - if ( r != MACH_MSG_SUCCESS ) - { - IOLog("%s: _performSpecialKeyMsg msg_send returned %d\n", - self->getName(), r); - } - if ( r == MACH_SEND_INVALID_DEST ) /* Invalidate the port */ - { - self->setSpecialKeyPort( - /* keyFlavor */ msg->key, - /* keyPort */ MACH_PORT_NULL); - } - IOFree( (void *)msg, sizeof (struct evioSpecialKeyMsg) ); -} - -/* - * This is run in the I/O thread, to perform the actual message send operation. - * Note that we perform a non-blocking send. The Event port in the event - * consumer has a queue depth of 1 message. Once the consumer picks up that - * message, it runs until the event queue is exhausted before trying to read - * another message. If a message is pending,there is no need to enqueue a - * second one. This also keeps us from blocking the I/O thread in a msg_send - * which could result in a deadlock if the consumer were to make a call into - * the event driver. - */ -void IOHIDSystem::_performKickEventConsumer(IOHIDSystem * self, void *) /* IOHIDAction */ -{ - kern_return_t r; - mach_msg_header_t *msgh - - xpr_ev_post("_performKickEventConsumer\n", 1,2,3,4,5); - IOTakeLock( self->kickConsumerLock); - self->needToKickEventConsumer = false; // Request received and processed - IOUnlock( self->kickConsumerLock); - - msgh = (mach_msg_header_t *)self->eventMsg; - if( msgh) { - - r = mach_msg_send_from_kernel( msgh, msgh->msgh_size); - switch ( r ) - { - case MACH_SEND_TIMED_OUT:/* Already has a message posted */ - case MACH_MSG_SUCCESS: /* Message is posted */ - break; - default: /* Log the error */ - IOLog("%s: _performKickEventConsumer msg_send returned %d\n", - self->getName(), r); - break; - } - } -} - -// -// Schedule the next periodic event to be run, based on the current state of -// the event system. We have to consider things here such as when the last -// periodic event pass ran, if there is currently any mouse delta accumulated, -// and how long it has been since the last event was consumed by an app (for -// driving the wait cursor). -// -// This code should only be run from the periodicEvents method or -// _setCursorPosition. -// -void IOHIDSystem::scheduleNextPeriodicEvent() -{ - if (CMP_ABSOLUTETIME( &waitFrameTime, &thisPeriodicRun) > 0) - { - AbsoluteTime time_for_next_run; - - clock_get_uptime(&time_for_next_run); - ADD_ABSOLUTETIME( &time_for_next_run, &periodicEventDelta); - - if (CMP_ABSOLUTETIME( &waitFrameTime, &time_for_next_run) < 0) { - timerES->wakeAtTime(waitFrameTime); - return; - } - } - - timerES->setTimeout(periodicEventDelta); -} - -// Periodic events are driven from this method. -// After taking care of all pending work, the method -// calls scheduleNextPeriodicEvent to compute and set the -// next callout. -// - -void IOHIDSystem::_periodicEvents(IOHIDSystem * self, - IOTimerEventSource *timer) -{ - self->periodicEvents(timer); -} - -void IOHIDSystem::periodicEvents(IOTimerEventSource * /* timer */) - /* IOTimerEventSource::Action, IOHIDAction */ -{ - unsigned int tick; - - // If eventsOpen is false, then the driver shmem is - // no longer valid, and it is in the process of shutting down. - // We should give up without rescheduling. - IOTakeLock( driverLock); - if ( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - - // Increment event time stamp last - clock_get_uptime(&thisPeriodicRun); - - // Temporary hack til we wean CGS off of VertRetraceClock - tick = EV_NS_TO_TICK(&thisPeriodicRun); - if ( tick == 0 ) - tick = 1; - evg->VertRetraceClock = tick; - - // Update cursor position if needed - if ( needSetCursorPosition == true ) - _setCursorPosition(&pointerLoc, false); - - // WAITCURSOR ACTION - if ( ev_try_lock(&evg->waitCursorSema) ) - { - if ( ev_try_lock(&evg->cursorSema) ) - { - // See if the current context has timed out - if ( (evg->AALastEventSent != evg->AALastEventConsumed) - && ((evg->VertRetraceClock - evg->AALastEventSent > - evg->waitThreshold))) - evg->ctxtTimedOut = TRUE; - // If wait cursor enabled and context timed out, do waitcursor - if (evg->waitCursorEnabled && evg->globalWaitCursorEnabled && - evg->ctxtTimedOut) - { - /* WAIT CURSOR SHOULD BE ON */ - if (!evg->waitCursorUp) - showWaitCursor(); - } else - { - /* WAIT CURSOR SHOULD BE OFF */ - if (evg->waitCursorUp && - CMP_ABSOLUTETIME(&waitSusTime, &thisPeriodicRun) <= 0) - hideWaitCursor(); - } - /* Animate cursor */ - if (evg->waitCursorUp && - CMP_ABSOLUTETIME(&waitFrameTime, &thisPeriodicRun) <= 0) - animateWaitCursor(); - ev_unlock(&evg->cursorSema); - if ((CMP_ABSOLUTETIME(&thisPeriodicRun, &autoDimTime) > 0) - && (!autoDimmed)) - doAutoDim(); - } - ev_unlock(&evg->waitCursorSema); - } - - scheduleNextPeriodicEvent(); - IOUnlock( driverLock); - - return; -} - -// -// Start the cursor system running. -// -// At this point, the WindowServer is up, running, and ready to process events. -// We will attach the keyboard and mouse, if none are available yet. -// - -bool IOHIDSystem::resetCursor() -{ - volatile Point * p; - UInt32 newScreens = 0; - SInt32 pinScreen = -1L; - - p = &evg->cursorLoc; - - /* Get mask of screens on which the cursor is present */ - EvScreen *screen = (EvScreen *)evScreen; - for (int i = 0; i < screens; i++ ) { - if ((screen[i].instance) && PtInRect(p, screen[i].bounds)) { - pinScreen = i; - newScreens |= (1 << i); - } - } - - if (newScreens == 0) - pinScreen = 0; - - // reset pin rect - cursorPin = *(((EvScreen*)evScreen)[pinScreen].bounds); - cursorPin.maxx--; /* Make half-open rectangle */ - cursorPin.maxy--; - cursorPinScreen = pinScreen; - - if (newScreens == 0) { - /* Pin new cursor position to cursorPin rect */ - p->x = (p->x < cursorPin.minx) ? - cursorPin.minx : ((p->x > cursorPin.maxx) ? - cursorPin.maxx : p->x); - p->y = (p->y < cursorPin.miny) ? - cursorPin.miny : ((p->y > cursorPin.maxy) ? - cursorPin.maxy : p->y); - - /* regenerate mask for new position */ - for (int i = 0; i < screens; i++ ) { - if ((screen[i].instance) && PtInRect(p, screen[i].bounds)) - newScreens |= (1 << i); - } - } - - cursorScreens = newScreens; - - pointerDelta.x += (evg->cursorLoc.x - pointerLoc.x); - pointerDelta.y += (evg->cursorLoc.y - pointerLoc.y); - pointerLoc.x = evg->cursorLoc.x; - pointerLoc.y = evg->cursorLoc.y; - - return( true ); -} - -bool IOHIDSystem::startCursor() -{ - bool ok; - - if (0 == screens) // no screens, no cursor - return( false ); - - resetCursor(); - setBrightness(); - showCursor(); - - // Start the cursor control callouts - ok = (kIOReturnSuccess == - sendWorkLoopCommand(this, (IOHIDAction)_periodicEvents, timerES)); - - cursorStarted = ok; - return( ok ); -} - -// -// Wait Cursor machinery. The driverLock should be held on entry to -// these methods, and the shared memory area must be set up. -// -void IOHIDSystem::showWaitCursor() -{ - xpr_ev_cursor("showWaitCursor\n",1,2,3,4,5); - evg->waitCursorUp = true; - hideCursor(); - evg->frame = EV_WAITCURSOR; - showCursor(); - // Set animation and sustain absolute times. - - waitSusTime = waitFrameTime = thisPeriodicRun; - ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate); - ADD_ABSOLUTETIME( &waitSusTime, &waitSustain); -} - -void IOHIDSystem::hideWaitCursor() -{ - xpr_ev_cursor("hideWaitCursor\n",1,2,3,4,5); - evg->waitCursorUp = false; - hideCursor(); - evg->frame = EV_STD_CURSOR; - showCursor(); - AbsoluteTime_to_scalar(&waitFrameTime) = 0; - AbsoluteTime_to_scalar(&waitSusTime ) = 0; -} - -void IOHIDSystem::animateWaitCursor() -{ - xpr_ev_cursor("animateWaitCursor\n",1,2,3,4,5); - changeCursor(evg->frame + 1); - // Set the next animation time. - waitFrameTime = thisPeriodicRun; - ADD_ABSOLUTETIME( &waitFrameTime, &waitFrameRate); -} - -void IOHIDSystem::changeCursor(int frame) -{ - evg->frame = - (frame > EV_MAXCURSOR) ? EV_WAITCURSOR : frame; - xpr_ev_cursor("changeCursor %d\n",evg->frame,2,3,4,5); - moveCursor(); -} - -// -// Return the screen number in which point p lies. Return -1 if the point -// lies outside of all registered screens. -// -int IOHIDSystem::pointToScreen(Point * p) -{ - int i; - EvScreen *screen = (EvScreen *)evScreen; - for (i=screens; --i != -1; ) { - if (screen[i].instance != 0 - && (p->x >= screen[i].bounds->minx) - && (p->x < screen[i].bounds->maxx) - && (p->y >= screen[i].bounds->miny) - && (p->y < screen[i].bounds->maxy)) - return i; - } - return(-1); /* Cursor outside of known screen boundary */ -} - -// -// API used to manipulate screen brightness -// -// On entry to each of these, the driverLock should be set. -// -// Set the current brightness -void IOHIDSystem::setBrightness(int b) -{ - if ( b < EV_SCREEN_MIN_BRIGHTNESS ) - b = EV_SCREEN_MIN_BRIGHTNESS; - else if ( b > EV_SCREEN_MAX_BRIGHTNESS ) - b = EV_SCREEN_MAX_BRIGHTNESS; - if ( b != curBright ) - { - curBright = b; - if ( autoDimmed == false ) - setBrightness(); - } -} - -int IOHIDSystem::brightness() -{ - return curBright; -} - -// Set the current brightness -void IOHIDSystem::setAutoDimBrightness(int b) -{ - if ( b < EV_SCREEN_MIN_BRIGHTNESS ) - b = EV_SCREEN_MIN_BRIGHTNESS; - else if ( b > EV_SCREEN_MAX_BRIGHTNESS ) - b = EV_SCREEN_MAX_BRIGHTNESS; - if ( b != dimmedBrightness ) - { - dimmedBrightness = b; - if ( autoDimmed == true ) - setBrightness(); - } -} - -int IOHIDSystem::autoDimBrightness() -{ - return dimmedBrightness; -} - -int IOHIDSystem::currentBrightness() // Return the current brightness -{ - if ( autoDimmed == true && dimmedBrightness < curBright ) - return dimmedBrightness; - else - return curBright; -} - -void IOHIDSystem::doAutoDim() -{ - autoDimmed = true; - setBrightness(); -} - -// Return display brightness to normal -void IOHIDSystem::undoAutoDim() -{ - autoDimmed = false; - setBrightness(); -} - -void IOHIDSystem::forceAutoDimState(bool dim) -{ - if ( dim == true ) - { - if ( autoDimmed == false ) - { - if ( eventsOpen == true ) - clock_get_uptime( &autoDimTime); - doAutoDim(); - } - } - else - { - if ( autoDimmed == true ) - { - if ( eventsOpen == true ) { - clock_get_uptime( &autoDimTime); - ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod); - } - undoAutoDim(); - } - } -} - -// -// API used to manipulate sound volume/attenuation -// -// Set the current brightness. -void IOHIDSystem::setAudioVolume(int v) -{ - if ( v < EV_AUDIO_MIN_VOLUME ) - v = EV_AUDIO_MIN_VOLUME; - else if ( v > EV_AUDIO_MAX_VOLUME ) - v = EV_AUDIO_MAX_VOLUME; - curVolume = v; -} - -// -// Volume set programatically, rather than from keyboard -// -void IOHIDSystem::setUserAudioVolume(int v) -{ - setAudioVolume(v); - // Let sound driver know about the change - evSpecialKeyMsg( NX_KEYTYPE_SOUND_UP, - /* direction */ NX_KEYDOWN, - /* flags */ 0, - /* level */ curVolume); -} - -int IOHIDSystem::audioVolume() -{ - return curVolume; -} - -// -// API used to drive event state out to attached screens -// -// On entry to each of these, the driverLock should be set. -// -inline void IOHIDSystem::setBrightness() // Propagate state out to screens -{ - evDispatch(/* command */ EVLEVEL); -} - -inline void IOHIDSystem::showCursor() -{ - evDispatch(/* command */ EVSHOW); -} -inline void IOHIDSystem::hideCursor() -{ - evDispatch(/* command */ EVHIDE); -} - -inline void IOHIDSystem::moveCursor() -{ - evDispatch(/* command */ EVMOVE); -} - -// -// - attachDefaultEventSources -// Attach the default event sources. -// -void IOHIDSystem::attachDefaultEventSources() -{ - OSObject * source; - OSIterator * sources; - - - sources = getProviderIterator(); - - if (!sources) return; - - while( (source = sources->getNextObject())) { - if (OSDynamicCast(IOHIDevice, source)) { - - registerEventSource((IOHIDevice *)source); - } - } - sources->release(); -} - -// -// - detachEventSources -// Detach all event sources -// -void IOHIDSystem::detachEventSources() -{ - OSIterator * iter; - IOHIDevice * srcInstance; - - iter = getOpenProviderIterator(); - if( iter) { - while( (srcInstance = (IOHIDevice *) iter->getNextObject())) { -#ifdef DEBUG - kprintf("detachEventSource:%s\n", srcInstance->getName()); -#endif - srcInstance->close(this); - } - iter->release(); - } -} - -// -// EventSrcClient implementation -// - -// -// A new device instance desires to be added to our list. -// Try to get ownership of the device. If we get it, add it to -// the list. -// -bool IOHIDSystem::registerEventSource(IOHIDevice * source) -{ - bool success = false; - -#ifdef DEBUG - kprintf("registerEventSource:%s\n", ((IOHIDevice*)source)->getName()); -#endif - - if ( OSDynamicCast(IOHIKeyboard, source) ) { - success = ((IOHIKeyboard*)source)->open(this, kIOServiceSeize, - (KeyboardEventAction) _keyboardEvent, - (KeyboardSpecialEventAction) _keyboardSpecialEvent, - (UpdateEventFlagsAction) _updateEventFlags); - } else if ( OSDynamicCast(IOHIPointing, source) ) { - success = ((IOHIPointing*)source)->open(this, kIOServiceSeize, - (RelativePointerEventAction) _relativePointerEvent, - (AbsolutePointerEventAction) _absolutePointerEvent, - (ScrollWheelEventAction) _scrollWheelEvent); - } - - if ( success == false ) - IOLog("%s: Seize of %s failed.\n", getName(), source->getName()); - - return success; -} - -IOReturn IOHIDSystem::message(UInt32 type, IOService * provider, - void * argument) -{ - IOReturn status = kIOReturnSuccess; - - switch (type) - { - case kIOMessageServiceIsTerminated: -#ifdef DEBUG - kprintf("detachEventSource:%s\n", provider->getName()); -#endif - provider->close( this ); - case kIOMessageServiceWasClosed: - break; - - default: - status = super::message(type, provider, argument); - break; - } - - return status; -} - -// -// This will scale the point at location in the coordinate system represented by bounds -// to the coordinate system of the current screen. -// This is needed for absolute pointer events that come from devices with different bounds. -// -void IOHIDSystem::_scaleLocationToCurrentScreen(Point *location, Bounds *bounds) -{ - // We probably also need to look at current screen offsets as well - // but that shouldn't matter until we provide tablets with a way to - // switch screens... - location->x = ((location->x - bounds->minx) * (cursorPin.maxx - cursorPin.minx + 1) - / (bounds->maxx - bounds->minx)) + cursorPin.minx; - location->y = ((location->y - bounds->miny) * (cursorPin.maxy - cursorPin.miny + 1) - / (bounds->maxy - bounds->miny)) + cursorPin.miny; - - return; -} - - -// -// Process a mouse status change. The driver should sign extend -// it's deltas and perform any bit flipping needed there. -// -// We take the state as presented and turn it into events. -// -void IOHIDSystem::_relativePointerEvent(IOHIDSystem * self, - int buttons, - /* deltaX */ int dx, - /* deltaY */ int dy, - /* atTime */ AbsoluteTime ts) -{ - self->relativePointerEvent(buttons, dx, dy, ts); -} - -void IOHIDSystem::relativePointerEvent(int buttons, - /* deltaX */ int dx, - /* deltaY */ int dy, - /* atTime */ AbsoluteTime ts) -{ - AbsoluteTime nextVBL, vblDeltaTime, eventDeltaTime, moveDeltaTime; - - if( displayManager != NULL ) // if there is a display manager, tell - displayManager->activityTickle(0,0); // it there is user activity - - IOTakeLock( driverLock); - if( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - // Fake up pressure changes from button state changes - if( (buttons & EV_LB) != (evg->buttons & EV_LB) ) - { - if ( buttons & EV_LB ) - lastPressure = MAXPRESSURE; - else - lastPressure = MINPRESSURE; - } - _setButtonState(buttons, /* atTime */ ts); - - // figure cursor movement - if( dx || dy ) - { - eventDeltaTime = ts; - SUB_ABSOLUTETIME( &eventDeltaTime, &lastEventTime ); - lastEventTime = ts; - - IOGraphicsDevice * instance = ((EvScreen*)evScreen)[cursorPinScreen].instance; - if( instance) - instance->getVBLTime( &nextVBL, &vblDeltaTime ); - else - nextVBL.hi = nextVBL.lo = vblDeltaTime.hi = vblDeltaTime.lo = 0; - - if( dx && ((dx ^ accumDX) < 0)) - accumDX = 0; - if( dy && ((dy ^ accumDY) < 0)) - accumDY = 0; - - KERNEL_DEBUG(0x0c000060 | DBG_FUNC_NONE, - nextVBL.hi, nextVBL.lo, postedVBLTime.hi, postedVBLTime.lo, 0); - - if( (nextVBL.lo || nextVBL.hi) - && (nextVBL.lo == postedVBLTime.lo) && (nextVBL.hi == postedVBLTime.hi)) { - accumDX += dx; - accumDY += dy; - - } else { - SInt32 num = 0, div = 0; - - dx += accumDX; - dy += accumDY; - - moveDeltaTime = ts; - SUB_ABSOLUTETIME( &moveDeltaTime, &lastMoveTime ); - lastMoveTime = ts; - - if( (eventDeltaTime.lo < vblDeltaTime.lo) && (0 == eventDeltaTime.hi) - && vblDeltaTime.lo && moveDeltaTime.lo) { - num = vblDeltaTime.lo; - div = moveDeltaTime.lo; - dx = (num * dx) / div; - dy = (num * dy) / div; - } - - KERNEL_DEBUG(0x0c000000 | DBG_FUNC_NONE, - dx, dy, num, div, 0); - - postedVBLTime = nextVBL; // we have posted for this vbl - accumDX = accumDY = 0; - - if( dx || dy ) { - pointerLoc.x += dx; - pointerLoc.y += dy; - pointerDelta.x += dx; - pointerDelta.y += dy; - _setCursorPosition(&pointerLoc, false); - } - } - } - IOUnlock( driverLock); -} - -void IOHIDSystem::_absolutePointerEvent(IOHIDSystem * self, - int buttons, - /* at */ Point * newLoc, - /* withBounds */ Bounds * bounds, - /* inProximity */ bool proximity, - /* withPressure */ int pressure, - /* withAngle */ int stylusAngle, - /* atTime */ AbsoluteTime ts) -{ - self->absolutePointerEvent(buttons, newLoc, bounds, proximity, - pressure, stylusAngle, ts); -} - -void IOHIDSystem::absolutePointerEvent(int buttons, - /* at */ Point * newLoc, - /* withBounds */ Bounds * bounds, - /* inProximity */ bool proximity, - /* withPressure */ int pressure, - /* withAngle */ int /* stylusAngle */, - /* atTime */ AbsoluteTime ts) - -{ - /* - * If you don't know what to pass for the following fields, pass the - * default values below: - * pressure = MINPRESSURE or MAXPRESSURE - * stylusAngle = 90 - */ - - NXEventData outData; /* dummy data */ - - if ( displayManager != NULL ) { // if there is a display manager, tell - displayManager->activityTickle(0,0); // it there is user activity - } - - IOTakeLock( driverLock); - if ( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - - lastPressure = pressure; - - _scaleLocationToCurrentScreen(newLoc, bounds); - if ( newLoc->x != pointerLoc.x || newLoc->y != pointerLoc.y ) - { - pointerDelta.x += (newLoc->x - pointerLoc.x); - pointerDelta.y += (newLoc->y - pointerLoc.y); - pointerLoc = *newLoc; - _setCursorPosition(&pointerLoc, false); - } - if ( lastProximity != proximity && proximity == true ) - { - evg->eventFlags |= NX_STYLUSPROXIMITYMASK; - bzero( (char *)&outData, sizeof outData ); - postEvent( NX_FLAGSCHANGED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - if ( proximity == true ) - _setButtonState(buttons, /* atTime */ ts); - if ( lastProximity != proximity && proximity == false ) - { - evg->eventFlags &= ~NX_STYLUSPROXIMITYMASK; - bzero( (char *)&outData, sizeof outData ); - postEvent( NX_FLAGSCHANGED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - lastProximity = proximity; - IOUnlock( driverLock); -} - -void IOHIDSystem::_scrollWheelEvent(IOHIDSystem * self, - short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - /* atTime */ AbsoluteTime ts) -{ - self->scrollWheelEvent(deltaAxis1, deltaAxis2, deltaAxis3, ts); -} - -void IOHIDSystem::scrollWheelEvent(short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - /* atTime */ AbsoluteTime ts) - -{ - NXEventData wheelData; - - if ((deltaAxis1 == 0) && (deltaAxis2 == 0) && (deltaAxis3 == 0)) { - return; - } - - IOTakeLock( driverLock); - if (!eventsOpen) - { - IOUnlock(driverLock); - return; - } - - bzero((char *)&wheelData, sizeof wheelData); - wheelData.scrollWheel.deltaAxis1 = deltaAxis1; - wheelData.scrollWheel.deltaAxis2 = deltaAxis2; - wheelData.scrollWheel.deltaAxis3 = deltaAxis3; - - postEvent( NX_SCROLLWHEELMOVED, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ &wheelData); - - IOUnlock(driverLock); - return; -} - -void IOHIDSystem::_tabletEvent(IOHIDSystem *self, - NXEventData *tabletData, - AbsoluteTime ts) -{ - self->tabletEvent(tabletData, ts); -} - -void IOHIDSystem::tabletEvent(NXEventData *tabletData, - AbsoluteTime ts) -{ - IOTakeLock(driverLock); - - if (eventsOpen) { - postEvent(NX_TABLETPOINTER, - (Point *)&evg->cursorLoc, - ts, - tabletData); - } - - IOUnlock(driverLock); - - return; -} - -void IOHIDSystem::_proximityEvent(IOHIDSystem *self, - NXEventData *proximityData, - AbsoluteTime ts) -{ - self->proximityEvent(proximityData, ts); -} - -void IOHIDSystem::proximityEvent(NXEventData *proximityData, - AbsoluteTime ts) -{ - IOTakeLock(driverLock); - - if (eventsOpen) { - postEvent(NX_TABLETPROXIMITY, - (Point *)&evg->cursorLoc, - ts, - proximityData); - } - - IOUnlock(driverLock); - - return; -} - -// -// Process a keyboard state change. -// -void IOHIDSystem::_keyboardEvent(IOHIDSystem * self, - unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts) -{ - self->keyboardEvent(eventType, flags, key, charCode, charSet, - origCharCode, origCharSet, keyboardType, repeat, ts); -} - -void IOHIDSystem::keyboardEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts) -{ - NXEventData outData; - - if ( ! (displayState & IOPMDeviceUsable) ) { // display is off, consume the keystroke - if ( eventType == NX_KEYDOWN ) { - return; - } - if ( displayManager != NULL ) { // but if there is a display manager, tell - displayManager->activityTickle(0,0); // it there is user activity - } - return; - } - - if ( displayManager != NULL ) { // if there is a display manager, tell - displayManager->activityTickle(0,0); // it there is user activity - } - - outData.key.repeat = repeat; - outData.key.keyCode = key; - outData.key.charSet = charSet; - outData.key.charCode = charCode; - outData.key.origCharSet = origCharSet; - outData.key.origCharCode = origCharCode; - outData.key.keyboardType = keyboardType; - - IOTakeLock( driverLock); - if ( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK) - | (flags & KEYBOARD_FLAGSMASK); - - postEvent( eventType, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - - IOUnlock( driverLock); -} - -void IOHIDSystem::_keyboardSpecialEvent( IOHIDSystem * self, - unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* specialty */ unsigned flavor, - /* guid */ UInt64 guid, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts) -{ - self->keyboardSpecialEvent(eventType, flags, key, flavor, guid, repeat, ts); -} - - -void IOHIDSystem::keyboardSpecialEvent( unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* specialty */ unsigned flavor, - /* guid */ UInt64 guid, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts) -{ - NXEventData outData; - int level = -1; - - bzero( (void *)&outData, sizeof outData ); - - IOTakeLock( driverLock); - if ( eventsOpen == false ) - { - IOUnlock( driverLock); - return; - } - - // Update flags. - evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK) - | (flags & KEYBOARD_FLAGSMASK); - - if ( eventType == NX_KEYDOWN ) - { - switch ( flavor ) - { - case NX_KEYTYPE_SOUND_UP: - if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) - { - //level = IOAudioManager::sharedInstance()->incrementMasterVolume(); - if (masterAudioFunctions && masterAudioFunctions->incrementMasterVolume) - { - masterAudioFunctions->incrementMasterVolume(); - } - } - else - { - if( !(evg->eventFlags & NX_COMMANDMASK) && - !(evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - (evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Open the sound preferences control panel. - KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser, kOpenPreferencePanel ); - } - } - break; - case NX_KEYTYPE_SOUND_DOWN: - if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) - { - //level = IOAudioManager::sharedInstance()->decrementMasterVolume(); - if (masterAudioFunctions && masterAudioFunctions->decrementMasterVolume) - { - masterAudioFunctions->decrementMasterVolume(); - } - } - else - { - if( !(evg->eventFlags & NX_COMMANDMASK) && - !(evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - (evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Open the sound preferences control panel. - KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser, kOpenPreferencePanel ); - } - } - break; - case NX_KEYTYPE_MUTE: - if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) - { - //level = IOAudioManager::sharedInstance()->toggleMasterMute(); - if (masterAudioFunctions && masterAudioFunctions->toggleMasterMute) - { - masterAudioFunctions->toggleMasterMute(); - } - } - else - { - if( !(evg->eventFlags & NX_COMMANDMASK) && - !(evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - (evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Open the sound preferences control panel. - KUNCExecute( "Sound.preference", kOpenAppAsConsoleUser, kOpenPreferencePanel ); - } - } - break; - case NX_KEYTYPE_EJECT: - - // Special key handlers: - // - // Command = invoke macsbug - // Command+option = sleep now - // Command+option+control = shutdown now - // Control = logout dialog - - if( (evg->eventFlags & NX_COMMANDMASK) && - !(evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - !(evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Post a power key event, Classic should pick this up and - // drop into MacsBug. - // - outData.compound.subType = NX_SUBTYPE_POWER_KEY; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - else if( (evg->eventFlags & NX_COMMANDMASK) && - !(evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - (evg->eventFlags & NX_ALTERNATEMASK) ) - { - //IOLog( "IOHIDSystem -- sleep now!\n" ); - - // Post the sleep now event. Someone else will handle the actual call. - // - outData.compound.subType = NX_SUBTYPE_SLEEP_EVENT; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - else if( (evg->eventFlags & NX_COMMANDMASK) && - (evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - (evg->eventFlags & NX_ALTERNATEMASK) ) - { - //IOLog( "IOHIDSystem -- shutdown now!\n" ); - - // Post the shutdown now event. Someone else will handle the actual call. - // - outData.compound.subType = NX_SUBTYPE_SHUTDOWN_EVENT; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - else if( (evg->eventFlags & NX_COMMANDMASK) && - (evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - !(evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Restart now! - //IOLog( "IOHIDSystem -- Restart now!\n" ); - - // Post the Restart now event. Someone else will handle the actual call. - // - outData.compound.subType = NX_SUBTYPE_RESTART_EVENT; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - else if( !(evg->eventFlags & NX_COMMANDMASK) && - (evg->eventFlags & NX_CONTROLMASK) && - !(evg->eventFlags & NX_SHIFTMASK) && - !(evg->eventFlags & NX_ALTERNATEMASK) ) - { - // Looks like we should put up the normal 'Power Key' dialog. - // - // Set the event flags to zero, because the system will not do the right - // thing if we don't zero this out (it will ignore the power key event - // we post, thinking that some modifiers are down). - // - evg->eventFlags = 0; - - // Post the power keydown event. - // - outData.compound.subType = NX_SUBTYPE_POWER_KEY; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - else - { - // After all that checking, no modifiers are down, so let's pump up a - // system defined eject event. This way we can have anyone who's watching - // for this event (aka LoginWindow) route this event to the right target - // (aka AutoDiskMounter). - - //IOLog( "IOHIDSystem--Normal Eject action!\n" ); - - // Post the eject keydown event. - // - outData.compound.subType = NX_SUBTYPE_EJECT_KEY; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - break; - - case NX_POWER_KEY: - outData.compound.subType = NX_SUBTYPE_POWER_KEY; - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - break; - } - } -#if 0 /* So far, nothing to do on keyup */ - else if ( eventType == NX_KEYUP ) - { - switch ( flavor ) - { - case NX_KEYTYPE_SOUND_UP: - break; - case NX_KEYTYPE_SOUND_DOWN: - break; - case NX_KEYTYPE_MUTE: - break; - case NX_POWER_KEY: - break; - } - } -#endif - if( (0 == (flags & SPECIALKEYS_MODIFIER_MASK)) - && ((1 << flavor) & NX_SPECIALKEY_POST_MASK)) { - outData.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; - outData.compound.misc.S[0] = flavor; - outData.compound.misc.C[2] = eventType; - outData.compound.misc.C[3] = repeat; - outData.compound.misc.L[1] = guid & 0xffffffff; - outData.compound.misc.L[2] = guid >> 32; - - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&pointerLoc, - /* atTime */ ts, - /* withData */ &outData); - } - - IOUnlock( driverLock); - if ( level != -1 ) // An interesting special key event occurred - { - evSpecialKeyMsg( flavor, - /* direction */ eventType, - /* flags */ flags, - /* level */ level); - } -} - -/* - * Update current event flags. Restricted to keyboard flags only, this - * method is used to silently update the flags state for keys which both - * generate characters and flag changes. The specs say we don't generate - * a flags-changed event for such keys. This method is also used to clear - * the keyboard flags on a keyboard subsystem reset. - */ -void IOHIDSystem::_updateEventFlags(IOHIDSystem * self, unsigned flags) -{ - self->updateEventFlags(flags); -} - -void IOHIDSystem::updateEventFlags(unsigned flags) -{ - IOTakeLock( driverLock); - if ( eventsOpen ) - evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK) - | (flags & KEYBOARD_FLAGSMASK); - IOUnlock( driverLock); -} - -// -// - _setButtonState:(int)buttons atTime:(int)t -// Update the button state. Generate button events as needed -// -void IOHIDSystem::_setButtonState(int buttons, - /* atTime */ AbsoluteTime ts) -{ - // Magic uber-mouse buttons changed event so we can get all of the buttons... - if(evg->buttons ^ buttons) - { - NXEventData evData; - unsigned long hwButtons, hwDelta, temp; - - /* I'd like to keep the event button mapping linear, so - I have to "undo" the LB/RB mouse bit numbering funkiness - before I pass the information down to the app. */ - /* Ideally this would all go away if we fixed EV_LB and EV_RB - to be bits 0 and 1 */ - hwButtons = buttons & ~7; /* Keep everything but bottom 3 bits. */ - hwButtons |= (buttons & 3) << 1; /* Map bits 01 to 12 */ - hwButtons |= (buttons & 4) >> 2; /* Map bit 2 back to bit 0 */ - temp = evg->buttons ^ buttons; - hwDelta = temp & ~7; - hwDelta |= (temp & 3) << 1; /* Map bits 01 to 12 */ - hwDelta |= (temp & 4) >> 2; /* Map bit 2 back to bit 0 */ - - evData.compound.reserved = 0; - evData.compound.subType = NX_SUBTYPE_AUX_MOUSE_BUTTONS; - evData.compound.misc.L[0] = hwDelta; - evData.compound.misc.L[1] = hwButtons; - - postEvent( NX_SYSDEFINED, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ &evData); - } - - if ((evg->buttons & EV_LB) != (buttons & EV_LB)) - { - if (buttons & EV_LB) - { - postEvent( NX_LMOUSEDOWN, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ NULL); - } - else - { - postEvent( NX_LMOUSEUP, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ NULL); - } - // After entering initial up/down event, set up - // coalescing state so drags will behave correctly - evg->dontCoalesce = evg->dontWantCoalesce; - if (evg->dontCoalesce) - evg->eventFlags |= NX_NONCOALSESCEDMASK; - else - evg->eventFlags &= ~NX_NONCOALSESCEDMASK; - } - - if ((evg->buttons & EV_RB) != (buttons & EV_RB)) { - if (buttons & EV_RB) { - postEvent( NX_RMOUSEDOWN, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ NULL); - } else { - postEvent( NX_RMOUSEUP, - /* at */ (Point *)&evg->cursorLoc, - /* atTime */ ts, - /* withData */ NULL); - } - } - - evg->buttons = buttons; -} -// -// Sets the cursor position (evg->cursorLoc) to the new -// location. The location is clipped against the cursor pin rectangle, -// mouse moved/dragged events are generated using the given event mask, -// and a mouse-exited event may be generated. The cursor image is -// moved. -// On entry, the driverLock should be set. -// -void IOHIDSystem::setCursorPosition(Point * newLoc, bool external) -{ - if ( eventsOpen == true ) - { - pointerDelta.x += (newLoc->x - pointerLoc.x); - pointerDelta.y += (newLoc->y - pointerLoc.y); - pointerLoc = *newLoc; - _setCursorPosition(newLoc, external); - } -} - -// -// This mechanism is used to update the cursor position, possibly generating -// messages to registered frame buffer devices and posting drag, tracking, and -// mouse motion events. -// -// On entry, the driverLock should be set. -// This can be called from setCursorPosition:(Point *)newLoc to set the -// position by a _IOSetParameterFromIntArray() call, directly from the absolute or -// relative pointer device routines, or on a timed event callback. -// -void IOHIDSystem::_setCursorPosition(Point * newLoc, bool external) -{ - bool cursorMoved = true; - - if (!screens) - return; - - if( ev_try_lock(&evg->cursorSema) == 0 ) // host using shmem - { - needSetCursorPosition = true; // try again later -// scheduleNextPeriodicEvent(); - return; - } - - // Past here we hold the cursorSema lock. Make sure the lock is - // cleared before returning or the system will be wedged. - - needSetCursorPosition = false; // We WILL succeed - - if (cursorCoupled || external) - { - UInt32 newScreens = 0; - SInt32 pinScreen = -1L; - - /* Get mask of screens on which the cursor is present */ - EvScreen *screen = (EvScreen *)evScreen; - for (int i = 0; i < screens; i++ ) { - if ((screen[i].instance) && PtInRect(newLoc, screen[i].bounds)) { - pinScreen = i; - newScreens |= (1 << i); - } - } - - if (newScreens == 0) { - /* At this point cursor has gone off all screens, - just clip it to one of the previous screens. */ - newLoc->x = (newLoc->x < cursorPin.minx) ? - cursorPin.minx : ((newLoc->x > cursorPin.maxx) ? - cursorPin.maxx : newLoc->x); - newLoc->y = (newLoc->y < cursorPin.miny) ? - cursorPin.miny : ((newLoc->y > cursorPin.maxy) ? - cursorPin.maxy : newLoc->y); - /* regenerate mask for new position */ - for (int i = 0; i < screens; i++ ) { - if ((screen[i].instance) && PtInRect(newLoc, screen[i].bounds)) { - pinScreen = i; - newScreens |= (1 << i); - } - } - } - - pointerLoc = *newLoc; // Sync up pointer with clipped cursor - /* Catch the no-move case */ - if ((evg->cursorLoc.x == newLoc->x) && (evg->cursorLoc.y == newLoc->y)) { - if ((pointerDelta.x == 0) && (pointerDelta.y == 0)) { - ev_unlock(&evg->cursorSema); - return; - } - cursorMoved = false; // mouse moved, but cursor didn't - } else { - evg->cursorLoc.x = newLoc->x; - evg->cursorLoc.y = newLoc->y; - - /* If cursor changed screens */ - if (newScreens != cursorScreens) { - hideCursor(); /* hide cursor on old screens */ - cursorScreens = newScreens; - cursorPin = *(((EvScreen*)evScreen)[pinScreen].bounds); - cursorPin.maxx--; /* Make half-open rectangle */ - cursorPin.maxy--; - cursorPinScreen = pinScreen; - showCursor(); - } else { - /* cursor moved on same screens */ - moveCursor(); - } - } - } else { - /* cursor uncoupled */ - pointerLoc.x = evg->cursorLoc.x; - pointerLoc.y = evg->cursorLoc.y; - } - - AbsoluteTime ts; - clock_get_uptime(&ts); - - /* See if anybody wants the mouse moved or dragged events */ - if (evg->movedMask) { - if ((evg->movedMask&NX_LMOUSEDRAGGEDMASK)&&(evg->buttons& EV_LB)) { - _postMouseMoveEvent(NX_LMOUSEDRAGGED, newLoc, ts); - } else if ((evg->movedMask&NX_RMOUSEDRAGGEDMASK) && (evg->buttons & EV_RB)) { - _postMouseMoveEvent(NX_RMOUSEDRAGGED, newLoc, ts); - } else if (evg->movedMask & NX_MOUSEMOVEDMASK) { - _postMouseMoveEvent(NX_MOUSEMOVED, newLoc, ts); - } - } - - /* check new cursor position for leaving evg->mouseRect */ - if (cursorMoved && evg->mouseRectValid && (!PtInRect(newLoc, &evg->mouseRect))) - { - if (evg->mouseRectValid) - { - postEvent( NX_MOUSEEXITED, - /* at */ newLoc, - /* atTime */ ts, - /* withData */ NULL); - evg->mouseRectValid = 0; - } - } - ev_unlock(&evg->cursorSema); -} - -void IOHIDSystem::_postMouseMoveEvent(int what, - Point * location, - AbsoluteTime ts) -{ - NXEventData data; - - data.mouseMove.dx = pointerDelta.x; - data.mouseMove.dy = pointerDelta.y; - - pointerDelta.x = 0; - pointerDelta.y = 0; - - postEvent(what, location, ts, &data); -} - -/** - ** IOUserClient methods - **/ - -IOReturn IOHIDSystem::newUserClient(task_t /* owningTask */, - /* withToken */ void * /* security_id */, - /* ofType */ UInt32 type, - /* client */ IOUserClient ** handler) -{ - IOUserClient * newConnect = 0; - IOReturn err = kIOReturnNoMemory; - - IOTakeLock( driverLock); - - do { - if( type == kIOHIDParamConnectType) { - if( paramConnect) { - newConnect = paramConnect; - newConnect->retain(); - } else if( eventsOpen) { - newConnect = new IOHIDParamUserClient; - } else { - err = kIOReturnNotOpen; - continue; - } - - } else if( type == kIOHIDServerConnectType) { - newConnect = new IOHIDUserClient; - } else - err = kIOReturnUnsupported; - - if( !newConnect) - continue; - - // initialization is getting out of hand - - if( (newConnect != paramConnect) && ( - (false == newConnect->init()) - || (false == newConnect->attach( this )) - || (false == newConnect->start( this )) - || ((type == kIOHIDServerConnectType) - && (err = evOpen())) - )) { - newConnect->detach( this ); - newConnect->release(); - newConnect = 0; - continue; - } - if( type == kIOHIDParamConnectType) - paramConnect = newConnect; - err = kIOReturnSuccess; - - } while( false ); - - IOUnlock( driverLock); - - *handler = newConnect; - return( err ); -} - - -IOReturn IOHIDSystem::setEventsEnable(void*p1,void*,void*,void*,void*,void*) -{ // IOMethod - bool enable = (bool)p1; - - if( enable) { - attachDefaultEventSources(); - _resetMouseParameters(); - _resetKeyboardParameters(); - } - return( kIOReturnSuccess); -} - -IOReturn IOHIDSystem::setCursorEnable(void*p1,void*,void*,void*,void*,void*) -{ // IOMethod - bool enable = (bool)p1; - IOReturn err = kIOReturnSuccess; - - IOTakeLock( driverLock); - if ( eventsOpen == false ) { - IOUnlock( driverLock); - return( kIOReturnNotOpen ); - } - - if( 0 == screens) { // Should be at least 1! - IOUnlock( driverLock); - return( kIOReturnNoDevice ); - } - - if( enable) { - if( cursorStarted) { - hideCursor(); - cursorEnabled = resetCursor(); - showCursor(); - } else - cursorEnabled = startCursor(); - } else - cursorEnabled = enable; - - cursorCoupled = cursorEnabled; - - IOUnlock( driverLock); - - return( err); -} - -IOReturn IOHIDSystem::extPostEvent(void*p1,void*,void*,void*,void*,void*) -{ // IOMethod - struct evioLLEvent * event = (struct evioLLEvent *)p1; - - IOTakeLock( driverLock); - - if( event->setCursor) - setCursorPosition(&event->location, true); - - if( event->setFlags) - evg->eventFlags = (evg->eventFlags & ~KEYBOARD_FLAGSMASK) - | (event->flags & KEYBOARD_FLAGSMASK); - - AbsoluteTime ts; - clock_get_uptime(&ts); - postEvent( event->type, - /* at */ &event->location, - /* atTime */ ts, - /* withData */ &event->data); - - IOUnlock( driverLock); - return( kIOReturnSuccess); -} - -IOReturn IOHIDSystem::extSetMouseLocation(void*p1,void*,void*,void*,void*,void*) -{ // IOMethod - Point * loc = (Point *)p1; - - IOTakeLock( driverLock); - setCursorPosition(loc, true); - IOUnlock( driverLock); - return( kIOReturnSuccess); -} - -IOReturn IOHIDSystem::extGetButtonEventNum(void*p1,void*p2,void*,void*,void*,void*) -{ // IOMethod - NXMouseButton button = (NXMouseButton)(int)p1; - int * eventNum = (int *)p2; - IOReturn err = kIOReturnSuccess; - - IOTakeLock( driverLock); - switch( button) { - case NX_LeftButton: - *eventNum = leftENum; - break; - case NX_RightButton: - *eventNum = rightENum; - break; - default: - err = kIOReturnBadArgument; - } - - IOUnlock( driverLock); - return( err); -} - -bool IOHIDSystem::updateProperties( void ) -{ - UInt64 clickTimeThreshNano; - UInt64 autoDimThresholdNano; - UInt64 autoDimTimeNano; - UInt64 idleTimeNano; - AbsoluteTime time1, time2; - bool ok; - - absolutetime_to_nanoseconds( clickTimeThresh, &clickTimeThreshNano); - absolutetime_to_nanoseconds( autoDimPeriod, &autoDimThresholdNano); - if( eventsOpen) { - clock_get_uptime( &time1); - if( autoDimmed) { - autoDimTimeNano = 0; - // now - (autoDimTime - autoDimPeriod) - SUB_ABSOLUTETIME( &time1, &autoDimTime); - ADD_ABSOLUTETIME( &time1, &autoDimPeriod); - absolutetime_to_nanoseconds( time1, &idleTimeNano); - } else { - // autoDimTime - now - time2 = autoDimTime; - SUB_ABSOLUTETIME( &time2, &time1); - absolutetime_to_nanoseconds( time2, &autoDimTimeNano); - // autoDimPeriod - (autoDimTime - evg->VertRetraceClock) - time1 = autoDimPeriod; - SUB_ABSOLUTETIME( &time1, &time2); - absolutetime_to_nanoseconds( time1, &idleTimeNano); - } - } else { - absolutetime_to_nanoseconds( autoDimPeriod, &autoDimTimeNano); - idleTimeNano = 0; // user is active - } - - ok = setProperty( kIOHIDClickTimeKey, &clickTimeThreshNano, - sizeof( UInt64)) - & setProperty( kIOHIDClickSpaceKey, &clickSpaceThresh, - sizeof( clickSpaceThresh)) - & setProperty( kIOHIDAutoDimThresholdKey, &autoDimThresholdNano, - sizeof( UInt64)) - & setProperty( kIOHIDAutoDimTimeKey, &autoDimTimeNano, - sizeof( UInt64)) - & setProperty( kIOHIDIdleTimeKey, &idleTimeNano, - sizeof( UInt64)) - & setProperty( kIOHIDAutoDimStateKey, &autoDimmed, - sizeof( autoDimmed)) - & setProperty( kIOHIDBrightnessKey, &curBright, - sizeof( curBright)) - & setProperty( kIOHIDAutoDimBrightnessKey, &dimmedBrightness, - sizeof( dimmedBrightness)); - - return( ok ); -} - -bool IOHIDSystem::serializeProperties( OSSerialize * s ) const -{ - ((IOHIDSystem *) this)->updateProperties(); - - return( super::serializeProperties( s )); -} - -IOReturn IOHIDSystem::setParamProperties( OSDictionary * dict ) -{ - OSData * data; - IOReturn err = kIOReturnSuccess; - - IOTakeLock( driverLock); - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDClickTimeKey)))) - { - UInt64 nano = *((UInt64 *)(data->getBytesNoCopy())); - nanoseconds_to_absolutetime(nano, &clickTimeThresh); - } - if( (data = OSDynamicCast( OSData, - dict->getObject(kIOHIDClickSpaceKey)))) { - clickSpaceThresh.x = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_X]; - clickSpaceThresh.y = ((UInt32 *) (data->getBytesNoCopy()))[EVSIOSCS_Y]; - } - - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimThresholdKey)))) { - AbsoluteTime oldPeriod = autoDimPeriod; - UInt64 nano = *((UInt64 *)(data->getBytesNoCopy())); - nanoseconds_to_absolutetime(nano, &autoDimPeriod); - // autoDimTime = autoDimTime - oldPeriod + autoDimPeriod; - SUB_ABSOLUTETIME( &autoDimTime, &oldPeriod); - ADD_ABSOLUTETIME( &autoDimTime, &autoDimPeriod); - } - - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimStateKey)))) - forceAutoDimState( 0 != *((SInt32 *) (data->getBytesNoCopy()))); - - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDBrightnessKey)))) - setBrightness( *((SInt32 *) (data->getBytesNoCopy()))); - - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDAutoDimBrightnessKey)))) - setAutoDimBrightness( *((SInt32 *) (data->getBytesNoCopy()))); - - IOUnlock( driverLock); - - return( err ); -} - diff --git a/iokit/Families/IOHIDSystem/IOHIDUserClient.cpp b/iokit/Families/IOHIDSystem/IOHIDUserClient.cpp deleted file mode 100644 index a4e1906b2..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDUserClient.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - - -#include <IOKit/IOLib.h> -#include <libkern/c++/OSContainers.h> - -#include "IOHIDUserClient.h" - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOUserClient - -OSDefineMetaClassAndStructors(IOHIDUserClient, IOUserClient) - -OSDefineMetaClassAndStructors(IOHIDParamUserClient, IOUserClient) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOHIDUserClient::start( IOService * _owner ) -{ - static const IOExternalMethod methodTemplate[] = { -/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 1 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 3 */ { NULL, NULL, kIOUCStructIStructO, sizeof(struct evioLLEvent), 0 }, -/* 4 */ { NULL, NULL, kIOUCStructIStructO, sizeof(Point), 0 }, -/* 5 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 1 } - }; - - if( !super::start( _owner )) - return( false); - - owner = (IOHIDSystem *) _owner; - - bcopy( methodTemplate, externals, sizeof( methodTemplate )); - - externals[0].object = owner; - externals[0].func = (IOMethod) &IOHIDSystem::createShmem; - - externals[1].object = owner; - externals[1].func = (IOMethod) &IOHIDSystem::setEventsEnable; - - externals[2].object = owner; - externals[2].func = (IOMethod) &IOHIDSystem::setCursorEnable; - - externals[3].object = owner; - externals[3].func = (IOMethod) &IOHIDSystem::extPostEvent; - - externals[4].object = owner; - externals[4].func = (IOMethod) &IOHIDSystem::extSetMouseLocation; - - externals[5].object = owner; - externals[5].func = (IOMethod) &IOHIDSystem::extGetButtonEventNum; - - return( true ); -} - -IOReturn IOHIDUserClient::clientClose( void ) -{ - owner->evClose(); -#ifdef DEBUG - kprintf("%s: client token invalidated\n", getName()); -#endif - - owner->serverConnect = 0; - detach( owner); - - return( kIOReturnSuccess); -} - -IOService * IOHIDUserClient::getService( void ) -{ - return( owner ); -} - -IOReturn IOHIDUserClient::registerNotificationPort( - mach_port_t port, - UInt32 type, - UInt32 refCon ) -{ - if( type != kIOHIDEventNotification) - return( kIOReturnUnsupported); - - owner->setEventPort(port); - return( kIOReturnSuccess); -} - -IOReturn IOHIDUserClient::connectClient( IOUserClient * client ) -{ - Bounds * bounds; - IOGraphicsDevice * graphicsDevice; - - // yikes - if( 0 == (graphicsDevice = OSDynamicCast(IOGraphicsDevice, - client->getProvider())) ) - return( kIOReturnBadArgument ); - - graphicsDevice->getBoundingRect(&bounds); - - owner->registerScreen(graphicsDevice, bounds); - - return( kIOReturnSuccess); -} - -IOReturn IOHIDUserClient::clientMemoryForType( UInt32 type, - UInt32 * flags, IOMemoryDescriptor ** memory ) -{ - - if( type != kIOHIDGlobalMemory) - return( kIOReturnBadArgument); - - *flags = 0; - owner->globalMemory->retain(); - *memory = owner->globalMemory; - - return( kIOReturnSuccess); -} - -IOExternalMethod * IOHIDUserClient::getExternalMethodForIndex( UInt32 index ) -{ - if( index < (sizeof( externals) / sizeof( externals[0]))) - return( externals + index); - else - return( NULL); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOHIDParamUserClient::start( IOService * _owner ) -{ - static const IOExternalMethod methodTemplate[] = { -/* 0 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 1 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 2 */ { NULL, NULL, kIOUCScalarIScalarO, 1, 0 }, -/* 3 */ { NULL, NULL, kIOUCStructIStructO, sizeof(struct evioLLEvent), 0 }, -/* 4 */ { NULL, NULL, kIOUCStructIStructO, sizeof(Point), 0 }, - }; - - if( !super::start( _owner )) - return( false); - - owner = (IOHIDSystem *) _owner; - - bcopy( methodTemplate, externals, sizeof( methodTemplate )); - - externals[3].object = owner; - externals[3].func = (IOMethod) &IOHIDSystem::extPostEvent; - - externals[4].object = owner; - externals[4].func = (IOMethod) &IOHIDSystem::extSetMouseLocation; - - return( true ); -} - -void IOHIDParamUserClient::free( void ) -{ - retain(); retain(); - owner->paramConnect = 0; - detach( owner); - super::free(); -} - -void IOHIDParamUserClient::release() const -{ - super::release(2); -} - - -IOReturn IOHIDParamUserClient::clientClose( void ) -{ - return( kIOReturnSuccess); -} - -IOService * IOHIDParamUserClient::getService( void ) -{ - return( owner ); -} - -IOExternalMethod * IOHIDParamUserClient::getExternalMethodForIndex( - UInt32 index ) -{ - // get the same library function to work for param & server connects - if( (index >= 3) - && (index < (sizeof( externals) / sizeof( externals[0])))) - return( externals + index); - else - return( NULL); -} - -IOReturn IOHIDParamUserClient::setProperties( OSObject * properties ) -{ - OSDictionary * dict; - OSIterator * iter; - IOHIDevice * eventSrc; - IOReturn err = kIOReturnSuccess; - IOReturn ret; - - dict = OSDynamicCast( OSDictionary, properties ); - if( dict) { - ret = owner->setParamProperties( dict ); - if( (ret != kIOReturnSuccess) && (ret != kIOReturnBadArgument)) - err = ret; - iter = owner->getOpenProviderIterator(); - - if( iter) { - while( (eventSrc = (IOHIDevice *) iter->getNextObject())) { - ret = eventSrc->setParamProperties( dict ); - if( (ret != kIOReturnSuccess) && (ret != kIOReturnBadArgument)) - err = ret; - } - iter->release(); - } - } else - err = kIOReturnBadArgument; - - return( err ); -} - diff --git a/iokit/Families/IOHIDSystem/IOHIDUserClient.h b/iokit/Families/IOHIDSystem/IOHIDUserClient.h deleted file mode 100644 index 84f842cae..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDUserClient.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - */ - - -#ifndef _IOKIT_IOHIDUSERCLIENT_H -#define _IOKIT_IOHIDUSERCLIENT_H - -#include <IOKit/IOUserClient.h> -#include <IOKit/hidsystem/IOHIDSystem.h> - - -class IOHIDUserClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOHIDUserClient) - -private: - - IOHIDSystem * owner; - - IOExternalMethod externals[ 6 ]; - -public: - // IOUserClient methods - virtual IOReturn clientClose( void ); - - virtual IOService * getService( void ); - - virtual IOReturn registerNotificationPort( - mach_port_t port, UInt32 type, UInt32 refCon ); - - virtual IOReturn connectClient( IOUserClient * client ); - - virtual IOReturn clientMemoryForType( UInt32 type, - UInt32 * flags, IOMemoryDescriptor ** memory ); - - virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ); - - // others - - bool start( IOService * provider ); - -}; - - -class IOHIDParamUserClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOHIDParamUserClient) - -private: - - IOHIDSystem * owner; - - IOExternalMethod externals[ 5 ]; - -public: - // OSObject methods - virtual void free( void ); - - virtual void release() const; - - // IOUserClient methods - virtual IOReturn clientClose( void ); - - virtual IOService * getService( void ); - - virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ); - - // others - - bool start( IOService * provider ); - virtual IOReturn setProperties( OSObject * properties ); - -}; - - -#endif /* ! _IOKIT_IOHIDUSERCLIENT_H */ diff --git a/iokit/Families/IOHIDSystem/IOHIDevice.cpp b/iokit/Families/IOHIDSystem/IOHIDevice.cpp deleted file mode 100644 index ad51bd67c..000000000 --- a/iokit/Families/IOHIDSystem/IOHIDevice.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/assert.h> -#include <IOKit/IOService.h> -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHIDParameter.h> - -#define super IOService -OSDefineMetaClassAndStructors(IOHIDevice, IOService); - -bool IOHIDevice::init(OSDictionary * properties) -{ - if (!super::init(properties)) return false; - - /* - * Initialize minimal state. - */ - - return true; -} - -void IOHIDevice::free() -{ - super::free(); -} - -IOHIDKind IOHIDevice::hidKind() -{ - return kHIUnknownDevice; -} - -UInt32 IOHIDevice::interfaceID() -{ - return 0; -} - -UInt32 IOHIDevice::deviceType() -{ - return 0; -} - -UInt64 IOHIDevice::getGUID() -{ - return(0xffffffffffffffffULL); -} - -bool IOHIDevice::updateProperties( void ) -{ - bool ok; - - ok = setProperty( kIOHIDKindKey, hidKind(), 32 ) - & setProperty( kIOHIDInterfaceIDKey, interfaceID(), 32 ) - & setProperty( kIOHIDSubinterfaceIDKey, deviceType(), 32 ); - - return( ok ); -} - -IOReturn IOHIDevice::setParamProperties( OSDictionary * dict ) -{ - return( kIOReturnSuccess ); -} - - diff --git a/iokit/Families/IOHIDSystem/IOHIKeyboard.cpp b/iokit/Families/IOHIDSystem/IOHIKeyboard.cpp deleted file mode 100644 index f0f9c14b5..000000000 --- a/iokit/Families/IOHIDSystem/IOHIKeyboard.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * - * From EventSrcPCKeyoard.m - PC Keyboard EventSrc subclass implementation - * Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * 20-Dec-00 bubba Save global repeat and delay values when - * devices are unplugged. Restore when device is reset. - * 24-Jan-01 bubba Don't auto-repeat on Power Key. This prevents infinite power key - * events from being generated when this key is hit on ADB keyboards. - */ - -#include <IOKit/IOLib.h> -#include <IOKit/hidsystem/IOHIKeyboard.h> -#include <IOKit/hidsystem/IOHIKeyboardMapper.h> -#include <IOKit/hidsystem/IOLLEvent.h> -#include <IOKit/hidsystem/IOHIDParameter.h> - -AbsoluteTime gKeyRepeat = { 0 }; // Delay between key repeats -AbsoluteTime gInitialKeyRepeat = { 0 }; // Delay before initial key repeat - -#define super IOHIDevice -OSDefineMetaClassAndStructors(IOHIKeyboard, IOHIDevice); - -bool IOHIKeyboard::init(OSDictionary * properties) -{ - if (!super::init(properties)) return false; - - /* - * Initialize minimal state. - */ - - _deviceLock = IOLockAlloc(); - _keyMap = 0; - _keyStateSize = 4*((maxKeyCodes()+(EVK_BITS_PER_UNIT-1))/EVK_BITS_PER_UNIT); - _keyState = (UInt32 *) IOMalloc(_keyStateSize); - - if (!_deviceLock || !_keyState) return false; - - IOLockInit(_deviceLock); - bzero(_keyState, _keyStateSize); - - return true; -} - -bool IOHIKeyboard::start(IOService * provider) -{ - if (!super::start(provider)) return false; - - /* - * IOHIKeyboard serves both as a service and a nub (we lead a double - * life). Register ourselves as a nub to kick off matching. - */ - - registerService(); - - return true; -} - -void IOHIKeyboard::free() -// Description: Go Away. Be careful when freeing the lock. -{ - IOLock * lock = NULL; - - // Save repeat rate and delay, so when we are replugged we'll be ready - // with the right values. - // - gKeyRepeat = _keyRepeat; - gInitialKeyRepeat = _initialKeyRepeat; - - if ( _deviceLock ) - { - lock = _deviceLock; - IOTakeLock( lock); - _deviceLock = NULL; - } - if ( _keyMap ) - _keyMap->release(); - if( _keyState ) - IOFree( _keyState, _keyStateSize); - if ( lock ) - { - IOUnlock( lock); - IOLockFree( lock); - } - super::free(); -} - -IOHIDKind IOHIKeyboard::hidKind() -{ - return kHIKeyboardDevice; -} - -bool IOHIKeyboard::updateProperties( void ) -{ - UInt64 keyRepeatNano; - UInt64 initialKeyRepeatNano; - bool ok; - - absolutetime_to_nanoseconds( _keyRepeat, &keyRepeatNano); - absolutetime_to_nanoseconds( _initialKeyRepeat, &initialKeyRepeatNano); - - ok = setProperty( kIOHIDKeyMappingKey, _keyMap ) - & setProperty( kIOHIDKeyRepeatKey, &keyRepeatNano, - sizeof(keyRepeatNano)) - & setProperty( kIOHIDInitialKeyRepeatKey, &initialKeyRepeatNano, - sizeof(initialKeyRepeatNano)); - - return( ok & super::updateProperties() ); -} - -IOReturn IOHIKeyboard::setParamProperties( OSDictionary * dict ) -{ - OSData * data; - IOReturn err = kIOReturnSuccess; - unsigned char * map; - IOHIKeyboardMapper * oldMap; - bool updated = false; - UInt64 nano; - IOTakeLock( _deviceLock); - - if( (data = OSDynamicCast( OSData, - dict->getObject(kIOHIDKeyRepeatKey)))) { - - nano = *((UInt64 *)(data->getBytesNoCopy())); - if( nano < EV_MINKEYREPEAT) - nano = EV_MINKEYREPEAT; - nanoseconds_to_absolutetime(nano, &_keyRepeat); - updated = true; - } - - if( (data = OSDynamicCast( OSData, - dict->getObject(kIOHIDInitialKeyRepeatKey)))) { - - nano = *((UInt64 *)(data->getBytesNoCopy())); - if( nano < EV_MINKEYREPEAT) - nano = EV_MINKEYREPEAT; - nanoseconds_to_absolutetime(nano, &_initialKeyRepeat); - updated = true; - } - - if( (data = OSDynamicCast( OSData, dict->getObject(kIOHIDKeyMappingKey)))) { - - map = (unsigned char *)IOMalloc( data->getLength() ); - bcopy( data->getBytesNoCopy(), map, data->getLength() ); - oldMap = _keyMap; - _keyMap = IOHIKeyboardMapper::keyboardMapper(this, map, data->getLength(), true); - if (_keyMap) { - if (oldMap) - oldMap->release(); - updated = true; - } else { - _keyMap = oldMap; - err = kIOReturnBadArgument; - } - } - IOUnlock( _deviceLock); - - if( dict->getObject(kIOHIDResetKeyboardKey)) - resetKeyboard(); - - if( updated ) - updateProperties(); - - return( err ); -} - -bool IOHIKeyboard::resetKeyboard() -// Description: Reset the keymapping to the default value and reconfigure -// the keyboards. -{ - const unsigned char *defaultKeymap; - UInt32 defaultKeymapLength; - - IOTakeLock( _deviceLock); - - if ( _keyMap ) - _keyMap->release(); - - // Set up default keymapping. - defaultKeymap = defaultKeymapOfLength(&defaultKeymapLength); - - _keyMap = IOHIKeyboardMapper::keyboardMapper( this, - defaultKeymap, - defaultKeymapLength, - false ); - if (_keyMap) - { - clock_interval_to_absolutetime_interval( EV_DEFAULTKEYREPEAT, - kNanosecondScale, &_keyRepeat); - clock_interval_to_absolutetime_interval( EV_DEFAULTINITIALREPEAT, - kNanosecondScale, &_initialKeyRepeat); - } - - // Use our globals if valid. That way, if we are unplugged and replugged, we'll - // have the proper values, instead of the lame default values. - // - if( gKeyRepeat.lo > 0 ) _keyRepeat = gKeyRepeat; - if( gInitialKeyRepeat.lo > 0 ) _initialKeyRepeat = gInitialKeyRepeat; - - updateProperties(); - - _interfaceType = interfaceID(); - _deviceType = deviceType(); - _guid = getGUID(); - - IOUnlock( _deviceLock); - return (_keyMap) ? true : false; -} - -void IOHIKeyboard::scheduleAutoRepeat() -// Description: Schedule a procedure to be called when a timeout has expired -// so that we can generate a repeated key. -// Preconditions: -// * _deviceLock should be held on entry -{ - if ( _calloutPending == true ) - { - thread_call_func_cancel(_autoRepeat, this, true); - _calloutPending = false; - } - if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) - { - AbsoluteTime deadline; - clock_absolutetime_interval_to_deadline(_downRepeatTime, &deadline); - thread_call_func_delayed(_autoRepeat, this, deadline); - _calloutPending = true; - } -} - -void IOHIKeyboard::_autoRepeat(thread_call_param_t arg, - thread_call_param_t) /* thread_call_func_t */ -{ - IOHIKeyboard *self = (IOHIKeyboard *) arg; - self->autoRepeat(); -} - -void IOHIKeyboard::autoRepeat() -// Description: Repeat the currently pressed key and schedule ourselves -// to be called again after another interval elapses. -// Preconditions: -// * Should only be executed on callout thread -// * _deviceLock should be unlocked on entry. -{ - IOTakeLock( _deviceLock); - if ( _calloutPending == false ) - { - IOUnlock( _deviceLock); - return; - } - _calloutPending = false; - _isRepeat = true; - - if ( AbsoluteTime_to_scalar(&_downRepeatTime) ) - { - // Device is due to generate a repeat - if (_keyMap) _keyMap->translateKeyCode(_codeToRepeat, - /* direction */ true, - /* keyBits */ _keyState); - _downRepeatTime = _keyRepeat; - } - - _isRepeat = false; - scheduleAutoRepeat(); - IOUnlock( _deviceLock); -} - -void IOHIKeyboard::setRepeat(unsigned eventType, unsigned keyCode) -// Description: Set up or tear down key repeat operations. The method -// that locks _deviceLock is a bit higher on the call stack. -// This method is invoked as a side effect of our own -// invocation of _keyMap->translateKeyCode(). -// Preconditions: -// * _deviceLock should be held upon entry. -{ - if ( _isRepeat == false ) // make sure we're not already repeating - { - if (eventType == NX_KEYDOWN) // Start repeat - { - // Set this key to repeat (push out last key if present) - _downRepeatTime = _initialKeyRepeat; // + _lastEventTime; - _codeToRepeat = keyCode; - // reschedule key repeat event here - scheduleAutoRepeat(); - } - else if (eventType == NX_KEYUP) // End repeat - { - /* Remove from downKey */ - if (_codeToRepeat == keyCode) - { - AbsoluteTime_to_scalar(&_downRepeatTime) = 0; - _codeToRepeat = (unsigned)-1; - scheduleAutoRepeat(); - } - } - } -} - -// -// BEGIN: Implementation of the methods required by IOHIKeyboardMapper. -// - -void IOHIKeyboard::keyboardEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned keyCode, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet) -// Description: We use this notification to set up our _keyRepeat timer -// and to pass along the event to our owner. This method -// will be called while the KeyMap object is processing -// the key code we've sent it using deliverKey. -{ - - if (_keyboardEventAction) /* upstream call */ - { - (*_keyboardEventAction)(_keyboardEventTarget, - eventType, - /* flags */ flags, - /* keyCode */ keyCode, - /* charCode */ charCode, - /* charSet */ charSet, - /* originalCharCode */ origCharCode, - /* originalCharSet */ origCharSet, - /* keyboardType */ _deviceType, - /* repeat */ _isRepeat, - /* atTime */ _lastEventTime); - } - - - if( keyCode == _keyMap->getParsedSpecialKey(NX_KEYTYPE_CAPS_LOCK) || - keyCode == _keyMap->getParsedSpecialKey(NX_POWER_KEY) ) - { - //Don't repeat caps lock on ADB/USB. 0x39 is default ADB code. - // We are here because KeyCaps needs to see 0x39 as a real key, - // not just another modifier bit. - - if (_interfaceType == NX_EVS_DEVICE_INTERFACE_ADB) - { - return; - } - } - - // Set up key repeat operations here. - setRepeat(eventType, keyCode); -} - -void IOHIKeyboard::keyboardSpecialEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned keyCode, - /* specialty */ unsigned flavor) -// Description: See the description for keyboardEvent. -{ - - if (_keyboardSpecialEventAction) /* upstream call */ - { - (*_keyboardSpecialEventAction)(_keyboardSpecialEventTarget, - eventType, - /* flags */ flags, - /* keyCode */ keyCode, - /* specialty */ flavor, - /* guid */ _guid, - /* repeat */ _isRepeat, - /* atTime */ _lastEventTime); - } - - // Set up key repeat operations here. - - // Don't repeat caps lock, numlock or power key. - // - if ( (flavor != NX_KEYTYPE_CAPS_LOCK) && (flavor != NX_KEYTYPE_NUM_LOCK) && - (flavor != NX_POWER_KEY) ) - { - setRepeat(eventType, keyCode); - } -} - -void IOHIKeyboard::updateEventFlags(unsigned flags) -// Description: Process non-event-generating flag changes. Simply pass this -// along to our owner. -{ - if (_updateEventFlagsAction) /* upstream call */ - { - (*_updateEventFlagsAction)(_updateEventFlagsTarget, flags); - } -} - -unsigned IOHIKeyboard::eventFlags() -// Description: Return global event flags In this world, there is only -// one keyboard device so device flags == global flags. -{ - return _eventFlags; -} - -unsigned IOHIKeyboard::deviceFlags() -// Description: Return per-device event flags. In this world, there is only -// one keyboard device so device flags == global flags. -{ - return _eventFlags; -} - -void IOHIKeyboard::setDeviceFlags(unsigned flags) -// Description: Set device event flags. In this world, there is only -// one keyboard device so device flags == global flags. -{ - _eventFlags = flags; -} - -bool IOHIKeyboard::alphaLock() -// Description: Return current alpha-lock state. This is a state tracking -// callback used by the KeyMap object. -{ - return _alphaLock; -} - -void IOHIKeyboard::setAlphaLock(bool val) -// Description: Set current alpha-lock state This is a state tracking -// callback used by the KeyMap object. -{ - _alphaLock = val; - setAlphaLockFeedback(val); -} - -bool IOHIKeyboard::numLock() -{ - return _numLock; -} - -void IOHIKeyboard::setNumLock(bool val) -{ - _numLock = val; - setNumLockFeedback(val); -} - -bool IOHIKeyboard::charKeyActive() -// Description: Return true If a character generating key down This is a state -// tracking callback used by the KeyMap object. -{ - return _charKeyActive; -} - -void IOHIKeyboard::setCharKeyActive(bool val) -// Description: Note whether a char generating key is down. This is a state -// tracking callback used by the KeyMap object. -{ - _charKeyActive = val; -} -// -// END: Implementation of the methods required by IOHIKeyboardMapper. -// - -void IOHIKeyboard::dispatchKeyboardEvent(unsigned int keyCode, - /* direction */ bool goingDown, - /* timeStamp */ AbsoluteTime time) -// Description: This method is the heart of event dispatching. The overlying -// subclass invokes this method with each event. We then -// get the event xlated and dispatched using a _keyMap instance. -// The event structure passed in by reference should not be freed. -{ - _lastEventTime = time; - - IOTakeLock( _deviceLock); - - if (_keyMap) _keyMap->translateKeyCode(keyCode, - /* direction */ goingDown, - /* keyBits */ _keyState); - IOUnlock( _deviceLock); -} - -const unsigned char * IOHIKeyboard::defaultKeymapOfLength(UInt32 * length) -{ - *length = 0; - return NULL; -} - -void IOHIKeyboard::setAlphaLockFeedback(bool /* val */) -{ - return; -} - -void IOHIKeyboard::setNumLockFeedback(bool /* val */) -{ - return; -} - -UInt32 IOHIKeyboard::maxKeyCodes() -{ - return( 0x80); -} - -bool IOHIKeyboard:: doesKeyLock ( unsigned key) -{ - return false; -} - -unsigned IOHIKeyboard:: getLEDStatus () -{ - return 0; -} - - -bool IOHIKeyboard::open(IOService * client, - IOOptionBits options, - KeyboardEventAction keAction, - KeyboardSpecialEventAction kseAction, - UpdateEventFlagsAction uefAction) -{ - if ( (!_keyMap) && (!resetKeyboard())) return false; - -// IOLog("***open -- gKeyRepeat.lo = %08lx\n", gKeyRepeat.lo ); -// IOLog("***open -- gInitialKeyRepeat.lo = %08lx\n", gInitialKeyRepeat.lo ); - - if (super::open(client, options)) - { - // Note: client object is already retained by superclass' open() - _keyboardEventTarget = client; - _keyboardEventAction = keAction; - _keyboardSpecialEventTarget = client; - _keyboardSpecialEventAction = kseAction; - _updateEventFlagsTarget = client; - _updateEventFlagsAction = uefAction; - - return true; - } - - return false; -} - -void IOHIKeyboard::close(IOService * client, IOOptionBits) -{ -// IOLog("***close -- gKeyRepeat.lo = %08lx\n", gKeyRepeat.lo ); -// IOLog("***close -- gInitialKeyRepeat.lo = %08lx\n", gInitialKeyRepeat.lo ); - - // Save repeat rate and delay, so when we are replugged we'll be ready - // with the right values. - // - gKeyRepeat = _keyRepeat; - gInitialKeyRepeat = _initialKeyRepeat; - - // kill autorepeat task - AbsoluteTime_to_scalar(&_downRepeatTime) = 0; - _codeToRepeat = (unsigned)-1; - scheduleAutoRepeat(); - // clear modifiers to avoid stuck keys - setAlphaLock(false); - if (_updateEventFlagsAction) - (*_updateEventFlagsAction)(_updateEventFlagsTarget, 0); _eventFlags = 0; - bzero(_keyState, _keyStateSize); - - _keyboardEventAction = NULL; - _keyboardEventTarget = 0; - _keyboardSpecialEventAction = NULL; - _keyboardSpecialEventTarget = 0; - _updateEventFlagsAction = NULL; - _updateEventFlagsTarget = 0; - - super::close(client); -} - diff --git a/iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp b/iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp deleted file mode 100644 index aac2e26bf..000000000 --- a/iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp +++ /dev/null @@ -1,768 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * KeyMap.m - Generic keymap string parser and keycode translator. - * - * HISTORY - * 19 June 1992 Mike Paquette at NeXT - * Created. - * 5 Aug 1993 Erik Kay at NeXT - * minor API cleanup - * 11 Nov 1993 Erik Kay at NeXT - * fix to allow prevent long sequences from overflowing the event queue - * 12 Nov 1998 Dan Markarian at Apple - * major cleanup of public API's; converted to C++ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/hidsystem/IOLLEvent.h> -#include <IOKit/hidsystem/IOHIKeyboard.h> -#include <IOKit/hidsystem/IOHIKeyboardMapper.h> - -#define super OSObject -OSDefineMetaClassAndStructors(IOHIKeyboardMapper, OSObject); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOHIKeyboardMapper * IOHIKeyboardMapper::keyboardMapper( - IOHIKeyboard * delegate, - const UInt8 * mapping, - UInt32 mappingLength, - bool mappingShouldBeFreed ) -{ - IOHIKeyboardMapper * me = new IOHIKeyboardMapper; - - if (me && !me->init(delegate, mapping, mappingLength, mappingShouldBeFreed)) - { - me->free(); - return 0; - } - - return me; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* - * Common KeyMap initialization - */ -bool IOHIKeyboardMapper::init( IOHIKeyboard * delegate, - const UInt8 * mapping, - UInt32 mappingLength, - bool mappingShouldBeFreed ) -{ - if (!super::init()) return false; - - _delegate = delegate; - - if (!parseKeyMapping(mapping, mappingLength, &_parsedMapping)) return false; - - _mappingShouldBeFreed = mappingShouldBeFreed; - _parsedMapping.mapping = mapping; - _parsedMapping.mappingLen = mappingLength; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOHIKeyboardMapper::free() -{ - if (_mappingShouldBeFreed && _parsedMapping.mapping) - IOFree((void *)_parsedMapping.mapping, _parsedMapping.mappingLen); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const UInt8 * IOHIKeyboardMapper::mapping() -{ - return (const UInt8 *)_parsedMapping.mapping; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 IOHIKeyboardMapper::mappingLength() -{ - return _parsedMapping.mappingLen; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOHIKeyboardMapper::serialize(OSSerialize *s) const -{ - OSData * data; - bool ok; - - if (s->previouslySerialized(this)) return true; - - data = OSData::withBytesNoCopy( (void *) _parsedMapping.mapping, _parsedMapping.mappingLen ); - if (data) { - ok = data->serialize(s); - data->release(); - } else - ok = false; - - return( ok ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// -// Perform the mapping of 'key' moving in the specified direction -// into events. -// - -void IOHIKeyboardMapper::translateKeyCode(UInt8 key, - bool keyDown, - kbdBitVector keyBits) -{ - unsigned char thisBits = _parsedMapping.keyBits[key]; - unsigned char * bp; - - /* do mod bit update and char generation in useful order */ - if (keyDown) - { - EVK_KEYDOWN(key, keyBits); - - if (thisBits & NX_MODMASK) doModCalc(key, keyBits); - if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown); - } - else - { - EVK_KEYUP(key, keyBits); - if (thisBits & NX_CHARGENMASK) doCharGen(key, keyDown); - if (thisBits & NX_MODMASK) doModCalc(key, keyBits); - } - - //Fix JIS localization. We are here because the JIS keys Yen, Ro, Eisu, - // Kana, and "," are not matched in _parsedMapping.keyBits[] above even - // though the keyboard drivers are sending the correct scan codes. - // The check for interfaceID() below makes sure both ADB and USB works. - // This fix has been tested with AppKit and Carbon for Kodiak 1H - if( 0 == (thisBits & (NX_MODMASK | NX_CHARGENMASK))) - if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) - { - unsigned charCode=0; - - switch (key) { - case 0x5F: // numpad ',' using raw ADB scan code - charCode = ','; - break; - case 0x5E: //ro - charCode = '_'; - break; - case 0x5d: //Yen - charCode = '\\'; - break; - case 0x0a: - charCode = 0xa7; - break; - case 0x66: // eisu - case 0x68: // kana - default: - // do nothing. AppKit has fix in 1H - break; - } - /* Post the keyboard event */ - _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, - /* flags */ _delegate->eventFlags(), - /* keyCode */ key, - /* charCode */ charCode, - /* charSet */ 0, //0 is adequate for JIS - /* originalCharCode */ 0, - /* originalCharSet */ 0); - } - -#ifdef OMITPENDINGKEYCAPS - //Make KeyCaps.app see the caps lock - if (key == _parsedMapping.specialKeys[NX_KEYTYPE_CAPS_LOCK]) //ADB caps lock 0x39 - { - if (_delegate->alphaLock() == keyDown) - //This logic is needed for non-locking USB caps lock - { - _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, - _delegate->eventFlags(), key, 0, 0, 0, 0); - } - } - - //Find scan code corresponding to PowerBook fn key (0x3f in ADB) - bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry - if (bp) - { - bp++; //now points to actual ADB scan code - if (key == *bp ) //ADB fn key should be 0x3f here - { - _delegate->keyboardEvent(keyDown ? NX_KEYDOWN : NX_KEYUP, - _delegate->eventFlags(), key, 0, 0, 0, 0); - } - } -#endif -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// -// Support goop for parseKeyMapping. These routines are -// used to walk through the keymapping string. The string -// may be composed of bytes or shorts. If using shorts, it -// MUST always be aligned to use short boundries. -// -typedef struct { - unsigned const char *bp; - unsigned const char *endPtr; - int shorts; -} NewMappingData; - -static inline unsigned int NextNum(NewMappingData *nmd) -{ - if (nmd->bp >= nmd->endPtr) - return(0); - if (nmd->shorts) - return(*((unsigned short *)nmd->bp)++); - else - return(*((unsigned char *)nmd->bp)++); -} - -// -// Perform the actual parsing operation on a keymap. Returns false on failure. -// - -bool IOHIKeyboardMapper::parseKeyMapping(const UInt8 * mapping, - UInt32 mappingLength, - NXParsedKeyMapping * parsedMapping) const -{ - NewMappingData nmd; - int i, j, k, l, n; - unsigned int m; - int keyMask, numMods; - int maxSeqNum = -1; - unsigned char * bp; - - - /* Initialize the new map. */ - bzero( parsedMapping, sizeof (NXParsedKeyMapping) ); - parsedMapping->maxMod = -1; - parsedMapping->numDefs = -1; - parsedMapping->numSeqs = -1; - - nmd.endPtr = mapping + mappingLength; - nmd.bp = mapping; - nmd.shorts = 1; // First value, the size, is always a short - - /* Start filling it in with the new data */ - parsedMapping->mapping = (unsigned char *)mapping; - parsedMapping->mappingLen = mappingLength; - parsedMapping->shorts = nmd.shorts = NextNum(&nmd); - - /* Walk through the modifier definitions */ - numMods = NextNum(&nmd); - for(i=0; i<numMods; i++) - { - /* Get bit number */ - if ((j = NextNum(&nmd)) >= NX_NUMMODIFIERS) - return false; - - /* Check maxMod */ - if (j > parsedMapping->maxMod) - parsedMapping->maxMod = j; - - /* record position of this def */ - parsedMapping->modDefs[j] = (unsigned char *)nmd.bp; - - /* Loop through each key assigned to this bit */ - for(k=0,n = NextNum(&nmd);k<n;k++) - { - /* Check that key code is valid */ - if ((l = NextNum(&nmd)) >= NX_NUMKEYCODES) - return false; - /* Make sure the key's not already assigned */ - if (parsedMapping->keyBits[l] & NX_MODMASK) - return false; - /* Set bit for modifier and which one */ - - //The "if" here is to patch the keymapping file. That file has nothing - // for num lock, so no change is required here for num lock. - // Also, laptop Macs have num lock handled by Buttons driver - if ((j != NX_MODIFIERKEY_ALPHALOCK) || (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) ) - { - parsedMapping->keyBits[l] |=NX_MODMASK | (j & NX_WHICHMODMASK); - } - - } - } - - //This is here because keymapping file has an entry for caps lock, but in - // order to trigger special code (line 646-), the entry needs to be zero - if (!_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) - parsedMapping->modDefs[NX_MODIFIERKEY_ALPHALOCK] = 0; - - //This section is here to force keymapping to include the PowerBook's secondary - // fn key as a new modifier key. This code can be removed once the keymapping - // file has the fn key (ADB=0x3f) in the modifiers section. - // NX_MODIFIERKEY_SECONDARYFN = 8 in ev_keymap.h - if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) - { - parsedMapping->keyBits[0x3f] |=NX_MODMASK | (NX_MODIFIERKEY_SECONDARYFN & NX_WHICHMODMASK); - } - - /* Walk through each key definition */ - parsedMapping->numDefs = NextNum(&nmd); - n = parsedMapping->numDefs; - for( i=0; i < NX_NUMKEYCODES; i++) - { - if (i < n) - { - parsedMapping->keyDefs[i] = (unsigned char *)nmd.bp; - if ((keyMask = NextNum(&nmd)) != (nmd.shorts ? 0xFFFF: 0x00FF)) - { - /* Set char gen bit for this guy: not a no-op */ - parsedMapping->keyBits[i] |= NX_CHARGENMASK; - /* Check key defs to find max sequence number */ - for(j=0, k=1; j<=parsedMapping->maxMod; j++, keyMask>>=1) - { - if (keyMask & 0x01) - k*= 2; - } - for(j=0; j<k; j++) - { - m = NextNum(&nmd); - l = NextNum(&nmd); - if (m == (unsigned)(nmd.shorts ? 0xFFFF: 0x00FF)) - if (((int)l) > maxSeqNum) - maxSeqNum = l; /* Update expected # of seqs */ - } - } - else /* unused code within active range */ - parsedMapping->keyDefs[i] = NULL; - } - else /* Unused code past active range */ - { - parsedMapping->keyDefs[i] = NULL; - } - } - /* Walk through sequence defs */ - parsedMapping->numSeqs = NextNum(&nmd); - /* If the map calls more sequences than are declared, bail out */ - if (parsedMapping->numSeqs <= maxSeqNum) - return false; - - /* Walk past all sequences */ - for(i = 0; i < parsedMapping->numSeqs; i++) - { - parsedMapping->seqDefs[i] = (unsigned char *)nmd.bp; - /* Walk thru entries in a seq. */ - for(j=0, l=NextNum(&nmd); j<l; j++) - { - NextNum(&nmd); - NextNum(&nmd); - } - } - /* Install Special device keys. These override default values. */ - numMods = NextNum(&nmd); /* Zero on old style keymaps */ - if ( numMods > NX_NUMSPECIALKEYS ) - return false; - if ( numMods ) - { - for ( i = 0; i < NX_NUMSPECIALKEYS; ++i ) - parsedMapping->specialKeys[i] = NX_NOSPECIALKEY; - - //This "if" will cover both ADB and USB keyboards. This code does not - // have to be here if the keymaps include these two entries. Keyboard - // drivers already have these entries, but keymapping file does not - if (_delegate->interfaceID() == NX_EVS_DEVICE_INTERFACE_ADB) - { - //ADB capslock: - parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] = 0x39; - - //ADB numlock for external keyboards, not PowerBook keyboards: - parsedMapping->specialKeys[NX_KEYTYPE_NUM_LOCK] = 0x47; - - //HELP key needs to be visible - parsedMapping->keyDefs[0x72] = parsedMapping->keyDefs[0x47]; - } - - //Keymapping file can override caps and num lock above now: - for ( i = 0; i < numMods; ++i ) - { - j = NextNum(&nmd); /* Which modifier key? */ - l = NextNum(&nmd); /* Scancode for modifier key */ - if ( j >= NX_NUMSPECIALKEYS ) - return false; - parsedMapping->specialKeys[j] = l; - } - } - else /* No special keys defs implies an old style keymap */ - { - return false; /* Old style keymaps are guaranteed to do */ - /* the wrong thing on ADB keyboards */ - } - /* Install bits for Special device keys */ - for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++) - { - if ( parsedMapping->specialKeys[i] != NX_NOSPECIALKEY ) - { - parsedMapping->keyBits[parsedMapping->specialKeys[i]] |= - (NX_CHARGENMASK | NX_SPECIALKEYMASK); - } - } - - //caps lock keys should not generate characters. - if (_delegate->doesKeyLock(NX_KEYTYPE_CAPS_LOCK)) - { - parsedMapping->keyBits[ parsedMapping->specialKeys[NX_KEYTYPE_CAPS_LOCK] ] - &= ~NX_CHARGENMASK; - } - - //Find scan code corresponding to PowerBook fn key (0x3f in ADB) - // and then make sure it does not generate a character - bp = _parsedMapping.modDefs[NX_MODIFIERKEY_SECONDARYFN]; //7th array entry - if (bp) - { - bp++; //now points to actual ADB scan code - parsedMapping->keyBits[ *bp ] &= ~NX_CHARGENMASK; - } - - return true; -} - - -//Retrieve a key from mapping above. Useful for IOHIKeyboard -UInt8 IOHIKeyboardMapper::getParsedSpecialKey(UInt8 logical) -{ - UInt8 retval; - - if ( logical < NX_NUMSPECIALKEYS) - retval = _parsedMapping.specialKeys[logical]; - else - retval = 0xff; //careful, 0 is mapped already - return retval; -} - - -static inline int NEXTNUM(unsigned char ** mapping, short shorts) -{ - int returnValue; - - if (shorts) - { - returnValue = *((unsigned short *)*mapping); - *mapping += sizeof(unsigned short); - } - else - { - returnValue = **((unsigned char **)mapping); - *mapping += sizeof(unsigned char); - } - - return returnValue; -} - -// -// Look up in the keymapping each key associated with the modifier bit. -// Look in the device state to see if that key is down. -// Return 1 if a key for modifier 'bit' is down. Return 0 if none is down -// -static inline int IsModifierDown(NXParsedKeyMapping *parsedMapping, - kbdBitVector keyBits, - int bit ) -{ - int i, n; - unsigned char *mapping; - unsigned key; - short shorts = parsedMapping->shorts; - - if ( (mapping = parsedMapping->modDefs[bit]) != 0 ) { - for(i=0, n=NEXTNUM(&mapping, shorts); i<n; i++) - { - key = NEXTNUM(&mapping, shorts); - if ( EVK_IS_KEYDOWN(key, keyBits) ) - return 1; - } - } - return 0; -} - -void IOHIKeyboardMapper::calcModBit(int bit, kbdBitVector keyBits) -{ - int bitMask; - unsigned myFlags; - - bitMask = 1<<(bit+16); - - /* Initially clear bit, as if key-up */ - myFlags = _delegate->deviceFlags() & (~bitMask); - /* Set bit if any associated keys are down */ - if ( IsModifierDown( &_parsedMapping, keyBits, bit ) ) - myFlags |= bitMask; - - if ( bit == NX_MODIFIERKEY_ALPHALOCK ) /* Caps Lock key */ - _delegate->setAlphaLock((myFlags & NX_ALPHASHIFTMASK) ? true : false); - else if ( bit == NX_MODIFIERKEY_NUMLOCK ) /* Num Lock key */ - _delegate->setNumLock((myFlags & NX_NUMERICPADMASK) ? true : false); - - _delegate->setDeviceFlags(myFlags); - -} - - -// -// Perform flag state update and generate flags changed events for this key. -// -void IOHIKeyboardMapper::doModCalc(int key, kbdBitVector keyBits) -{ - int thisBits; - thisBits = _parsedMapping.keyBits[key]; - if (thisBits & NX_MODMASK) - { - calcModBit((thisBits & NX_WHICHMODMASK), keyBits); - /* The driver generates flags-changed events only when there is - no key-down or key-up event generated */ - if (!(thisBits & NX_CHARGENMASK)) - { - /* Post the flags-changed event */ - _delegate->keyboardEvent(NX_FLAGSCHANGED, - /* flags */ _delegate->eventFlags(), - /* keyCode */ key, - /* charCode */ 0, - /* charSet */ 0, - /* originalCharCode */ 0, - /* originalCharSet */ 0); - } - else /* Update, but don't generate an event */ - _delegate->updateEventFlags(_delegate->eventFlags()); - } -} - -// -// Perform character event generation for this key -// -void IOHIKeyboardMapper::doCharGen(int keyCode, bool down) -{ - int i, n, eventType, adjust, thisMask, modifiers, saveModifiers; - short shorts; - unsigned charSet, origCharSet; - unsigned charCode, origCharCode; - unsigned char *mapping; - unsigned eventFlags, origflags; - - _delegate->setCharKeyActive(true); // a character generating key is active - - eventType = (down == true) ? NX_KEYDOWN : NX_KEYUP; - eventFlags = _delegate->eventFlags(); - saveModifiers = eventFlags >> 16; // machine independent mod bits - /* Set NX_ALPHASHIFTMASK based on alphaLock OR shift active */ - if( saveModifiers & (NX_SHIFTMASK >> 16)) - saveModifiers |= (NX_ALPHASHIFTMASK >> 16); - - - /* Get this key's key mapping */ - shorts = _parsedMapping.shorts; - mapping = _parsedMapping.keyDefs[keyCode]; - modifiers = saveModifiers; - if ( mapping ) - { - - - /* Build offset for this key */ - thisMask = NEXTNUM(&mapping, shorts); - if (thisMask && modifiers) - { - adjust = (shorts ? sizeof(short) : sizeof(char))*2; - for( i = 0; i <= _parsedMapping.maxMod; ++i) - { - if (thisMask & 0x01) - { - if (modifiers & 0x01) - mapping += adjust; - adjust *= 2; - } - thisMask >>= 1; - modifiers >>= 1; - } - } - charSet = NEXTNUM(&mapping, shorts); - charCode = NEXTNUM(&mapping, shorts); - - /* construct "unmodified" character */ - mapping = _parsedMapping.keyDefs[keyCode]; - modifiers = saveModifiers & ((NX_ALPHASHIFTMASK | NX_SHIFTMASK) >> 16); - - thisMask = NEXTNUM(&mapping, shorts); - if (thisMask && modifiers) - { - adjust = (shorts ? sizeof(short) : sizeof(char)) * 2; - for ( i = 0; i <= _parsedMapping.maxMod; ++i) - { - if (thisMask & 0x01) - { - if (modifiers & 0x01) - mapping += adjust; - adjust *= 2; - } - thisMask >>= 1; - modifiers >>= 1; - } - } - origCharSet = NEXTNUM(&mapping, shorts); - origCharCode = NEXTNUM(&mapping, shorts); - - if (charSet == (unsigned)(shorts ? 0xFFFF : 0x00FF)) - { - // Process as a character sequence - // charCode holds the sequence number - mapping = _parsedMapping.seqDefs[charCode]; - - origflags = eventFlags; - for(i=0,n=NEXTNUM(&mapping, shorts);i<n;i++) - { - if ( (charSet = NEXTNUM(&mapping, shorts)) == 0xFF ) /* metakey */ - { - if ( down == true ) /* down or repeat */ - { - eventFlags |= (1 << (NEXTNUM(&mapping, shorts) + 16)); - _delegate->keyboardEvent(NX_FLAGSCHANGED, - /* flags */ _delegate->deviceFlags(), - /* keyCode */ keyCode, - /* charCode */ 0, - /* charSet */ 0, - /* originalCharCode */ 0, - /* originalCharSet */ 0); - } - else - NEXTNUM(&mapping, shorts); /* Skip over value */ - } - else - { - charCode = NEXTNUM(&mapping, shorts); - _delegate->keyboardEvent(eventType, - /* flags */ eventFlags, - /* keyCode */ keyCode, - /* charCode */ charCode, - /* charSet */ charSet, - /* originalCharCode */ charCode, - /* originalCharSet */ charSet); - } - } - /* Done with macro. Restore the flags if needed. */ - if ( eventFlags != origflags ) - { - _delegate->keyboardEvent(NX_FLAGSCHANGED, - /* flags */ _delegate->deviceFlags(), - /* keyCode */ keyCode, - /* charCode */ 0, - /* charSet */ 0, - /* originalCharCode */ 0, - /* originalCharSet */ 0); - eventFlags = origflags; - } - } - else /* A simple character generating key */ - { - _delegate->keyboardEvent(eventType, - /* flags */ eventFlags, - /* keyCode */ keyCode, - /* charCode */ charCode, - /* charSet */ charSet, - /* originalCharCode */ origCharCode, - /* originalCharSet */ origCharSet); - } - } /* if (mapping) */ - - /* - * Check for a device control key: note that they always have CHARGEN - * bit set - */ - if (_parsedMapping.keyBits[keyCode] & NX_SPECIALKEYMASK) - { - for(i=0; i<NX_NUM_SCANNED_SPECIALKEYS; i++) - { - if ( keyCode == _parsedMapping.specialKeys[i] ) - { - _delegate->keyboardSpecialEvent(eventType, - /* flags */ eventFlags, - /* keyCode */ keyCode, - /* specialty */ i); - /* - * Special keys hack for letting an arbitrary (non-locking) - * key act as a CAPS-LOCK key. If a special CAPS LOCK key - * is designated, and there is no key designated for the - * AlphaLock function, then we'll let the special key toggle - * the AlphaLock state. - */ - if (i == NX_KEYTYPE_CAPS_LOCK - && down == true - && !_parsedMapping.modDefs[NX_MODIFIERKEY_ALPHALOCK] ) - { - unsigned myFlags = _delegate->deviceFlags(); - bool alphaLock = (_delegate->alphaLock() == false); - - // Set delegate's alphaLock state - _delegate->setAlphaLock(alphaLock); - // Update the delegate's flags - if ( alphaLock ) - myFlags |= NX_ALPHASHIFTMASK; - else - myFlags &= ~NX_ALPHASHIFTMASK; - - _delegate->setDeviceFlags(myFlags); - - _delegate->keyboardEvent(NX_FLAGSCHANGED, - /* flags */ myFlags, - /* keyCode */ keyCode, - /* charCode */ 0, - /* charSet */ 0, - /* originalCharCode */ 0, - /* originalCharSet */ 0); - } - else if (i == NX_KEYTYPE_NUM_LOCK - && down == true - && !_parsedMapping.modDefs[NX_MODIFIERKEY_NUMLOCK] ) - { - unsigned myFlags = _delegate->deviceFlags(); - bool numLock = (_delegate->numLock() == false); - - // Set delegate's alphaLock state - _delegate->setNumLock(numLock); - if ( numLock ) - myFlags |= NX_NUMERICPADMASK; - else - myFlags &= ~NX_NUMERICPADMASK; - - _delegate->setDeviceFlags(myFlags); - _delegate->keyboardEvent(NX_FLAGSCHANGED, - /* flags */ myFlags, - /* keyCode */ keyCode, - /* charCode */ 0, - /* charSet */ 0, - /* originalCharCode */ 0, - /* originalCharSet */ 0); - } - - break; - } - } - } -} diff --git a/iokit/Families/IOHIDSystem/IOHIPointing.cpp b/iokit/Families/IOHIDSystem/IOHIPointing.cpp deleted file mode 100644 index 9c6719c13..000000000 --- a/iokit/Families/IOHIDSystem/IOHIPointing.cpp +++ /dev/null @@ -1,790 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * 17 July 1998 sdouglas - * 22 Dec 2000 bubba - save global acceleration state when device is unplugged. - */ - -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> -#include <IOKit/hidsystem/IOHIPointing.h> -#include <IOKit/hidsystem/IOHIDParameter.h> -#include <IOKit/pwr_mgt/RootDomain.h> - - -#ifndef abs -#define abs(_a) ((_a >= 0) ? _a : -_a) -#endif - -#define super IOHIDevice - -// Global variable glob_accel won't get clobbered by sleep/wake code, -// which will re-init this driver. The Window Server does not re-send -// the original acceleration value, so we need to restore it on unplugs -// and sleeps. - -IOFixed glob_accel = 0x8000; - -bool HIPointinghasRoot( OSObject * us, void *, IOService * yourDevice ); - -OSDefineMetaClassAndStructors(IOHIPointing, IOHIDevice); - -bool IOHIPointing::init(OSDictionary * properties) -{ - if (!super::init(properties)) return false; - - /* - * Initialize minimal state. - */ - - _fractX = 0; - _fractY = 0; - _acceleration = -1; - _convertAbsoluteToRelative = false; - _contactToMove = false; - _hadContact = false; - _pressureThresholdToClick = 128; - _previousLocation.x = 0; - _previousLocation.y = 0; - _rootDomain = 0; - - _deviceLock = IOLockAlloc(); - - if (!_deviceLock) return false; - - IOLockInit(_deviceLock); - - return true; -} - -bool IOHIPointing::start(IOService * provider) -{ - if (!super::start(provider)) return false; - - /* - * IOHIPointing serves both as a service and a nub (we lead a double - * life). Register ourselves as a nub to kick off matching. - */ - - registerService(); - addNotification( gIOPublishNotification,serviceMatching("IOPMrootDomain"), - (IOServiceNotificationHandler)HIPointinghasRoot, this, 0 ); - - return true; -} - -/* Here are some power management functions so we can tell when system is - going to sleep. We need to remember the acceleration value */ -bool HIPointinghasRoot( OSObject * us, void *, IOService * yourDevice ) -{ - if (( yourDevice != NULL ) && ((IOHIPointing *)us)->_rootDomain == 0) - { - ((IOHIPointing *)us)->_rootDomain = yourDevice; - ((IOPMrootDomain *)yourDevice)->registerInterestedDriver((IOService *) us); - } - return true; -} - -IOReturn IOHIPointing::powerStateWillChangeTo ( IOPMPowerFlags theFlags, unsigned long unused1, - IOService* unused2) -{ - if ( ! (theFlags & IOPMPowerOn) ) - { - glob_accel = _acceleration; //Save old value before driver is torn down - } - return IOPMAckImplied; -} - -IOReturn IOHIPointing::powerStateDidChangeTo ( IOPMPowerFlags theFlags, unsigned long unused1, - IOService* unused2) -{ - if (theFlags & IOPMPowerOn) - { - if (glob_accel > 0x10000) //Just in case saved value is out of bounds - glob_accel = 0x10000; - setupForAcceleration(glob_accel); - updateProperties(); - } - return IOPMAckImplied; -} - - - -void IOHIPointing::free() -// Description: Go Away. Be careful when freeing the lock. -{ - glob_accel = _acceleration; -// IOLog("***free -- glob_accel = %08lx\n", glob_accel ); - - if (_deviceLock) - { - IOLock * lock; - - IOTakeLock(_deviceLock); - - lock = _deviceLock; - _deviceLock = NULL; - - IOUnlock(lock); - IOLockFree(lock); - } - if (_rootDomain) - { - _rootDomain->deRegisterInterestedDriver((IOService *) this); - _rootDomain = 0; - } - super::free(); -} - -bool IOHIPointing::open(IOService * client, - IOOptionBits options, - RelativePointerEventAction rpeAction, - AbsolutePointerEventAction apeAction, - ScrollWheelEventAction sweAction) -{ -// IOLog("***open -- glob_accel = %08lx\n", glob_accel ); - if ( (-1 == _acceleration) && (!resetPointer())) return false; -// IOLog("***open -- after reset is called, glob_accel = %08lx\n", glob_accel ); - if (super::open(client, options)) - { - // Note: client object is already retained by superclass' open() - _relativePointerEventTarget = client; - _relativePointerEventAction = rpeAction; - _absolutePointerEventTarget = client; - _absolutePointerEventAction = apeAction; - _scrollWheelEventTarget = client; - _scrollWheelEventAction = sweAction; - return true; - } - - return false; -} - -void IOHIPointing::close(IOService * client, IOOptionBits) -{ - glob_accel = _acceleration; - // IOLog("***close -- glob_accel = %08lx\n", glob_accel ); - - _relativePointerEventAction = NULL; - _relativePointerEventTarget = 0; - _absolutePointerEventAction = NULL; - _absolutePointerEventTarget = 0; - if (_rootDomain) - { - _rootDomain->deRegisterInterestedDriver((IOService *) this); - _rootDomain = 0; - } - super::close(client); -} - -IOHIDKind IOHIPointing::hidKind() -{ - return kHIRelativePointingDevice; -} - -struct CursorDeviceSegment { - SInt32 devUnits; - SInt32 slope; - SInt32 intercept; -}; -typedef struct CursorDeviceSegment CursorDeviceSegment; - -void IOHIPointing::scalePointer(int * dxp, int * dyp) -// Description: Perform pointer acceleration computations here. -// Given the resolution, dx, dy, and time, compute the velocity -// of the pointer over a Manhatten distance in inches/second. -// Using this velocity, do a lookup in the pointerScaling table -// to select a scaling factor. Scale dx and dy up as appropriate. -// Preconditions: -// * _deviceLock should be held on entry -{ - - SInt32 dx, dy; - SInt32 absDx, absDy; - SInt32 mag; - IOFixed scale; - CursorDeviceSegment * segment; - - if( !_scaleSegments) - return; - - dx = (*dxp) << 16; - dy = (*dyp) << 16; - absDx = (dx < 0) ? -dx : dx; - absDy = (dy < 0) ? -dy : dy; - - if( absDx > absDy) - mag = (absDx + (absDy / 2)); - else - mag = (absDy + (absDx / 2)); - - if( !mag) - return; - - // scale - for( - segment = (CursorDeviceSegment *) _scaleSegments; - mag > segment->devUnits; - segment++) {} - - scale = IOFixedDivide( - segment->intercept + IOFixedMultiply( mag, segment->slope ), - mag ); - - dx = IOFixedMultiply( dx, scale ); - dy = IOFixedMultiply( dy, scale ); - - // add fract parts - dx += _fractX; - dy += _fractY; - - *dxp = dx / 65536; - *dyp = dy / 65536; - - // get fractional part with sign extend - if( dx >= 0) - _fractX = dx & 0xffff; - else - _fractX = dx | 0xffff0000; - if( dy >= 0) - _fractY = dy & 0xffff; - else - _fractY = dy | 0xffff0000; -} - -/* - Routine: Interpolate - This routine interpolates to find a point on the line [x1,y1] [x2,y2] which - is intersected by the line [x3,y3] [x3,y"]. The resulting y' is calculated - by interpolating between y3 and y", towards the higher acceleration curve. -*/ - -static SInt32 Interpolate( SInt32 x1, SInt32 y1, - SInt32 x2, SInt32 y2, - SInt32 x3, SInt32 y3, - SInt32 scale, Boolean lower ) -{ - - SInt32 slope; - SInt32 intercept; - SInt32 resultY; - - slope = IOFixedDivide( y2 - y1, x2 - x1 ); - intercept = y1 - IOFixedMultiply( slope, x1 ); - resultY = intercept + IOFixedMultiply( slope, x3 ); - if( lower) - resultY = y3 - IOFixedMultiply( scale, y3 - resultY ); - else - resultY = resultY + IOFixedMultiply( scale, y3 - resultY ); - - return( resultY ); -} - - -static SInt32 Fetch32( const UInt16 * p ) -{ - SInt32 result; - - result = (*(p++)) << 16; - result |= (*(p++)); - - return( result ); -} - -void IOHIPointing::setupForAcceleration( IOFixed desired ) -{ - OSData * data; - const UInt16 * lowTable = 0; - const UInt16 * highTable; - - SInt32 x1, y1, x2, y2, x3, y3; - SInt32 prevX1, prevY1; - SInt32 upperX, upperY; - SInt32 lowerX, lowerY; - SInt32 lowAccl = 0, lowPoints = 0; - SInt32 highAccl, highPoints; - SInt32 scale; - UInt32 count; - Boolean lower; - - SInt32 pointerResolution = resolution(); - SInt32 frameRate = (67 << 16); - SInt32 screenResolution = (72 << 16); - SInt32 devScale, crsrScale; - SInt32 scaledX1, scaledY1; - SInt32 scaledX2, scaledY2; - - CursorDeviceSegment * segments; - CursorDeviceSegment * segment; - SInt32 segCount; - - assert(pointerResolution); - data = copyAccelerationTable(); - if( !data) - return; - - if( desired < (IOFixed) 0) { - // disabling mouse scaling - if(_scaleSegments && _scaleSegCount) - IODelete( _scaleSegments, - CursorDeviceSegment, _scaleSegCount ); - _scaleSegments = NULL; - _scaleSegCount = 0; - data->release(); - return; - } - - highTable = (const UInt16 *) data->getBytesNoCopy(); - - devScale = IOFixedDivide( pointerResolution, frameRate ); - crsrScale = IOFixedDivide( screenResolution, frameRate ); - - scaledX1 = scaledY1 = 0; - - scale = Fetch32( highTable ); - highTable += 4; - - _acceleration = desired; - - // normalize table's default (scale) to 0.5 - if( desired > 0x8000) { - desired = IOFixedMultiply( desired - 0x8000, - 0x10000 - scale ); - desired <<= 1; - desired += scale; - } else { - desired = IOFixedMultiply( desired, scale ); - desired <<= 1; - } - if( desired > (1 << 16)) - desired = (1 << 16); - - count = *(highTable++); - - // find curves bracketing the desired value - do { - highAccl = Fetch32( highTable ); - highTable += 2; - highPoints = *(highTable++); - - if( desired <= highAccl) - break; - - lowTable = highTable; - lowAccl = highAccl; - lowPoints = highPoints; - highTable += lowPoints * 4; - - } while( true ); - - // scale between the two - if( lowTable) - scale = IOFixedDivide( desired - lowAccl, - highAccl - lowAccl ); - // or take all the high one - else { - scale = (1 << 16); - lowTable = highTable; - lowAccl = highAccl; - lowPoints = 0; - } - - if( lowPoints > highPoints) - segCount = lowPoints; - else - segCount = highPoints; - segCount *= 2; -/* IOLog("lowPoints %ld, highPoints %ld, segCount %ld\n", - lowPoints, highPoints, segCount); */ - segments = IONew( CursorDeviceSegment, segCount ); - assert( segments ); - segment = segments; - - x1 = prevX1 = y1 = prevY1 = 0; - - lowerX = Fetch32( lowTable ); - lowTable += 2; - lowerY = Fetch32( lowTable ); - lowTable += 2; - upperX = Fetch32( highTable ); - highTable += 2; - upperY = Fetch32( highTable ); - highTable += 2; - - do { - // consume next point from first X - lower = (lowPoints && (!highPoints || (lowerX <= upperX))); - - if( lower) { - /* highline */ - x2 = upperX; - y2 = upperY; - x3 = lowerX; - y3 = lowerY; - if( lowPoints && (--lowPoints)) { - lowerX = Fetch32( lowTable ); - lowTable += 2; - lowerY = Fetch32( lowTable ); - lowTable += 2; - } - } else { - /* lowline */ - x2 = lowerX; - y2 = lowerY; - x3 = upperX; - y3 = upperY; - if( highPoints && (--highPoints)) { - upperX = Fetch32( highTable ); - highTable += 2; - upperY = Fetch32( highTable ); - highTable += 2; - } - } - { - // convert to line segment - assert( segment < (segments + segCount) ); - - scaledX2 = IOFixedMultiply( devScale, /* newX */ x3 ); - scaledY2 = IOFixedMultiply( crsrScale, - /* newY */ Interpolate( x1, y1, x2, y2, x3, y3, - scale, lower ) ); - if( lowPoints || highPoints) - segment->devUnits = scaledX2; - else - segment->devUnits = 0x7fffffff; - segment->slope = IOFixedDivide( scaledY2 - scaledY1, - scaledX2 - scaledX1 ); - segment->intercept = scaledY2 - - IOFixedMultiply( segment->slope, scaledX2 ); -/* IOLog("devUnits = %08lx, slope = %08lx, intercept = %08lx\n", - segment->devUnits, segment->slope, segment->intercept); */ - - scaledX1 = scaledX2; - scaledY1 = scaledY2; - segment++; - } - - // continue on from last point - if( lowPoints && highPoints) { - if( lowerX > upperX) { - prevX1 = x1; - prevY1 = y1; - } else { - /* swaplines */ - prevX1 = x1; - prevY1 = y1; - x1 = x3; - y1 = y3; - } - } else { - x2 = x1; - y2 = y1; - x1 = prevX1; - y1 = prevY1; - prevX1 = x2; - prevY1 = y2; - } - - } while( lowPoints || highPoints ); - - if( _scaleSegCount && _scaleSegments) - IODelete( _scaleSegments, - CursorDeviceSegment, _scaleSegCount ); - _scaleSegCount = segCount; - _scaleSegments = (void *) segments; - - _fractX = _fractY = 0; - - data->release(); -} - - -bool IOHIPointing::resetPointer() -{ - IOTakeLock( _deviceLock); - - _buttonMode = NX_RightButton; -// IOLog("***resetPointer -- glob_accel = %08lx", glob_accel ); - if( glob_accel > 0 ) - { - // Restore the last acceleration value, since we may have been hot - // unplugged and re-plugged. - setupForAcceleration(glob_accel); - } - else - { - setupForAcceleration(0x8000); - } - updateProperties(); - - IOUnlock( _deviceLock); - return true; -} - -void IOHIPointing::dispatchAbsolutePointerEvent(Point * newLoc, - Bounds * bounds, - UInt32 buttonState, - bool proximity, - int pressure, - int pressureMin, - int pressureMax, - int stylusAngle, - AbsoluteTime ts) -{ - int buttons = 0; - int dx, dy; - - IOTakeLock(_deviceLock); - - if (buttonState & 1) { - buttons |= EV_LB; - } - - if (buttonCount() > 1) { - if (buttonState & -2) { // any other buttons - buttons |= EV_RB; - } - } - - if ((_pressureThresholdToClick < 255) && ((pressure - pressureMin) > ((pressureMax - pressureMin) * _pressureThresholdToClick / 256))) { - buttons |= EV_LB; - } - - if (_buttonMode == NX_OneButton) { - if ((buttons & (EV_LB|EV_RB)) != 0) { - buttons = EV_LB; - } - } - - if (_convertAbsoluteToRelative) { - dx = newLoc->x - _previousLocation.x; - dy = newLoc->y - _previousLocation.y; - - if ((_contactToMove && !_hadContact && (pressure > pressureMin)) || (abs(dx) > ((bounds->maxx - bounds->minx) / 20)) || (abs(dy) > ((bounds->maxy - bounds->miny) / 20))) { - dx = 0; - dy = 0; - } else { - scalePointer(&dx, &dy); - } - - _previousLocation.x = newLoc->x; - _previousLocation.y = newLoc->y; - } - - IOUnlock(_deviceLock); - - _hadContact = (pressure > pressureMin); - - if (!_contactToMove || (pressure > pressureMin)) { - pressure -= pressureMin; - if (pressure > 255) { - pressure = 255; - } - if (_convertAbsoluteToRelative) { - if (_relativePointerEventAction && _relativePointerEventTarget) { - (*_relativePointerEventAction)(_relativePointerEventTarget, - buttons, - dx, - dy, - ts); - } - } else { - if (_absolutePointerEventAction && _absolutePointerEventTarget) { - (*_absolutePointerEventAction)(_absolutePointerEventTarget, - buttons, - newLoc, - bounds, - proximity, - pressure, - stylusAngle, - ts); - } - } - } - - return; -} - -void IOHIPointing::dispatchRelativePointerEvent(int dx, - int dy, - UInt32 buttonState, - AbsoluteTime ts) -{ - int buttons; - - IOTakeLock( _deviceLock); - - buttons = 0; - - if( buttonState & 1) - buttons |= EV_LB; - - if( buttonCount() > 1) { - if( buttonState & 2) // any others down - buttons |= EV_RB; - // Other magic bit reshuffling stuff. It seems there was space - // left over at some point for a "middle" mouse button between EV_LB and EV_RB - if(buttonState & 4) - buttons |= 2; - // Add in the rest of the buttons in a linear fasion... - buttons |= buttonState & ~0x7; - } - - // Perform pointer acceleration computations - scalePointer(&dx, &dy); - - // Perform button tying and mapping. This - // stuff applies to relative posn devices (mice) only. - if ( _buttonMode == NX_OneButton ) - { - // Remap both Left and Right (but no others?) to Left. - if ( (buttons & (EV_LB|EV_RB)) != 0 ) { - buttons |= EV_LB; - buttons &= ~EV_RB; - } - } - else if ( (buttonCount() > 1) && (_buttonMode == NX_LeftButton) ) - // Menus on left button. Swap! - { - int temp = 0; - if ( buttons & EV_LB ) - temp = EV_RB; - if ( buttons & EV_RB ) - temp |= EV_LB; - // Swap Left and Right, preserve everything else - buttons = (buttons & ~(EV_LB|EV_RB)) | temp; - } - IOUnlock( _deviceLock); - - if (_relativePointerEventAction) /* upstream call */ - { - (*_relativePointerEventAction)(_relativePointerEventTarget, - /* buttons */ buttons, - /* deltaX */ dx, - /* deltaY */ dy, - /* atTime */ ts); - } -} - -void IOHIPointing::dispatchScrollWheelEvent(short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - AbsoluteTime ts) -{ - if (_scrollWheelEventAction) { - (*_scrollWheelEventAction)(_scrollWheelEventTarget, - deltaAxis1, - deltaAxis2, - deltaAxis3, - ts); - } -} - -bool IOHIPointing::updateProperties( void ) -{ - bool ok; - UInt32 res = resolution(); - - ok = setProperty( kIOHIDPointerResolutionKey, &res, sizeof( res)) - & setProperty( kIOHIDPointerAccelerationKey, &_acceleration, - sizeof( _acceleration)) - & setProperty( kIOHIDPointerConvertAbsoluteKey, &_convertAbsoluteToRelative, - sizeof( _convertAbsoluteToRelative)) - & setProperty( kIOHIDPointerContactToMoveKey, &_contactToMove, - sizeof( _contactToMove)); - - return( ok & super::updateProperties() ); -} - -IOReturn IOHIPointing::setParamProperties( OSDictionary * dict ) -{ - OSData * data; - IOReturn err = kIOReturnSuccess; - bool updated = false; - UInt8 * bytes; - - IOTakeLock( _deviceLock); - if( (data = OSDynamicCast( OSData, - dict->getObject(kIOHIDPointerAccelerationKey)))) { - - setupForAcceleration( *((IOFixed *)data->getBytesNoCopy()) ); - updated = true; - } - IOUnlock( _deviceLock); - - if( dict->getObject(kIOHIDResetPointerKey)) - resetPointer(); - - if ((data = OSDynamicCast(OSData, - dict->getObject(kIOHIDPointerConvertAbsoluteKey)))) { - bytes = (UInt8 *) data->getBytesNoCopy(); - _convertAbsoluteToRelative = (bytes[0] != 0) ? true : false; - updated = true; - } - - if ((data = OSDynamicCast(OSData, - dict->getObject(kIOHIDPointerContactToMoveKey)))) { - bytes = (UInt8 *) data->getBytesNoCopy(); - _contactToMove = (bytes[0] != 0) ? true : false; - updated = true; - } - - if( updated ) - updateProperties(); - - return( err ); -} - -// subclasses override - -IOItemCount IOHIPointing::buttonCount() -{ - return (1); -} - -IOFixed IOHIPointing::resolution() -{ - return (100 << 16); -} - -OSData * IOHIPointing::copyAccelerationTable() -{ -static const UInt16 accl[] = { - 0x0000, 0x8000, - 0x4032, 0x3030, 0x0002, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, - 0x0001, 0x0000, 0x0001, 0x0000, 0x0009, 0x0000, 0x713B, 0x0000, - 0x6000, 0x0004, 0x4EC5, 0x0010, 0x8000, 0x000C, 0x0000, 0x005F, - 0x0000, 0x0016, 0xEC4F, 0x008B, 0x0000, 0x001D, 0x3B14, 0x0094, - 0x8000, 0x0022, 0x7627, 0x0096, 0x0000, 0x0024, 0x6276, 0x0096, - 0x0000, 0x0026, 0x0000, 0x0096, 0x0000, 0x0028, 0x0000, 0x0096, - 0x0000 -}; - - OSData * data = OSDynamicCast( OSData, - getProperty( "HIDPointerAccelerationTable" )); - if( data) - data->retain(); - else - data = OSData::withBytesNoCopy( accl, sizeof( accl ) ); - - return( data ); -} diff --git a/iokit/Families/IOHIDSystem/IOHITablet.cpp b/iokit/Families/IOHIDSystem/IOHITablet.cpp deleted file mode 100644 index 8ab0e26a6..000000000 --- a/iokit/Families/IOHIDSystem/IOHITablet.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/hidsystem/IOHITablet.h> -#include <IOKit/hidsystem/IOHITabletPointer.h> - -OSDefineMetaClassAndStructors(IOHITablet, IOHIPointing); - -UInt16 IOHITablet::generateTabletID() -{ - static UInt16 _nextTabletID = 0; - return _nextTabletID++; -} - -bool IOHITablet::init(OSDictionary *propTable) -{ - if (!IOHIPointing::init(propTable)) { - return false; - } - - _systemTabletID = generateTabletID(); - setProperty(kIOHISystemTabletID, (unsigned long long)_systemTabletID, 16); - - return true; -} - -bool IOHITablet::open(IOService *client, - IOOptionBits options, - RelativePointerEventAction rpeAction, - AbsolutePointerEventAction apeAction, - ScrollWheelEventAction sweAction, - TabletEventAction tabletAction, - ProximityEventAction proximityAction) -{ - if (!IOHIPointing::open(client, options, rpeAction, apeAction, sweAction)) { - return false; - } - - _tabletEventTarget = client; - _tabletEventAction = tabletAction; - _proximityEventTarget = client; - _proximityEventAction = proximityAction; - - return true; -} - -void IOHITablet::dispatchTabletEvent(NXEventData *tabletEvent, - AbsoluteTime ts) -{ - if (_tabletEventAction) { - (*_tabletEventAction)(_tabletEventTarget, - tabletEvent, - ts); - } -} - -void IOHITablet::dispatchProximityEvent(NXEventData *proximityEvent, - AbsoluteTime ts) -{ - if (_proximityEventAction) { - (*_proximityEventAction)(_proximityEventTarget, - proximityEvent, - ts); - } -} - -bool IOHITablet::startTabletPointer(IOHITabletPointer *pointer, OSDictionary *properties) -{ - bool result = false; - - do { - if (!pointer) - break; - - if (!pointer->init(properties)) - break; - - if (!pointer->attach(this)) - break; - - if (!pointer->start(this)) - break; - - result = true; - } while (false); - - return result; -} - diff --git a/iokit/Families/IOHIDSystem/IOHITabletPointer.cpp b/iokit/Families/IOHIDSystem/IOHITabletPointer.cpp deleted file mode 100644 index 91837cb5c..000000000 --- a/iokit/Families/IOHIDSystem/IOHITabletPointer.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/hidsystem/IOHITabletPointer.h> - -OSDefineMetaClassAndStructors(IOHITabletPointer, IOHIDevice) - -UInt16 IOHITabletPointer::generateDeviceID() -{ - static _nextDeviceID = 0; - return _nextDeviceID++; -} - -bool IOHITabletPointer::init( OSDictionary *propTable ) -{ - if (!IOHIDevice::init(propTable)) { - return false; - } - - _deviceID = generateDeviceID(); - setProperty(kIOHITabletPointerDeviceID, (unsigned long long)_deviceID, 16); - - return true; -} - -bool IOService::attach( IOService * provider ) -{ - if (!IOHIDevice::attach(provider)) { - return false; - } - - _tablet = OSDynamicCast(IOHITablet, provider); - - return true; -} - -void IOHITabletPointer::dispatchTabletEvent(NXEventData *tabletEvent, - AbsoluteTime ts) -{ - if (_tablet) { - _tablet->dispatchTabletEvent(tabletEvent, ts); - } -} - -void IOHITabletPointer::dispatchProximityEvent(NXEventData *proximityEvent, - AbsoluteTime ts) -{ - if (_tablet) { - _tablet->dispatchProximityEvent(proximityEvent, ts); - } -} diff --git a/iokit/Families/IONDRVSupport/IONDRV.cpp b/iokit/Families/IONDRVSupport/IONDRV.cpp deleted file mode 100644 index db912cf14..000000000 --- a/iokit/Families/IONDRVSupport/IONDRV.cpp +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 Jul 98 - start IOKit - * sdouglas 14 Dec 98 - start cpp. - */ - - - -#include <IOKit/IOLib.h> -#include <libkern/c++/OSContainers.h> - -extern "C" { -#include <pexpert/pexpert.h> -}; - -#include "IONDRV.h" -#include "IOPEFLoader.h" - -#define LOG if(1) kprintf - -#define USE_TREE_NDRVS 1 -#define USE_ROM_NDRVS 1 - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super OSObject - -OSDefineMetaClassAndStructors(IONDRV, OSObject) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IONDRV * IONDRV::instantiate( IORegistryEntry * regEntry, - IOLogicalAddress container, - IOByteCount containerSize, - IONDRVUndefinedSymbolHandler undefHandler, - void * self ) -{ - OSStatus err = 1; - IONDRV * inst; - - inst = new IONDRV; - - if( inst) do { - if( false == inst->init()) - continue; - - err = PCodeOpen( (void *)container, containerSize, &inst->pcInst ); - if( err) - continue; - - err = PCodeInstantiate( inst->pcInst, undefHandler, self ); - if( err) - continue; - - inst->getSymbol( "DoDriverIO", - (IOLogicalAddress *) &inst->fDoDriverIO ); - if( kIOReturnSuccess == inst->getSymbol( "TheDriverDescription", - (IOLogicalAddress *) &inst->theDriverDesc )) { - - char * name; - int plen; - - name = (char *) inst->theDriverDesc->driverOSRuntimeInfo.driverName; - plen = name[ 0 ]; - strncpy( name, name + 1, plen); - name[ plen ] = 0; - - kprintf("ndrv version %08x\n", - inst->theDriverDesc-> driverType.version); - } - - } while( false); - - if( inst && err) { - inst->release(); - inst = 0; - } - - return( inst ); -} - -void IONDRV::free( void ) -{ - if( pcInst) - PCodeClose( pcInst ); - super::free(); -} - -IOReturn IONDRV::getSymbol( const char * symbolName, - IOLogicalAddress * address ) -{ - OSStatus err; - - err = PCodeFindExport( pcInst, symbolName, - (LogicalAddress *)address, NULL ); - if( err) - *address = 0; - - return( err); -} - -#if 0 - if( (err = NDRVGetShimClass( ioDevice, instance, 0, classNames )) - ) continue; - err = [propTable createProperty:"AAPL,dk_Driver Name" flags:0 - value:classNames length:strlen( classNames) ]; - err = [propTable createProperty:"AAPL,dk_Server Name" flags:0 - value:classNames length:strlen( classNames) ]; - -OSStatus NDRVGetShimClass( id ioDevice, NDRVInstance instance, UInt32 serviceIndex, char * className ) -{ - NDRVInstanceVars * ndrvInst = (NDRVInstanceVars *) instance; - OSStatus err; - static const char * driverDescProperty = "TheDriverDescription"; - static const char * frameBufferShim = "IONDRVFramebuffer"; - DriverDescription * desc; - UInt32 serviceType; - - className[ 0 ] = 0; - do { - err = PCodeFindExport( ndrvInst->pcInst, driverDescProperty, (IOLogicalAddress *)&desc, NULL ); - if( err) continue; - - if( desc->driverDescSignature != kTheDescriptionSignature) { - err = -1; - continue; - } - if( serviceIndex >= desc->driverServices.nServices) { - err = -1; - continue; - } - - serviceType = desc->driverServices.service[ serviceIndex ].serviceType; - switch( desc->driverServices.service[ serviceIndex ].serviceCategory) { - - case kServiceCategoryNdrvDriver: - if( serviceType == kNdrvTypeIsVideo) { - strcpy( className, frameBufferShim); - break; - } - default: - err = -1; - } - } while( false); - - return( err); -} -#endif - - - -IOReturn IONDRV::doDriverIO( UInt32 commandID, void * contents, - UInt32 commandCode, UInt32 commandKind ) -{ - OSStatus err; - - if( 0 == fDoDriverIO) - return( kIOReturnUnsupported ); - - err = CallTVector( /*AddressSpaceID*/ 0, (void *)commandID, contents, - (void *)commandCode, (void *)commandKind, /*p6*/ 0, - fDoDriverIO ); - -#if 0 - if( err) { - UInt32 i; - static const char * commands[] = - { "kOpenCommand", "kCloseCommand", - "kReadCommand", "kWriteCommand", - "kControlCommand", "kStatusCommand", "kKillIOCommand", - "kInitializeCommand", "kFinalizeCommand", - "kReplaceCommand", "kSupersededCommand" }; - - LOG("Driver failed (%d) on %s : ", err, commands[ commandCode ] ); - - switch( commandCode) { - case kControlCommand: - case kStatusCommand: - LOG("%d : ", ((UInt16 *)contents)[ 0x1a / 2 ]); - contents = ((void **)contents)[ 0x1c / 4 ]; - for( i = 0; i<5; i++ ) - LOG("%08x, ", ((UInt32 *)contents)[i] ); - break; - } - LOG("\n"); - } -#endif - - return( err); -} - - -IONDRV * IONDRV::fromRegistryEntry( IORegistryEntry * regEntry, - IONDRVUndefinedSymbolHandler handler, - void * self ) -{ - IOLogicalAddress pef = 0; - IOByteCount propSize = 0; - OSData * prop; - IONDRV * inst; - - inst = (IONDRV *) regEntry->getProperty("AAPL,ndrvInst"); - if( inst) { - inst->retain(); - return( inst ); - } - - prop = (OSData *) regEntry->getProperty( "driver,AAPL,MacOS,PowerPC" ); - if( USE_TREE_NDRVS && prop) { - pef = (IOLogicalAddress) prop->getBytesNoCopy(); - propSize = prop->getLength(); - } - - // God awful hack: - // Some onboard devices don't have the ndrv in the tree. The booter - // can load & match PEF's but only from disk, not network boots. - -#if USE_ROM_NDRVS - if( !pef && (0 == strcmp( regEntry->getName(), "ATY,mach64_3DU")) ) { - - int * patch; - - patch = (int *) 0xffe88140; - propSize = 0x10a80; - - // Check ati PEF exists there - if( patch[ 0x1f0 / 4 ] == 'ATIU') { - - pef = (IOLogicalAddress) IOMalloc( propSize ); - bcopy( (void *) patch, (void *) pef, propSize ); - } - } - - if( !pef && (0 == strcmp( regEntry->getName(), "ATY,mach64_3DUPro")) ) { - - int * patch; - - patch = (int *) 0xffe99510; - propSize = 0x12008; - // Check ati PEF exists there - if( patch[ 0x1fc / 4 ] != 'ATIU') { - - // silk version - patch = (int *) 0xffe99550; - propSize = 0x12058; - if( patch[ 0x1fc / 4 ] != 'ATIU') - propSize = 0; - } - - if( propSize) { - pef = (IOLogicalAddress) IOMalloc( propSize ); - bcopy( (void *) patch, (void *) pef, propSize ); - } - } - - if( !pef && (0 == strcmp( regEntry->getName(), "control")) ) { - -#define ins(i,d,a,simm) ((i<<26)+(d<<21)+(a<<16)+simm) - int * patch; - - patch = (int *) 0xffe6bd50; - propSize = 0xac10; - - // Check control PEF exists there - if( patch[ 0x41ac / 4 ] == ins( 32, 3, 0, 0x544)) { // lwz r3,0x544(0) - - pef = (IOLogicalAddress) IOMalloc( propSize ); - bcopy( (void *) patch, (void *) pef, propSize ); - patch = (int *) pef; - // patch out low mem accesses - patch[ 0x8680 / 4 ] = ins( 14, 12, 0, 0); // addi r12,0,0x0 - patch[ 0x41ac / 4 ] = ins( 14, 3, 0, 0x544); // addi r3,0,0x544; - patch[ 0x8fa0 / 4 ] = ins( 14, 3, 0, 0x648); // addi r3,0,0x648; - } - } -#endif - - if( pef) { - kprintf( "pef = %08x, %08x\n", pef, propSize ); - inst = IONDRV::instantiate( regEntry, pef, propSize, handler, self ); - if( inst ) - regEntry->setProperty( "AAPL,ndrvInst", inst); - - } else - inst = 0; - - return( inst ); -} - -const char * IONDRV::driverName( void ) -{ - return( (const char *) theDriverDesc->driverOSRuntimeInfo.driverName); -} - - diff --git a/iokit/Families/IONDRVSupport/IONDRV.h b/iokit/Families/IONDRVSupport/IONDRV.h deleted file mode 100644 index f4f05282a..000000000 --- a/iokit/Families/IONDRVSupport/IONDRV.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - */ - - -#ifndef __IONDRV__ -#define __IONDRV__ - -#include <IOKit/IORegistryEntry.h> -#include <IOKit/IOInterruptEventSource.h> - -#include <IOKit/ndrvsupport/IOMacOSTypes.h> -#include <IOKit/ndrvsupport/IONDRVSupport.h> - -#pragma options align=mac68k - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void * RegEntryID[4]; - -struct DriverInitInfo { - UInt16 refNum; - RegEntryID deviceEntry; -}; - -#define MAKE_REG_ENTRY(regEntryID,obj) \ - regEntryID[ 0 ] = (void *) obj; \ - regEntryID[ 1 ] = (void *) ~(UInt32)obj; \ - regEntryID[ 2 ] = (void *) 0x53696d65; \ - regEntryID[ 3 ] = (void *) 0x52756c7a; - -#define REG_ENTRY_TO_OBJ(regEntryID,obj) \ - if( (UInt32)((obj = ((IORegistryEntry **)regEntryID)[ 0 ])) \ - != ~((UInt32 *)regEntryID)[ 1 ] ) \ - return( -2538); - -#define REG_ENTRY_TO_OBJ_RET(regEntryID,obj,ret) \ - if( (UInt32)((obj = ((IORegistryEntry **)regEntryID)[ 0 ])) \ - != ~((UInt32 *)regEntryID)[ 1 ] ) \ - return( ret); - -#define REG_ENTRY_TO_PT(regEntryID,obj) \ - IORegistryEntry * obj; \ - if( (UInt32)((obj = ((IORegistryEntry **)regEntryID)[ 0 ])) \ - != ~((UInt32 *)regEntryID)[ 1 ] ) \ - return( -2538); - -#define REG_ENTRY_TO_SERVICE(regEntryID,type,obj) \ - IORegistryEntry * regEntry; \ - type * obj; \ - if( (UInt32)((regEntry = ((IORegistryEntry **)regEntryID)[ 0 ])) \ - != ~((UInt32 *)regEntryID)[ 1 ] ) \ - return( -2538); \ - if( 0 == (obj = OSDynamicCast( type, regEntry))) \ - return( -2542); - -struct CntrlParam { - void * qLink; - short qType; - short ioTrap; - void * ioCmdAddr; - void * ioCompletion; - short ioResult; - char * ioNamePtr; - short ioVRefNum; - short ioCRefNum; - short csCode; - void * csParams; - short csParam[9]; -}; -typedef struct CntrlParam CntrlParam, *CntrlParamPtr; - -#pragma options align=reset - -enum { - kOpenCommand = 0, - kCloseCommand = 1, - kReadCommand = 2, - kWriteCommand = 3, - kControlCommand = 4, - kStatusCommand = 5, - kKillIOCommand = 6, - kInitializeCommand = 7, /* init driver and device*/ - kFinalizeCommand = 8, /* shutdown driver and device*/ - kReplaceCommand = 9, /* replace an old driver*/ - kSupersededCommand = 10 /* prepare to be replaced by a new driver*/ -}; -enum { - kSynchronousIOCommandKind = 0x00000001, - kAsynchronousIOCommandKind = 0x00000002, - kImmediateIOCommandKind = 0x00000004 -}; - - -extern OSStatus CallTVector( - void * p1, void * p2, void * p3, void * p4, void * p5, void * p6, - struct IOTVector * entry ); - -#ifdef __cplusplus -} -#endif - -class IONDRV : public OSObject -{ - OSDeclareDefaultStructors(IONDRV) - -private: - void * pcInst; - struct IOTVector * fDoDriverIO; - struct DriverDescription * theDriverDesc; - -public: - static IONDRV * instantiate( IORegistryEntry * regEntry, - IOLogicalAddress container, - IOByteCount containerSize, - IONDRVUndefinedSymbolHandler handler, - void * self ); - - static IONDRV * fromRegistryEntry( IORegistryEntry * regEntry, - IONDRVUndefinedSymbolHandler handler, - void * self); - - virtual void free( void ); - - virtual IOReturn getSymbol( const char * symbolName, - IOLogicalAddress * address ); - - virtual const char * driverName( void ); - - virtual IOReturn doDriverIO( UInt32 commandID, void * contents, - UInt32 commandCode, UInt32 commandKind ); - -}; - -struct IONDRVInterruptSource { - void * refCon; - struct IOTVector * handler; - struct IOTVector * enabler; - struct IOTVector * disabler; - bool registered; - bool enabled; -}; - -class IONDRVInterruptSet : public OSObject { - - OSDeclareDefaultStructors(IONDRVInterruptSet) - -public: - IOService * provider; - IOOptionBits options; - UInt32 count; - IONDRVInterruptSource * sources; - IONDRVInterruptSet * child; - - static IONDRVInterruptSet * with(IOService * provider, - IOOptionBits options, SInt32 count); - void free(); -}; - -#endif /* __IONDRV__ */ - diff --git a/iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp b/iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp deleted file mode 100644 index e6adf5dbc..000000000 --- a/iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp +++ /dev/null @@ -1,2224 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 24 Jul 98 - start IOKit. - * sdouglas 15 Dec 98 - cpp. - * - */ - -#include <IOKit/IOLib.h> -#include <IOKit/IOPlatformExpert.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOLocks.h> -#include <IOKit/pwr_mgt/RootDomain.h> -#include <IOKit/ndrvsupport/IONDRVFramebuffer.h> -#include <IOKit/pci/IOAGPDevice.h> -#include <IOKit/assert.h> - -#include <libkern/c++/OSContainers.h> - -#include "IONDRV.h" - -#include <string.h> - -#define kAppleAudioVideoJackStateKey "AppleAudioVideoJackState" - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class IOATINDRV : public IONDRVFramebuffer -{ - OSDeclareDefaultStructors(IOATINDRV) - -public: - virtual IOReturn getStartupDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ); - virtual IODeviceMemory * findVRAM( void ); - -}; - -class IOATI128NDRV : public IOATINDRV -{ - OSDeclareDefaultStructors(IOATI128NDRV) - -public: - virtual void flushCursor( void ); -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -struct _VSLService { - class IONDRVFramebuffer * framebuffer; - IOSelect type; - IOFBInterruptProc handler; - OSObject * target; - void * ref; - _VSLService * next; -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// IONDRVFramebuffer has two power states, off and on - -enum { kIONDRVFramebufferPowerStateCount = 2 }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOFramebuffer - -OSDefineMetaClassAndStructors(IONDRVFramebuffer, IOFramebuffer) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -//============ -//= External = -//============ - -IOService * IONDRVFramebuffer::probe( IOService * provider, - SInt32 * score ) -{ - IOService * inst = this; - IOService * newInst = 0; - const char * name; - - if( !super::probe( provider, score )) - return( 0 ); - - if( 0 != provider->getProperty(kIONDRVIgnoreKey)) return( 0 ); - - if( /* IONDRV::fromRegistryEntry( provider ) || */ true) { - - provider->setProperty(kIONDRVForXKey, this, sizeof(this) ); - - // temporary for in-kernel acceleration - name = provider->getName(); - if( 0 == strncmp("ATY,Rage128", name, strlen("ATY,Rage128"))) - newInst = new IOATI128NDRV; - else if( 0 == strncmp("ATY,", name, strlen("ATY,"))) - newInst = new IOATINDRV; - - if( newInst) { - if( ! newInst->init( inst->getPropertyTable())) { - newInst->release(); - newInst = 0; - } - inst = newInst; - } - } else - inst = 0; - - return( inst ); -} - -IOReturn IONDRVFramebuffer::setProperties( OSObject * properties ) -{ - OSDictionary * dict; - OSData * data; - IOReturn kr = kIOReturnUnsupported; - - if( !(dict = OSDynamicCast( OSDictionary, properties))) - return( kIOReturnBadArgument); - - if( (data = OSDynamicCast(OSData, - dict->getObject("driver,AAPL,MacOS,PowerPC")))) { - - if( ndrvState) - return( kIOReturnStillOpen ); - - if( ndrv) - ndrv->release(); - nub->setProperty("driver,AAPL,MacOS,PowerPC", data); - nub->removeProperty("AAPL,ndrvInst"); - ndrv = IONDRV::fromRegistryEntry( nub, &_undefinedSymbolHandler, (void *) this ); - if( ndrv) - setName( ndrv->driverName()); - - kr = kIOReturnSuccess; - } - - return( kr ); -} - -static IOPMrootDomain * gIOPMRootDomain; - -bool IONDRVFramebuffer::start( IOService * provider ) -{ - bool ok = false; - IOService * parent; - OSData * data; - - do { - cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid; - - nub = provider; - ndrv = IONDRV::fromRegistryEntry( provider, &_undefinedSymbolHandler, this ); - if( ndrv) - setName( ndrv->driverName()); - startAt8 = 3; - consoleDevice = (0 != provider->getProperty("AAPL,boot-display")); - powerState = 1; - - if( 0 == nub->getDeviceMemoryCount()) { - parent = OSDynamicCast( IOService, nub->getParentEntry(gIODTPlane)); - if( parent) { - parent->getResources(); - OSArray * array = parent->getDeviceMemory(); - array->retain(); - nub->setDeviceMemory( array); - array->release(); - } - } - - if( false == super::start( nub )) - continue; - - if( !gIOPMRootDomain) - gIOPMRootDomain = (IOPMrootDomain *) - IORegistryEntry::fromPath("/IOPowerConnection/IOPMrootDomain", gIOPowerPlane); - if( gIOPMRootDomain) - platformDeepSleep = (gIOPMRootDomain->getSleepSupported() - & kFrameBufferDeepSleepSupported) ? 1 : 0; - - // default flags can be overriden - accessFlags = 0; - if(0 == strncmp("3Dfx", provider->getName(), strlen("3Dfx"))) - accessFlags |= kFramebufferDisableAltivecAccess; - - if( (data = OSDynamicCast( OSData, provider->getProperty(kIOFBHostAccessFlagsKey)))) - accessFlags = *((UInt32 *) data->getBytesNoCopy()); - - ok = true; // Success - - } while( false); - - return( ok); -} - -bool IONDRVFramebuffer::isConsoleDevice( void ) -{ - return( consoleDevice ); -} - -// osfmk/ppc/mappings.h -extern "C" { extern void ignore_zero_fault(boolean_t); } - -IOReturn IONDRVFramebuffer::enableController( void ) -{ - IOReturn err; - const char * logname; - OSData * data; - - logname = getProvider()->getName(); - - if( 0 == strcmp( "control", logname)) - waitForService( resourceMatching( "IOiic0" )); - - if( 0 == ndrv) - err = kIOReturnNotReady; - else - err = IONDRVLibrariesInitialize( getProvider() ); - - if( kIOReturnSuccess == err) do { - - // find out about onboard audio/video jack state - // OSObject * notify = - addNotification( gIOPublishNotification, - resourceMatching(kAppleAudioVideoJackStateKey), - _videoJackStateChangeHandler, this, 0 ); - - ignore_zero_fault( true ); - err = checkDriver(); - ignore_zero_fault( false ); - - if( err) { - IOLog("%s: Not usable\n", logname ); - if( err == -999) - IOLog("%s: driver incompatible.\n", logname ); - continue; - } - getCurrentConfiguration(); - vramMemory = findVRAM(); - - // disable clamshell sleep on a single head portable - if( gIOPMRootDomain - && (0 == OSDynamicCast( IOPCIDevice, getProvider())) - && (data = OSDynamicCast( OSData, - getProvider()->getProperty("ATY,PanelActive")))) { - - if( 0 == *((UInt32 *) data->getBytesNoCopy())) - gIOPMRootDomain->receivePowerNotification( kIOPMIgnoreClamshell); - } - - // initialize power management of the device - initForPM(); - - } while( false); - - return( err); -} - -bool IONDRVFramebuffer::_videoJackStateChangeHandler( void * target, void * ref, - IOService * resourceService ) -{ - IONDRVFramebuffer * self = (IONDRVFramebuffer *) target; - IOReturn err; - UInt32 jackData; - - OSObject * jackValue = resourceService->getProperty(kAppleAudioVideoJackStateKey); - if( !jackValue) - return( true ); - - jackData = (jackValue == kOSBooleanTrue); - - self->nub->setProperty( kAppleAudioVideoJackStateKey, &jackData, sizeof(jackData) ); - resourceService->removeProperty(kAppleAudioVideoJackStateKey); - - return( true ); -} - -IODeviceMemory * IONDRVFramebuffer::getVRAMRange( void ) -{ - if( vramMemory) - vramMemory->retain(); - - return( vramMemory ); -} - -const IOTVector * IONDRVFramebuffer::_undefinedSymbolHandler( void * self, - const char * libraryName, const char * symbolName ) -{ - return( ((IONDRVFramebuffer *)self)->undefinedSymbolHandler( libraryName, symbolName) ); -} - -const IOTVector * IONDRVFramebuffer::undefinedSymbolHandler( const char * libraryName, - const char * symbolName ) -{ - return( 0 ); -} - -void IONDRVFramebuffer::free( void ) -{ - super::free(); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IONDRVFramebuffer::registerForInterruptType( IOSelect interruptType, - IOFBInterruptProc proc, OSObject * target, void * ref, - void ** interruptRef ) - -{ - _VSLService * service; - IOReturn err; - - if( (interruptType == kIOFBVBLInterruptType) - && (getProvider()->getProperty("Ignore VBL"))) - return( kIOReturnUnsupported ); - - for( service = vslServices; - service && (service->type != interruptType); - service = service->next ) {} - - if( service) { - - if( service->handler) - err = kIOReturnBusy; - - else { - service->target = target; - service->ref = ref; - service->handler = proc; - *interruptRef = service; - err = kIOReturnSuccess; - } - - } else - err = kIOReturnNoResources; - - return( err ); -} - -IOReturn IONDRVFramebuffer::unregisterInterrupt( void * interruptRef ) -{ - _VSLService * service = (_VSLService *) interruptRef; - - service->handler = 0; - - return( kIOReturnSuccess ); -} - -IOReturn IONDRVFramebuffer::setInterruptState( void * interruptRef, - UInt32 state ) -{ - return( kIOReturnUnsupported ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -//// VSL calls - -OSStatus IONDRVFramebuffer::VSLNewInterruptService( - void * entryID, - IOSelect serviceType, - _VSLService ** vslService ) -{ - IORegistryEntry * regEntry; - IONDRVFramebuffer * fb; - _VSLService * service; - IOReturn err = kIOReturnSuccess; - - REG_ENTRY_TO_OBJ( (const RegEntryID *) entryID, regEntry) - - fb = OSDynamicCast( IONDRVFramebuffer, - regEntry->getChildEntry( gIOServicePlane )); - assert( fb ); - - if( fb) { - service = IONew( _VSLService, 1 ); - - if( service) { - service->framebuffer = fb; - service->type = serviceType; - service->handler = 0; - service->next = fb->vslServices; - fb->vslServices = service; - - *vslService = service; - - } else - err = kIOReturnNoMemory; - - } else - err = kIOReturnBadArgument; - - return( err ); -} - -OSStatus IONDRVFramebuffer::VSLDisposeInterruptService(_VSLService * vslService) -{ - IONDRVFramebuffer * fb; - _VSLService * next; - _VSLService * prev; - - if( vslService) { - - fb = vslService->framebuffer; - - prev = fb->vslServices; - if( prev == vslService) - fb->vslServices = vslService->next; - else { - while( ((next = prev->next) != vslService) && next) - prev = next; - if( next) - prev->next = vslService->next; - } - - IODelete( vslService, _VSLService, 1 ); - } - - return( kIOReturnSuccess ); -} - -OSStatus IONDRVFramebuffer::VSLDoInterruptService( _VSLService * vslService ) -{ - IOFBInterruptProc proc; - - if( vslService) { - if( (proc = vslService->handler)) - (*proc) (vslService->target, vslService->ref); - } - - return( kIOReturnSuccess ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -struct _VSLCursorRef { - IOFramebuffer * framebuffer; - void * cursorImage; -}; - -Boolean IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor( - void * cursorRef, - IOHardwareCursorDescriptor * hwDesc, - IOHardwareCursorInfo * hwCursorInfo ) -{ - _VSLCursorRef * cursor = (_VSLCursorRef *) cursorRef; - bool ok; - - if( hwCursorInfo->colorMap) - hwCursorInfo->colorMap += 1; - ok = cursor->framebuffer->convertCursorImage( - cursor->cursorImage, hwDesc, hwCursorInfo ); - if( hwCursorInfo->colorMap) - hwCursorInfo->colorMap -= 1; - - return( ok ); -} - -IOReturn IONDRVFramebuffer::setCursorImage( void * cursorImage ) -{ - _VSLCursorRef cursorRef; - VDSetHardwareCursorRec setCursor; - IOReturn err; - - if( 0 == powerState) - return( kIOReturnSuccess ); - - cursorRef.framebuffer = this; - cursorRef.cursorImage = cursorImage; - - setCursor.csCursorRef = (void *) &cursorRef; - setCursor.csReserved1 = 0; - setCursor.csReserved2 = 0; - - err = doControl( cscSetHardwareCursor, &setCursor ); - - return( err ); -} - -IOReturn IONDRVFramebuffer::setCursorState( SInt32 x, SInt32 y, bool visible ) -{ - VDDrawHardwareCursorRec drawCursor; - IOReturn err; - - if( 0 == powerState) - return( kIOReturnSuccess ); - - if( 0 == OSIncrementAtomic( &ndrvEnter)) - { - - drawCursor.csCursorX = x; - drawCursor.csCursorY = y; - drawCursor.csCursorVisible = visible; - drawCursor.csReserved1 = 0; - drawCursor.csReserved2 = 0; - - err = doControl( cscDrawHardwareCursor, &drawCursor ); - - } else - err = kIOReturnBusy; - - OSDecrementAtomic( &ndrvEnter ); - - return( err ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -//============ -//= Internal = -//============ - -IOReturn IONDRVFramebuffer::doControl( UInt32 code, void * params ) -{ - IOReturn err; - CntrlParam pb; - - if( ndrvState == 0) - return( kIOReturnNotOpen); - - pb.qLink = 0; - pb.csCode = code; - pb.csParams = params; - - OSIncrementAtomic( &ndrvEnter ); - err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb, - kControlCommand, kImmediateIOCommandKind ); - OSDecrementAtomic( &ndrvEnter ); - - return( err); -} - -IOReturn IONDRVFramebuffer::doStatus( UInt32 code, void * params ) -{ - IOReturn err; - CntrlParam pb; - - if( ndrvState == 0) - return( kIOReturnNotOpen); - - pb.qLink = 0; - pb.csCode = code; - pb.csParams = params; - - OSIncrementAtomic( &ndrvEnter ); - err = ndrv->doDriverIO( /*ID*/ (UInt32) &pb, &pb, - kStatusCommand, kImmediateIOCommandKind ); - OSDecrementAtomic( &ndrvEnter ); - - return( err); -} - - -IOReturn IONDRVFramebuffer::checkDriver( void ) -{ - OSStatus err = noErr; - struct DriverInitInfo initInfo; - CntrlParam pb; - VDClutBehavior clutSetting; - VDGammaRecord gammaRec; - VDSwitchInfoRec switchInfo; - IOTimingInformation info; - VDPageInfo pageInfo; - - if( ndrvState == 0) { - do { - initInfo.refNum = 0xffcd; // ...sure. - MAKE_REG_ENTRY(initInfo.deviceEntry, nub ) - - err = ndrv->doDriverIO( 0, &initInfo, - kInitializeCommand, kImmediateIOCommandKind ); - if( err) continue; - - err = ndrv->doDriverIO( 0, &pb, - kOpenCommand, kImmediateIOCommandKind ); - - } while( false); - - if( err) - return( err); - - // allow calls to ndrv - ndrvState = 1; - - if( (noErr == doStatus( cscGetCurMode, &switchInfo )) - && (noErr == getTimingInfoForDisplayMode( switchInfo.csData, &info)) - && (timingApple_0x0_0hz_Offline == info.appleTimingID)) { - - IOLog("%s: display offline\n", getName()); - err = kIOReturnOffline; - return( err); - } else - ndrvState = 2; - -#if IONDRVI2CLOG - do { - VDCommunicationInfoRec commInfo; - - bzero( &commInfo, sizeof( commInfo)); - commInfo.csBusID = kVideoDefaultBus; - - err = doStatus( cscGetCommunicationInfo, &commInfo ); - IOLog("%s: cscGetCommunicationInfo: ", getName()); - if( kIOReturnSuccess != err) { - IOLog("fails with %ld\n", err); - continue; - } - if( commInfo.csSupportedTypes & (1<<kVideoDDCciReplyType) ) - IOLog("supports kVideoDDCciReplyType, "); - if( commInfo.csSupportedTypes & (1<<kVideoSimpleI2CType) ) { - IOLog("supports kVideoSimpleI2CType"); - VDCommunicationRec comm; - UInt8 edidData[132]; - UInt8 edidRequest[2]; - - edidData[0] = 0xAA; - edidData[1] = 0xAA; - edidData[2] = 0xAA; - edidData[3] = 0xAA; - edidData[128] = 0xAA; - edidData[129] = 0xAA; - edidData[130] = 0xAA; - edidData[131] = 0xAA; - - memset( edidData, 0xAA, sizeof( edidData)); - - edidRequest[0] = 0; - edidRequest[1] = 0; - - comm.csBusID = kVideoDefaultBus; - comm.csReserved0 = 0; - comm.csReserved1 = 0; - comm.csReserved2 = 0; - - comm.csSendAddress = 0xA0; - comm.csSendType = kVideoSimpleI2CType; - comm.csSendBuffer = &edidRequest[0]; - comm.csSendSize = 0x01; - - comm.csReplyAddress = 0xA1; - comm.csReplyType = kVideoSimpleI2CType; - comm.csReplyBuffer = &edidData[0]; - comm.csReplySize = 128; - - comm.csReserved3 = 0; - comm.csReserved4 = 0; - comm.csReserved5 = 0; - comm.csReserved6 = 0; - - do { - err = doControl( cscDoCommunication, &comm ); - IOLog("\nI2C read block[%x](%ld)\n", edidRequest[0], err); - if( kIOReturnSuccess != err) - break; - IOLog(" 0 1 2 3 4 5 6 7 8 9 A B C D E F"); - for( int i = 0; i < 128; i++) { - if( 0 == (i & 15)) - IOLog("\n%02x: ", i); - IOLog("%02x ", edidData[i]); - } - IOLog("\n"); - if( edidRequest[0] || (0 == edidData[126])) - break; - edidRequest[0] = 0x80; - } while( true ); - } - - } while( false ); -#endif /* IONDRVI2CLOG */ - - // duplicate QD InitGDevice - pageInfo.csMode = switchInfo.csMode; - pageInfo.csData = 0; - pageInfo.csPage = 0; - doControl( cscGrayPage, &pageInfo); - - clutSetting = kSetClutAtSetEntries; - lastClutSetting = clutSetting; - doControl( cscSetClutBehavior, &clutSetting); - - do { - VDDisplayTimingRangeRec rangeRec; - - bzero( &rangeRec, sizeof( rangeRec)); - err = doStatus( cscGetTimingRanges, &rangeRec ); - if( kIOReturnSuccess != err) - continue; - - setProperty( kIOFBTimingRangeKey, &rangeRec, sizeof( rangeRec)); - - } while( false ); - -#if 1 - // bogus for ROM control - do { - - VDGetGammaListRec scan; - VDRetrieveGammaRec get; - GammaTbl * table; - char name[ 64 ]; - - scan.csPreviousGammaTableID = kGammaTableIDFindFirst; - scan.csGammaTableName = name; - err = doStatus( cscGetGammaInfoList, &scan); - if( err || (scan.csGammaTableID == (GammaTableID) kGammaTableIDNoMoreTables)) - continue; - - table = (GammaTbl *)IOMalloc( scan.csGammaTableSize); - if( 0 == table) - continue; - get.csGammaTableID = scan.csGammaTableID; - get.csGammaTablePtr = table; - - err = doStatus( cscRetrieveGammaTable, &get ); - if( noErr == err) { - kprintf("Setting gamma %s\n", scan.csGammaTableName); - gammaRec.csGTable = (Ptr) table; - doControl( cscSetGamma, &gammaRec ); - } - - IOFree( table, scan.csGammaTableSize); - - } while( false); -#endif - } - return( noErr); -} - - -UInt32 IONDRVFramebuffer::iterateAllModes( IODisplayModeID * displayModeIDs ) -{ - VDResolutionInfoRec info; - UInt32 num = 0; - - info.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; - - while( - (noErr == doStatus( cscGetNextResolution, &info)) - && ((SInt32) info.csDisplayModeID > 0) ) { - - if( displayModeIDs) - displayModeIDs[ num ] = info.csDisplayModeID; - - info.csPreviousDisplayModeID = info.csDisplayModeID; - num++; - } - - if( detailedTimings) { - IOItemCount count, i; - - count = detailedTimings->getCount(); - if( displayModeIDs) { - for( i = 0; i < count; i++) - displayModeIDs[ num + i ] = kDisplayModeIDReservedBase + i; - } - num += count; - } - - return( num); -} - -IOReturn IONDRVFramebuffer::getResInfoForArbMode( IODisplayModeID modeID, - IODisplayModeInformation * info ) -{ - VDVideoParametersInfoRec pixelParams; - VPBlock pixelInfo; - VDDetailedTimingRec * detailed; - IOIndex depth; - IOReturn err; - - err = validateDisplayMode( modeID, 0, &detailed ); - - for( depth = -1; err == kIOReturnSuccess; ) { - pixelParams.csDisplayModeID = modeID; - pixelParams.csDepthMode = ++depth + kDepthMode1; - pixelParams.csVPBlockPtr = &pixelInfo; - err = doStatus( cscGetVideoParameters, &pixelParams ); - } - - if( depth) { - info->maxDepthIndex = depth - 1; - info->nominalWidth = pixelInfo.vpBounds.right; - info->nominalHeight = pixelInfo.vpBounds.bottom; - if( detailed) - info->refreshRate = detailed->csPixelClock * 65536ULL / - ((detailed->csVerticalActive + detailed->csVerticalBlanking) - * (detailed->csHorizontalActive + detailed->csHorizontalBlanking)); - else - info->refreshRate = 0; - - err = kIOReturnSuccess; - } - - return( err ); -} - -IOReturn IONDRVFramebuffer::getResInfoForMode( IODisplayModeID modeID, - IODisplayModeInformation * info ) -{ - - bzero( info, sizeof( *info)); - - if( (UInt32) modeID >= (UInt32) kDisplayModeIDReservedBase) - return( getResInfoForArbMode( modeID, info )); - - // unfortunately, there is no "kDisplayModeIDFindSpecific" - if( cachedVDResolution.csDisplayModeID != (UInt32) modeID) { - - // try the next after cached mode - cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID; - if( (noErr != doStatus( cscGetNextResolution, &cachedVDResolution)) - || (cachedVDResolution.csDisplayModeID != (UInt32) modeID) ) { - - // else full blown iterate - cachedVDResolution.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; - while( - (noErr == doStatus( cscGetNextResolution, &cachedVDResolution)) - && (cachedVDResolution.csDisplayModeID != (UInt32) modeID) - && ((SInt32) cachedVDResolution.csDisplayModeID > 0)) { - - cachedVDResolution.csPreviousDisplayModeID = cachedVDResolution.csDisplayModeID; - } - } - } - - if( cachedVDResolution.csDisplayModeID != (UInt32) modeID) { - cachedVDResolution.csDisplayModeID = kDisplayModeIDInvalid; - return( kIOReturnUnsupportedMode); - - } else { - - info->maxDepthIndex = cachedVDResolution.csMaxDepthMode - kDepthMode1; - info->nominalWidth = cachedVDResolution.csHorizontalPixels; - info->nominalHeight = cachedVDResolution.csVerticalLines; - info->refreshRate = cachedVDResolution.csRefreshRate; - - return( noErr); - } -} - -enum { - kModePreflight = 1, - kDisplayModeIDPreflight = kDisplayModeIDReservedBase + 1000 -}; - -IOReturn IONDRVFramebuffer::setDetailedTiming( - IODisplayModeID mode, IOOptionBits options, - void * _desc, IOByteCount descripSize ) -{ - IOReturn err; - VDResolutionInfoRec info; - VDDetailedTimingRec * desc = (VDDetailedTimingRec *)_desc; - VDDetailedTimingRec look; - IOIndex index; - bool notPreflight = (0 == (options & kModePreflight)); - - // current must be ok - if( mode == currentDisplayMode) - return( kIOReturnSuccess ); - - index = mode - kDisplayModeIDReservedBase; - bzero( &look, sizeof( VDDetailedTimingRec) ); - look.csTimingSize = sizeof( VDDetailedTimingRec); - - // look for a programmable - for( - info.csPreviousDisplayModeID = kDisplayModeIDFindFirstProgrammable; - (noErr == (err = doStatus( cscGetNextResolution, &info))); - info.csPreviousDisplayModeID = info.csDisplayModeID) { - - if( (SInt32) info.csDisplayModeID < 0) { - err = kIOReturnNoResources; - break; - } - - look.csDisplayModeID = info.csDisplayModeID; - err = doStatus( cscGetDetailedTiming, &look ); - if( err != kIOReturnSuccess) - continue; - - // don't toss current - if( look.csDisplayModeAlias == (UInt32) currentDisplayMode) - continue; - - // see if already set to the right timing - if( (look.csDisplayModeAlias == (UInt32) mode) - && (look.csDisplayModeState == kDMSModeReady) - && (notPreflight) - && (detailedTimingsCurrent[index] == detailedTimingsSeed)) - break; - - // set it free - if( look.csDisplayModeState != kDMSModeFree) { - look.csDisplayModeID = info.csDisplayModeID; - look.csDisplayModeAlias = 0; - look.csDisplayModeState = kDMSModeFree; - err = doControl( cscSetDetailedTiming, &look ); - if( err != kIOReturnSuccess) - continue; - } - // set it ready - desc->csDisplayModeID = info.csDisplayModeID; - desc->csDisplayModeAlias = mode; - desc->csDisplayModeSeed = look.csDisplayModeSeed; - desc->csDisplayModeState = kDMSModeReady; - err = doControl( cscSetDetailedTiming, desc ); - - if( kIOReturnSuccess == err) { - if( notPreflight) - // don't stomp orig record - desc = &look; - err = doStatus( cscGetDetailedTiming, desc ); - } - if( notPreflight && (kIOReturnSuccess == err)) - detailedTimingsCurrent[index] = detailedTimingsSeed; - - break; - } - - return( err ); -} - -IOReturn IONDRVFramebuffer::validateDisplayMode( - IODisplayModeID _mode, IOOptionBits flags, - VDDetailedTimingRec ** detailed ) -{ - UInt32 mode = _mode; - IOReturn err = kIOReturnSuccess; - OSData * data; - const void * bytes; - - if( detailed) - *detailed = (VDDetailedTimingRec *) 0; - - if( mode >= (UInt32) kDisplayModeIDReservedBase) do { - - if( mode == (UInt32) kDisplayModeIDBootProgrammable) - continue; - - err = kIOReturnBadArgument; - if( !detailedTimings) - continue; - - data = OSDynamicCast( OSData, detailedTimings->getObject( - mode - kDisplayModeIDReservedBase)); - if( !data) - continue; - - bytes = data->getBytesNoCopy(); - err = setDetailedTiming( mode, 0, (void *) bytes, data->getLength() ); - if( err != kIOReturnSuccess) - continue; - - if( detailed) - *detailed = (VDDetailedTimingRec *) bytes; - - } while( false ); - - return( err ); -} - -void IONDRVFramebuffer::getCurrentConfiguration( void ) -{ - IOReturn err; - VDSwitchInfoRec switchInfo; - VDGrayRecord grayRec; - - grayRec.csMode = 0; // turn off luminance map - err = doControl( cscSetGray, &grayRec ); - // driver refused => mono display - grayMode = ((noErr == err) && (0 != grayRec.csMode)); - - err = doStatus( cscGetCurMode, &switchInfo ); - if( err == noErr) { - currentDisplayMode = switchInfo.csData; - currentDepth = switchInfo.csMode - kDepthMode1; - currentPage = switchInfo.csPage; - if( 0 == (physicalFramebuffer = pmap_extract( kernel_pmap, - ((vm_address_t) switchInfo.csBaseAddr) ))) - physicalFramebuffer = (UInt32) switchInfo.csBaseAddr; - } else - IOLog("%s: cscGetCurMode failed\n", nub->getName()); -} - -IODeviceMemory * IONDRVFramebuffer::makeSubRange( - IOPhysicalAddress start, - IOPhysicalLength length ) -{ - IODeviceMemory * mem = 0; - UInt32 numMaps, i; - IOService * device; - - device = nub; - numMaps = device->getDeviceMemoryCount(); - - for( i = 0; (!mem) && (i < numMaps); i++) { - mem = device->getDeviceMemoryWithIndex(i); - if( !mem) - continue; - mem = IODeviceMemory::withSubRange( mem, - start - mem->getPhysicalAddress(), length ); - } - if( !mem) - mem = IODeviceMemory::withRange( start, length ); - - return( mem ); -} - -IODeviceMemory * IONDRVFramebuffer::getApertureRange( IOPixelAperture aper ) -{ - IOReturn err; - IOPixelInformation info; - IOByteCount bytes; - - err = getPixelInformation( currentDisplayMode, currentDepth, aper, - &info ); - if( err) - return( 0 ); - - bytes = (info.bytesPerRow * info.activeHeight) + 128; - - return( makeSubRange( physicalFramebuffer, bytes )); -} - -IODeviceMemory * IONDRVFramebuffer::findVRAM( void ) -{ - VDVideoParametersInfoRec pixelParams; - VPBlock pixelInfo; - VDResolutionInfoRec vdRes; - UInt32 size; - IOPhysicalAddress vramBase = physicalFramebuffer; - IOByteCount vramLength; - IOReturn err; - OSData * prop; - - vramLength = 0; - prop = OSDynamicCast( OSData, nub->getProperty("VRAM,memsize")); - - if( prop) { - vramLength = *((IOByteCount *)prop->getBytesNoCopy()); - if( vramLength) { - vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000; - vramBase &= 0xffff0000; - } - } - - if( !vramLength) { - - vdRes.csPreviousDisplayModeID = kDisplayModeIDFindFirstResolution; - while( - (noErr == doStatus( cscGetNextResolution, &vdRes)) - && ((SInt32) vdRes.csDisplayModeID > 0) ) - { - pixelParams.csDisplayModeID = vdRes.csDisplayModeID; - pixelParams.csDepthMode = vdRes.csMaxDepthMode; - pixelParams.csVPBlockPtr = &pixelInfo; - err = doStatus( cscGetVideoParameters, &pixelParams); - if( err) - continue; - - // Control hangs its framebuffer off the end of the aperture to support - // 832 x 624 @ 32bpp. The commented out version will correctly calculate - // the vram length, but DPS needs the full extent to be mapped, so we'll - // end up mapping an extra page that will address vram through the - // little endian aperture. No other drivers like this known. -#if 1 - size = 0x40 + pixelInfo.vpBounds.bottom * - (pixelInfo.vpRowBytes & 0x7fff); -#else - size = ( (pixelInfo.vpBounds.right * pixelInfo.vpPixelSize) / 8) // last line - + (pixelInfo.vpBounds.bottom - 1) * - (pixelInfo.vpRowBytes & 0x7fff); -#endif - if( size > vramLength) - vramLength = size; - - vdRes.csPreviousDisplayModeID = vdRes.csDisplayModeID; - } - - vramLength = (vramLength + (vramBase & 0xffff) + 0xffff) & 0xffff0000; - vramBase &= 0xffff0000; - } - - return( makeSubRange( vramBase, vramLength )); -} - - -//============ -//= External = -//============ - -const char * IONDRVFramebuffer::getPixelFormats( void ) -{ - static const char * ndrvPixelFormats = - IO1BitIndexedPixels "\0" - IO2BitIndexedPixels "\0" - IO4BitIndexedPixels "\0" - IO8BitIndexedPixels "\0" - IO16BitDirectPixels "\0" - IO32BitDirectPixels "\0" - "\0"; - - return( ndrvPixelFormats); -} - -IOItemCount IONDRVFramebuffer::getDisplayModeCount( void ) -{ - return( iterateAllModes( 0 )); -} - -IOReturn IONDRVFramebuffer::getDisplayModes( IODisplayModeID * allDisplayModes ) -{ - iterateAllModes( allDisplayModes ); - return( kIOReturnSuccess ); -} - -IOReturn IONDRVFramebuffer::validateDetailedTiming( - void * desc, IOByteCount descripSize ) -{ - IOReturn err; - - err = setDetailedTiming( kDisplayModeIDPreflight, - kModePreflight, desc, descripSize); - - return( err ); -} - -IOReturn IONDRVFramebuffer::setDetailedTimings( OSArray * array ) -{ - IOReturn err; - UInt32 * newCurrent; - IOItemCount newCount; - - newCount = array->getCount(); - newCurrent = IONew(UInt32, newCount); - if( newCurrent) { - if( detailedTimings) - IODelete( detailedTimingsCurrent, UInt32, detailedTimings->getCount()); - detailedTimingsCurrent = newCurrent; - bzero( newCurrent, newCount * sizeof( UInt32)); - setProperty( kIOFBDetailedTimingsKey, array ); // retains - detailedTimings = array; - detailedTimingsSeed++; - - if( currentDisplayMode == kDisplayModeIDBootProgrammable) { - VDDetailedTimingRec look; - VDDetailedTimingRec * detailed; - OSData * data; - IODisplayModeID newDisplayMode; - - newDisplayMode = currentDisplayMode; - - bzero( &look, sizeof( VDDetailedTimingRec) ); - look.csTimingSize = sizeof( VDDetailedTimingRec); - look.csDisplayModeID = kDisplayModeIDBootProgrammable; - err = doStatus( cscGetDetailedTiming, &look ); - - if( kIOReturnSuccess == err) - for( int i = 0; - (data = OSDynamicCast( OSData, detailedTimings->getObject(i))); - i++) { - - detailed = (VDDetailedTimingRec *) data->getBytesNoCopy(); - if( (detailed->csHorizontalActive == look.csHorizontalActive) - && (detailed->csVerticalActive == look.csVerticalActive)) { - - newDisplayMode = i + kDisplayModeIDReservedBase; - break; - } - } - if( newDisplayMode != currentDisplayMode) { - err = validateDisplayMode( newDisplayMode, 0, 0 ); - currentDisplayMode = newDisplayMode; - } - } - - err = kIOReturnSuccess; - } else - err = kIOReturnNoMemory; - - return( err ); -} - -IOReturn IONDRVFramebuffer::getInformationForDisplayMode( - IODisplayModeID displayMode, IODisplayModeInformation * info ) -{ - IOReturn err; - - err = getResInfoForMode( displayMode, info ); - if( err) - err = kIOReturnUnsupportedMode; - - return( err ); -} - - -UInt64 IONDRVFramebuffer::getPixelFormatsForDisplayMode( - IODisplayModeID /* displayMode */, IOIndex depthIndex ) -{ - return( 1 << (depthIndex + startAt8)); -} - -IOReturn IONDRVFramebuffer::getPixelInformation( - IODisplayModeID displayMode, IOIndex depth, - IOPixelAperture aperture, IOPixelInformation * info ) -{ - SInt32 err; - VDVideoParametersInfoRec pixelParams; - VPBlock pixelInfo; - const char * formats; - UInt32 mask; - int index; - - bzero( info, sizeof( *info)); - - if( aperture) - return( kIOReturnUnsupportedMode); - - err = validateDisplayMode( displayMode, 0, 0 ); - if( err) - return( err ); - - do { - pixelParams.csDisplayModeID = displayMode; - pixelParams.csDepthMode = depth + kDepthMode1; - pixelParams.csVPBlockPtr = &pixelInfo; - err = doStatus( cscGetVideoParameters, &pixelParams ); - if( err) - continue; - - info->flags = accessFlags; - - info->activeWidth = pixelInfo.vpBounds.right; - info->activeHeight = pixelInfo.vpBounds.bottom; - info->bytesPerRow = pixelInfo.vpRowBytes & 0x7fff; - info->bytesPerPlane = pixelInfo.vpPlaneBytes; - info->bitsPerPixel = pixelInfo.vpPixelSize; - - formats = getPixelFormats(); - mask = getPixelFormatsForDisplayMode( displayMode, depth ); - - for( index = 0; index < 32; index++) { - if( (mask & (1 << index)) && ((aperture--) == 0)) { - strcpy( info->pixelFormat, formats); - break; - } - formats += strlen( formats) + 1; - } - - if( 0 == strcmp("PPPPPPPP", info->pixelFormat)) { - info->pixelType = kIOCLUTPixels; - info->componentMasks[0] = 0xff; - info->bitsPerPixel = 8; - info->componentCount = 1; - info->bitsPerComponent = 8; - - } else if( 0 == strcmp("-RRRRRGGGGGBBBBB", info->pixelFormat)) { - info->pixelType = kIORGBDirectPixels; - info->componentMasks[0] = 0x7c00; - info->componentMasks[1] = 0x03e0; - info->componentMasks[2] = 0x001f; - info->bitsPerPixel = 16; - info->componentCount = 3; - info->bitsPerComponent = 5; - - } else if( 0 == strcmp("--------RRRRRRRRGGGGGGGGBBBBBBBB", - info->pixelFormat)) { - info->pixelType = kIORGBDirectPixels; - info->componentMasks[0] = 0x00ff0000; - info->componentMasks[1] = 0x0000ff00; - info->componentMasks[2] = 0x000000ff; - info->bitsPerPixel = 32; - info->componentCount = 3; - info->bitsPerComponent = 8; - } - - } while( false); - - return( err); -} - -IOReturn IONDRVFramebuffer::getTimingInfoForDisplayMode( - IODisplayModeID displayMode, IOTimingInformation * info ) -{ - VDTimingInfoRec timingInfo; - OSStatus err; - - err = validateDisplayMode( displayMode, 0, 0 ); - if( err) - return( err ); - - timingInfo.csTimingMode = displayMode; - // in case the driver doesn't do it: - timingInfo.csTimingFormat = kDeclROMtables; - err = doStatus( cscGetModeTiming, &timingInfo); - if( err == noErr) { - if( timingInfo.csTimingFormat == kDeclROMtables) - info->appleTimingID = timingInfo.csTimingData; - else - info->appleTimingID = timingInvalid; - - return( kIOReturnSuccess); - } - - return( kIOReturnUnsupportedMode); -} - -IOReturn IONDRVFramebuffer::getCurrentDisplayMode( - IODisplayModeID * displayMode, IOIndex * depth ) -{ - if( displayMode) - *displayMode = currentDisplayMode; - if( depth) - *depth = currentDepth; - - return( kIOReturnSuccess); -} - -IOReturn IONDRVFramebuffer::setDisplayMode( IODisplayModeID displayMode, IOIndex depth ) -{ - SInt32 err; - VDSwitchInfoRec switchInfo; - VDPageInfo pageInfo; - - err = validateDisplayMode( displayMode, 0, 0 ); - if( err) - return( err ); - - ignore_zero_fault( true ); - switchInfo.csData = displayMode; - switchInfo.csMode = depth + kDepthMode1; - switchInfo.csPage = 0; - err = doControl( cscSwitchMode, &switchInfo); - if(err) - IOLog("%s: cscSwitchMode:%d\n", nub->getName(), (int)err); - - // duplicate QD InitGDevice - pageInfo.csMode = switchInfo.csMode; - pageInfo.csData = 0; - pageInfo.csPage = 0; - doControl( cscSetMode, &pageInfo); - doControl( cscGrayPage, &pageInfo); - ignore_zero_fault( false ); - - getCurrentConfiguration(); - - return( err); -} - -IOReturn IONDRVFramebuffer::setStartupDisplayMode( - IODisplayModeID displayMode, IOIndex depth ) -{ - SInt32 err; - VDSwitchInfoRec switchInfo; - - err = validateDisplayMode( displayMode, 0, 0 ); - if( err) - return( err ); - - switchInfo.csData = displayMode; - switchInfo.csMode = depth + kDepthMode1; - err = doControl( cscSavePreferredConfiguration, &switchInfo); - return( err); -} - -IOReturn IONDRVFramebuffer::getStartupDisplayMode( - IODisplayModeID * displayMode, IOIndex * depth ) -{ - SInt32 err; - VDSwitchInfoRec switchInfo; - - err = doStatus( cscGetPreferredConfiguration, &switchInfo); - if( err == noErr) { - *displayMode = switchInfo.csData; - *depth = switchInfo.csMode - kDepthMode1; - } - return( err); -} - -IOReturn IONDRVFramebuffer::setApertureEnable( IOPixelAperture /* aperture */, - IOOptionBits /* enable */ ) -{ - return( kIOReturnSuccess); -} - -IOReturn IONDRVFramebuffer::setCLUTWithEntries( - IOColorEntry * colors, UInt32 index, UInt32 numEntries, - IOOptionBits options ) -{ - IOReturn err; - UInt32 code; - VDSetEntryRecord setEntryRec; - VDClutBehavior clutSetting; - VDGrayRecord grayRec; - - if( 0 == powerState) - return( kIOReturnSuccess ); - - if( options & kSetCLUTWithLuminance) - grayRec.csMode = 1; // turn on luminance map - else - grayRec.csMode = 0; // turn off luminance map - - if( grayRec.csMode != lastGrayMode) { - doControl( cscSetGray, &grayRec); - lastGrayMode = grayRec.csMode; - } - - if( options & kSetCLUTImmediately) - clutSetting = kSetClutAtSetEntries; - else - clutSetting = kSetClutAtVBL; - - if( clutSetting != lastClutSetting) { - doControl( cscSetClutBehavior, &clutSetting); - lastClutSetting = clutSetting; - } - - if( options & kSetCLUTByValue) - setEntryRec.csStart = -1; - else - setEntryRec.csStart = index; - - setEntryRec.csTable = (ColorSpec *) colors; - setEntryRec.csCount = numEntries - 1; - if( directMode) - code = cscDirectSetEntries; - else - code = cscSetEntries; - err = doControl( code, &setEntryRec); - - return( err); -} - -IOReturn IONDRVFramebuffer::setGammaTable( UInt32 channelCount, UInt32 dataCount, - UInt32 dataWidth, void * data ) -{ - IOReturn err; - VDGammaRecord gammaRec; - struct GammaTbl { - short gVersion; /*gamma version number*/ - short gType; /*gamma data type*/ - short gFormulaSize; /*Formula data size */ - short gChanCnt; /*number of channels of data */ - short gDataCnt; /*number of values/channel */ - short gDataWidth; /*bits/corrected value */ - /* (data packed to next larger byte size) */ - UInt8 gFormulaData[0]; /* data for formulas followed by gamma values */ - }; - GammaTbl * table = NULL; - IOByteCount dataLen = 0; - - if( 0 == powerState) - return( kIOReturnSuccess ); - - if( data) { - dataLen = (dataWidth + 7) / 8; - dataLen *= dataCount * channelCount; - table = (GammaTbl *) IOMalloc( dataLen + sizeof( struct GammaTbl)); - if( NULL == table) - return( kIOReturnNoMemory); - - table->gVersion = 0; - table->gType = 0; - table->gFormulaSize = 0; - table->gChanCnt = channelCount; - table->gDataCnt = dataCount; - table->gDataWidth = dataWidth; - bcopy( data, table->gFormulaData, dataLen); - } - - gammaRec.csGTable = (Ptr) table; - err = doControl( cscSetGamma, &gammaRec); - if( table) - IOFree( table, dataLen + sizeof( struct GammaTbl)); - - return( err); -} - -IOReturn IONDRVFramebuffer::getAttribute( IOSelect attribute, UInt32 * value ) -{ - IOReturn err = kIOReturnSuccess; - VDSupportsHardwareCursorRec hwCrsrSupport; - - switch( attribute ) { - - case kIOHardwareCursorAttribute: - - *value = ((kIOReturnSuccess == - doStatus( cscSupportsHardwareCursor, &hwCrsrSupport)) - && (hwCrsrSupport.csSupportsHardwareCursor)); - break; - - default: - err = super::getAttribute( attribute, value ); - } - - return( err ); -} - -UInt32 IONDRVFramebuffer::getConnectionCount( void ) -{ - VDMultiConnectInfoRec theRecord; - - if( doStatus(cscGetMultiConnect,&theRecord) == 0 ) { - return theRecord.csDisplayCountOrNumber; - } - return 1; -} - -/* - File: DDCPowerOnOffUtils.c <CS3> -*/ - -enum{ - kVCPSendSize = 8, - kVCPReplySize = 64, - kI2CDisplayWriteAddress = 0x6E, - kI2CDisplayReadAddress = 0x6F, - // Messed up specification says checksum should be calculated with ACCESS.bus value of 50. - kI2CDisplayReadHostCheckSumAddress = 0x50, - // Messed up specification says checksum should be calculated with ACCESS.bus value of 50. - kI2CDisplayReadHostAddress = 0x51, - - kI2CVCPGetCode = 0x01, - kI2CVCPGetLength = 0x82, - kI2CVCPGetMessageSize = 0x05, - - kI2CVCPReplyLength = 0x88, - kI2CNullReplyLength = 0x80, - kI2CNullReplyCheckSum = 0xBE, - - kI2CVCPSetCode = 0x03, - kI2CVCPSetLength = 0x84, - kI2CVCPReplyCode = 0x02, - - kDDCPowerOn = 0x01, - kDDCPowerOff = 0x04 -}; -enum { - kBasicI2CCommTransactionsMask = ( (1<<kVideoNoTransactionType) | (1<<kVideoSimpleI2CType) - | (1<<kVideoDDCciReplyType) ) -}; - -void IONDRVFramebuffer::displayI2CPower( bool enable ) -{ - VDCommunicationRec i2CRecord; - VDCommunicationInfoRec i2cInfoRecord; - Byte sendBuffer[8]; - Byte replyBuffer[kVCPReplySize]; - UInt32 supportedCommFlags = 0; - // Don't do it if we're told it's not supported - bool setThisDisplay = true; - - // - // Some displays (like Fiji) do not support the reading - // of the current power state. Others (like Mitsubishi - // Diamond Pro 710) report that they do not support - // power management calls. - // - // I'll avoid sending the power command only in the - // case that I get a valid reply that does says - // it does not support the power selector. - // - - bzero( &i2cInfoRecord, sizeof(i2cInfoRecord) ); - if( noErr != doStatus( cscGetCommunicationInfo, &i2cInfoRecord)) - return; - if( kBasicI2CCommTransactionsMask != (i2cInfoRecord.csSupportedTypes & kBasicI2CCommTransactionsMask)) - return; - if( !shouldDoI2CPower) - return; - - supportedCommFlags = i2cInfoRecord.csSupportedCommFlags; - bzero( &i2CRecord, sizeof(i2CRecord) ); - bzero( &sendBuffer, sizeof(sendBuffer) ); - bzero( &replyBuffer, sizeof(replyBuffer) ); - - sendBuffer[0] = kI2CDisplayReadHostAddress; - sendBuffer[1] = kI2CVCPGetLength; - sendBuffer[2] = kI2CVCPGetCode; // GetVCP command - sendBuffer[3] = 0xD6; - sendBuffer[4] = kI2CDisplayWriteAddress ^ - sendBuffer[0] ^ sendBuffer[1] ^ - sendBuffer[2] ^ sendBuffer[3]; - - i2CRecord.csBusID = kVideoDefaultBus; - i2CRecord.csSendType = kVideoSimpleI2CType; - i2CRecord.csSendAddress = kI2CDisplayWriteAddress; - i2CRecord.csSendBuffer = &sendBuffer; - i2CRecord.csSendSize = 7; - i2CRecord.csReplyType = kVideoDDCciReplyType; - i2CRecord.csReplyAddress = kI2CDisplayReadAddress; - i2CRecord.csReplyBuffer = &replyBuffer; - i2CRecord.csReplySize = kVCPReplySize; - - if( supportedCommFlags & kVideoReplyMicroSecDelayMask ) - { - // We know some displays are slow, this is an important call to get right - i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask; - // 50 milliseconds should be enough time for the display to respond. - i2CRecord.csMinReplyDelay = 50 * 1000; - } - - if( (noErr == doControl( cscDoCommunication, &i2CRecord)) - && (kI2CDisplayWriteAddress == replyBuffer[0]) - && (kI2CVCPReplyLength == replyBuffer[1]) - && (kI2CVCPReplyCode == replyBuffer[2])) { - Byte checkSum = kI2CDisplayReadHostCheckSumAddress ^ // host address - replyBuffer[0] ^ // source address - replyBuffer[1] ^ // message length (0x88) - replyBuffer[2] ^ // VCP type code - replyBuffer[3] ^ // result code - replyBuffer[4] ^ // VCP op code - replyBuffer[5] ^ // VCP type code - replyBuffer[6] ^ // Max value MSB - replyBuffer[7] ^ // Max value LSB - replyBuffer[8] ^ // Current value MSB - replyBuffer[9]; // Current value LSB - - if( (checkSum == replyBuffer[10]) && // Did the check sum match AND - (0 != replyBuffer[3])) // Are we not supposed to support this feature? - setThisDisplay = false; // Don't do it if we're told it's not supported - } - - if( setThisDisplay) { - - bzero( &i2CRecord, sizeof(i2CRecord) ); - bzero( &sendBuffer, sizeof(sendBuffer) ); - bzero( &replyBuffer, sizeof(replyBuffer) ); - - sendBuffer[0] = kI2CDisplayReadHostAddress; - sendBuffer[1] = kI2CVCPSetLength; - sendBuffer[2] = kI2CVCPSetCode; // SetVCP command - sendBuffer[3] = 0xD6; - sendBuffer[4] = 0; // MSB - sendBuffer[5] = enable ? kDDCPowerOn : kDDCPowerOff; // LSB - sendBuffer[6] = kI2CDisplayWriteAddress ^ - sendBuffer[0] ^ sendBuffer[1] ^ - sendBuffer[2] ^ sendBuffer[3] ^ - sendBuffer[4] ^ sendBuffer[5]; - - i2CRecord.csBusID = kVideoDefaultBus; - i2CRecord.csSendAddress = kI2CDisplayWriteAddress; - i2CRecord.csSendType = kVideoSimpleI2CType; - i2CRecord.csSendBuffer = &sendBuffer; - i2CRecord.csSendSize = 7; - i2CRecord.csReplyType = kVideoNoTransactionType; - i2CRecord.csReplyAddress = 0; - i2CRecord.csReplyBuffer = 0; - i2CRecord.csReplySize = 0; - - if( supportedCommFlags & kVideoReplyMicroSecDelayMask) { - // We know some displays are slow, this is an important call to get right - i2CRecord.csCommFlags |= kVideoReplyMicroSecDelayMask; - // 50 milliseconds should be enough time for the display to respond. - i2CRecord.csMinReplyDelay = 50 * 1000; - } - - doControl( cscDoCommunication, &i2CRecord); - } -} -IOReturn IONDRVFramebuffer::setAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 info ) -{ - IOReturn err; - VDSyncInfoRec theVDSyncInfoRec; - VDPowerStateRec sleepInfo; - - switch( attribute ) { - - case kConnectionSyncEnable: - - theVDSyncInfoRec.csMode = (unsigned char)(info>>8); - theVDSyncInfoRec.csFlags = (unsigned char)(info & 0xFF); - doControl( cscSetSync, &theVDSyncInfoRec); - - sleepInfo.powerState = ((info>>8) & 0xff) ? kAVPowerSuspend : kAVPowerOn; - sleepInfo.powerFlags = 0; - sleepInfo.powerReserved1 = 0; - sleepInfo.powerReserved2 = 0; - doControl( cscSetPowerState, &sleepInfo); - - displayI2CPower( ((info>>8) & 0xff) ? false : true ); - - err = kIOReturnSuccess; - break; - - default: - err = super::setAttributeForConnection( connectIndex, - attribute, info ); - break; - } - return( err ); -} - - -IOReturn IONDRVFramebuffer::getAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 * value ) -{ - IOReturn ret; - VDSyncInfoRec theVDSyncInfoRec; - - switch( attribute ) { - - case kConnectionSyncFlags: - // find out current state of sync lines - theVDSyncInfoRec.csMode = 0x00; - doStatus(cscGetSync,&theVDSyncInfoRec); - * value = theVDSyncInfoRec.csMode; - ret = kIOReturnSuccess; - break; - case kConnectionSyncEnable: - // what are the sync-controlling capabilities of the ndrv? - theVDSyncInfoRec.csMode = 0xFF; - doStatus(cscGetSync,&theVDSyncInfoRec); - * value = (UInt32)theVDSyncInfoRec.csMode; - ret = kIOReturnSuccess; - break; - case kConnectionSupportsHLDDCSense: - case kConnectionSupportsAppleSense: - ret = kIOReturnSuccess; - break; - default: - ret = super::getAttributeForConnection( connectIndex, - attribute, value ); - break; - } - - return( ret ); -} - -IOReturn IONDRVFramebuffer::getAppleSense( IOIndex connectIndex, - UInt32 * senseType, - UInt32 * primary, - UInt32 * extended, - UInt32 * displayType ) -{ - OSStatus err; - VDMultiConnectInfoRec multiConnect; - UInt32 sense, extSense; - - if( connectIndex == 0 ) - err = doStatus( cscGetConnection, &multiConnect.csConnectInfo); - - else { - multiConnect.csDisplayCountOrNumber = connectIndex; - err = doControl( cscSetMultiConnect, &multiConnect); - } - if( err) - return( err); - - if( multiConnect.csConnectInfo.csConnectFlags - & ((1<<kReportsTagging) | (1<<kTaggingInfoNonStandard)) - != ((1<<kReportsTagging)) ) - - err = kIOReturnUnsupported; - - else { - - sense = multiConnect.csConnectInfo.csConnectTaggedType; - extSense = multiConnect.csConnectInfo.csConnectTaggedData; - // bug fixes for really old ATI driver - if( sense == 0) { - if( extSense == 6) { - sense = kRSCSix; - extSense = kESCSixStandard; - } - else - if( extSense == 4) { - sense = kRSCFour; - extSense = kESCFourNTSC; - } - } - if( primary) - *primary = sense; - if( extended) - *extended = extSense; - if( displayType) - *displayType = multiConnect.csConnectInfo.csDisplayType; - if( senseType) - *senseType = 0; - } - return( err); -} - -IOReturn IONDRVFramebuffer::connectFlags( IOIndex /* connectIndex */, - IODisplayModeID displayMode, IOOptionBits * flags ) -{ - VDTimingInfoRec timingInfo; - OSStatus err; - - timingInfo.csTimingMode = displayMode; - // in case the driver doesn't do it: - timingInfo.csTimingFormat = kDeclROMtables; - err = doStatus( cscGetModeTiming, &timingInfo); - - if( kDetailedTimingFormat == timingInfo.csTimingFormat) - *flags = kDisplayModeValidFlag | kDisplayModeSafeFlag; - else - *flags = timingInfo.csTimingFlags; - - return( err ); -} - - -bool IONDRVFramebuffer::hasDDCConnect( IOIndex connectIndex ) -{ - OSStatus err; - VDMultiConnectInfoRec multiConnect; - enum { kNeedFlags = (1<<kReportsDDCConnection) - | (1<<kHasDDCConnection) }; - if( connectIndex == 0 ) - err = doStatus( cscGetConnection, &multiConnect.csConnectInfo); - else { - multiConnect.csDisplayCountOrNumber = connectIndex; - err = doControl( cscSetMultiConnect, &multiConnect); - } - if( err) - return( err); - - return( (multiConnect.csConnectInfo.csConnectFlags & kNeedFlags) - == kNeedFlags ); -} - -// I2C first year for Apple displays. -// Apple monitors older than this (and Manta) -// are never called with I2C commands -enum { - kFirstAppleI2CYear = 1999, - kAppleVESAVendorID = 0x0610 -}; - -struct EDID { - UInt8 header[8]; - UInt8 vendorProduct[4]; - UInt8 serialNumber[4]; - UInt8 weekOfManufacture; - UInt8 yearOfManufacture; - UInt8 version; - UInt8 revision; - UInt8 displayParams[5]; - UInt8 colorCharacteristics[10]; - UInt8 establishedTimings[3]; - UInt16 standardTimings[8]; - UInt8 descriptors[4][18]; - UInt8 extension; - UInt8 checksum; -}; - -static bool IsApplePowerBlock(UInt8 * theBlock) -{ - return( theBlock && - 0x00000000 == *(UInt32 *)&theBlock[0] && - 0x00 == theBlock[4] && - 0x06 == theBlock[5] && - 0x10 == theBlock[6] ); -} - -IOReturn IONDRVFramebuffer::getDDCBlock( IOIndex /* connectIndex */, - UInt32 blockNumber, - IOSelect blockType, - IOOptionBits options, - UInt8 * data, IOByteCount * length ) - -{ - OSStatus err = 0; - VDDDCBlockRec ddcRec; - ByteCount actualLength = *length; - - ddcRec.ddcBlockNumber = blockNumber; - ddcRec.ddcBlockType = blockType; - ddcRec.ddcFlags = options; - - err = doStatus( cscGetDDCBlock, &ddcRec); - - if( err == noErr) { - - if( actualLength < kDDCBlockSize) - actualLength = actualLength; - else - actualLength = kDDCBlockSize; - bcopy( ddcRec.ddcBlockData, data, actualLength); - *length = actualLength; - - if( (1 == blockNumber) && (kIODDCBlockTypeEDID == blockType) - && (actualLength >= sizeof( EDID))) do { - - EDID * edid; - UInt32 vendor; - UInt32 product; - - edid = (EDID *) data; - vendor = (edid->vendorProduct[0] << 8) | edid->vendorProduct[1]; - product = (edid->vendorProduct[3] << 8) | edid->vendorProduct[2]; - if( kAppleVESAVendorID == vendor) { - if( (0x01F4 == product) || (0x9D02 == product)) - continue; - if( edid->yearOfManufacture && ((edid->yearOfManufacture + 1990) < kFirstAppleI2CYear)) - continue; - } - shouldDoI2CPower = (IsApplePowerBlock( &edid->descriptors[1][0]) - || IsApplePowerBlock( &edid->descriptors[2][0]) - || IsApplePowerBlock( &edid->descriptors[3][0])); - - } while( false ); - } - - IOLog("%s: i2cPower %d\n", getName(), shouldDoI2CPower); - - return( err); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// initForPM -// -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -void IONDRVFramebuffer::initForPM( void ) -{ - static const IOPMPowerState powerStates[ kIONDRVFramebufferPowerStateCount ] = { - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } - }; - // register ourselves with superclass policy-maker - registerPowerDriver( this, (IOPMPowerState *) powerStates, - kIONDRVFramebufferPowerStateCount ); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// maxCapabilityForDomainState -// -// This simple device needs only power. If the power domain is supplying -// power, the frame buffer can be on. If there is no power it can only be off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -unsigned long IONDRVFramebuffer::maxCapabilityForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn) - return( kIONDRVFramebufferPowerStateCount - 1); - else - return( 0); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// initialPowerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. -// -// This implementation is incomplete. It only works in a system where -// the frame buffer is never turned off. When we cross that bridge, -// instead of returning 1, it should return 1 if the frame buffer -// is on, or 0 if it is off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -unsigned long IONDRVFramebuffer::initialPowerStateForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn) - return( kIONDRVFramebufferPowerStateCount - 1); - else - return( 0); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// powerStateForDomainState -// -// The power domain may be changing state. If power is on in the new -// state, that will not affect our state at all. If domain power is off, -// we can attain only our lowest state, which is off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -unsigned long IONDRVFramebuffer::powerStateForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn) - return( pm_vars->myCurrentState); - else - return( 0); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// setPowerState -// -// Called by the superclass to turn the frame buffer on and off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IONDRVFramebuffer::setPowerState( unsigned long powerStateOrdinal, - IOService * whichDevice ) -{ - static const unsigned long states[2][2] = - { { kAVPowerOff, kAVPowerOn }, - { kHardwareSleep, kHardwareWake } }; - - VDPowerStateRec sleepInfo; - IOReturn err; - int deepSleep = 0; - UInt32 newState; - IOAGPDevice * agpDev; - - if( powerStateOrdinal == powerState) - return( IOPMAckImplied ); - - if( 0 == powerStateOrdinal) - super::setPowerState( powerStateOrdinal, whichDevice ); - - sleepInfo.powerState = 0; - sleepInfo.powerFlags = 0; - sleepInfo.powerReserved1 = 0; - sleepInfo.powerReserved2 = 0; - - err = doStatus( cscGetPowerState, &sleepInfo); - if( (kIOReturnSuccess == err) - && (kPowerStateSleepCanPowerOffMask & sleepInfo.powerFlags)) - deepSleep = platformDeepSleep; - - newState = states[deepSleep & 1][powerStateOrdinal & 1]; - sleepInfo.powerState = newState; - sleepInfo.powerFlags = 0; - sleepInfo.powerReserved1 = 0; - sleepInfo.powerReserved2 = 0; - -#if 1 - if( newState == kHardwareSleep) { - IOMemoryDescriptor * vram; - if( (vram = getVRAMRange())) { - vram->redirect( kernel_task, true ); - vram->release(); - } - } -#endif - - ignore_zero_fault( true ); - boolean_t ints = ml_set_interrupts_enabled( false ); - - err = doControl( cscSetPowerState, &sleepInfo); - - ml_set_interrupts_enabled( ints ); - ignore_zero_fault( false ); - -#if 1 - if( newState == kHardwareWake) { - IOMemoryDescriptor * vram; - if( (vram = getVRAMRange())) { - vram->redirect( kernel_task, false ); - vram->release(); - } - } -#endif - - if( powerStateOrdinal) { - powerState = powerStateOrdinal; - if( kAVPowerOn == newState) { - VDPageInfo pageInfo; - pageInfo.csData = 0; - pageInfo.csPage = 0; - doControl( cscGrayPage, &pageInfo); - resetCursor(); - } else { - IOSleep( 100 ); - setCursorImage( 0 ); - } - - agpDev = OSDynamicCast(IOAGPDevice, nub); - if( !agpDev) - agpDev = OSDynamicCast( IOAGPDevice, nub->getParentEntry(gIODTPlane)); - if( agpDev) - agpDev->resetAGP(); - } - powerState = powerStateOrdinal; - - if( powerStateOrdinal) - super::setPowerState( powerStateOrdinal, whichDevice ); - - return( IOPMAckImplied ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// ATI patches. -// Real problem : getStartupMode doesn't. - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IONDRVFramebuffer - -OSDefineMetaClassAndStructors(IOATINDRV, IONDRVFramebuffer) -OSDefineMetaClassAndStructors(IOATI128NDRV, IOATINDRV) - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOATINDRV::getStartupDisplayMode( - IODisplayModeID * displayMode, IOIndex * depth ) -{ - UInt16 * nvram; - OSData * prop; - - prop = OSDynamicCast( OSData, nub->getProperty("Sime")); - if( prop) { - nvram = (UInt16 *) prop->getBytesNoCopy(); - *displayMode = nvram[ 0 ]; // 1 is physDisplayMode - *depth = nvram[ 2 ] - kDepthMode1; - return( kIOReturnSuccess); - } else - return(super::getStartupDisplayMode( displayMode, depth)); -} - -IODeviceMemory * IOATINDRV::findVRAM( void ) -{ - OSData * prop; - IOByteCount * lengths; - IOIndex count; - IOPhysicalAddress vramBase; - IOByteCount vramLength; - - prop = OSDynamicCast( OSData, nub->getProperty("ATY,memsize")); - if( !prop) - return( super::findVRAM()); - - lengths = (IOByteCount *) prop->getBytesNoCopy(); - count = prop->getLength() / sizeof(IOByteCount); - - prop = OSDynamicCast( OSData, nub->getProperty("ATY,Base")); - - if( prop && (count > 1)) { - vramBase = *((IOPhysicalAddress *)prop->getBytesNoCopy()); - vramLength = lengths[1]; - vramBase &= ~(vramLength - 1); - } else { - vramBase = physicalFramebuffer; - vramLength = lengths[0]; - } - - if( !vramLength) - return( super::findVRAM()); - - vramLength = (vramLength + (vramBase & 0xffff)) & 0xffff0000; - vramBase &= 0xffff0000; - - return( makeSubRange( vramBase, vramLength )); -} - -static int g128ExtraCurs = 8; -static int g128DeltaCurs = 0x25c0; - -void IOATI128NDRV::flushCursor( void ) -{ - volatile UInt32 * fb; - UInt32 x; - int i; - - fb = (volatile UInt32 *) frameBuffer; - for( i = 0; i < g128ExtraCurs; i++) { - x += *(fb++); - fb += g128DeltaCurs; - } -} - - - -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 0); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 1); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 2); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 3); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 4); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 5); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 6); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 7); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 8); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 9); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 10); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 11); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 12); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 13); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 14); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 15); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 16); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 17); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 18); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 19); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 20); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 21); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 22); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 23); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 24); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 25); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 26); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 27); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 28); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 29); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 30); -OSMetaClassDefineReservedUnused(IONDRVFramebuffer, 31); diff --git a/iokit/Families/IONDRVSupport/IONDRVLibraries.cpp b/iokit/Families/IONDRVSupport/IONDRVLibraries.cpp deleted file mode 100644 index 24ab2ee5c..000000000 --- a/iokit/Families/IONDRVSupport/IONDRVLibraries.cpp +++ /dev/null @@ -1,1781 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 Jul 98 - start IOKit - * sdouglas 14 Dec 98 - start cpp. - */ - - -#include <IOKit/IOLib.h> -#include <libkern/c++/OSContainers.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOPlatformExpert.h> -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/ndrvsupport/IONDRVSupport.h> -#include <IOKit/ndrvsupport/IONDRVFramebuffer.h> - -#include <libkern/OSByteOrder.h> -#include <libkern/OSAtomic.h> -#include <IOKit/assert.h> - -#include <pexpert/pexpert.h> - -#include "IOPEFLibraries.h" -#include "IOPEFLoader.h" -#include "IONDRV.h" - -#include <string.h> - -extern "C" -{ - -extern void *kern_os_malloc(size_t size); -extern void kern_os_free(void * addr); - -#define LOG if(1) kprintf - -#define LOGNAMEREG 0 - -/* NameRegistry error codes */ -enum { - nrLockedErr = -2536, - nrNotEnoughMemoryErr = -2537, - nrInvalidNodeErr = -2538, - nrNotFoundErr = -2539, - nrNotCreatedErr = -2540, - nrNameErr = -2541, - nrNotSlotDeviceErr = -2542, - nrDataTruncatedErr = -2543, - nrPowerErr = -2544, - nrPowerSwitchAbortErr = -2545, - nrTypeMismatchErr = -2546, - nrNotModifiedErr = -2547, - nrOverrunErr = -2548, - nrResultCodeBase = -2549, - nrPathNotFound = -2550, /* a path component lookup failed */ - nrPathBufferTooSmall = -2551, /* buffer for path is too small */ - nrInvalidEntryIterationOp = -2552, /* invalid entry iteration operation */ - nrPropertyAlreadyExists = -2553, /* property already exists */ - nrIterationDone = -2554, /* iteration operation is done */ - nrExitedIteratorScope = -2555, /* outer scope of iterator was exited */ - nrTransactionAborted = -2556 /* transaction was aborted */ -}; - -enum { - kNVRAMProperty = 0x00000020L, // matches NR - kRegMaximumPropertyNameLength = 31 -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -UInt32 _eEndianSwap32Bit( UInt32 data ) -{ - return( OSReadSwapInt32(&data, 0)); -} - -UInt16 _eEndianSwap16Bit( UInt16 data ) -{ - return( OSReadSwapInt16(&data, 0)); -} - -OSStatus _eExpMgrConfigReadLong( RegEntryID entryID, UInt8 offset, UInt32 * value ) -{ - IORegistryEntry * regEntry; - IOPCIDevice * ioDevice; - UInt32 adj; - - REG_ENTRY_TO_OBJ( entryID, regEntry) - - ioDevice = OSDynamicCast( IOPCIDevice, regEntry ); - if( !ioDevice) - ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) ); - if( !ioDevice) - return( nrNotSlotDeviceErr ); - - adj = ioDevice->configRead32( offset ); -#if 0 - IOMemoryMap * map = 0; - if( (offset >= kIOPCIConfigBaseAddress2) - && (offset <= kIOPCIConfigBaseAddress5)) { - if( (map = ioDevice->mapDeviceMemoryWithRegister( offset, kIOMapReference))) { - adj = (adj & 3) | (map->getVirtualAddress()); - map->release(); - } - } -#endif - *value = adj; - - return( noErr ); -} - -OSStatus _eExpMgrConfigWriteLong( RegEntryID entryID, UInt8 offset, UInt32 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->configWrite32( offset, value); - - return( noErr ); -} - - -OSStatus _eExpMgrConfigReadWord( RegEntryID entryID, UInt8 offset, UInt16 * value ) -{ - IORegistryEntry * regEntry; - IOPCIDevice * ioDevice; - - REG_ENTRY_TO_OBJ( entryID, regEntry) - - ioDevice = OSDynamicCast( IOPCIDevice, regEntry ); - if( !ioDevice) - ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) ); - if( !ioDevice) - return( nrNotSlotDeviceErr ); - - *value = ioDevice->configRead16( offset ); - - return( noErr ); -} - -OSStatus _eExpMgrConfigWriteWord( RegEntryID entryID, UInt8 offset, UInt16 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->configWrite16( offset, value); - - return( noErr); -} - -OSStatus _eExpMgrConfigReadByte( RegEntryID entryID, UInt8 offset, UInt8 * value ) -{ - IORegistryEntry * regEntry; - IOPCIDevice * ioDevice; - - REG_ENTRY_TO_OBJ( entryID, regEntry) - - ioDevice = OSDynamicCast( IOPCIDevice, regEntry ); - if( !ioDevice) - ioDevice = OSDynamicCast( IOPCIDevice, regEntry->getParentEntry( gIODTPlane) ); - if( !ioDevice) - return( nrNotSlotDeviceErr ); - - *value = ioDevice->configRead8( offset ); - - return( noErr ); -} - -OSStatus _eExpMgrConfigWriteByte( RegEntryID entryID, UInt8 offset, UInt8 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->configWrite8( offset, value); - - return( noErr); -} - -OSStatus _eExpMgrIOReadLong( RegEntryID entryID, UInt16 offset, UInt32 * value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - *value = ioDevice->ioRead32( offset ); - - return( noErr); -} - -OSStatus _eExpMgrIOWriteLong( RegEntryID entryID, UInt16 offset, UInt32 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->ioWrite32( offset, value ); - - return( noErr); -} - -OSStatus _eExpMgrIOReadWord( RegEntryID entryID, UInt16 offset, UInt16 * value ) -{ - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - *value = ioDevice->ioRead16( offset ); - - return( noErr); -} - -OSStatus _eExpMgrIOWriteWord( RegEntryID entryID, UInt16 offset, UInt16 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->ioWrite16( offset, value ); - - return( noErr); -} - -OSStatus _eExpMgrIOReadByte( RegEntryID entryID, UInt16 offset, UInt8 * value ) -{ - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - *value = ioDevice->ioRead8( offset ); - - return( noErr); -} - -OSStatus _eExpMgrIOWriteByte( RegEntryID entryID, UInt16 offset, UInt8 value ) -{ - - REG_ENTRY_TO_SERVICE( entryID, IOPCIDevice, ioDevice) - - ioDevice->ioWrite8( offset, value ); - - return( noErr); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSStatus _eRegistryEntryIDCopy( RegEntryID entryID, RegEntryID to ) -{ - bcopy( entryID, to, sizeof( RegEntryID) ); - return( noErr); -} - - -OSStatus _eRegistryEntryIDInit( RegEntryID entryID ) -{ - MAKE_REG_ENTRY( entryID, 0); - return( noErr); -} - -/* - * Compare EntryID's for equality or if invalid - * - * If a NULL value is given for either id1 or id2, the other id - * is compared with an invalid ID. If both are NULL, the id's - * are consided equal (result = true). - * note: invalid != uninitialized - */ -Boolean _eRegistryEntryIDCompare( RegEntryID entryID1, RegEntryID entryID2 ) -{ - IORegistryEntry * regEntry1; - IORegistryEntry * regEntry2; - - if( entryID1) { - REG_ENTRY_TO_OBJ_RET( entryID1, regEntry1, false) - } else - regEntry1 = 0; - - if( entryID2) { - REG_ENTRY_TO_OBJ_RET( entryID2, regEntry2, false) - } else - regEntry2 = 0; - - return( regEntry1 == regEntry2 ); -} - -OSStatus _eRegistryPropertyGetSize( void *entryID, char *propertyName, - UInt32 * propertySize ) -{ - OSStatus err = noErr; - OSData * prop; - - REG_ENTRY_TO_PT( entryID, regEntry) - - prop = (OSData *) regEntry->getProperty( propertyName); - if( prop) - *propertySize = prop->getLength(); - else - err = nrNotFoundErr; - -#if LOGNAMEREG - LOG("RegistryPropertyGetSize: %s : %d\n", propertyName, err); -#endif - return( err); - -} - -OSStatus _eRegistryPropertyGet(void *entryID, char *propertyName, UInt32 *propertyValue, UInt32 *propertySize) -{ - OSStatus err = noErr; - OSData * prop; - UInt32 len; - - REG_ENTRY_TO_PT( entryID, regEntry) - - prop = OSDynamicCast( OSData, regEntry->getProperty( propertyName)); - if( prop) { - - len = *propertySize; - *propertySize = prop->getLength(); - len = (len > prop->getLength()) ? prop->getLength() : len; - bcopy( prop->getBytesNoCopy(), propertyValue, len); -#if LOGNAMEREG - LOG("value: %08x ", *propertyValue); -#endif - } else - err = nrNotFoundErr; - -#if LOGNAMEREG - LOG("RegistryPropertyGet: %s : %d\n", propertyName, err); -#endif - return( err); -} - -OSStatus _eRegistryPropertyCreate( void *entryID, char *propertyName, - void * propertyValue, UInt32 propertySize ) -{ - OSStatus err = noErr; - OSData * prop; - - REG_ENTRY_TO_PT( entryID, regEntry) - - prop = OSData::withBytes( propertyValue, propertySize ); - - if( prop) { - - regEntry->setProperty( propertyName, prop); - prop->release(); - - } else - err = nrNotCreatedErr; - -#if LOGNAMEREG - LOG("RegistryPropertyCreate: %s : %d\n", propertyName, err); -#endif - return( err); -} - -OSStatus _eRegistryPropertyDelete( void *entryID, char *propertyName ) -{ - OSStatus err = noErr; - OSObject * old; - - REG_ENTRY_TO_PT( entryID, regEntry) - - old = regEntry->getProperty(propertyName); - if ( old ) - regEntry->removeProperty(propertyName); - else - err = nrNotFoundErr; - -#if LOGNAMEREG - LOG("RegistryPropertyDelete: %s : %d\n", propertyName, err); -#endif - return( err); -} - -void IONDRVSetNVRAMPropertyName( IORegistryEntry * regEntry, - const OSSymbol * sym ) -{ - regEntry->setProperty( "IONVRAMProperty", (OSObject *) sym ); -} - -static IOReturn IONDRVSetNVRAMPropertyValue( IORegistryEntry * regEntry, - const OSSymbol * name, OSData * value ) -{ - IOReturn err; - IODTPlatformExpert * platform = - (IODTPlatformExpert *) IOService::getPlatform(); - - err = platform->writeNVRAMProperty( regEntry, name, value ); - - return( err ); -} - -OSStatus _eRegistryPropertySet( void *entryID, char *propertyName, void * propertyValue, UInt32 propertySize ) -{ - OSStatus err = noErr; - OSData * prop; - const OSSymbol * sym; - - REG_ENTRY_TO_PT( entryID, regEntry) - - sym = OSSymbol::withCString( propertyName ); - if( !sym) - return( kIOReturnNoMemory ); - - prop = OSDynamicCast( OSData, regEntry->getProperty( sym )); - if( 0 == prop) - err = nrNotFoundErr; - - else if( (prop = OSData::withBytes( propertyValue, propertySize))) { - regEntry->setProperty( sym, prop); - - if( (sym == (const OSSymbol *) - regEntry->getProperty("IONVRAMProperty"))) - err = IONDRVSetNVRAMPropertyValue( regEntry, sym, prop ); - prop->release(); - - } else - err = nrNotCreatedErr; - - sym->release(); - -#if LOGNAMEREG - LOG("RegistryPropertySet: %s : %d\n", propertyName, err); -#endif - return( err); -} - -OSStatus _eRegistryPropertyGetMod(void * entryID, char * propertyName, - UInt32 * mod) -{ - const OSSymbol * sym; - - REG_ENTRY_TO_PT( entryID, regEntry) - - if( (sym = OSDynamicCast( OSSymbol, - regEntry->getProperty("IONVRAMProperty"))) - && (0 == strcmp( propertyName, sym->getCStringNoCopy()))) - - *mod = kNVRAMProperty; - else - *mod = 0; - - return( noErr); -} - -OSStatus _eRegistryPropertySetMod(void *entryID, char *propertyName, - UInt32 mod ) -{ - OSStatus err = noErr; - OSData * data; - const OSSymbol * sym; - - REG_ENTRY_TO_PT( entryID, regEntry) - - if( (mod & kNVRAMProperty) - && (sym = OSSymbol::withCString( propertyName ))) { - - if( (data = OSDynamicCast( OSData, regEntry->getProperty( sym))) ) { - err = IONDRVSetNVRAMPropertyValue( regEntry, sym, data ); - if( kIOReturnSuccess == err) - IONDRVSetNVRAMPropertyName( regEntry, sym ); - } - sym->release(); - } - - return( err); -} - -OSStatus _eVSLSetDisplayConfiguration(RegEntryID * entryID, - char * propertyName, - void * configData, - long configDataSize) -{ - IOReturn err = nrNotCreatedErr; - IORegistryEntry * options; - const OSSymbol * sym = 0; - OSData * data = 0; - enum { kMaxDisplayConfigDataSize = 64 }; - - if( (configDataSize > kMaxDisplayConfigDataSize) - || (strlen(propertyName) > kRegMaximumPropertyNameLength)) - return( nrNotCreatedErr ); - - do { - options = IORegistryEntry::fromPath( "/options", gIODTPlane); - if( !options) - continue; - data = OSData::withBytes( configData, configDataSize ); - if( !data) - continue; - sym = OSSymbol::withCString( propertyName ); - if( !sym) - continue; - if( !options->setProperty( sym, data )) - continue; - err = kIOReturnSuccess; - - } while( false ); - - if( options) - options->release(); - if( data) - data->release(); - if( sym) - sym->release(); - - return( err ); -} - -OSStatus _eRegistryPropertyIterateCreate( RegEntryID * entryID, - OSCollectionIterator ** cookie) -{ - - REG_ENTRY_TO_PT( entryID, regEntry) - - // NB. unsynchronized. But should only happen on an owned nub! - // Should non OSData be filtered out? - *cookie = OSCollectionIterator::withCollection( - regEntry->getPropertyTable()); - - if( *cookie) - return( noErr); - else - return( nrNotEnoughMemoryErr); -} - -OSStatus _eRegistryPropertyIterateDispose( OSCollectionIterator ** cookie) -{ - if( *cookie) { - (*cookie)->release(); - *cookie = NULL; - return( noErr); - } else - return( nrIterationDone); -} - - -OSStatus _eRegistryPropertyIterate( OSCollectionIterator ** cookie, - char * name, Boolean * done ) -{ - const OSSymbol * key; - - key = (const OSSymbol *) (*cookie)->getNextObject(); - if( key) - strncpy( name, key->getCStringNoCopy(), kRegMaximumPropertyNameLength); - - // Seems to be differences in handling "done". - // ATI assumes done = true when getting the last property. - // The Book says done is true after last property. - // ATI does check err, so this will work. - // Control ignores err and checks done. - - *done = (key == 0); - - if( 0 != key) - return( noErr); - else - return( nrIterationDone ); -} - -OSStatus -_eRegistryEntryIterateCreate( IORegistryIterator ** cookie) -{ - *cookie = IORegistryIterator::iterateOver( gIODTPlane ); - if( *cookie) - return( noErr); - else - return( nrNotEnoughMemoryErr); -} - -OSStatus -_eRegistryEntryIterateDispose( IORegistryIterator ** cookie) -{ - if( *cookie) { - (*cookie)->release(); - *cookie = NULL; - return( noErr); - } else - return( nrIterationDone); -} - -OSStatus -_eRegistryEntryIterate( IORegistryIterator ** cookie, - UInt32 /* relationship */, - RegEntryID foundEntry, - Boolean * done) -{ - IORegistryEntry * regEntry; - - // TODO: check requested type of iteration - regEntry = (*cookie)->getNextObjectRecursive(); - - MAKE_REG_ENTRY( foundEntry, regEntry); - *done = (0 == regEntry); - -#if LOGNAMEREG - if( regEntry) - LOG("RegistryEntryIterate: %s\n", regEntry->getName( gIODTPlane )); -#endif - - if( regEntry) - return( noErr); - else - return( nrNotFoundErr); -} - -OSStatus -_eRegistryCStrEntryToName( const RegEntryID * entryID, - RegEntryID parentEntry, - char * nameComponent, - Boolean * done ) -{ - IORegistryEntry * regEntry; - - REG_ENTRY_TO_OBJ( entryID, regEntry) - - strncpy( nameComponent, regEntry->getName( gIODTPlane ), kRegMaximumPropertyNameLength ); - nameComponent[ kRegMaximumPropertyNameLength ] = 0; - - regEntry = regEntry->getParentEntry( gIODTPlane ); - if( regEntry) { - MAKE_REG_ENTRY( parentEntry, regEntry); - *done = false; - } else - *done = true; - - return( noErr); -} - -OSStatus -_eRegistryCStrEntryLookup( const RegEntryID * parentEntry, - const char * path, - RegEntryID newEntry) -{ - IOReturn err; - IORegistryEntry * regEntry = 0; - char * buf; - char * cvtPath; - char c; -#define kDTRoot "Devices:device-tree:" -#define kMacIORoot "Devices:device-tree:pci:mac-io:" - - if( parentEntry) { - REG_ENTRY_TO_OBJ( parentEntry, regEntry) - } else - regEntry = 0; - - buf = IONew( char, 512 ); - if( !buf) - return( nrNotEnoughMemoryErr ); - - cvtPath = buf; - if( ':' == path[0]) - path++; - else if( 0 == strncmp( path, kMacIORoot, strlen( kMacIORoot ))) { - path += strlen( kMacIORoot ) - 7; - regEntry = 0; - } - else if( 0 == strncmp( path, kDTRoot, strlen( kDTRoot ))) { - path += strlen( kDTRoot ) - 1; - regEntry = 0; - } - - do { - c = *(path++); - if( ':' == c) - c = '/'; - *(cvtPath++) = c; - } while( c != 0 ); - - if( regEntry) - regEntry = regEntry->childFromPath( buf, gIODTPlane ); - else - regEntry = IORegistryEntry::fromPath( buf, gIODTPlane ); - - if( regEntry) { - MAKE_REG_ENTRY( newEntry, regEntry); - regEntry->release(); - err = noErr; - } else - err = nrNotFoundErr; - - IODelete( buf, char, 512 ); - - return( err ); -} - - -OSStatus -_eRegistryCStrEntryCreate( const RegEntryID * parentEntry, - char * name, - RegEntryID newEntry) -{ - IORegistryEntry * newDev; - IORegistryEntry * parent; - - REG_ENTRY_TO_OBJ( parentEntry, parent) - - // NOT published - - newDev = new IORegistryEntry; - if( newDev && (false == newDev->init())) - newDev = 0; - - if( newDev) { - newDev->attachToParent( parent, gIODTPlane ); - if( ':' == name[0]) - name++; - newDev->setName( name ); - } - - MAKE_REG_ENTRY( newEntry, newDev); - - if( newDev) - return( noErr); - else - return( nrNotCreatedErr); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -extern "C" { - -// in NDRVLibrariesAsm.s -extern void _eSynchronizeIO( void ); - -// platform expert -extern vm_offset_t -PEResidentAddress( vm_offset_t address, vm_size_t length ); - -}; - -enum { - kProcessorCacheModeDefault = 0, - kProcessorCacheModeInhibited = 1, - kProcessorCacheModeWriteThrough = 2, - kProcessorCacheModeCopyBack = 3 -}; - -OSStatus _eSetProcessorCacheMode( UInt32 /* space */, void * /* addr */, - UInt32 /* len */, UInt32 /* mode */ ) -{ -#if 0 - struct phys_entry* pp; - vm_offset_t spa; - vm_offset_t epa; - int wimg; - - // This doesn't change any existing kernel mapping eg. BAT changes etc. - // but this is enough to change user level mappings for DPS etc. - // Should use a kernel service when one is available. - - spa = kvtophys( (vm_offset_t)addr); - if( spa == 0) { - spa = PEResidentAddress( (vm_offset_t)addr, len); - if( spa == 0) - return( kIOReturnVMError); - } - epa = (len + spa + 0xfff) & 0xfffff000; - spa &= 0xfffff000; - - switch( mode) { - case kProcessorCacheModeWriteThrough: - wimg = PTE_WIMG_WT_CACHED_COHERENT_GUARDED; - break; - case kProcessorCacheModeCopyBack: - wimg = PTE_WIMG_CB_CACHED_COHERENT_GUARDED; - break; - default: - wimg = PTE_WIMG_UNCACHED_COHERENT_GUARDED; - break; - } - - while( spa < epa) { - pp = pmap_find_physentry(spa); - if (pp != PHYS_NULL) - pp->pte1.bits.wimg = wimg; - spa += PAGE_SIZE; - } -#endif - _eSynchronizeIO(); - return( noErr); -} - -char * _ePStrCopy( char *to, const char *from ) -{ - UInt32 len; - char * copy; - - copy = to; - len = *(from++); - *(copy++) = len; - bcopy( from, copy, len); - return( to); -} - -LogicalAddress _ePoolAllocateResident(ByteCount byteSize, Boolean clear) -{ - LogicalAddress mem; - - mem = (LogicalAddress) kern_os_malloc( (size_t) byteSize ); - if( clear && mem) - memset( mem, 0, byteSize); - - return( mem); -} - -OSStatus _ePoolDeallocate( LogicalAddress address ) -{ - kern_os_free( (void *) address ); - return( noErr); -} - -UInt32 _eCurrentExecutionLevel(void) -{ - return(0); // == kTaskLevel, HWInt == 6 -} - -// don't expect any callers of this -OSErr _eIOCommandIsComplete( UInt32 /* commandID */, OSErr result) -{ - LOG("_eIOCommandIsComplete\n"); - return( result); // !!??!! -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include <kern/clock.h> - - -AbsoluteTime _eUpTime( void ) -{ - AbsoluteTime result; - - clock_get_uptime( &result); - - return( result); -} - -AbsoluteTime _eAddAbsoluteToAbsolute(AbsoluteTime left, AbsoluteTime right) -{ - AbsoluteTime result = left; - - ADD_ABSOLUTETIME( &left, &right); - - return( result); -} - - -AbsoluteTime _eSubAbsoluteFromAbsolute(AbsoluteTime left, AbsoluteTime right) -{ - AbsoluteTime result = left; - - // !! ATI bug fix here: - // They expect the 64-bit result to be signed. The spec says < 0 => 0 - // To workaround, make sure this routine takes 10 us to execute. - IODelay( 10); - - if( CMP_ABSOLUTETIME( &result, &right) < 0) { - AbsoluteTime_to_scalar( &result ) = 0; - } else { - result = left; - SUB_ABSOLUTETIME( &result, &right); - } - - return( result); -} - - -AbsoluteTime _eDurationToAbsolute( Duration theDuration) -{ - AbsoluteTime result; - - if( theDuration > 0) { - clock_interval_to_absolutetime_interval( theDuration, kMillisecondScale, - &result ); - - } else { - clock_interval_to_absolutetime_interval( (-theDuration), kMicrosecondScale, - &result ); - } - - return( result); -} - -AbsoluteTime _eAddDurationToAbsolute( Duration duration, AbsoluteTime absolute ) -{ - return( _eAddAbsoluteToAbsolute(_eDurationToAbsolute( duration), absolute)); -} - -#define UnsignedWideToUInt64(x) (*(UInt64 *)(x)) -#define UInt64ToUnsignedWide(x) (*(UnsignedWide *)(x)) - -AbsoluteTime _eNanosecondsToAbsolute ( UnsignedWide theNanoseconds) -{ - AbsoluteTime result; - UInt64 nano = UnsignedWideToUInt64(&theNanoseconds); - - nanoseconds_to_absolutetime( nano, &result); - - return( result); -} - -UnsignedWide _eAbsoluteToNanoseconds( AbsoluteTime absolute ) -{ - UnsignedWide result; - UInt64 nano; - - absolutetime_to_nanoseconds( absolute, &nano); - result = UInt64ToUnsignedWide( &nano ); - - return( result); -} - -Duration _eAbsoluteDeltaToDuration( AbsoluteTime left, AbsoluteTime right ) -{ - Duration dur; - AbsoluteTime result; - UInt64 nano; - - if( CMP_ABSOLUTETIME( &left, &right) < 0) - return( 0); - - result = left; - SUB_ABSOLUTETIME( &result, &right); - absolutetime_to_nanoseconds( result, &nano); - - if( nano >= ((1ULL << 31) * 1000ULL)) { - // +ve milliseconds - if( nano >= ((1ULL << 31) * 1000ULL * 1000ULL)) - dur = 0x7fffffff; - else - dur = nano / 1000000ULL; - } else { - // -ve microseconds - dur = -(nano / 1000ULL); - } - - return( dur); -} - - -OSStatus _eDelayForHardware( AbsoluteTime time ) -{ - AbsoluteTime deadline; - - clock_absolutetime_interval_to_deadline( time, &deadline ); - clock_delay_until( deadline ); - - return( noErr); -} - -OSStatus _eDelayFor( Duration theDuration ) -{ -#if 1 - -// In Marconi, DelayFor uses the old toolbox Delay routine -// which is based on the 60 Hz timer. Durations are not -// rounded up when converting to ticks. Yes, really. -// Some ATI drivers call DelayFor(1) 50000 times starting up. -// There is some 64-bit math there so we'd better reproduce -// the overhead of that calculation. - -#define DELAY_FOR_TICK_NANO 16666666 -#define DELAY_FOR_TICK_MILLI 17 -#define NANO32_MILLI 4295 - - UnsignedWide nano; - AbsoluteTime abs; - unsigned int ms; - - abs = _eDurationToAbsolute( theDuration); - nano = _eAbsoluteToNanoseconds( abs); - - ms = (nano.lo / DELAY_FOR_TICK_NANO) * DELAY_FOR_TICK_MILLI; - ms += nano.hi * NANO32_MILLI; - if( ms) - IOSleep( ms); - -#else - // Accurate, but incompatible, version - -#define SLEEP_THRESHOLD 5000 - - if( theDuration < 0) { - - // us duration - theDuration -= theDuration; - if( theDuration > SLEEP_THRESHOLD) - IOSleep( (theDuration + 999) / 1000); - else - IODelay( theDuration); - - } else { - - // ms duration - if( theDuration > (SLEEP_THRESHOLD / 1000)) - IOSleep( theDuration ); // ms - else - IODelay( theDuration * 1000); // us - } -#endif - - return( noErr); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSStatus _eCallOSTrapUniversalProc( UInt32 /* theProc */, - UInt32 procInfo, UInt32 trap, UInt8 * pb ) -{ - OSStatus err = -40; - struct PMgrOpParamBlock { - SInt16 pmCommand; - SInt16 pmLength; - UInt8 * pmSBuffer; - UInt8 * pmRBuffer; - UInt8 pmData[4]; - }; -#define readExtSwitches 0xDC - - if( (procInfo == 0x133822) - && (trap == 0xa085) ) { - - PMgrOpParamBlock * pmOp = (PMgrOpParamBlock *) pb; - - if( (readExtSwitches == pmOp->pmCommand) && pmOp->pmRBuffer) { - OSNumber * num = OSDynamicCast(OSNumber, - IOService::getPlatform()->getProperty("AppleExtSwitchBootState")); - *pmOp->pmRBuffer = (num->unsigned32BitValue() & 1); - err = noErr; - } - - } else if( (procInfo == 0x133822) - && (trap == 0xa092) ) { - - UInt8 addr, reg, data; - - addr = pb[ 2 ]; - reg = pb[ 3 ]; - pb = *( (UInt8 **) ((UInt32) pb + 8)); - data = pb[ 1 ]; - (*PE_write_IIC)( addr, reg, data ); - err = noErr; - } - return( err); -} - -const UInt32 * _eGetKeys( void ) -{ - static const UInt32 zeros[] = { 0, 0, 0, 0 }; - - return( zeros); -} - -UInt32 _eGetIndADB( void * adbInfo, UInt32 /* index */) -{ - bzero( adbInfo, 10); - return( 0); // orig address -} - -char * _eLMGetPowerMgrVars( void ) -{ - static char * powerMgrVars = NULL; - - if( powerMgrVars == NULL) { - powerMgrVars = (char *) IOMalloc( 0x3c0); - if( powerMgrVars) - bzero( powerMgrVars, 0x3c0); - } - return( powerMgrVars); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSStatus _eNoErr( void ) -{ - return( noErr); -} - -OSStatus _eFail( void ) -{ - return( -40); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// fix this! - -#define heathrowID ((volatile UInt32 *)0xf3000034) -#define heathrowTermEna (1 << 3) -#define heathrowTermDir (1 << 0) - -#define heathrowFeatureControl ((volatile UInt32 *)0xf3000038) -#define heathrowMBRES (1 << 24) - -#define heathrowBrightnessControl ((volatile UInt8 *)0xf3000032) -#define defaultBrightness 144 -#define heathrowContrastControl ((volatile UInt8 *)0xf3000033) -#define defaultContrast 183 - -#define gossamerSystemReg1 ((volatile UInt16 *)0xff000004) -#define gossamerAllInOne (1 << 4) - -void _eATISetMBRES( UInt32 state ) -{ - UInt32 value; - - value = *heathrowFeatureControl; - - if( state == 0) - value &= ~heathrowMBRES; - else if( state == 1) - value |= heathrowMBRES; - - *heathrowFeatureControl = value; - eieio(); -} - -void _eATISetMonitorTermination( Boolean enable ) -{ - - UInt32 value; - - value = *heathrowID; - - value |= heathrowTermEna; - if( enable) - value |= heathrowTermDir; - else - value &= ~heathrowTermDir; - - *heathrowID = value; - eieio(); -} - -Boolean _eATIIsAllInOne( void ) -{ - Boolean rtn; - static bool didBrightness; - - rtn = (0 == ((*gossamerSystemReg1) & gossamerAllInOne)); - if( rtn && !didBrightness) { - *heathrowBrightnessControl = defaultBrightness; - eieio(); - *heathrowContrastControl = defaultContrast; - eieio(); - didBrightness = true; - } - return( rtn); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -static void IONDRVInterruptAction( OSObject * target, void * refCon, - IOService * provider, int index ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - SInt32 result; - - set = (IONDRVInterruptSet *) target; - index++; - - do { - - assert( (UInt32) index <= set->count); - if( (UInt32) index > set->count) - break; - - source = set->sources + index; - result = CallTVector( set, (void *) index, source->refCon, 0, 0, 0, - source->handler ); - - switch( result ) { - - case kIONDRVIsrIsNotComplete: - index++; - case kIONDRVIsrIsComplete: - break; - - case kIONDRVMemberNumberParent: - assert( false ); - break; - - default: - index = result; - set = set->child; - break; - } - - } while( result != kIONDRVIsrIsComplete ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -static SInt32 IONDRVStdInterruptHandler( IONDRVInterruptSetMember setMember, - void *refCon, UInt32 theIntCount ) -{ -// assert( false ); - - return( kIONDRVIsrIsComplete ); -} - -static bool IONDRVStdInterruptDisabler( IONDRVInterruptSetMember setMember, - void *refCon ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - bool was; - - set = (IONDRVInterruptSet *) setMember.setID; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - assert( setMember.member <= set->count ); - source = set->sources + setMember.member; - - was = source->enabled; - source->enabled = false; - - assert( set->provider ); - set->provider->disableInterrupt( setMember.member - 1 ); - - return( was ); -} - -static void IONDRVStdInterruptEnabler( IONDRVInterruptSetMember setMember, - void *refCon ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - - set = (IONDRVInterruptSet *) setMember.setID; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - assert( setMember.member <= set->count ); - source = set->sources + setMember.member; - - source->enabled = true; - - assert( set->provider ); - - if( !source->registered) { - source->registered = true; - set->provider->registerInterrupt( setMember.member - 1, set, - &IONDRVInterruptAction, (void *) 0x53 ); - } - - set->provider->enableInterrupt( setMember.member - 1 ); -} - -static IOTVector tvIONDRVStdInterruptHandler = { IONDRVStdInterruptHandler, 0 }; -static IOTVector tvIONDRVStdInterruptEnabler = { IONDRVStdInterruptEnabler, 0 }; -static IOTVector tvIONDRVStdInterruptDisabler = { IONDRVStdInterruptDisabler, 0 }; - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -OSStatus -_eGetInterruptFunctions( void * setID, - UInt32 member, - void ** refCon, - IOTVector ** handler, - IOTVector ** enabler, - IOTVector ** disabler ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - OSStatus err = noErr; - - set = (IONDRVInterruptSet *) setID; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - assert( member <= set->count ); - source = set->sources + member; - - if( refCon) - *refCon = source->refCon; - if( handler) - *handler = source->handler; - if( enabler) - *enabler = source->enabler; - if( disabler) - *disabler = source->disabler; - - return( err); -} - -IOReturn -IONDRVInstallInterruptFunctions(void * setID, - UInt32 member, - void * refCon, - IOTVector * handler, - IOTVector * enabler, - IOTVector * disabler ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - OSStatus err = noErr; - - set = (IONDRVInterruptSet *) setID; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - if( member > set->count ) - return( paramErr ); - source = set->sources + member; - - source->refCon = refCon; - if( handler) - source->handler = handler; - if( enabler) - source->enabler = enabler; - if( disabler) - source->disabler = disabler; - - return( err); -} - -OSStatus -_eInstallInterruptFunctions(void * setID, - UInt32 member, - void * refCon, - IOTVector * handler, - IOTVector * enabler, - IOTVector * disabler ) -{ - return( IONDRVInstallInterruptFunctions( setID, member, refCon, - handler, enabler, disabler )); -} - -OSStatus -_eCreateInterruptSet( void * parentSet, - UInt32 parentMember, - UInt32 setSize, - void ** setID, - IOOptionBits options ) -{ - IONDRVInterruptSet * set; - IONDRVInterruptSet * newSet; - IONDRVInterruptSource * source; - OSStatus err = noErr; - - set = (IONDRVInterruptSet *) parentSet; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - assert( parentMember <= set->count ); - source = set->sources + parentMember; - - newSet = IONDRVInterruptSet::with( 0, options, setSize ); - assert( newSet ); - - if( newSet) for( UInt32 i = 1; i <= setSize; i++ ) { - - source = newSet->sources + i; - source->handler = &tvIONDRVStdInterruptHandler; - source->enabler = &tvIONDRVStdInterruptEnabler; - source->disabler = &tvIONDRVStdInterruptDisabler; - } - - set->child = newSet; - *setID = newSet; - - return( err ); -} - -OSStatus -_eDeleteInterruptSet( void * setID ) -{ - IONDRVInterruptSet * set; - OSStatus err = noErr; - - set = (IONDRVInterruptSet *) setID; - assert( OSDynamicCast( IONDRVInterruptSet, set )); - - set->release(); - - return( err ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define MAKEFUNC(s,e) { s, e, 0 } - -static FunctionEntry PCILibFuncs[] = -{ - MAKEFUNC( "ExpMgrConfigReadLong", _eExpMgrConfigReadLong), - MAKEFUNC( "ExpMgrConfigReadWord", _eExpMgrConfigReadWord), - MAKEFUNC( "ExpMgrConfigReadByte", _eExpMgrConfigReadByte), - MAKEFUNC( "ExpMgrConfigWriteLong", _eExpMgrConfigWriteLong), - MAKEFUNC( "ExpMgrConfigWriteWord", _eExpMgrConfigWriteWord), - MAKEFUNC( "ExpMgrConfigWriteByte", _eExpMgrConfigWriteByte), - - MAKEFUNC( "ExpMgrIOReadLong", _eExpMgrIOReadLong), - MAKEFUNC( "ExpMgrIOReadWord", _eExpMgrIOReadWord), - MAKEFUNC( "ExpMgrIOReadByte", _eExpMgrIOReadByte), - MAKEFUNC( "ExpMgrIOWriteLong", _eExpMgrIOWriteLong), - MAKEFUNC( "ExpMgrIOWriteWord", _eExpMgrIOWriteWord), - MAKEFUNC( "ExpMgrIOWriteByte", _eExpMgrIOWriteByte), - - MAKEFUNC( "EndianSwap16Bit", _eEndianSwap16Bit), - MAKEFUNC( "EndianSwap32Bit", _eEndianSwap32Bit) -}; - -static FunctionEntry VideoServicesLibFuncs[] = -{ - MAKEFUNC( "VSLPrepareCursorForHardwareCursor", - IONDRVFramebuffer::VSLPrepareCursorForHardwareCursor), - MAKEFUNC( "VSLNewInterruptService", IONDRVFramebuffer::VSLNewInterruptService), - MAKEFUNC( "VSLDisposeInterruptService", IONDRVFramebuffer::VSLDisposeInterruptService), - MAKEFUNC( "VSLDoInterruptService", IONDRVFramebuffer::VSLDoInterruptService), - MAKEFUNC( "VSLSetDisplayConfiguration", _eVSLSetDisplayConfiguration) -}; - -static FunctionEntry NameRegistryLibFuncs[] = -{ - MAKEFUNC( "RegistryEntryIDCopy", _eRegistryEntryIDCopy), - MAKEFUNC( "RegistryEntryIDInit", _eRegistryEntryIDInit), - MAKEFUNC( "RegistryEntryIDDispose", _eNoErr), - MAKEFUNC( "RegistryEntryIDCompare", _eRegistryEntryIDCompare), - MAKEFUNC( "RegistryPropertyGetSize", _eRegistryPropertyGetSize), - MAKEFUNC( "RegistryPropertyGet", _eRegistryPropertyGet), - MAKEFUNC( "RegistryPropertyGetMod", _eRegistryPropertyGetMod), - MAKEFUNC( "RegistryPropertySetMod", _eRegistryPropertySetMod), - - MAKEFUNC( "RegistryPropertyIterateCreate", _eRegistryPropertyIterateCreate), - MAKEFUNC( "RegistryPropertyIterateDispose", _eRegistryPropertyIterateDispose), - MAKEFUNC( "RegistryPropertyIterate", _eRegistryPropertyIterate), - - MAKEFUNC( "RegistryEntryIterateCreate", _eRegistryEntryIterateCreate), - MAKEFUNC( "RegistryEntryIterateDispose", _eRegistryEntryIterateDispose), - MAKEFUNC( "RegistryEntryIterate", _eRegistryEntryIterate), - MAKEFUNC( "RegistryCStrEntryToName", _eRegistryCStrEntryToName), - MAKEFUNC( "RegistryCStrEntryLookup", _eRegistryCStrEntryLookup), - - MAKEFUNC( "RegistryCStrEntryCreate", _eRegistryCStrEntryCreate), - MAKEFUNC( "RegistryEntryDelete", _eNoErr), - - MAKEFUNC( "RegistryPropertyCreate", _eRegistryPropertyCreate), - MAKEFUNC( "RegistryPropertyDelete", _eRegistryPropertyDelete), - MAKEFUNC( "RegistryPropertySet", _eRegistryPropertySet) -}; - - -static FunctionEntry DriverServicesLibFuncs[] = -{ - MAKEFUNC( "SynchronizeIO", _eSynchronizeIO), - MAKEFUNC( "SetProcessorCacheMode", _eSetProcessorCacheMode), - MAKEFUNC( "BlockCopy", bcopy), - MAKEFUNC( "BlockMove", bcopy), - MAKEFUNC( "BlockMoveData", bcopy), - MAKEFUNC( "CStrCopy", strcpy), - MAKEFUNC( "CStrCmp", strcmp), - MAKEFUNC( "CStrLen", strlen), - MAKEFUNC( "CStrCat", strcat), - MAKEFUNC( "CStrNCopy", strncpy), - MAKEFUNC( "CStrNCmp", strncmp), - MAKEFUNC( "CStrNCat", strncat), - MAKEFUNC( "PStrCopy", _ePStrCopy), - - MAKEFUNC( "PoolAllocateResident", _ePoolAllocateResident), - MAKEFUNC( "MemAllocatePhysicallyContiguous", _ePoolAllocateResident), - MAKEFUNC( "PoolDeallocate", _ePoolDeallocate), - - MAKEFUNC( "UpTime", _eUpTime), - MAKEFUNC( "AbsoluteDeltaToDuration", _eAbsoluteDeltaToDuration), - MAKEFUNC( "AddAbsoluteToAbsolute", _eAddAbsoluteToAbsolute), - MAKEFUNC( "SubAbsoluteFromAbsolute", _eSubAbsoluteFromAbsolute), - MAKEFUNC( "AddDurationToAbsolute", _eAddDurationToAbsolute), - MAKEFUNC( "NanosecondsToAbsolute", _eNanosecondsToAbsolute), - MAKEFUNC( "AbsoluteToNanoseconds", _eAbsoluteToNanoseconds), - MAKEFUNC( "DurationToAbsolute", _eDurationToAbsolute), - MAKEFUNC( "DelayForHardware", _eDelayForHardware), - MAKEFUNC( "DelayFor", _eDelayFor), - - MAKEFUNC( "CurrentExecutionLevel", _eCurrentExecutionLevel), - MAKEFUNC( "IOCommandIsComplete", _eIOCommandIsComplete), - - MAKEFUNC( "SysDebugStr", _eNoErr), - MAKEFUNC( "SysDebug", _eNoErr), - - MAKEFUNC( "CompareAndSwap", OSCompareAndSwap), - - MAKEFUNC( "CreateInterruptSet", _eCreateInterruptSet), - MAKEFUNC( "DeleteInterruptSet", _eDeleteInterruptSet), - MAKEFUNC( "GetInterruptFunctions", _eGetInterruptFunctions), - MAKEFUNC( "InstallInterruptFunctions", _eInstallInterruptFunctions) - -}; - -static FunctionEntry ATIUtilsFuncs[] = -{ - // Gossamer onboard ATI - MAKEFUNC( "ATISetMBRES", _eATISetMBRES), - MAKEFUNC( "ATISetMonitorTermination", _eATISetMonitorTermination), - MAKEFUNC( "ATIIsAllInOne", _eATIIsAllInOne) -}; - -// These are all out of spec - -static FunctionEntry InterfaceLibFuncs[] = -{ - // Apple control : XPRam and EgretDispatch - MAKEFUNC( "CallUniversalProc", _eFail), - MAKEFUNC( "CallOSTrapUniversalProc", _eCallOSTrapUniversalProc), - - // Apple chips65550 -// MAKEFUNC( "NewRoutineDescriptor", _eCallOSTrapUniversalProc), -// MAKEFUNC( "DisposeRoutineDescriptor", _eNoErr), -// MAKEFUNC( "InsTime", _eInsTime), -// MAKEFUNC( "PrimeTime", _ePrimeTime), - - // Radius PrecisionColor 16 - MAKEFUNC( "CountADBs", _eNoErr), - MAKEFUNC( "GetIndADB", _eGetIndADB), - MAKEFUNC( "GetKeys", _eGetKeys) -}; - -static FunctionEntry PrivateInterfaceLibFuncs[] = -{ - // Apple chips65550 - MAKEFUNC( "LMGetPowerMgrVars", _eLMGetPowerMgrVars ) -}; - -#define NUMLIBRARIES 7 -const ItemCount IONumNDRVLibraries = NUMLIBRARIES; -LibraryEntry IONDRVLibraries[ NUMLIBRARIES ] = -{ - { "PCILib", sizeof(PCILibFuncs) / sizeof(FunctionEntry), PCILibFuncs }, - { "VideoServicesLib", sizeof(VideoServicesLibFuncs) / sizeof(FunctionEntry), VideoServicesLibFuncs }, - { "NameRegistryLib", sizeof(NameRegistryLibFuncs) / sizeof(FunctionEntry), NameRegistryLibFuncs }, - { "DriverServicesLib", sizeof(DriverServicesLibFuncs) / sizeof(FunctionEntry), DriverServicesLibFuncs }, - - // G3 - { "ATIUtils", sizeof(ATIUtilsFuncs) / sizeof(FunctionEntry), ATIUtilsFuncs }, - - // out of spec stuff - { "InterfaceLib", sizeof(InterfaceLibFuncs) / sizeof(FunctionEntry), InterfaceLibFuncs }, - { "PrivateInterfaceLib", sizeof(PrivateInterfaceLibFuncs) / sizeof(FunctionEntry), PrivateInterfaceLibFuncs } -}; - -} /* extern "C" */ - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super OSObject - -OSDefineMetaClassAndStructors(IONDRVInterruptSet, OSObject) - -IONDRVInterruptSet * IONDRVInterruptSet::with(IOService * provider, - IOOptionBits options, SInt32 count ) -{ - IONDRVInterruptSet * set; - - set = new IONDRVInterruptSet; - if( set && !set->init()) { - set->release(); - set = 0; - } - - if( set) { - - set->provider = provider; - set->options = options; - set->count = count; - - count++; - set->sources = IONew( IONDRVInterruptSource, count ); - assert( set->sources ); - bzero( set->sources, count * sizeof( IONDRVInterruptSource)); - } - - return( set ); -} - -void IONDRVInterruptSet::free() -{ - if( sources) - IODelete( sources, IONDRVInterruptSource, count + 1 ); - - super::free(); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#if NDRVLIBTEST - -static void IONDRVLibrariesTest( IOService * provider ) -{ - UInt64 nano; - UnsignedWide nano2; - AbsoluteTime abs1, abs2; - - nano = 1000ULL; - abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano)); - IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo); - nano2 = _eAbsoluteToNanoseconds(abs1); - IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo); - AbsoluteTime_to_scalar(&abs2) = 0; - IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2)); - - nano = 0x13161b000ULL; - abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano)); - IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo); - nano2 = _eAbsoluteToNanoseconds(abs1); - IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo); - AbsoluteTime_to_scalar(&abs2) = 0; - IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2)); - - nano = 0x6acfc00000000ULL; - abs1 = _eNanosecondsToAbsolute(UInt64ToUnsignedWide(&nano)); - IOLog("_eNanosecondsToAbsolute %08lx:%08lx\n", abs1.hi, abs1.lo); - nano2 = _eAbsoluteToNanoseconds(abs1); - IOLog("_eAbsoluteToNanoseconds %08lx:%08lx\n", nano2.hi, nano2.lo); - AbsoluteTime_to_scalar(&abs2) = 0; - IOLog("_eAbsoluteDeltaToDuration %ld\n", _eAbsoluteDeltaToDuration(abs1,abs2)); - - abs1 = _eUpTime(); - IODelay(10); - abs2 = _eUpTime(); - IOLog("10us duration %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1)); - - abs1 = _eUpTime(); - for( int i =0; i < 50000; i++) - _eDelayFor(1); - abs2 = _eUpTime(); - IOLog("50000 DelayFor(1) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1)); - - abs1 = _eUpTime(); - _eDelayFor(50); - abs2 = _eUpTime(); - IOLog("DelayFor(50) %ld\n", _eAbsoluteDeltaToDuration(abs2,abs1)); - - abs1 = _eDurationToAbsolute( -10); - IOLog("_eDurationToAbsolute(-10) %08lx:%08lx\n", abs1.hi, abs1.lo); - abs1 = _eDurationToAbsolute( 10); - IOLog("_eDurationToAbsolute(10) %08lx:%08lx\n", abs1.hi, abs1.lo); - -} -#endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IONDRVLibrariesInitialize( IOService * provider ) -{ - IODTPlatformExpert * platform; - const OSSymbol * sym; - OSData * data; - OSArray * intSpec; - unsigned int len, i; - -#if NDRVLIBTEST - IONDRVLibrariesTest( provider ); -#endif - - // copy nvram property - - if( (platform = OSDynamicCast( IODTPlatformExpert, - IOService::getPlatform()))) { - -// IOService::waitForService( IOService::resourceMatching( "IONVRAM" )); - - if( kIOReturnSuccess == platform->readNVRAMProperty( provider, - &sym, &data )) { - - IONDRVSetNVRAMPropertyName( provider, sym ); - provider->setProperty( sym, data); - data->release(); - sym->release(); - } - } - - // create interrupt properties, if none present - - if( (intSpec = (OSArray *)provider->getProperty( gIOInterruptSpecifiersKey)) - && (0 == provider->getProperty( gIODTAAPLInterruptsKey ))) { - // make AAPL,interrupts property if not present (NW) - for( i = 0, len = 0; i < intSpec->getCount(); i++ ) { - data = (OSData *) intSpec->getObject(i); - assert( data ); - len += data->getLength(); - } - if( len) - data = OSData::withCapacity( len ); - if( data) { - for( i = 0; i < intSpec->getCount(); i++ ) - data->appendBytes( (OSData *) intSpec->getObject(i)); - provider->setProperty( gIODTAAPLInterruptsKey, data ); - data->release(); - } - } - - // make NDRV interrupts - - data = OSData::withCapacity( kIONDRVISTPropertyMemberCount - * sizeof( IONDRVInterruptSetMember)); - - IONDRVInterruptSetMember setMember; - IONDRVInterruptSet * set; - IONDRVInterruptSource * source; - - set = IONDRVInterruptSet::with( provider, 0, - kIONDRVISTPropertyMemberCount ); - - if( set) for( i = 1; i <= kIONDRVISTPropertyMemberCount; i++ ) { - - source = set->sources + i; - source->handler = &tvIONDRVStdInterruptHandler; - source->enabler = &tvIONDRVStdInterruptEnabler; - source->disabler = &tvIONDRVStdInterruptDisabler; - - setMember.setID = (void *) set; - setMember.member = i; - data->appendBytes( &setMember, sizeof( setMember)); - - } else - data = 0; - - if( data) { - provider->setProperty( kIONDRVISTPropertyName, data ); - data->release(); - data = 0; - } - - // map memory - - IOItemCount numMaps = provider->getDeviceMemoryCount(); - IOVirtualAddress virtAddress; - - for( i = 0; i < numMaps; i++) { - IODeviceMemory * mem; - IOMemoryMap * map; - bool consoleDevice; - - consoleDevice = (0 != provider->getProperty("AAPL,boot-display")); - - mem = provider->getDeviceMemoryWithIndex( i ); - if( 0 == mem) - continue; - - // set up a 1-1 mapping for the BAT map of the console device - // remove this soon - if( consoleDevice && (0 == mem->map( kIOMapReference))) - mem->setMapping( kernel_task, mem->getPhysicalAddress() ); - - map = mem->map(); - if( 0 == map) { -// IOLog("%s: map[%ld] failed\n", provider->getName(), i); - continue; - } - - virtAddress = map->getVirtualAddress(); - if( !data) - data = OSData::withCapacity( numMaps * sizeof( IOVirtualAddress)); - if( !data) - continue; - data->appendBytes( &virtAddress, sizeof( IOVirtualAddress)); - kprintf("ndrv base = %lx\n", virtAddress); - } - - // NDRV aperture vectors - if( data) { - provider->setProperty( "AAPL,address", data ); - data->release(); - } - - return( kIOReturnSuccess ); -} - diff --git a/iokit/Families/IONDRVSupport/IOPEFInternals.c b/iokit/Families/IONDRVSupport/IOPEFInternals.c deleted file mode 100644 index 13c8cc051..000000000 --- a/iokit/Families/IONDRVSupport/IOPEFInternals.c +++ /dev/null @@ -1,2108 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - */ - - - -/* - File: PEFLoader.c - - Contains: PEF loader implementation. - - Version: Maxwell - - Copyright: © 1994-1996 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: Alan Lillich - - Other Contact: <<unknown>> - - Technology: Core Runtime - - Writers: - - (AWL) Alan Lillich - (ELE) Erik Eidt - - Change History (most recent first): - - <26> 10/4/96 AWL Disable partial unpacking tests. - <25> 9/26/96 AWL Fix assertions to have the right polarity. - <24> 9/18/96 AWL Simplify UnpackPartialSection. - <23> 8/27/96 AWL Support partial unpacking in PEF_UnpackSection. - <22> 8/23/96 AWL (1379028) Propagate changes from CodeFragmentContainerPriv. - <21> 8/16/96 AWL Isolate memory utilities to work with both CFM and ProtoCFM. - <20> 4/18/96 AWL (1342167) Fix problems with relocations for in-place sections. - <19> 4/2/96 AWL (1336962) Fix checks for missing optional parameters. - <18> 3/7/96 AWL Remove unused variable in PEF_UnpackSection. - <17> 2/28/96 AWL Adapt for new container handler model. - <16> 1/19/96 AWL Changes for D11. - <15> 10/10/95 AWL Minor cleanup for CodeWarrior's strict checking. - <14> 6/14/95 AWL Pick up flags from CFMWhere ASAP. - <13> 5/23/95 AWL Introduce temporary hack to workaround build problem for 68K - ModernOS booting code. *** THIS BREAKS REAL 68K BUILDS! *** - <12> 2/8/95 AWL Update debug output calls. - <11> 12/14/94 AWL Changes for Maxwell D4 build. - <10> 12/2/94 AWL Disable reexported import optimization because of problems with - missing weak libraries. It could be put back later with the - addition of a "resolvedImports" bit vector. - <9> 9/9/94 AWL Switch to the "real" API and SPI headers. - <8> 9/2/94 AWL Error codes are now in Errors.h. - <7> 7/28/94 AWL Return cfragSymbolNotFound instead of paramErr from - PLFindExportInfo. (#1177313) - <6> 7/12/94 AWL Fix load-in-place processing in SetRegionAddress. - <5> 6/20/94 AWL Allow the CFL info pointer to be NULL for a "get procs" call to - OpenContainer. - <4> 5/9/94 AWL Change PLGetSpecialSectionInfo to handle some of the wierdness - in nonloaded sections. - <3> 4/28/94 AWL Simplify cross address space use for booting. Fix problem with - load in place, should not require SetRegionAddress. - <2> 2/25/94 AWL Update for Q&D solution to loading across address spaces. - Fix problem in PLGetSpecialSectionInfo switch statement. - <1> 2/15/94 AWL Initial checkin for kernel based CFM. - - ------------------------------------------------------------------------------------ - - <31> 09/15/93 AWL (&ELE) Add CFL prefix to hash functions. - <30> 09/08/93 ELE (&AWL) Fix sneaky little typo that causes load failure. - <29> 08/30/93 AWL Add declaration so that 68K native CFM compiles. - <28> 08/26/93 AWL Move CFTypes.h and CFLoader.h up with other Apple private - headers. - <26> 07/08/93 AWL (&ELE) Fixed version field names in import file IDs. - Remove version < 0 checks as versions are unsigned. - <25> 06/16/93 ELE ELE & AWL Change to New Pool allocation. - <24> 06/09/93 ELE ELE & AWL Fix bug in GetSpecialSection for debugger. - <23> 06/09/93 JRG ELE & AWL Changes: - <22> 06/08/93 ELE (&AWL) Shift to allocation bottleneck. Added support for - packed data sections. Switched to new CFLoader section - attribute bits. - <21> 02/15/93 ELE Changed NewPtr->NewPtrSys - <20> 02/03/93 ELE Added architecture pass thru to GetVersion per CFL Spec. - <19> 12/23/92 ELE Fixed bug where init routine was being returned for the - term routine. - <17> 10/29/92 ELE GetVersion - added dateStamp. - <16> 10/01/92 ELE fix bug in use in place, update of header! - <15> 10/01/92 ELE fix bug in use in place! - <14> 09/28/92 ELE needed to update field expIndex from Find/GetExportInfo. - <13> 09/23/92 ELE updated to new PEF format, updated to new CF Loader SPI. - <12> 09/23/92 ELE Latest version. - -*/ - - -#include "IOPEFInternals.h" - -// =========================================================================================== - -#define PEF_Assert(a) if( !(a)) kprintf("PEF_Assert:") -#define PEF_BlockMove(src,dst,len) memcpy(dst,src,len) -#define PEF_BlockClear(dst,len) memset(dst,0,len) -extern Boolean PCFM_CompareBytes ( const Byte * left, - const Byte * right, - ByteCount count ); -#define PEF_CompareBytes(a,b,c) PCFM_CompareBytes(a,b,c) - -#define EnableCFMDebugging 0 - -// =========================================================================================== - - -enum { - kPEFHandlerProcCount = 18 -}; - -static CFContHandlerProcs PEFHandlerProcs = { - kPEFHandlerProcCount, - kCFContHandlerABIVersion, - - PEF_OpenContainer, // 1 - PEF_CloseContainer, // 2 - PEF_GetContainerInfo, // 3 - - PEF_GetSectionCount, // 4 - PEF_GetSectionInfo, // 5 - PEF_FindSectionInfo, // 6 - PEF_SetSectionAddress, // 7 - - PEF_GetAnonymousSymbolLocations, // 8 - - PEF_GetExportedSymbolCount, // 9 - PEF_GetExportedSymbolInfo, // 10 - PEF_FindExportedSymbolInfo, // 11 - - PEF_GetImportCounts, // 12 - PEF_GetImportedLibraryInfo, // 13 - PEF_GetImportedSymbolInfo, // 14 - PEF_SetImportedSymbolAddress, // 15 - - PEF_UnpackSection, // 16 - PEF_RelocateSection, // 17 - PEF_RelocateImportsOnly, // 18 -}; - - -#if EnableCFMDebugging - static char gDebugMessage [256]; -#endif - -// =========================================================================================== - -const unsigned char opcode [128] = { - krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT, - krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT, - krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT, - krDDAT,krDDAT,krDDAT,krDDAT, krDDAT,krDDAT,krDDAT,krDDAT, - - krCODE,krDATA,krDESC,krDSC2, krVTBL,krSYMR,krXXXX,krXXXX, - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, - krSYMB,krCDIS,krDTIS,krSECN, krXXXX,krXXXX,krXXXX,krXXXX, - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, - - krDELT,krDELT,krDELT,krDELT, krDELT,krDELT,krDELT,krDELT, - krRPT ,krRPT ,krRPT ,krRPT , krRPT ,krRPT ,krRPT ,krRPT , - krLABS,krLABS,krLSYM,krLSYM, krXXXX,krXXXX,krXXXX,krXXXX, - krLRPT,krLRPT,krLSEC,krLSEC, krXXXX,krXXXX,krXXXX,krXXXX, - - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, - krXXXX,krXXXX,krXXXX,krXXXX, krXXXX,krXXXX,krXXXX,krXXXX, -}; - -// ¤ -// =========================================================================================== -// GetNameLength () -// ================ - - -static ByteCount GetNameLength ( BytePtr nameStart ) -{ - BytePtr nameEnd = nameStart; - - - if ( nameStart != NULL ) { - while ( *nameEnd != 0 ) nameEnd += 1; - } - - return (nameEnd - nameStart); - - -} // GetNameLength () - - -// ¤ -// =========================================================================================== -// FindRelocationInfo () -// ===================== - - -static LoaderRelExpHeader * FindRelocationInfo ( PEFPrivateInfo * pefPrivate, - ItemCount sectionIndex ) -{ - LoaderRelExpHeader * relocInfo = NULL; - const ItemCount loopLimit = pefPrivate->ldrHeader->numSections; - ItemCount relocIndex; - - - for ( relocIndex = 0; relocIndex < loopLimit; relocIndex += 1 ) { - relocInfo = &pefPrivate->ldrSections[relocIndex]; - if ( sectionIndex == relocInfo->sectionNumber ) return relocInfo; - } - return NULL; - - -} // FindRelocationInfo () - - -// ¤ -// =========================================================================================== -// GetSectionName () -// ================= - - -static void GetSectionName ( PEFPrivateInfo * pefPrivate, - SectionHeader * sectionHeader, - CFContHashedName * sectionName ) -{ - CFContStringHash nameHash = 0; - BytePtr nameText = NULL; - ByteCount nameLength; - - - if ( sectionHeader->sectionName != -1 ) { - nameText = pefPrivate->stringTable + sectionHeader->sectionName; - nameLength = GetNameLength ( nameText ); - nameHash = CFContHashName ( nameText, nameLength ); - } - - sectionName->nameHash = nameHash; - sectionName->nameText = nameText; - - -} // GetSectionName () - - -// ¤ -// =========================================================================================== -// PEF_OpenContainer () -// ==================== - - -OSStatus PEF_OpenContainer ( LogicalAddress mappedAddress, - LogicalAddress runningAddress, - ByteCount containerLength, - KernelProcessID runningProcessID, - const CFContHashedName * cfragName, - CFContOpenOptions options, - CFContAllocateMem Allocate, - CFContReleaseMem Release, - CFContHandlerRef * containerRef, - CFContHandlerProcsPtr * handlerProcs ) -{ - #pragma unused ( containerLength ) - #pragma unused ( runningProcessID ) - #pragma unused ( cfragName ) - - OSStatus err = -1;//cfragCFMInternalErr; - FileHeader * fileHeader = (FileHeader *) mappedAddress; - PEFPrivateInfo * pefPrivate = NULL; - SectionHeader * loaderSection = NULL; - SInt32 sectionIndex; - - - if ( (sizeof ( PEF_SBits32 ) != 4) | (sizeof ( PEF_UBits32 ) != 4) ) goto InternalError; // ! Is "int" 32 bits? - - if ( (Allocate == NULL) || - (Release == NULL) || - (containerRef == NULL) || - (handlerProcs == NULL) ) goto ParameterError; - - *containerRef = NULL; // Clear for errors, only set on OK path. - *handlerProcs = NULL; - - - // --------------------------------------------------------------------------------- - // Allow the container address to be null as a special case to get the loader procs. - // Otherwise validate the header as acceptable PEF. - - if ( mappedAddress == NULL ) goto OK; - - if ( (fileHeader->magic1 != kPEFMagic1) || - (fileHeader->magic2 != kPEFMagic2) || - (fileHeader->fileTypeID != kPEFTypeID) || - (fileHeader->versionNumber != kPEFVersion) ) goto FragmentFormatError; - - - // ----------------------------------------------- - // Allocate and initialize the private info block. - - pefPrivate = (PEFPrivateInfo *) ((*Allocate) ( sizeof ( PEFPrivateInfo ) )); - if ( pefPrivate == NULL ) goto PrivateMemoryError; - - PEF_BlockClear ( pefPrivate, sizeof ( *pefPrivate ) ); - - pefPrivate->Allocate = Allocate; - pefPrivate->Release = Release; - pefPrivate->mappedContainer = (BytePtr) mappedAddress; - pefPrivate->runningContainer = (BytePtr) runningAddress; - pefPrivate->sectionCount = fileHeader->loadableSections; - pefPrivate->sections = (SectionHeader *) (fileHeader + 1); - pefPrivate->stringTable = (BytePtr) (&pefPrivate->sections[fileHeader->numberSections]); - pefPrivate->loadInPlace = ((options & kCFContPrepareInPlaceMask) != 0); - - // ----------------------------------------------------- - // Find the loader section and extract important fields. - - for ( sectionIndex = 0; sectionIndex < fileHeader->numberSections; sectionIndex += 1 ) { - loaderSection = & pefPrivate->sections[sectionIndex]; - if ( loaderSection->regionKind == kPEFLoaderSection ) break; - } - if ( sectionIndex == fileHeader->numberSections ) goto FragmentCorruptError; - - pefPrivate->ldrSectionNo = sectionIndex; - pefPrivate->ldrHeader = (LoaderHeader *) ((BytePtr)mappedAddress + loaderSection->containerOffset); - pefPrivate->ldrStringTable = (BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->stringsOffset; - - pefPrivate->ldrImportFiles = (LoaderImportFileID *) (pefPrivate->ldrHeader + 1); - pefPrivate->ldrImportSymbols = (LoaderImport *) (pefPrivate->ldrImportFiles + pefPrivate->ldrHeader->numImportFiles); - pefPrivate->ldrSections = (LoaderRelExpHeader *) (pefPrivate->ldrImportSymbols + pefPrivate->ldrHeader->numImportSyms); - pefPrivate->ldrRelocations = (BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->relocationsOffset; - - pefPrivate->ldrHashSlot = (HashSlotEntry *) ((BytePtr)pefPrivate->ldrHeader + pefPrivate->ldrHeader->hashSlotTable); - pefPrivate->ldrHashChain = (HashChainEntry *) (pefPrivate->ldrHashSlot + (1 << pefPrivate->ldrHeader->hashSlotTabSize)); - pefPrivate->ldrExportSymbols = (LoaderExport *) (pefPrivate->ldrHashChain + pefPrivate->ldrHeader->numExportSyms); - - // ---------------------------------------------------- - // Set up the array to store resolved import addresses. - - if ( pefPrivate->ldrHeader->numImportSyms > 0 ) { - pefPrivate->imports = (BytePtr *) ((*Allocate) ( pefPrivate->ldrHeader->numImportSyms * sizeof ( BytePtr ) )); - if ( pefPrivate->imports == NULL ) goto PrivateMemoryError; - } - - // ----------------------------------------------------------------- - // Set up the pointers to the arrays of section origins and offsets. - - if (pefPrivate->sectionCount <= kBuiltinSectionArraySize) { - pefPrivate->mappedOrigins = & pefPrivate->originArray[0]; - pefPrivate->runningOffsets = & pefPrivate->offsetArray[0]; - } else { - pefPrivate->mappedOrigins = (BytePtr *) ((*Allocate) ( pefPrivate->sectionCount * sizeof ( BytePtr ) )); - if ( pefPrivate->mappedOrigins == NULL ) goto PrivateMemoryError; - pefPrivate->runningOffsets = (ByteCount *) ((*Allocate) ( pefPrivate->sectionCount * sizeof ( ByteCount ) )); - if ( pefPrivate->runningOffsets == NULL ) goto PrivateMemoryError; - } - - // --------------------------------------------------------------------------------------- - // Fill in the origin and offset arrays. The origin array gives the base address of the - // section instance as visible in the loader's address space. I.e. it tells the loader - // where it can access the loaded section contents. The offset array tells what to add - // for relocations refering to that section. So it must be based on running addresses and - // must "remove" the presumed running address. If the section will be used in place we - // must compute the final values here. Otherwise SetRegionAddress will be called later to - // provide the mapped and running addresses. Validate load in place restrictions too. - - // ??? We really ought to consider getting rid of the preset for in-place usage and make - // ??? that case as close as possible to the normal case. - - // ! Note that although the ByteCount type used in the offset arrays is unsigned, ignoring - // ! overflow lets things work right for a full -4GB to +4GB offset range. - - for ( sectionIndex = 0; sectionIndex < pefPrivate->sectionCount; sectionIndex += 1 ) { - - SectionHeader * section = & pefPrivate->sections[sectionIndex]; - - pefPrivate->mappedOrigins[sectionIndex] = (BytePtr) -1; // ! Just a diagnostic tag. - pefPrivate->runningOffsets[sectionIndex] = - ((ByteCount) section->sectionAddress); // Subtract the presumed address. - - if ( pefPrivate->loadInPlace ) { - if ( (section->regionKind == kPEFPIDataSection) || (section->execSize != section->rawSize) ) goto FragmentUsageError; - section->sectionAddress = pefPrivate->runningContainer + section->containerOffset; - pefPrivate->mappedOrigins[sectionIndex] = pefPrivate->mappedContainer + section->containerOffset; - pefPrivate->runningOffsets[sectionIndex] += (ByteCount) section->sectionAddress; // Add in the new address. - } - - } - - if ( options & kCFContPrepareInPlaceMask ) fileHeader->memoryAddress = runningAddress; - - -OK: - err = noErr; - *handlerProcs = &PEFHandlerProcs; - *containerRef = (CFContHandlerRef) pefPrivate; - -EXIT: - return err; - -ERROR: - (void) PEF_CloseContainer ( (CFContHandlerRef) pefPrivate, kNilOptions ); - goto EXIT; - -InternalError: - err = cfragCFMInternalErr; - goto ERROR; - -ParameterError: - err = paramErr; - goto ERROR; - -FragmentFormatError: - err = cfragFragmentFormatErr; - goto ERROR; - -PrivateMemoryError: - err = cfragNoPrivateMemErr; - goto ERROR; - -FragmentCorruptError: - err = cfragFragmentCorruptErr; - goto ERROR; - -FragmentUsageError: - err = cfragFragmentUsageErr; - goto ERROR; - - -} // PEF_OpenContainer () - - -// ¤ -// =========================================================================================== -// PEF_CloseContainer () -// ===================== - - -OSStatus PEF_CloseContainer ( CFContHandlerRef containerRef, - CFContCloseOptions options ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - CFContReleaseMem Release = NULL; - - - if ( pefPrivate == NULL ) goto OK; // Simplifies error cleanup from PEF_OpenContainer. - - - Release = pefPrivate->Release; - - if ( pefPrivate->sectionCount > kBuiltinSectionArraySize ) { - if ( pefPrivate->mappedOrigins != NULL ) { - (*Release) ( pefPrivate->mappedOrigins ); - pefPrivate->mappedOrigins = NULL; - } - if ( pefPrivate->runningOffsets != NULL ) { - (*Release) ( pefPrivate->runningOffsets ); - pefPrivate->runningOffsets = NULL; - } - } - - if ( pefPrivate->imports != NULL ) { - (*Release) ( pefPrivate->imports ); - pefPrivate->imports = NULL; - } - - pefPrivate->resolved = 0; // ! Disables reexported import optimization. - - if ( ! (options & kCFContPartialCloseMask) ) (*Release) ( pefPrivate ); - - -OK: - err = noErr; - return err; - -} // PEF_CloseContainer () - - -// ¤ -// =========================================================================================== -// PEF_GetContainerInfo () -// ======================= - - -OSStatus PEF_GetContainerInfo ( CFContHandlerRef containerRef, - PBVersion infoVersion, - CFContContainerInfo * containerInfo ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - FileHeader * fileHeader = NULL; - - - if ( (pefPrivate == NULL) || (containerInfo == NULL) ) goto ParameterError; - if ( infoVersion != kCFContContainerInfoVersion ) goto ParameterError; - - - fileHeader = (FileHeader *) pefPrivate->mappedContainer; - - containerInfo->cfragName.nameHash = 0; // PEF does not have an embedded name. - containerInfo->cfragName.nameText = NULL; - - containerInfo->modDate = fileHeader->dateTimeStamp; - containerInfo->architecture = fileHeader->architectureID; - containerInfo->currentVersion = fileHeader->currentVersion; - containerInfo->oldImpVersion = fileHeader->oldImpVersion; - containerInfo->oldDefVersion = fileHeader->oldDefVersion; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetContainerInfo () - - -// ¤ -// =========================================================================================== -// PEF_GetSectionCount () -// ====================== - - -OSStatus PEF_GetSectionCount ( CFContHandlerRef containerRef, - ItemCount * sectionCount ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - - if ( (pefPrivate == NULL) || (sectionCount == NULL) ) goto ParameterError; - - *sectionCount = pefPrivate->sectionCount; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetSectionCount () - - -// ¤ -// =========================================================================================== -// PEF_GetSectionInfo () -// ===================== - - -OSStatus PEF_GetSectionInfo ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - PBVersion infoVersion, - CFContSectionInfo * sectionInfo ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - SectionHeader * sectionHeader = NULL; - - - if ( (pefPrivate == NULL) || (sectionInfo == NULL) ) goto ParameterError; - if ( infoVersion != kCFContSectionInfoVersion ) goto ParameterError; - if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError; - - - sectionHeader = &pefPrivate->sections[sectionIndex]; - - GetSectionName ( pefPrivate, sectionHeader, §ionInfo->sectionName ); - - sectionInfo->sharing = sectionHeader->shareKind; - sectionInfo->alignment = sectionHeader->alignment; - sectionInfo->reservedA = 0; - sectionInfo->containerOffset = sectionHeader->containerOffset; - sectionInfo->containerLength = sectionHeader->rawSize; - sectionInfo->unpackedLength = sectionHeader->initSize; - sectionInfo->totalLength = sectionHeader->execSize; - sectionInfo->defaultAddress = sectionHeader->sectionAddress; - - sectionInfo->options = kNilOptions; - if ( FindRelocationInfo ( pefPrivate, sectionIndex ) != NULL ) sectionInfo->options |= kRelocatedCFContSectionMask; - - switch ( pefPrivate->sections[sectionIndex].regionKind ) { - case kPEFCodeSection : - sectionInfo->access = kCFContNormalCode; - break; - case kPEFDataSection : - sectionInfo->access = kCFContWriteableData; - break; - case kPEFPIDataSection : - sectionInfo->access = kCFContWriteableData; - sectionInfo->options |= kPackedCFContSectionMask; - break; - case kPEFConstantSection : - sectionInfo->access = kCFContReadOnlyData; - break; - case kPEFExecDataSection : - sectionInfo->access = kCFContWriteableData | kCFContMemExecuteMask; - break; - default : - sectionInfo->access = kCFContReadOnlyData; // ! Not necessarily right, but safe. - break; - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetSectionInfo () - - -// ¤ -// =========================================================================================== -// PEF_FindSectionInfo () -// ====================== - - -OSStatus PEF_FindSectionInfo ( CFContHandlerRef containerRef, - const CFContHashedName * sectionName, - PBVersion infoVersion, - ItemCount * sectionIndex, // May be null. - CFContSectionInfo * sectionInfo ) // May be null. -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - SectionHeader * sectionHeader = NULL; - CFContHashedName hashedName; - - ItemCount tempIndex; - CFContSectionInfo tempInfo; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( (sectionInfo != NULL) && (infoVersion != kCFContSectionInfoVersion) ) goto ParameterError; - - if ( sectionIndex == NULL ) sectionIndex = &tempIndex; - if ( sectionInfo == NULL ) sectionInfo = &tempInfo; - - - for ( tempIndex = 0; tempIndex < pefPrivate->sectionCount; tempIndex += 1 ) { - sectionHeader = &pefPrivate->sections[tempIndex]; - GetSectionName ( pefPrivate, sectionHeader, &hashedName ); - if ( (hashedName.nameHash == sectionName->nameHash) && - (PEF_CompareBytes ( hashedName.nameText, sectionName->nameText, CFContStringHashLength ( hashedName.nameHash ) )) ) break; - } - if ( tempIndex == pefPrivate->sectionCount ) goto NoSectionError; - *sectionIndex = tempIndex; - - err = PEF_GetSectionInfo ( containerRef, tempIndex, infoVersion, sectionInfo ); - if ( err != noErr ) goto ERROR; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - -NoSectionError: - err = cfragNoSectionErr; - goto ERROR; - - -} // PEF_FindSectionInfo () - - -// ¤ -// =========================================================================================== -// PEF_SetSectionAddress () -// ======================== - - -OSStatus PEF_SetSectionAddress ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - LogicalAddress mappedAddress, - LogicalAddress runningAddress ) -{ - OSErr err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - SectionHeader * section = NULL; - - - if ( (pefPrivate == NULL) || (sectionIndex >= pefPrivate->sectionCount) ) goto ParameterError; - - - // -------------------------------------------------------------------------------------- - // For a load in place usage we've already set the addresses, make sure these match. - // Otherwise set both addresses. Note that the "presumed" address is already subtracted. - - section = & pefPrivate->sections[sectionIndex]; - - if ( ! pefPrivate->loadInPlace ) { - - pefPrivate->mappedOrigins[sectionIndex] = (BytePtr) mappedAddress; - pefPrivate->runningOffsets[sectionIndex] += (ByteCount) runningAddress; - - } else { - - if ( (runningAddress != section->sectionAddress) || - (mappedAddress != pefPrivate->mappedOrigins[sectionIndex]) ) goto UsageError; - - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - -UsageError: - err = cfragFragmentUsageErr; - goto ERROR; - - -} // PEF_SetSectionAddress () - - -// ¤ -// =========================================================================================== -// PEF_GetAnonymousSymbolLocations () -// ================================== - - -extern OSStatus PEF_GetAnonymousSymbolLocations ( CFContHandlerRef containerRef, - CFContLogicalLocation * mainLocation, // May be null. - CFContLogicalLocation * initLocation, // May be null. - CFContLogicalLocation * termLocation ) // May be null. -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - LoaderHeader * ldrHeader = NULL; - - CFContLogicalLocation tempLocation; - - - if ( (pefPrivate == NULL) ) goto ParameterError; - - if ( mainLocation == NULL ) mainLocation = &tempLocation; - if ( initLocation == NULL ) initLocation = &tempLocation; - if ( termLocation == NULL ) termLocation = &tempLocation; - - - ldrHeader = pefPrivate->ldrHeader; - - mainLocation->section = ldrHeader->entryPointSection; - mainLocation->offset = ldrHeader->entryPointOffset; - - initLocation->section = ldrHeader->initPointSection; - initLocation->offset = ldrHeader->initPointOffset; - - termLocation->section = ldrHeader->termPointSection; - termLocation->offset = ldrHeader->termPointOffset; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetAnonymousSymbolLocations () - - -// ¤ -// =========================================================================================== -// PEF_GetExportedSymbolCount () -// ============================= - - -extern OSStatus PEF_GetExportedSymbolCount ( CFContHandlerRef containerRef, - ItemCount * exportCount ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - - if ( (pefPrivate == NULL) || (exportCount == NULL) ) goto ParameterError; - - *exportCount = pefPrivate->ldrHeader->numExportSyms; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetExportedSymbolCount () - - -// ¤ -// =========================================================================================== -// PEF_GetExportedSymbolInfo () -// ============================ - - -OSStatus PEF_GetExportedSymbolInfo ( CFContHandlerRef containerRef, - CFContSignedIndex exportIndex, - PBVersion infoVersion, - CFContExportedSymbolInfo * exportInfo ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - LoaderExport * exportedSymbol = NULL; - - - if ( (pefPrivate == NULL) || (exportInfo == NULL) ) goto ParameterError; - if ( exportIndex >= pefPrivate->ldrHeader->numExportSyms ) goto ParameterError; - if ( infoVersion != kCFContExportedSymbolInfoVersion ) goto ParameterError; - - - if ( exportIndex >= 0 ) { - - exportedSymbol = &pefPrivate->ldrExportSymbols[exportIndex]; - - exportInfo->symbolName.nameHash = pefPrivate->ldrHashChain[exportIndex].hashword; - exportInfo->symbolName.nameText = &pefPrivate->ldrStringTable[exportedSymbol->nameOffset]; - - exportInfo->symbolClass = exportedSymbol->symClass; - exportInfo->reservedA = 0; - exportInfo->reservedB = 0; - exportInfo->options = kNilOptions; - - exportInfo->location.section = exportedSymbol->sectionNumber; - - #if 1 // *** Disable the reexported import optimization. - exportInfo->location.offset = exportedSymbol->offset; - #else - // This is the buggy optimization. It has problems with missing weak libraries. - // Addition of a "resolvedImports" bit vector is probably the way to fix it, but it - // may not be much of an optimization then. - if ( (! pefPrivate->resolved) || (exportedSymbol->sectionNumber != kReExportImport) ) { - exportInfo->location.offset = exportedSymbol->address; - } else { - exportInfo->location.section = kPhysicalExport; - exportInfo->location.offset = pefPrivate->imports[exportedSymbol->address]; - } - #endif - - } else { - - CFContLogicalLocation mainLocation; - CFContLogicalLocation initLocation; - CFContLogicalLocation termLocation; - - err = PEF_GetAnonymousSymbolLocations ( containerRef, &mainLocation, &initLocation, &termLocation ); - if ( err != noErr ) goto ERROR; - - switch ( exportIndex ) { - case kMainCFragSymbolIndex : - exportInfo->location = mainLocation; - exportInfo->symbolClass = 0xFF; // !!! Ought to have a kUnknownCFragSymbol constant. - break; - case kInitCFragSymbolIndex : - exportInfo->location = initLocation; - exportInfo->symbolClass = kTVectorCFragSymbol; // ! Very well better be! - break; - case kTermCFragSymbolIndex : - exportInfo->location = termLocation; - exportInfo->symbolClass = kTVectorCFragSymbol; // ! Very well better be! - break; - default : - goto ParameterError; - } - - exportInfo->symbolName.nameHash = 0; - exportInfo->symbolName.nameText = NULL; - - exportInfo->reservedA = 0; - exportInfo->reservedB = 0; - exportInfo->options = kNilOptions; - - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetExportedSymbolInfo () - - -// ¤ -// =========================================================================================== -// PEF_FindExportedSymbolInfo () -// ============================= - - -OSStatus PEF_FindExportedSymbolInfo ( CFContHandlerRef containerRef, - const CFContHashedName * exportName, - PBVersion infoVersion, - ItemCount * exportIndex_o, // May be null. - CFContExportedSymbolInfo * exportInfo ) // May be null. -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - LoaderExport * exportedSymbol = NULL; - CFContStringHash * hashwordList = NULL; - CFContStringHash * nextHashword = NULL; - HashSlotEntry * hashSlot = NULL; - ByteCount nameLength = CFContStringHashLength ( exportName->nameHash ); - ItemCount exportIndex; - ItemCount slotIndex; - ItemCount chainLimit; - Boolean nameMatch; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( infoVersion != kCFContExportedSymbolInfoVersion ) goto ParameterError; - - - hashwordList = &pefPrivate->ldrHashChain[0].hashword; - - slotIndex = GetPEFHashSlot ( exportName->nameHash, pefPrivate->ldrHeader->hashSlotTabSize ); - hashSlot = &pefPrivate->ldrHashSlot[slotIndex]; - - exportIndex = hashSlot->chainIndex; - chainLimit = exportIndex + hashSlot->chainCount; - nextHashword = &hashwordList[exportIndex]; - - while ( exportIndex < chainLimit ) { - - if ( *nextHashword == exportName->nameHash ) { - exportedSymbol = &pefPrivate->ldrExportSymbols[exportIndex]; - nameMatch = PEF_CompareBytes ( exportName->nameText, - &pefPrivate->ldrStringTable[exportedSymbol->nameOffset], - nameLength ); - if ( nameMatch ) goto Found; - } - - exportIndex += 1; - nextHashword += 1; // ! Pointer arithmetic. - } - goto NotFoundError; - -Found: - if ( exportIndex_o != NULL ) *exportIndex_o = exportIndex; - if ( exportInfo != NULL ) { - err = PEF_GetExportedSymbolInfo ( containerRef, exportIndex, infoVersion, exportInfo ); - if ( err != noErr ) goto ERROR; - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - -NotFoundError: - err = cfragNoSymbolErr; - goto ERROR; - - -} // PEF_FindExportedSymbolInfo () - - -// ¤ -// =========================================================================================== -// PEF_GetImportCounts () -// ====================== - - -OSStatus PEF_GetImportCounts ( CFContHandlerRef containerRef, - ItemCount * libraryCount, // May be null. - ItemCount * symbolCount ) // May be null. -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - - if ( pefPrivate == NULL ) goto ParameterError; - - if ( libraryCount != NULL ) *libraryCount = pefPrivate->ldrHeader->numImportFiles; - if ( symbolCount != NULL ) *symbolCount = pefPrivate->ldrHeader->numImportSyms; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetImportCounts () - - -// ¤ -// =========================================================================================== -// PEF_GetImportedLibraryInfo () -// ============================= - - -OSStatus PEF_GetImportedLibraryInfo ( CFContHandlerRef containerRef, - ItemCount libraryIndex, - PBVersion infoVersion, - CFContImportedLibraryInfo * libraryInfo ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - LoaderImportFileID * importedLibrary = NULL; - BytePtr nameText = NULL; - ByteCount nameLength; - - - if ( (pefPrivate == NULL) || (libraryInfo == NULL) ) goto ParameterError; - if ( infoVersion != kCFContImportedLibraryInfoVersion ) goto ParameterError; - if ( libraryIndex >= pefPrivate->ldrHeader->numImportFiles ) goto ParameterError; - - - importedLibrary = &pefPrivate->ldrImportFiles[libraryIndex]; - - nameText = &pefPrivate->ldrStringTable[importedLibrary->fileNameOffset]; - nameLength = GetNameLength ( nameText ); - - libraryInfo->libraryName.nameHash = CFContHashName ( nameText, nameLength ); - libraryInfo->libraryName.nameText = nameText; - - libraryInfo->linkedVersion = importedLibrary->linkedVersion; - libraryInfo->oldImpVersion = importedLibrary->oldImpVersion; - libraryInfo->options = kNilOptions; - - if ( importedLibrary->options & kPEFInitBeforeMask ) libraryInfo->options |= kCFContInitBeforeMask; - if ( importedLibrary->options & kPEFWeakLibraryMask ) libraryInfo->options |= kCFContWeakLibraryMask; - if ( importedLibrary->options & kPEFDeferredBindMask ) libraryInfo->options |= kCFContDeferredBindMask; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_GetImportedLibraryInfo () - - -// ¤ -// =========================================================================================== -// PEF_GetImportedSymbolInfo () -// ============================ - - -OSStatus PEF_GetImportedSymbolInfo ( CFContHandlerRef containerRef, - ItemCount symbolIndex, - PBVersion infoVersion, - CFContImportedSymbolInfo * symbolInfo ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - LoaderImport * importedSymbol = NULL; - LoaderImportFileID * importedLibrary = NULL; - BytePtr nameText = NULL; - ByteCount nameLength; - ItemCount libraryCount; - ItemCount libraryIndex; - - - if ( (pefPrivate == NULL) || (symbolInfo == NULL) ) goto ParameterError; - if ( infoVersion != kCFContImportedSymbolInfoVersion ) goto ParameterError; - if ( symbolIndex >= pefPrivate->ldrHeader->numImportSyms ) goto ParameterError; - - - importedSymbol = &pefPrivate->ldrImportSymbols[symbolIndex]; - libraryCount = pefPrivate->ldrHeader->numImportFiles; - - nameText = &pefPrivate->ldrStringTable[importedSymbol->nameOffset]; - nameLength = GetNameLength ( nameText ); - - symbolInfo->symbolName.nameHash = CFContHashName ( nameText, nameLength ); - symbolInfo->symbolName.nameText = nameText; - - symbolInfo->symbolClass = importedSymbol->symClass & 0x0F; - symbolInfo->reservedA = 0; - symbolInfo->reservedB = 0; - symbolInfo->options = 0; - - if ( importedSymbol->symClass & kPEFWeakSymbolMask ) symbolInfo->options |= kCFContWeakSymbolMask; - - for ( libraryIndex = 0; libraryIndex < libraryCount; libraryIndex += 1 ) { - importedLibrary = &pefPrivate->ldrImportFiles[libraryIndex]; - if ( (importedLibrary->impFirst <= symbolIndex) && - (symbolIndex < (importedLibrary->impFirst + importedLibrary->numImports)) ) { - break; - } - } - if ( libraryIndex == libraryCount ) goto FragmentCorruptError; - - symbolInfo->libraryIndex = libraryIndex; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - -FragmentCorruptError: - err = cfragFragmentCorruptErr; - goto ERROR; - - -} // PEF_GetImportedSymbolInfo () - - -// ¤ -// =========================================================================================== -// PEF_SetImportedSymbolAddress () -// =============================== - - -OSStatus PEF_SetImportedSymbolAddress ( CFContHandlerRef containerRef, - ItemCount symbolIndex, - LogicalAddress symbolAddress ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( symbolIndex >= pefPrivate->ldrHeader->numImportSyms ) goto ParameterError; - - - pefPrivate->imports[symbolIndex] = symbolAddress; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_SetImportedSymbolAddress () - - -// ¤ -// =========================================================================================== -// GetPackedDataCount () -// ===================== - - -static UInt32 GetPackedDataCount ( UInt8 * * byteHandle ) -{ - UInt32 count = 0; - UInt8 * bytePtr = *byteHandle; - UInt8 currByte; - - - do { - currByte = *bytePtr++; - count = (count << kPEFPkDataVCountShift) | (currByte & kPEFPkDataVCountMask); - } while ( (currByte & kPEFPkDataVCountEndMask) != 0 ); - - *byteHandle = bytePtr; - - return count; - - -} // GetPackedDataCount () - - -// ¤ -// =========================================================================================== -// UnpackFullSection () -// ==================== - - -// ------------------------------------------------------------------------------------------ -// This is the "normal" case from CFM, unpacking all of the packed portion. Along the way we -// make sure we're not writing beyond the end of the unpacked data. At the end we make sure -// that all we didn't read past the end of the packed data, and that all of the output was -// written. - -// ! Note that the xyzEnd pointers are the actual end of the range, not one byte beyond. This -// ! routine will work if the output end address is 0xFFFFFFFF, but not if the packed end is. - -// ! Don't do range comparisons as "(lowAddr + length) > highAddr", because this might wrap -// ! the end high end of the address space. Always do "(highAddr - lowAddr) > length". - -// ??? We should gather some statistics on actual usage to see whether it is worthwhile to -// ??? have local customized code for common cases. E.g. block fill of 1, 2, or 4 bytes, or -// ??? of interleaved repeats with 1/2/4 byte common or custom portions. - - -static OSStatus UnpackFullSection ( BytePtr packedBase, - BytePtr packedEnd, - BytePtr outputBase, - BytePtr outputEnd ) -{ - OSStatus err = cfragCFMInternalErr; - BytePtr packedPos = packedBase; - BytePtr outputPos = outputBase; - BytePtr outPosLimit = outputEnd + 1; // ! Might be zero if outputEnd is 0xFFFFFFFF. - - UInt8 currByte; - UInt8 opcode; - UInt32 count1; - UInt32 count2; - UInt32 count3; - - - if ( (packedEnd + 1) == 0 ) goto FragmentUsageError; - - - while ( packedPos <= packedEnd ) { - - - currByte = *packedPos++; - opcode = currByte >> kPEFPkDataOpcodeShift; - count1 = currByte & kPEFPkDataCount5Mask; - - if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos ); - - - switch ( opcode ) { - - - case kPEFPkDataZero : - - if ( (outPosLimit - outputPos) < count1 ) goto FragmentCorruptError; - - PEF_BlockClear ( outputPos, count1 ); - outputPos += count1; - - break; - - - case kPEFPkDataBlock : - - if ( (outPosLimit - outputPos) < count1 ) goto FragmentCorruptError; - - PEF_BlockMove ( packedPos, outputPos, count1 ); - packedPos += count1; - outputPos += count1; - - break; - - - case kPEFPkDataRepeat : // ??? Need a BlockFill routine? - - count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less. - - if ( (outPosLimit - outputPos) < (count1 * count2) ) goto FragmentCorruptError; - - if ( count1 == 1 ) { // ??? Is this worth the bother? Other sizes? - - currByte = *packedPos++; - for ( ; count2 != 0; count2 -= 1 ) *outputPos++ = currByte; - - } else { - - for ( ; count2 != 0; count2 -= 1 ) { - PEF_BlockMove ( packedPos, outputPos, count1 ); - outputPos += count1; - } - packedPos += count1; - - } - - break; - - - case kPEFPkDataRepeatBlock : - - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - - if ( (outPosLimit - outputPos) < (((count1 + count2) * count3) + count1) ) goto FragmentCorruptError; - - { - BytePtr commonPos = packedPos; - - packedPos += count1; // Skip the common part. - - for ( ; count3 != 0; count3 -= 1 ) { - - PEF_BlockMove ( commonPos, outputPos, count1 ); - outputPos += count1; - - PEF_BlockMove ( packedPos, outputPos, count2 ); - packedPos += count2; - outputPos += count2; - - } - - PEF_BlockMove ( commonPos, outputPos, count1 ); - outputPos += count1; - - } - - break; - - - case kPEFPkDataRepeatZero : - - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - - if ( (outPosLimit - outputPos) < (((count1 + count2) * count3) + count1) ) goto FragmentCorruptError; - - PEF_BlockClear ( outputPos, count1 ); - outputPos += count1; - - for ( ; count3 != 0; count3 -= 1 ) { - - PEF_BlockMove ( packedPos, outputPos, count2 ); - packedPos += count2; - outputPos += count2; - - PEF_BlockClear ( outputPos, count1 ); - outputPos += count1; - - } - - break; - - - default : - goto FragmentCorruptError; - - } - - } - - - if ( (packedPos != (packedEnd + 1)) || (outputPos != outPosLimit) ) goto FragmentCorruptError; - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - - -FragmentUsageError: - err = cfragFragmentUsageErr; - goto ERROR; - -FragmentCorruptError: - err = cfragFragmentCorruptErr; - goto ERROR; - - -} // UnpackFullSection () - - -// ¤ -// =========================================================================================== -// UnpackPartialSection () -// ======================= - - -// ------------------------------------------------------------------------------------------- -// This is the case where we want to extract some arbitrary portion of a section as it would -// be when instantiated but not relocated. We have to interpret the packed part up to the -// desired output start, then continue begin unpacking for real. If we run out of packed data -// before filling the output, we fill the rest of the output with zeroes. - -// ! We have to be very careful in the skip logic because the current operation probably spans -// ! the skip/output boundary. We have to be similarly careful at the output end because the -// ! current operation probably spans the tail of the output. Don't forget that the partial -// ! output at the start could also fill the output and overflow the tail! - -// ! Note that the xyzEnd pointers are the actual end of the range, not one byte beyond. This -// ! routine might not work if outputEnd is 0xFFFFFFFF. This is because outputPos points to -// ! the next byte to be written. The loops that are controlled by "outputPos < outputBase" -// ! or "outputPos <= outputEnd" would fail in this case if outputPos were "outputEnd + 1", -// ! i.e. outputPos would be zero. - -// ! Don't do range comparisons as "(lowAddr + length) > highAddr", because this might wrap -// ! the end high end of the address space. Always do "(highAddr - lowAddr) > length". - - -// ------------------------------------------------------------------------------------------- - - -static void PartialBlockClear ( BytePtr outputBase, - ByteCount outputStartOffset, - ByteCount outputEndOffset, - ByteCount outputOffset, - ByteCount count ) -{ - - if ( ((outputOffset + count) <= outputStartOffset) || (outputOffset > outputEndOffset) ) return; // Nothing to output. - - if ( outputOffset < outputStartOffset ) { - count -= (outputStartOffset - outputOffset); - outputOffset = outputStartOffset; - } - - if ( count > (outputEndOffset - outputOffset + 1) ) count = outputEndOffset - outputOffset + 1; - - PEF_BlockClear ( outputBase + (outputOffset - outputStartOffset), count ); - -} // PartialBlockClear (); - - -// ------------------------------------------------------------------------------------------- - - -static void PartialBlockMove ( BytePtr source, - BytePtr outputBase, - ByteCount outputStartOffset, - ByteCount outputEndOffset, - ByteCount outputOffset, - ByteCount count ) -{ - - if ( ((outputOffset + count) <= outputStartOffset) || (outputOffset > outputEndOffset) ) return; // Nothing to output. - - if ( outputOffset < outputStartOffset ) { - const ByteCount skipCount = outputStartOffset - outputOffset; - source += skipCount; - count -= skipCount; - outputOffset = outputStartOffset; - } - - if ( count > (outputEndOffset - outputOffset + 1) ) count = outputEndOffset - outputOffset + 1; - - PEF_BlockMove ( source, outputBase + (outputOffset - outputStartOffset), count ); - -} // PartialBlockClear (); - - -// ------------------------------------------------------------------------------------------- - - -static OSStatus UnpackPartialSection ( BytePtr packedBase, - BytePtr packedEnd, - BytePtr outputBase, - BytePtr outputEnd, - ByteCount outputStartOffset ) -{ - OSStatus err = cfragCFMInternalErr; - const ByteCount outputEndOffset = outputStartOffset + (outputEnd - outputBase); - BytePtr packedPos = NULL; - BytePtr packedBoundary = NULL; - ByteCount outputOffset; - ByteCount outputBoundary; - - UInt8 currByte; - UInt8 opcode; - UInt32 count1; - UInt32 count2; - UInt32 count3; - - - if ( ((packedEnd + 1) == 0) || ((outputEnd + 1) == 0) ) goto FragmentUsageError; - - - // -------------------------------------------------------------------------------------- - // Skip the packed data until we get within the output range. We know there is something - // to unpack, otherwise the zero fill of the output would be done by the caller. This - // loop sets outputOffset to the end of what would be unpacked, until the outputOffset is - // beyond the outputStartOffset. I.e. until we hit the first operation that would create - // actual output. - - outputOffset = 0; - packedPos = packedBase; - - do { - - packedBoundary = packedPos; // The start of the current operation. - outputBoundary = outputOffset; - - currByte = *packedPos++; - opcode = currByte >> kPEFPkDataOpcodeShift; - count1 = currByte & kPEFPkDataCount5Mask; - - if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos ); - - switch ( opcode ) { - - case kPEFPkDataZero : - outputOffset += count1; - break; - - case kPEFPkDataBlock : - packedPos += count1; - outputOffset += count1; - break; - - case kPEFPkDataRepeat : - count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less. - packedPos += count1; - outputOffset += count1 * count2; - break; - - - case kPEFPkDataRepeatBlock : - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - packedPos += count1 + (count2 * count3); - outputOffset += count1 + ((count1 + count2) * count3); - break; - - - case kPEFPkDataRepeatZero : - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - packedPos += count2 * count3; - outputOffset += count1 + ((count1 + count2) * count3); - break; - - - default : - goto FragmentCorruptError; - - } - - } while ( outputOffset <= outputStartOffset ); - - - //---------------------------------------------------------------------------------------- - // Now do the actual unpacking. This uses a copy of the full unpack logic with special - // block copy/clear routines. These special routines do the bounds checking, only writing - // output where actually allowed. This involves "unnecessary" checks for the "middle" - // operations that are fully within the range, but vastly simplifies the boundary cases. - - packedPos = packedBoundary; // Reset to the operation that spans the output start. - outputOffset = outputBoundary; - - do { - - currByte = *packedPos++; - opcode = currByte >> kPEFPkDataOpcodeShift; - count1 = currByte & kPEFPkDataCount5Mask; - - if ( count1 == 0 ) count1 = GetPackedDataCount ( &packedPos ); - - switch ( opcode ) { - - case kPEFPkDataZero : - PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - break; - - case kPEFPkDataBlock : - PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - packedPos += count1; - outputOffset += count1; - break; - - case kPEFPkDataRepeat : // ??? Need a BlockFill routine? - count2 = GetPackedDataCount ( &packedPos ) + 1; // ! Stored count is 1 less. - for ( ; count2 != 0; count2 -= 1 ) { - PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - } - packedPos += count1; - break; - - case kPEFPkDataRepeatBlock : - - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - - { - BytePtr commonPos = packedPos; - - packedPos += count1; // Skip the common part. - - for ( ; count3 != 0; count3 -= 1 ) { - - PartialBlockMove ( commonPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - - PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count2 ); - packedPos += count2; - outputOffset += count2; - - } - - PartialBlockMove ( commonPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - - } - - break; - - case kPEFPkDataRepeatZero : - - count2 = GetPackedDataCount ( &packedPos ); - count3 = GetPackedDataCount ( &packedPos ); - - PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - - for ( ; count3 != 0; count3 -= 1 ) { - - PartialBlockMove ( packedPos, outputBase, outputStartOffset, outputEndOffset, outputOffset, count2 ); - packedPos += count2; - outputOffset += count2; - - PartialBlockClear ( outputBase, outputStartOffset, outputEndOffset, outputOffset, count1 ); - outputOffset += count1; - - } - - break; - - default : - goto FragmentCorruptError; - - } - - } while ( (outputOffset <= outputEndOffset) && (packedPos <= packedEnd) ); - - - // ------------------------------------------ - // Finally block clear anything that is left. - - if ( outputOffset <= outputEndOffset ) { - PEF_BlockClear ( outputBase + (outputOffset - outputStartOffset), outputEndOffset - outputOffset + 1 ); - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - - -FragmentUsageError: - err = cfragFragmentUsageErr; - goto ERROR; - -FragmentCorruptError: - err = cfragFragmentCorruptErr; - goto ERROR; - - -} // UnpackPartialSection () - - -// ¤ -// =========================================================================================== -// PEF_UnpackSection () -// ==================== - - -OSStatus PEF_UnpackSection ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - ByteCount sectionOffset, - LogicalAddress bufferAddress, - ByteCount bufferLength ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - SectionHeader * section = NULL; - BytePtr packedBase = NULL; - BytePtr packedEnd = NULL; - BytePtr outputBase = bufferAddress; - BytePtr outputEnd = outputBase + bufferLength - 1; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError; - if ( (bufferAddress == NULL) && (bufferLength != 0) ) goto ParameterError; - - section = &pefPrivate->sections[sectionIndex]; - if ( (sectionOffset + bufferLength) > section->execSize ) goto ParameterError; - - packedBase = pefPrivate->mappedContainer + section->containerOffset; - packedEnd = packedBase + section->rawSize - 1; - - - if ( (sectionOffset == 0) && (bufferLength == section->initSize) ) { - - err = UnpackFullSection ( packedBase, packedEnd, outputBase, outputEnd ); - if ( err != noErr ) goto ERROR; - - if ( false && EnableCFMDebugging && (section->execSize > 8) ) { // Force some tests of partial unpacking. - - UInt32 word; - BytePtr partContents = (*pefPrivate->Allocate) ( section->execSize - 2 ); - - PEF_Assert ( partContents != NULL ); - - err = PEF_UnpackSection ( containerRef, sectionIndex, 1, &word, 4 ); - PEF_Assert ( err == noErr ); - - err = PEF_UnpackSection ( containerRef, sectionIndex, section->execSize / 2, &word, 4 ); - PEF_Assert ( err == noErr ); - - err = PEF_UnpackSection ( containerRef, sectionIndex, section->execSize - 5, &word, 4 ); - PEF_Assert ( err == noErr ); - - err = PEF_UnpackSection ( containerRef, sectionIndex, 1, partContents, section->execSize - 2 ); - PEF_Assert ( err == noErr ); - - (*pefPrivate->Release) ( partContents ); - } - - } else { - - if ( section->initSize < sectionOffset ) { - PEF_BlockClear ( bufferAddress, bufferLength ); - } else { - err = UnpackPartialSection ( packedBase, packedEnd, outputBase, outputEnd, sectionOffset ); - if ( err != noErr ) goto ERROR; - } - - if ( EnableCFMDebugging ) { // See if the partial output agrees with full output. - - BytePtr fullContents = (*pefPrivate->Allocate) ( section->execSize ); - - PEF_Assert ( fullContents != NULL ); - PEF_BlockClear ( fullContents, section->execSize ); - - err = UnpackFullSection ( packedBase, packedEnd, fullContents, fullContents + section->initSize - 1 ); - PEF_Assert ( err == noErr ); - - PEF_Assert ( PEF_CompareBytes ( fullContents + sectionOffset, bufferAddress, bufferLength ) ); - - (*pefPrivate->Release) ( fullContents ); - - } - - } - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_UnpackSection () - - -// ¤ -// =========================================================================================== -// PEF_RelocateSection () -// ====================== - - -// *** This needs cleaning up. - - -OSStatus PEF_RelocateSection ( CFContHandlerRef containerRef, - ItemCount sectionIndex ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - BytePtr * raddr; - ByteCount dataA; - int cnt; // ! Must be signed. - ByteCount codeA; - LoaderRelExpHeader * ldRelHdr; - Relocation *reloc, *rlend; - Relocation r; - long rpt; // ! Must be signed. - long secn; - long rsymi; - BytePtr *imports; - ByteCount *regions; - long i; - long relNum; - BytePtr regStart; - SectionHeader * section; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError; - - regStart = pefPrivate->mappedOrigins[sectionIndex]; - section = & pefPrivate->sections [sectionIndex]; - - pefPrivate->resolved = 1; // !!! Really means relocated, and should be set on exit. - - for (i = 0; ; i++) { - if ( i >= pefPrivate->sectionCount ) return noErr; // No relocations for this section. - ldRelHdr = & pefPrivate->ldrSections [i]; - if ( ldRelHdr->sectionNumber == sectionIndex ) break; - } - - regions = pefPrivate->runningOffsets; - imports = pefPrivate->imports; - - reloc = (Relocation *) (pefPrivate->ldrRelocations + ldRelHdr->relocationsOffset); - rlend = (Relocation *) ((RelocInstr *) reloc + ldRelHdr->numRelocations); - raddr = (BytePtr *) regStart; // ! Change the stride from 1 to 4. - rsymi = 0; - codeA = regions [0]; - dataA = regions [1]; - rpt = 0; - - #if 0 - sprintf ( gDebugMessage, "PLPrepareRegion: start @ %.8X\n", raddr ); - PutSerialMesssage ( gDebugMessage ); - #endif - - relNum = 0; - while (reloc < rlend) { - - r = *reloc; - reloc = (Relocation *) ((RelocInstr *) reloc + 1); - - switch ( opcode [r.opcode.op] ) { - case krDDAT : - raddr = (BytePtr *) ((BytePtr)raddr + (r.deltadata.delta_d4 * 4)); // ! Reduce stride to 1. - cnt = r.deltadata.cnt; - while (--cnt >= 0) { - *raddr++ += dataA; - } - break; - - case krCODE : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += codeA; - } - break; - - case krDATA : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += dataA; - } - break; - - case krDESC : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += codeA; - *raddr++ += dataA; - raddr++; - } - break; - - case krDSC2 : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += codeA; - *raddr++ += dataA; - } - break; - - case krVTBL : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += dataA; - raddr++; - } - break; - - case krSYMR : - cnt = r.run.cnt_m1 + 1; - while (--cnt >= 0) { - *raddr++ += (ByteCount) imports [rsymi++]; - } - break; - - case krSYMB : - rsymi = r.glp.idx; - *raddr++ += (ByteCount) imports [rsymi++]; - break; - - case krCDIS : - codeA = regions [r.glp.idx]; - break; - - case krDTIS : - dataA = regions [r.glp.idx]; - break; - - case krSECN : - *raddr++ += regions [r.glp.idx]; - break; - - case krDELT : - raddr = (BytePtr *) ((BytePtr) raddr + r.delta.delta_m1 + 1); // ! Reduce stride to 1. - #if 0 - sprintf ( gDebugMessage, "PLPrepareRegion: delta to %.8X\n", raddr ); - PutSerialMesssage ( gDebugMessage ); - #endif - break; - - case krRPT : - if (--rpt == 0) break; // count was 1 --> rpt done - if (rpt < 0) // first time rpt encountered? - rpt = r.rpt.rcnt_m1 + 1; // yes- initialize rpt count - cnt = r.rpt.icnt_m1 + 2; // yes or no - back up cnt instrs - reloc = (Relocation *) ((RelocInstr *) reloc - cnt); - break; - - case krLABS : - raddr = (BytePtr *) ((r.large1.idx_top << 16) + reloc->bot + regStart); - reloc = (Relocation *) ((RelocInstr *) reloc + 1); - #if 0 - sprintf ( gDebugMessage, "PLPrepareRegion: abs to %.8X\n", raddr ); - PutSerialMesssage ( gDebugMessage ); - #endif - break; - - case krLSYM : - rsymi = (r.large1.idx_top << 16) + reloc->bot; - reloc = (Relocation *) ((RelocInstr *) reloc + 1); - *raddr++ += (ByteCount) imports [rsymi++]; - break; - - case krLRPT : - if (--rpt == 0) { - reloc = (Relocation *) ((RelocInstr *) reloc + 1); - break; - } - if (rpt < 0) - rpt = (r.large2.idx_top << 16) + reloc->bot; - cnt = r.large2.cnt_m1 + 2; - reloc = (Relocation *) ((RelocInstr *) reloc - cnt); - break; - - case krLSEC : - secn = (r.large2.idx_top << 16) + reloc->bot; - switch (r.large2.cnt_m1) { - case 0 : *raddr++ += regions [secn]; break; - case 1 : codeA = regions [secn]; break; - case 2 : dataA = regions [secn]; break; - } - reloc = (Relocation *) ((RelocInstr *) reloc + 1); - break; - - default : - goto FragmentCorruptError; - } - } - - - #if 0 - sprintf ( gDebugMessage, "PLPrepareRegion: end @ %.8X\n", raddr ); - PutSerialMesssage ( gDebugMessage ); - #endif - - err = noErr; - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - -FragmentCorruptError: - err = cfragFragmentCorruptErr; - goto ERROR; - - -} // PEF_RelocateSection () - - -// ¤ -// =========================================================================================== -// PEF_RelocateImportsOnly () -// ========================== - - -OSStatus PEF_RelocateImportsOnly ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - ItemCount libraryIndex ) -{ - OSStatus err = cfragCFMInternalErr; - PEFPrivateInfo * pefPrivate = (PEFPrivateInfo *) containerRef; - - - if ( pefPrivate == NULL ) goto ParameterError; - if ( sectionIndex >= pefPrivate->sectionCount ) goto ParameterError; - if ( libraryIndex >= pefPrivate->ldrHeader->numImportFiles ) goto ParameterError; - - - if ( pefPrivate == NULL ) goto ParameterError; - - - return unimpErr; // !!! Fix this! - -EXIT: - return err; - -ERROR: - goto EXIT; - -ParameterError: - err = paramErr; - goto ERROR; - - -} // PEF_RelocateImportsOnly () - diff --git a/iokit/Families/IONDRVSupport/IOPEFInternals.h b/iokit/Families/IONDRVSupport/IOPEFInternals.h deleted file mode 100644 index 083f62c8b..000000000 --- a/iokit/Families/IONDRVSupport/IOPEFInternals.h +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - */ - - -/* - File: zPEF.h - - Contains: PEF format declarations. - - Version: Maxwell - - Copyright: © 1992-1996 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: Alan Lillich - - Other Contact: <<unknown>> - - Technology: Core Runtime - - Writers: - - (AWL) Alan Lillich - (ELE) Erik Eidt - - Change History (most recent first): - - <7> 2/28/96 AWL Adapt for new container handler model. - <6> 4/12/95 AWL Fix bit field problem. - <5> 8/29/94 AWL Remove "never" share mode. - <4> 8/23/94 AWL Update section sharing constants. - <3> 4/28/94 AWL Simplify cross address space use for booting. - <2> 4/11/94 AWL Use 68K alignment for the export symbol structure. - <1> 2/15/94 AWL Initial checkin for kernel based CFM. - - ------------------------------------------------------------------------------------- - - <7> 8/26/93 AWL Move CFTypes.h and CFLoader.h up with other Apple private headers. - <5> 7/8/93 AWL (&ELE) Fixed version field names in import file IDs - <4> 6/9/93 JRG ELE & AWL Changes: - <4> 06/08/93 AWL (&ELE) Added more standard section types and packed data opcodes. - <3> 9/23/92 ELE added precomputed hash table for improved runtime performance. - - Version 1.3 Erik Eidt 9/23/92 updated for new hash table capabilities - Version 1.2 Erik Eidt 7/8/92 updated for new relocations and other loader section size optimizations - Version 1.1 Cheryl Lins 5/27/92 updated for PEF 1.2 definition - Version 1.0 Cheryl Lins 4/7/92 initial version -*/ - - -#ifndef __IOPEFINTERNALS__ -#define __IOPEFINTERNALS__ 1 - -#include "IOPEFLoader.h" - - -typedef signed int PEF_SBits32; // ! Can't use SInt32, it is "signed long". -typedef unsigned int PEF_UBits32; // ! Can't use UInt32, it is "unsigned long". - - -#pragma options align=mac68k - -/*========== File Header ==========*/ - -typedef struct { - UInt16 magic1; /* magic flag describing execution machine and environment */ - UInt16 magic2; /* magic flag describing execution machine and environment */ - OSType fileTypeID; /* OSType identifier = 'pef' */ - OSType architectureID; /* OSType identifier = 'pwpc' */ - UInt32 versionNumber; /* version number of this file format */ - UInt32 dateTimeStamp; /* Macintosh date/time stamp */ - UInt32 oldDefVersion; /* old definition version number */ - UInt32 oldImpVersion; /* old implementation version number */ - UInt32 currentVersion; /* current version number */ - SInt16 numberSections; /* number of sections */ - SInt16 loadableSections; /* number of sections that are loadable for execution, - also the section # of first non-loadable section */ - BytePtr memoryAddress; /* the location this container was last loaded */ -} FileHeader, *FileHeaderPtr; - -#define kPEFVersion 1 /* current version number */ -#define kPEFMagic1 0x4A6F /* value of magic1 for PEF */ -#define kPEFMagic2 0x7921 /* value of magic2 for PEF */ -#define kPEFTypeID 0x70656666 /* value of fileTypeID for 'peff' */ -#define kPowerPCID 0x70777063 /* value of architecture ID 'pwpc' */ - -/*========== Section Header ==========*/ - -typedef struct { - ByteCount sectionName; /* offset into global string table for section name */ - BytePtr sectionAddress; /* preferred base address for the section */ - ByteCount execSize; /* section size in bytes during execution in memory including zero initialization */ - ByteCount initSize; /* section size in bytes during execution in memory before zero initialization */ - ByteCount rawSize; /* section size in bytes in container before loading */ - ByteCount containerOffset;/* container offest to section's raw data */ - UInt8 regionKind; /* section/region classification */ - UInt8 shareKind; /* sharing classification */ - UInt8 alignment; /* execution alignment requirement (0=byte,1=half,2=word,3=doubleword,4=quadword..) */ - UInt8 reservedA; -} SectionHeader, *SectionHeaderPtr; - -/* TCFLSectionKind */ -#define kPEFCodeSection 0 -#define kPEFDataSection 1 -#define kPEFPIDataSection 2 -#define kPEFConstantSection 3 -#define kPEFLoaderSection 4 -#define kPEFDebugSection 5 -#define kPEFExecDataSection 6 -#define kPEFExceptionSection 7 -#define kPEFTracebackSection 8 - -/* TCFLShareKind */ -#define kPEFContextShare 1 -#define kPEFGlobalShare 4 -#define kPEFProtectedShare 5 - -/* Defines for PIDataSections */ -#define kPEFZero 0 -#define kPEFBlock 1 -#define kPEFRepeat 2 -#define kPEFRepeatBlock 3 -#define kPEFRepeatZero 4 -#define kPEFNoOpcode 0x0fff -#define kPEFOpcodeShift 5 -#define kPEFFirstOperandMask 31 - - -/*========== Loader Header ==========*/ - -typedef struct { - SInt32 entryPointSection; /* section number containing entry point descriptor */ - ByteCount entryPointOffset; /* offset to entry point descriptor within section */ - - SInt32 initPointSection; /* section number containing entry point descriptor */ - ByteCount initPointOffset; /* offset to entry point descriptor within section */ - - SInt32 termPointSection; /* section number containing entry point descriptor */ - ByteCount termPointOffset; /* offset to entry point descriptor within section */ - - ItemCount numImportFiles; /* number of import file id entries */ - ItemCount numImportSyms; /* number of import symbol table entries */ - ItemCount numSections; /* number of sections with load-time relocations */ - ByteCount relocationsOffset; /* offset to relocation descriptions table */ - - ByteCount stringsOffset; /* offset to loader string table */ - - ByteCount hashSlotTable; /* offset to hash slot table */ - ItemCount hashSlotTabSize; /* number of hash slot entries */ - ItemCount numExportSyms; /* number of export symbol table entries */ -} LoaderHeader, *LoaderHeaderPtr; - -/*========== Loader Section Header ==========*/ - -typedef struct { - SInt16 sectionNumber; /* reference to primary section number */ - SInt16 reservedA; /* if TSectNum were 16 bits, which it isn't */ - ItemCount numRelocations; /* number of loader relocations for this section */ - ByteCount relocationsOffset; /* offset to relocation descriptions for this section */ -} LoaderRelExpHeader, *LoaderRelExpHeaderPtr; - -/*========== Loader Import File ID's Entry ==========*/ - -typedef struct { - ByteCount fileNameOffset; /* offset into loader string table for file name */ - UInt32 oldImpVersion; /* oldest compatible implementation library */ - UInt32 linkedVersion; /* current version at link time */ - ItemCount numImports; /* number of imports from this file */ - ItemCount impFirst; /* number of the first imports from this file (relative to all imports) */ - UInt8 options; /* call this libraries initialization routine before mine */ - UInt8 reservedA; - UInt16 reservedB; -} LoaderImportFileID, *LoaderImportFileIDPtr; - -#define kPEFInitBeforeMask 0x80 -#define kPEFWeakLibraryMask 0x40 -#define kPEFDeferredBindMask 0x20 - -/*========== Loader Import Symbol Table Entry ==========*/ - -typedef struct { - PEF_UBits32 symClass : 8; // Actually ot type TCFLSymbolClass. - PEF_UBits32 nameOffset : 24; -} LoaderImport, *LoaderImportPtr; - -#define kPEFWeakSymbolMask 0x80 - -/*========== Loader Export Hash Slot Table Entry ==========*/ - -typedef struct { - PEF_UBits32 chainCount : 14; - PEF_UBits32 chainIndex : 18; -} HashSlotEntry, *HashSlotEntryPtr; - -#define PEFHashHighBits(hashword,bitCount) ((hashword) >> (bitCount)) -#define PEFHashMaskBits(hashword,bitCount) (((UInt32)(1) << (bitCount)) - 1) - -#define GetPEFHashSlot(hashword,bitCount) \ - ( (ItemCount) (((hashword) ^ PEFHashHighBits((hashword),(bitCount))) & PEFHashMaskBits((hashword),(bitCount))) ) - -/*========== Loader Export Hash Chain Table Entry ==========*/ - -typedef struct { - UInt32 hashword; /* (hashword >> 16) == nameLength !! */ -} HashChainEntry, *HashChainEntryPtr; - -/*========== Loader Export Symbol Table Entry ==========*/ - -/* Section number controls how 'address' is interpreted. - >=0: section number exporting the symbol; 'address' is offset from start of the section to - the symbol being exported (ie address of a routine or data item) - -1: value is absolute (non-relocatable) - -2: value is a physical address (non-relocatable) - -3: re-export imported symbol whose number is in 'address' -*/ - -/* this struct is stored in the file, non-aligned: size = 10 */ -typedef struct { - PEF_UBits32 symClass : 8; // Actually ot type TCFLSymbolClass. - PEF_UBits32 nameOffset : 24; - ByteCount offset; /* offset into section to exported symbol */ - SInt16 sectionNumber; -} LoaderExport, *LoaderExportPtr; - -#define SIZEOF_LoaderExport (sizeof (TUnsigned32)*2 + sizeof (SInt16)) - - -#define kPEFAbsoluteExport -1 -#define kPEFPhysicalExport -2 -#define kPEFReExportImport -3 - -/*========== Loader Relocation Entry ==========*/ - -typedef UInt16 RelocInstr; - -typedef union { - struct { unsigned op:7, rest:9; } opcode; - struct { unsigned op:2, delta_d4:8, cnt:6; } deltadata; - struct { unsigned op:7, cnt_m1:9; } run; - struct { unsigned op:7, idx:9; } glp; - struct { unsigned op:4, delta_m1:12; } delta; - struct { unsigned op:4, icnt_m1:4, rcnt_m1:8; } rpt; - struct { unsigned op:6, idx_top:10; } large1; - struct { unsigned op:6, cnt_m1:4, idx_top:6; } large2; - UInt16 instr; - UInt16 bot; -} Relocation; - -// opcode definitions which can be used with -// Relocation.opcode.op:7, if masked properly -// by the up coming table -// (NOTE: a half word of 0 is garunteed to be an unused relocation instruction) - -#define krDDAT 0x00 // type deltadata - -#define krCODE 0x20 // type run -#define krDATA 0x21 // type run -#define krDESC 0x22 // type run -#define krDSC2 0x23 // type run -#define krVTBL 0x24 // type run -#define krSYMR 0x25 // type run -// 0x26 -// 0x2F - -#define krSYMB 0x30 // type glp -#define krCDIS 0x31 // type glp -#define krDTIS 0x32 // type glp -#define krSECN 0x33 // type glp -// 0x34 -// 0x3F - -#define krDELT 0x40 // type delta -#define krRPT 0x48 // type rpt - -#define krLABS 0x50 // type large1 -#define krLSYM 0x52 // type large1 -// 0x54 -// 0x56 - -#define krLRPT 0x58 // type large2 -#define krLSEC 0x5A // type large2 -// 0x5C -// 0x5E - - // LSEC usage: - // LSEC 0, n -- Long SECN - // LSEC 1, n -- Long CDIS - // LSEC 2, n -- Long DTIS - // LSEC 3, n -- free - // LSEC 15, n -- free - -// constants that indicate the maximum sizes of fields -// (before packing, ie: subtracting one, in some cases) - -#define ksDELTA 4096 // delta max for DELTA from - -#define ksDDDMAX 1023 // delta max for DELTA-DAT (DDAT) form -#define ksDDRMAX 63 // run max for DELTA-DAT (DDAT) form - -#define ksCODE 512 // count max for CODE form -#define ksDATA 512 // count max for DATA form -#define ksDEMAX 512 // count max for DESC form -#define ksVTMAX 512 // count max for VTBL form -#define ksISMAX 512 // count max for IMPS form -#define ksRPTMAX 256 // count max for RPT form - -#define IsLARG(op) (((op) & 0x70) == 0x50) - -#define RELOPSHFT 9 - -#define ksDVDMAX 0 // (63) delta max for DELTA-VTBL (DVBL) form -#define ksDVRMAX 0 // (256) run max for DELTA-VTBL (DVBL) form - -#define krXXXX 0xff - - -/* - From: PEFBinaryFormat.i - Revision: 9 -*/ - -enum { - /* The packed data opcodes. */ - kPEFPkDataZero = 0, /* Zero fill "count" bytes. */ - kPEFPkDataBlock = 1, /* Block copy "count" bytes. */ - kPEFPkDataRepeat = 2, /* Repeat "count" bytes "count2"+1 times. */ - kPEFPkDataRepeatBlock = 3, /* Interleaved repeated and unique data. */ - kPEFPkDataRepeatZero = 4 /* Interleaved zero and unique data. */ -}; - - -enum { - kPEFPkDataOpcodeShift = 5, - kPEFPkDataCount5Mask = 0x1F, - kPEFPkDataMaxCount5 = 31, - kPEFPkDataVCountShift = 7, - kPEFPkDataVCountMask = 0x7F, - kPEFPkDataVCountEndMask = 0x80 -}; - -#define PEFPkDataOpcode(byte) ( ((UInt8)(byte)) >> kPEFPkDataOpcodeShift ) - -#define PEFPkDataCount5(byte) ( ((UInt8)(byte)) & kPEFPkDataCount5Mask ) - -#define PEFPkDataComposeInstr(opcode,count5) \ - ( (((UInt8)(opcode)) << kPEFPkDataOpcodeShift) | ((UInt8)(count5)) ) - - - - - -/* - File: CodeFragmentContainerPriv.h - - Contains: Physical container routines of the ModernOS version of CFM. - - Version: Maxwell - - DRI: Alan Lillich - - Copyright: © 1984-1996 by Apple Computer, Inc. - All rights reserved. - - BuildInfo: Built by: Simon Douglas - With Interfacer: 2.0d13 (PowerPC native) - From: CodeFragmentContainerPriv.i - Revision: 9 - Dated: 10/9/96 - Last change by: AWL - Last comment: Remove special SMP sharing, using prepare option instead. - - Bugs: Report bugs to Radar component Ã’System InterfacesÓ, Ã’LatestÓ - List the version information (from above) in the Problem Description. - -*/ -/* - ------------------------------------------------------------------------------------------- - This file contains what used to be called the CFLoader interface. The name was changed to - fit the newer convention of having CodeFragment as a common prefix, and to reduce pervasive - confusion between the Code Fragment Manager and the Code Fragment Loaders, promulgated by - the long history of the Segment Loader. This file defines the abstract interface to the - physical representation of code fragments. - !!! This version has minimal comments, the main purpose is to get things compiled. -*/ - - -/* - ¤ - =========================================================================================== - General Types and Constants - =========================== -*/ -typedef SInt32 CFContSignedIndex; -typedef UInt32 CFContStringHash; -#define CFContStringHashLength(hashValue) ((hashValue) >> 16) -struct CFContHashedName { - CFContStringHash nameHash; /* ! Includes the name length.*/ - BytePtr nameText; -}; -typedef struct CFContHashedName CFContHashedName; - -/* - ------------------------------------------ - Declarations for code fragment containers. -*/ - -enum { - kCFContContainerInfoVersion = 0x00010001 -}; - -struct CFContContainerInfo { - CFContHashedName cfragName; - UInt32 modDate; /* !!! Abstract type?*/ - OSType architecture; - CFragVersionNumber currentVersion; - CFragVersionNumber oldImpVersion; - CFragVersionNumber oldDefVersion; - UInt32 reservedA; - void * reservedB; -}; -typedef struct CFContContainerInfo CFContContainerInfo; - -/* - ---------------------------------------- - Declarations for code fragment sections. -*/ -struct CFContLogicalLocation { - CFContSignedIndex section; /* "Real" sections use zero based indices, special ones are negative.*/ - ByteCount offset; -}; -typedef struct CFContLogicalLocation CFContLogicalLocation; - - -enum { - kCFContNoSectionIndex = -1, - kCFContAbsoluteSectionIndex = -2, - kCFContReexportSectionIndex = -3 -}; - -typedef UInt8 CFContSectionSharing; - -enum { - kCFContShareSectionInClosure = 0, /* ! Not supported at present!*/ - kCFContShareSectionInProcess = 1, - kCFContShareSectionAcrossSystem = 4, - kCFContShareSectionWithProtection = 5 -}; - -typedef UInt8 CFContMemoryAccess; - -enum { - kCFContMemReadMask = 0x01, /* Readable memory can also be executed.*/ - kCFContMemWriteMask = 0x02, - kCFContMemExecuteMask = 0x04, /* ! Affects cache actions, not protection!*/ - kCFContReadOnlyData = kCFContMemReadMask, - kCFContWriteableData = kCFContMemReadMask | kCFContMemWriteMask, - kCFContNormalCode = kCFContMemReadMask | kCFContMemExecuteMask, - kCFContExcludedMemory = 0 -}; - -typedef UInt32 CFContSectionOptions; - -enum { - /* Values for CFContSectionOptions.*/ - kPackedCFContSectionMask = 0x01, /* Stored contents are compressed.*/ - kRelocatedCFContSectionMask = 0x02, /* Section contents have relocations.*/ - kEmptyFillCFContSectionMask = 0x04, /* The extension part may be left untouched.*/ - kResidentCFContSectionMask = 0x08, - kPrefaultCFContSectionMask = 0x10 -}; - - -enum { - kCFContSectionInfoVersion = 0x00010001 -}; - -struct CFContSectionInfo { - CFContHashedName sectionName; - CFContMemoryAccess access; - CFContSectionSharing sharing; - UInt8 alignment; /* ! The power of 2, a.k.a. number of low order zero bits.*/ - UInt8 reservedA; - CFContSectionOptions options; - ByteCount containerOffset; - ByteCount containerLength; - ByteCount unpackedLength; - ByteCount totalLength; - LogicalAddress defaultAddress; - UInt32 reservedB; - void * reservedC; -}; -typedef struct CFContSectionInfo CFContSectionInfo; - -/* - ---------------------------------- - Declarations for exported symbols. -*/ -typedef UInt32 CFContExportedSymbolOptions; -/* - ! enum { // Values for CFContExportedSymbolOptions. - ! // ! No options at present. - ! }; -*/ - -enum { - kCFContExportedSymbolInfoVersion = 0x00010001 -}; - -struct CFContExportedSymbolInfo { - CFContHashedName symbolName; - CFContLogicalLocation location; - CFContExportedSymbolOptions options; - CFragSymbolClass symbolClass; - UInt8 reservedA; - UInt16 reservedB; - UInt32 reservedC; - void * reservedD; -}; -typedef struct CFContExportedSymbolInfo CFContExportedSymbolInfo; - -/* - ------------------------------------------------ - Declarations for imported libraries and symbols. -*/ -typedef UInt32 CFContImportedLibraryOptions; - -enum { - /* Values for CFContImportedLibraryOptions.*/ - kCFContWeakLibraryMask = 0x01, /* ! Same as kCFContWeakSymbolMask to reduce errors.*/ - kCFContInitBeforeMask = 0x02, - kCFContDeferredBindMask = 0x04 -}; - - -enum { - kCFContImportedLibraryInfoVersion = 0x00010001 -}; - -struct CFContImportedLibraryInfo { - CFContHashedName libraryName; - CFragVersionNumber linkedVersion; - CFragVersionNumber oldImpVersion; - CFContImportedLibraryOptions options; -}; -typedef struct CFContImportedLibraryInfo CFContImportedLibraryInfo; - -typedef UInt32 CFContImportedSymbolOptions; - -enum { - /* Values for CFContImportedSymbolOptions.*/ - kCFContWeakSymbolMask = 0x01 /* ! Same as kCFContWeakLibraryMask to reduce errors.*/ -}; - - -enum { - kCFContImportedSymbolInfoVersion = 0x00010001 -}; - -struct CFContImportedSymbolInfo { - CFContHashedName symbolName; - ItemCount libraryIndex; - CFContImportedSymbolOptions options; - CFragSymbolClass symbolClass; - UInt8 reservedA; - UInt16 reservedB; - UInt32 reservedC; - void * reservedD; -}; -typedef struct CFContImportedSymbolInfo CFContImportedSymbolInfo; - -/* - ------------------------------------------------- - Declarations for dealing with container handlers. -*/ -typedef UInt32 CFContOpenOptions; - -enum { - /* Values for CFContOpenOptions.*/ - kCFContPrepareInPlaceMask = 0x01, - kCFContMinimalOpenMask = 0x02 -}; - -typedef UInt32 CFContCloseOptions; - -enum { - /* Values for CFContCloseOptions.*/ - kCFContPartialCloseMask = 0x01 -}; - -typedef struct OpaqueCFContHandlerRef* CFContHandlerRef; -typedef struct CFContHandlerProcs CFContHandlerProcs; -typedef CFContHandlerProcs *CFContHandlerProcsPtr; -typedef LogicalAddress (*CFContAllocateMem)(ByteCount size); -typedef void (*CFContReleaseMem)(LogicalAddress address); -/* - ¤ - =========================================================================================== - Container Handler Routines - ========================== -*/ -typedef OSStatus (*CFCont_OpenContainer)(LogicalAddress mappedAddress, LogicalAddress runningAddress, ByteCount containerLength, KernelProcessID runningProcessID, const CFContHashedName *cfragName, CFContOpenOptions options, CFContAllocateMem Allocate, CFContReleaseMem Release, CFContHandlerRef *containerRef, CFContHandlerProcsPtr *handlerProcs); -typedef OSStatus (*CFCont_CloseContainer)(CFContHandlerRef containerRef, CFContCloseOptions options); -typedef OSStatus (*CFCont_GetContainerInfo)(CFContHandlerRef containerRef, PBVersion infoVersion, CFContContainerInfo *containerInfo); -/* -------------------------------------------------------------------------------------------*/ -typedef OSStatus (*CFCont_GetSectionCount)(CFContHandlerRef containerRef, ItemCount *sectionCount); -typedef OSStatus (*CFCont_GetSectionInfo)(CFContHandlerRef containerRef, ItemCount sectionIndex, PBVersion infoVersion, CFContSectionInfo *sectionInfo); -typedef OSStatus (*CFCont_FindSectionInfo)(CFContHandlerRef containerRef, const CFContHashedName *sectionName, PBVersion infoVersion, ItemCount *sectionIndex, CFContSectionInfo *sectionInfo); -typedef OSStatus (*CFCont_SetSectionAddress)(CFContHandlerRef containerRef, ItemCount sectionIndex, LogicalAddress mappedAddress, LogicalAddress runningAddress); -/* -------------------------------------------------------------------------------------------*/ -typedef OSStatus (*CFCont_GetAnonymousSymbolLocations)(CFContHandlerRef containerRef, CFContLogicalLocation *mainLocation, CFContLogicalLocation *initLocation, CFContLogicalLocation *termLocation); -/* -------------------------------------------------------------------------------------------*/ -typedef OSStatus (*CFCont_GetExportedSymbolCount)(CFContHandlerRef containerRef, ItemCount *exportCount); -typedef OSStatus (*CFCont_GetExportedSymbolInfo)(CFContHandlerRef containerRef, CFContSignedIndex exportedIndex, PBVersion infoVersion, CFContExportedSymbolInfo *exportInfo); -typedef OSStatus (*CFCont_FindExportedSymbolInfo)(CFContHandlerRef containerRef, const CFContHashedName *exportName, PBVersion infoVersion, ItemCount *exportIndex, CFContExportedSymbolInfo *exportInfo); -/* -------------------------------------------------------------------------------------------*/ -typedef OSStatus (*CFCont_GetImportCounts)(CFContHandlerRef containerRef, ItemCount *libraryCount, ItemCount *symbolCount); -typedef OSStatus (*CFCont_GetImportedLibraryInfo)(CFContHandlerRef containerRef, ItemCount libraryIndex, PBVersion infoVersion, CFContImportedLibraryInfo *libraryInfo); -typedef OSStatus (*CFCont_GetImportedSymbolInfo)(CFContHandlerRef containerRef, ItemCount symbolIndex, PBVersion infoVersion, CFContImportedSymbolInfo *symbolInfo); -typedef OSStatus (*CFCont_SetImportedSymbolAddress)(CFContHandlerRef containerRef, ItemCount symbolIndex, LogicalAddress symbolAddress); -/* -------------------------------------------------------------------------------------------*/ -typedef OSStatus (*CFCont_UnpackSection)(CFContHandlerRef containerRef, ItemCount sectionIndex, ByteCount sectionOffset, LogicalAddress bufferAddress, ByteCount bufferLength); -typedef OSStatus (*CFCont_RelocateSection)(CFContHandlerRef containerRef, ItemCount sectionIndex); -typedef OSStatus (*CFCont_RelocateImportsOnly)(CFContHandlerRef containerRef, ItemCount sectionIndex, ItemCount libraryIndex); -typedef OSStatus (*CFCont_MakeSectionExecutable)(CFContHandlerRef containerRef, ItemCount sectionIndex); -typedef OSStatus (*CFCont_AllocateSection)(CFContHandlerRef containerRef, ItemCount sectionIndex, LogicalAddress *mappedAddress, LogicalAddress *runningAddress); -typedef OSStatus (*CFCont_ReleaseSection)(CFContHandlerRef containerRef, ItemCount sectionIndex); -/* -------------------------------------------------------------------------------------------*/ - -#if 0 -struct CFContHandlerInfo { - OrderedItemName orderedName; - OrderRequirements orderedReq; - CFCont_OpenContainer OpenHandler; -}; -typedef struct CFContHandlerInfo CFContHandlerInfo; -#endif - -struct CFContHandlerProcs { - ItemCount procCount; - CFragShortVersionPair abiVersion; - - CFCont_OpenContainer OpenContainer; /* 1*/ - CFCont_CloseContainer CloseContainer; /* 2*/ - CFCont_GetContainerInfo GetContainerInfo; /* 3*/ - - CFCont_GetSectionCount GetSectionCount; /* 4*/ - CFCont_GetSectionInfo GetSectionInfo; /* 5*/ - CFCont_FindSectionInfo FindSectionInfo; /* 6*/ - CFCont_SetSectionAddress SetSectionAddress; /* 7*/ - - CFCont_GetAnonymousSymbolLocations GetAnonymousSymbolLocations; /* 8*/ - - CFCont_GetExportedSymbolCount GetExportedSymbolCount; /* 9*/ - CFCont_GetExportedSymbolInfo GetExportedSymbolInfo; /* 10*/ - CFCont_FindExportedSymbolInfo FindExportedSymbolInfo; /* 11*/ - - CFCont_GetImportCounts GetImportCounts; /* 12*/ - CFCont_GetImportedLibraryInfo GetImportedLibraryInfo; /* 13*/ - CFCont_GetImportedSymbolInfo GetImportedSymbolInfo; /* 14*/ - CFCont_SetImportedSymbolAddress SetImportedSymbolAddress; /* 15*/ - - CFCont_UnpackSection UnpackSection; /* 16*/ - CFCont_RelocateSection RelocateSection; /* 17*/ - CFCont_RelocateImportsOnly RelocateImportsOnly; /* 18*/ - CFCont_MakeSectionExecutable MakeSectionExecutable; /* 19 (Opt.)*/ - CFCont_AllocateSection AllocateSection; /* 20 (Opt.)*/ - CFCont_ReleaseSection ReleaseSection; /* 21 (Opt.)*/ -}; - - -enum { - kCFContMinimumProcCount = 18, - kCFContCurrentProcCount = 21, - kCFContHandlerABIVersion = 0x00010001 -}; - -/* - ----------------------------------------------------------------------------------------- - The ABI version is a pair of UInt16s used as simple counters. The high order part is the - current version number, the low order part is the oldest compatible definition version. - number. This pair is to be used by the specific container handlers to describe what - version of the container handler ABI they support. - 0x00010001 - ---------- - The initial release of this ABI. (The old CFLoader ABI does not count.) - ¤ - =========================================================================================== - General Routines - ================ -*/ -extern CFContStringHash CFContHashName(BytePtr nameText, ByteCount nameLength); - -#if 0 - -/* -------------------------------------------------------------------------------------------*/ -extern OSStatus CFContOpenContainer(LogicalAddress mappedAddress, LogicalAddress runningAddress, ByteCount containerLength, KernelProcessID runningProcessID, const CFContHashedName *cfragName, CFContOpenOptions options, CFContAllocateMem Allocate, CFContReleaseMem Release, CFContHandlerRef *containerRef, CFContHandlerProcsPtr *handlerProcs); - -/* -------------------------------------------------------------------------------------------*/ -extern OSStatus CFContRegisterContainerHandler(const OrderedItemName *orderedName, const OrderRequirements *orderedReq, CFCont_OpenContainer OpenHandler, OrderedItemName *rejectingHandler); - -extern OSStatus CFContUnregisterContainerHandler(const OrderedItemName *orderedName); - -extern OSStatus CFContGetContainerHandlers(ItemCount requestedCount, ItemCount *totalCount, CFContHandlerInfo *handlers); - -/* -------------------------------------------------------------------------------------------*/ -#endif - - - - - - -/* - File: PEFLoader.h - - Contains: PEF Loader Interface. - - Version: Maxwell - - Copyright: © 1992-1996 by Apple Computer, Inc., all rights reserved. - - File Ownership: - - DRI: Alan Lillich - - Other Contact: <<unknown>> - - Technology: Core Runtime - - Writers: - - (AWL) Alan Lillich - (ELE) Erik Eidt - - Change History (most recent first): - - <7> 8/23/96 AWL (1379028) Propagate changes from CodeFragmentContainerPriv. - <6> 2/28/96 AWL Adapt for new container handler model. - <5> 6/20/94 AWL Move private PEF loader info struct here to be visible to the - booting "wacky" PEF loader. - <4> 6/8/94 AWL Make all CFL routines visible for direct use in special cases - such as booting. - <3> 5/16/94 AWL Fix typo. - <2> 2/25/94 AWL Update for Q&D solution to loading across address spaces. - <1> 2/15/94 AWL Initial checkin for kernel based CFM. -*/ - -// =========================================================================================== - -enum { - kBuiltinSectionArraySize = 4 -}; - -struct PEFPrivateInfo { // !!! Clean up field names, collapse Booleans, etc. - CFContAllocateMem Allocate; - CFContReleaseMem Release; - BytePtr mappedContainer; - BytePtr runningContainer; - ItemCount sectionCount; // Just the instantiated sections. - SectionHeader * sections; - BytePtr stringTable; - ItemCount ldrSectionNo; - LoaderHeader * ldrHeader; - BytePtr ldrStringTable; - LoaderRelExpHeader * ldrSections; - LoaderImportFileID * ldrImportFiles; - LoaderImport * ldrImportSymbols; - HashSlotEntry * ldrHashSlot; - HashChainEntry * ldrHashChain; - LoaderExport * ldrExportSymbols; - BytePtr ldrRelocations; - BytePtr * mappedOrigins; // Mapped base address for each section. - ByteCount * runningOffsets; // Running offset from presumed address. - BytePtr * imports; - BytePtr originArray [kBuiltinSectionArraySize]; // ! Only used if big enough. - ByteCount offsetArray [kBuiltinSectionArraySize]; // ! Only used if big enough. - Boolean loadInPlace; - Boolean resolved; -}; - -typedef struct PEFPrivateInfo PEFPrivateInfo; - - -// =========================================================================================== - - -extern OSStatus PEF_OpenContainer ( LogicalAddress mappedAddress, - LogicalAddress runningAddress, - ByteCount containerLength, - KernelProcessID runningProcessID, - const CFContHashedName * cfragName, - CFContOpenOptions options, - CFContAllocateMem Allocate, - CFContReleaseMem Release, - CFContHandlerRef * containerRef_o, - CFContHandlerProcs * * handlerProcs_o ); - -extern OSStatus PEF_CloseContainer ( CFContHandlerRef containerRef, - CFContCloseOptions options ); - -extern OSStatus PEF_GetContainerInfo ( CFContHandlerRef containerRef, - PBVersion infoVersion, - CFContContainerInfo * containerInfo ); - -// ------------------------------------------------------------------------------------------- - -extern OSStatus PEF_GetSectionCount ( CFContHandlerRef containerRef, - ItemCount * sectionCount ); - -extern OSStatus PEF_GetSectionInfo ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - PBVersion infoVersion, - CFContSectionInfo * sectionInfo ); - -extern OSStatus PEF_FindSectionInfo ( CFContHandlerRef containerRef, - const CFContHashedName * sectionName, - PBVersion infoVersion, - ItemCount * sectionIndex, // May be null. - CFContSectionInfo * sectionInfo ); // May be null. - -extern OSStatus PEF_SetSectionAddress ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - LogicalAddress mappedAddress, - LogicalAddress runningAddress ); - -// ------------------------------------------------------------------------------------------- - -extern OSStatus PEF_GetAnonymousSymbolLocations ( CFContHandlerRef containerRef, - CFContLogicalLocation * mainLocation, // May be null. - CFContLogicalLocation * initLocation, // May be null. - CFContLogicalLocation * termLocation ); // May be null. - -// ------------------------------------------------------------------------------------------- - -extern OSStatus PEF_GetExportedSymbolCount ( CFContHandlerRef containerRef, - ItemCount * exportCount ); - -extern OSStatus PEF_GetExportedSymbolInfo ( CFContHandlerRef containerRef, - CFContSignedIndex exportIndex, - PBVersion infoVersion, - CFContExportedSymbolInfo * exportInfo ); - -extern OSStatus PEF_FindExportedSymbolInfo ( CFContHandlerRef containerRef, - const CFContHashedName * exportName, - PBVersion infoVersion, - ItemCount * exportIndex, // May be null. - CFContExportedSymbolInfo * exportInfo ); // May be null. - -// ------------------------------------------------------------------------------------------- - -extern OSStatus PEF_GetImportCounts ( CFContHandlerRef containerRef, - ItemCount * libraryCount, // May be null. - ItemCount * symbolCount ); // May be null. - -extern OSStatus PEF_GetImportedLibraryInfo ( CFContHandlerRef containerRef, - ItemCount libraryIndex, - PBVersion infoVersion, - CFContImportedLibraryInfo * libraryInfo ); - -extern OSStatus PEF_GetImportedSymbolInfo ( CFContHandlerRef containerRef, - ItemCount symbolIndex, - PBVersion infoVersion, - CFContImportedSymbolInfo * symbolInfo ); - -extern OSStatus PEF_SetImportedSymbolAddress ( CFContHandlerRef containerRef, - ItemCount symbolIndex, - LogicalAddress symbolAddress ); - -// ------------------------------------------------------------------------------------------- - -extern OSStatus PEF_UnpackSection ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - ByteCount sectionOffset, - LogicalAddress bufferAddress, - ByteCount bufferLength ); - -extern OSStatus PEF_RelocateSection ( CFContHandlerRef containerRef, - ItemCount sectionIndex ); - -extern OSStatus PEF_RelocateImportsOnly ( CFContHandlerRef containerRef, - ItemCount sectionIndex, - ItemCount libraryIndex ); - -struct CFragInitBlock { - void * contextID; - void * closureID; - void * connectionID; - SInt32 where; // locator rec - LogicalAddress address; - ByteCount length; - Boolean inPlace; - UInt8 resvA; - UInt16 resvB; - char * libName; - UInt32 resvC; -}; -typedef struct CFragInitBlock CFragInitBlock; - -#pragma options align=reset - -#endif // __IOPEFINTERNALS__ - diff --git a/iokit/Families/IONDRVSupport/IOPEFLoader.c b/iokit/Families/IONDRVSupport/IOPEFLoader.c deleted file mode 100644 index 27e50ba4a..000000000 --- a/iokit/Families/IONDRVSupport/IOPEFLoader.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * From pieces of ProtoCFM, Alan Lillich. - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - */ - - -#include <IOKit/IOLib.h> -#include <IOKit/ndrvsupport/IONDRVSupport.h> - -#include "IOPEFLibraries.h" -#include "IOPEFLoader.h" -#include "IOPEFInternals.h" - - - -#define LOG if(0) IOLog -#define INFO if(0) IOLog - -struct SectionVars { - LogicalAddress address; - ByteCount allocSize; - ByteCount unpackedLength; - Boolean isPacked; -}; -typedef struct SectionVars SectionVars; - -struct InstanceVars { - BytePtr pef; // container in memory - CFContHandlerRef cRef; - CFContHandlerProcs * cProcs; - ItemCount numSections; - SectionVars * sections; - IONDRVUndefinedSymbolHandler undefinedHandler; - void * undefHandlerSelf; -}; -typedef struct InstanceVars InstanceVars; - - -static OSStatus LocationToAddress( InstanceVars * inst, - CFContLogicalLocation * location, LogicalAddress * address ); -static OSStatus SatisfyImports( InstanceVars * inst ); -static OSStatus Instantiate( InstanceVars * inst ); - - -#define PCFM_BlockCopy(src,dst,len) memcpy(dst,src,len) -#define PCFM_BlockClear(dst,len) memset(dst,0,len) -#define PCFM_MakeExecutable(addr,len) flush_dcache((vm_offset_t)addr, len, 0); \ - invalidate_icache((vm_offset_t)addr, len, 0) - -extern OSStatus CallTVector( - void * p1, void * p2, void * p3, void * p4, void * p5, void * p6, - LogicalAddress entry ); - -// ¤ -// =========================================================================================== -// CFContHashName () -// ================= - - -CFContStringHash CFContHashName ( BytePtr nameText, - ByteCount nameLength ) -{ - BytePtr currChar = nameText; - SInt32 hashValue = 0; // ! Signed to match old published PEF algorithm. - ByteCount length = 0; - ByteCount limit; - CFContStringHash result; - - #define PseudoRotate(x) ( ( (x) << 1 ) - ( (x) >> (16) ) ) - - - for ( limit = nameLength; limit > 0; limit -= 1 ) { - if ( *currChar == NULL ) break; - hashValue = (PseudoRotate ( hashValue )) ^ *currChar; - currChar += 1; - length += 1; - } - - result = (length << 16) | ((UInt16) ((hashValue ^ (hashValue >> 16)) & 0xFFFF)); - - return result; - - -} // CFContHashName () - - -// ¤ -// =========================================================================================== -// PCFM_CompareBytes () -// ==================== - - -Boolean PCFM_CompareBytes ( const Byte * left, - const Byte * right, - ByteCount count ) -{ - // !!! Blechola! Switch to a standard routine ASAP! - - UInt32 * wLeft; - UInt32 * wRight; - UInt8 * bLeft; - UInt8 * bRight; - - ByteCount leftMiss = (UInt32)left & 0x00000003; - ByteCount rightMiss = (UInt32)right & 0x00000003; - - - bLeft = (UInt8 *) left; - bRight = (UInt8 *) right; - - if ( (leftMiss != 0) && (rightMiss != 0) ) { - ByteCount align = leftMiss; - if ( align > count ) align = count; - while ( align > 0 ) { - if ( *bLeft++ != *bRight++ ) goto NoMatch; - align -= 1; - count -= 1; - } - } - - wLeft = (UInt32 *) bLeft; - wRight = (UInt32 *) bRight; - while ( count >= 4 ) { - if ( *wLeft++ != *wRight++ ) goto NoMatch; - count -= 4; - } - - bLeft = (UInt8 *) wLeft; - bRight = (UInt8 *) wRight; - while ( count > 0 ) { - if ( *bLeft++ != *bRight++ ) goto NoMatch; - count -= 1; - } - - return true; - - -NoMatch: - return false; - - -} // PCFM_CompareBytes () - -// =========================================================================================== - -LogicalAddress PCodeAllocateMem( ByteCount size ); -void PCodeReleaseMem( LogicalAddress address ); -extern void *kern_os_malloc(size_t size); -extern void kern_os_free(void * addr); - -LogicalAddress -PCodeAllocateMem( ByteCount size ) -{ - return( (LogicalAddress) kern_os_malloc( (size_t) size )); -} - -void -PCodeReleaseMem( LogicalAddress address ) -{ - kern_os_free( (void *) address ); -} - -// =========================================================================================== - -OSStatus -PCodeOpen( LogicalAddress container, ByteCount containerSize, PCodeInstance * instance ) -{ - OSStatus err; - InstanceVars * inst; - - inst = PCodeAllocateMem( sizeof( InstanceVars)); - *instance = inst; - - inst->pef = (BytePtr) container; - // procID, name, options - err = PEF_OpenContainer( container, container, containerSize, 0, 0, 0, - PCodeAllocateMem, PCodeReleaseMem, - &inst->cRef, &inst->cProcs ); - if( err) LOG( "PEF_OpenContainer = %ld\n", err ); - - return( err); -} - -OSStatus -PCodeInstantiate( PCodeInstance instance, - IONDRVUndefinedSymbolHandler handler, void * self ) -{ - OSStatus err; - InstanceVars * inst = instance; - CFContLogicalLocation initLocation; - LogicalAddress tv; - CFragInitBlock initInfo; - - inst->undefinedHandler = handler; - inst->undefHandlerSelf = self; - - do { - err = Instantiate( inst ); - if( err) - continue; - - // call INIT - err = PEF_GetAnonymousSymbolLocations( inst->cRef, NULL, &initLocation, NULL ); - if( err) - continue; - err = LocationToAddress( inst, &initLocation, &tv ); - if( err || (tv == NULL) ) - continue; - bzero( &initInfo, sizeof( initInfo)); - err = CallTVector( &initInfo, 0, 0, 0, 0, 0, tv ); - - } while( false); - - return( err); -} - - -OSStatus -PCodeClose( PCodeInstance instance ) -{ - OSStatus err; - InstanceVars * inst = instance; - SectionVars * section; - int i; - - if( !inst) - return( noErr); - - err = PEF_CloseContainer( inst->cRef, 0 ); - if( err) LOG( "PEF_CloseContainer = %ld\n", err ); - - if( inst->sections ) { - for( i = 0; i < inst->numSections; i++) { - section = inst->sections + i; - if( section->allocSize) - PCodeReleaseMem( section->address); - } - PCodeReleaseMem(inst->sections); - } - - return( err); -} - -OSStatus -PCodeFindExport( PCodeInstance instance, const char * symbolName, LogicalAddress * address, CFragSymbolClass * symbolClass ) -{ - CFContExportedSymbolInfo symInfo; - CFContHashedName hashName; - OSStatus err; - InstanceVars * inst = instance; - - hashName.nameHash = CFContHashName( (UInt8 *) symbolName, strlen( symbolName) ); - hashName.nameText = (UInt8 *) symbolName; - - err = PEF_FindExportedSymbolInfo( inst->cRef, &hashName, - kCFContExportedSymbolInfoVersion, (void *) 0, &symInfo ); - if( err) { - LOG( "PEF_FindExportedSymbolInfo = %ld\n", err ); - return( err); - } - - if( address); - err = LocationToAddress( inst, &symInfo.location, address ); - if( symbolClass) - *symbolClass = symInfo.symbolClass; - - return( err); -} - -OSStatus -PCodeFindMain( PCodeInstance instance, LogicalAddress * mainAddress ) -{ - InstanceVars * inst = instance; - CFContLogicalLocation mainLocation; - OSStatus err; - - err = PEF_GetAnonymousSymbolLocations( inst->cRef, &mainLocation, NULL, NULL ); - - if( err == noErr) - err = LocationToAddress( inst, &mainLocation, mainAddress ); - - return( err); -} - - - -// =========================================================================================== - -static OSStatus -LocationToAddress( InstanceVars * inst, CFContLogicalLocation * location, - LogicalAddress * address ) -{ - BytePtr sectionBase; - OSStatus err = noErr; - - if ( location->section >= 0 ) { - sectionBase = (BytePtr) (inst->sections + location->section)->address; - *address = (LogicalAddress) (sectionBase + location->offset); - - } else if ( location->section == kCFContAbsoluteSectionIndex ) { - *address = (LogicalAddress) location->offset; - - } else if ( location->section == kCFContNoSectionIndex ) { - *address = (LogicalAddress) kUnresolvedCFragSymbolAddress; - - } else - err = cfragFragmentFormatErr; - - return( err); -} - - -static OSStatus -Instantiate( InstanceVars * inst ) -{ - CFContHandlerRef cRef; - ItemCount numSects, sectionIndex; - CFContSectionInfo sectionInfo; - CFContSectionInfo * section; - OSStatus err; - - cRef = inst->cRef; - - err = PEF_GetSectionCount( cRef, &numSects ); - if( err) LOG( "PEF_GetSectionCount = %ld\n", err ); - INFO( "Num sects = %ld\n", numSects ); - - inst->numSections = numSects; - inst->sections = PCodeAllocateMem( numSects * sizeof( SectionVars )); - - for( sectionIndex = 0; sectionIndex < numSects; sectionIndex++ ) - { - Boolean isPacked, isMappable; - Boolean needAlloc, needCopy, needClear; - LogicalAddress sectionAddress; - SectionVars * sectionVars; - - sectionVars = inst->sections + sectionIndex; - section = §ionInfo; - - err = PEF_GetSectionInfo( cRef, sectionIndex, kCFContSectionInfoVersion, section ); - if( err) LOG( "PEF_GetSectionInfo = %ld\n", err ); - -#if 0 - if ( sectionInfo.sharing == kCFContShareSectionInClosure ) goto SectionSharingError; - if ( (! (sectionInfo.access & kCFContMemWriteMask)) && - (sectionInfo.options & kRelocatedCFContSectionMask) ) goto SectionOptionsError; -#endif - - isPacked = ((section->options & kPackedCFContSectionMask) != 0); - isMappable = (! isPacked) && - (! (section->options & kRelocatedCFContSectionMask)) && - (! (section->access & kCFContMemWriteMask)); - - if ( ! isMappable ) { - // ---------------------------------------------------------------------------------- - // Mappable really means "fully expanded in container", so sections that are not mappable - // need to be allocated. The loader will do the initialization copying. This is the - // standard case for packed PEF data sections. - needAlloc = true; - needCopy = (! isPacked); - needClear = (section->totalLength != section->unpackedLength); - - } else if ( ! (section->access & kCFContMemWriteMask) ) { - // ----------------------------------------------------------------------------------- - // A "mappable" read only section. Make sure it is fully present, i.e. no zero filled - // extension. This is the standard case for code and literal sections. - if ( section->totalLength != section->unpackedLength ) { - err = cfragFragmentUsageErr; // !!! Needs error label & message. -// goto ERROR; - } - needAlloc = false; - needCopy = false; - needClear = false; - - } else { - // ----------------------------------------------------------------------------------- - // A "mappable", writeable, don't use in place section. This is the standard case for - // unpacked data sections. - needAlloc = true; - needCopy = true; - needClear = (section->totalLength != section->unpackedLength); - } - - if ( needAlloc ) { - // *** Should honor the container's alignment specifications. - sectionAddress = PCodeAllocateMem( section->totalLength ); //, 4, allocMode ); - } else { - sectionAddress = inst->pef + section->containerOffset; - } - - // -------------------------------------------------------------------------------------- - // !!! The copy/clear code should be moved to the loader as part of the split of the - // !!! unpack/relocate operations. It isn't clear at this point if both the read and - // !!! write sides should be touched. What if the write side pushes out pages brought in - // !!! by the read side? We should also have better advice to say all bytes are changed. - - if ( needCopy ) { - BytePtr source = inst->pef + section->containerOffset; - BytePtr dest = sectionAddress; - ByteCount length = section->unpackedLength; - - PCFM_BlockCopy ( source, dest, length ); - } - - if ( needClear ) { - BytePtr dest = (BytePtr) sectionAddress + section->unpackedLength; - ByteCount length = section->totalLength - section->unpackedLength; - - PCFM_BlockClear ( dest, length ); - } - - // ------------------------------------------------------------------------------------- - // If CFM was responsible for bringing the container into memory then we have to get the - // I&D caches in sync for the (read-only & use-in-place) code sections. - - if ( (section->access & kCFContMemExecuteMask) - && (! (section->access & kCFContMemWriteMask)) && isMappable ) { - PCFM_MakeExecutable ( sectionAddress, section->unpackedLength ); - } - - err = PEF_SetSectionAddress( cRef, sectionIndex, sectionAddress, sectionAddress ); - if( err) LOG( "PEF_SetSectionAddress = %ld\n", err ); - - sectionVars->address = sectionAddress; - sectionVars->unpackedLength = section->unpackedLength; - sectionVars->isPacked = isPacked; - if( needAlloc) - sectionVars->allocSize = section->totalLength; - else - sectionVars->allocSize = 0; - } - - // ------------------------------------------------------------------------------------- - - err = SatisfyImports( inst ); - if( err) LOG( "SatisfyImports = %ld\n", err ); - - // ------------------------------------------------------------------------------------- - - for( sectionIndex = 0; sectionIndex < numSects; sectionIndex++ ) - { - SectionVars * sectionVars; - - sectionVars = inst->sections + sectionIndex; - - INFO("Section[%ld] ", sectionIndex ); - - if ( sectionVars->isPacked ) { - INFO("unpacking..."); - err = PEF_UnpackSection( cRef, - sectionIndex, - 0, // Unpack the whole section. - sectionVars->address, - sectionVars->unpackedLength ); - if( err) LOG( "PEF_UnpackSection = %ld\n", err ); - } - - INFO("reloc..."); - err = PEF_RelocateSection( cRef, sectionIndex ); - - INFO(" address = 0x%08lx\n", (UInt32) sectionVars->address ); - } - - if( err) LOG( "Instantiate = %ld\n", err ); - - return( err); -} - -struct StubFunction { - LogicalAddress pc; - LogicalAddress toc; - char name[64]; -}; -typedef struct StubFunction StubFunction; - -OSStatus IONDRVUnimplementedVector( UInt32 p1, UInt32 p2, UInt32 p3, UInt32 p4 ) -{ - char * name = (char *) get_R2(); - - LOG("-*- %s : %lx, %lx, %lx, %lx\n", name, p1, p2, p3, p4); - - set_R2( (UInt32) name); - - return( -53); -} - -static OSStatus -SatisfyImports( InstanceVars * inst ) -{ - CFContImportedSymbolInfo symInfo; - - OSStatus err = 0; - CFContHandlerRef cRef; - ItemCount numLibs, numSyms, index, i; - struct CFLibInfo { - CFContImportedLibraryInfo info; - LibraryEntry * found; - }; - struct CFLibInfo * libInfo; - struct CFLibInfo * curLib; - FunctionEntry * funcs; - const IOTVector * symAddr; - StubFunction * stub; - - cRef = inst->cRef; - err = PEF_GetImportCounts( cRef, &numLibs, &numSyms ); - if( err) LOG( "PEF_GetImportCounts = %ld\n", err ); - - libInfo = PCodeAllocateMem( numLibs * sizeof( struct CFLibInfo)); - PCFM_BlockClear( libInfo, numLibs * sizeof( struct CFLibInfo)); - - for( index = 0; index < numLibs; index++ ) - { - curLib = libInfo + index; - err = PEF_GetImportedLibraryInfo( cRef, index, kCFContImportedLibraryInfoVersion, &curLib->info); - if( err) LOG( "PEF_GetImportCounts = %ld\n", err ); - - for( i = 0; i < IONumNDRVLibraries; i++ ) { - if( strcmp( (char *) curLib->info.libraryName.nameText, - IONDRVLibraries[ i ].name) == 0) { - curLib->found = &IONDRVLibraries[ i ]; - break; - } - } - } - - for( index = 0; index < numSyms; index++ ) - { - err = PEF_GetImportedSymbolInfo( cRef, index, kCFContImportedSymbolInfoVersion, &symInfo ); - if( err) LOG( "PEF_GetImportedSymbolInfo = %ld\n", err ); - - curLib = libInfo + symInfo.libraryIndex; - - symAddr = NULL; - if( curLib->found) { - for( i = 0; i < curLib->found->numSyms; i++ ) { - - funcs = curLib->found->functions + i; - if( strcmp( (char *) symInfo.symbolName.nameText, funcs->name ) == 0) { - symAddr = (IOTVector *) &funcs->address; - break; - } - } - - } else if( inst->undefinedHandler) - symAddr = (*inst->undefinedHandler)(inst->undefHandlerSelf, - curLib->info.libraryName.nameText, - symInfo.symbolName.nameText ); - if( symAddr == NULL) { - - LOG("Undefined %s:%s ", curLib->info.libraryName.nameText, symInfo.symbolName.nameText ); - - stub = IOMalloc( sizeof( StubFunction)); - symAddr = (IOTVector *) &stub->pc; - stub->pc = IONDRVUnimplementedVector; - stub->toc = &stub->name[0]; - strncpy( stub->name, symInfo.symbolName.nameText, 60); - } - - err = PEF_SetImportedSymbolAddress( cRef, index, (IOTVector *) symAddr ); - if( err) LOG( "PEF_SetImportedSymbolAddress = %ld\n", err ); - } - - PCodeReleaseMem( libInfo); - - return( err); -} - - - - diff --git a/iokit/Families/IONDRVSupport/IOPEFLoader.h b/iokit/Families/IONDRVSupport/IOPEFLoader.h deleted file mode 100644 index b08704e09..000000000 --- a/iokit/Families/IONDRVSupport/IOPEFLoader.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - * sdouglas 21 July 98 - start IOKit - */ - - -#ifndef _IOKIT_IOPEFLOADER_H -#define _IOKIT_IOPEFLOADER_H - - -#include <IOKit/ndrvsupport/IOMacOSTypes.h> -#include <IOKit/ndrvsupport/IONDRVSupport.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -enum { - cfragFirstErrCode = -2800, /* The first value in the range of CFM errors.*/ - cfragContextIDErr = -2800, /* The context ID was not valid.*/ - cfragConnectionIDErr = -2801, /* The connection ID was not valid.*/ - cfragNoSymbolErr = -2802, /* The specified symbol was not found.*/ - cfragNoSectionErr = -2803, /* The specified section was not found.*/ - cfragNoLibraryErr = -2804, /* The named library was not found.*/ - cfragDupRegistrationErr = -2805, /* The registration name was already in use.*/ - cfragFragmentFormatErr = -2806, /* A fragment's container format is unknown.*/ - cfragUnresolvedErr = -2807, /* A fragment had "hard" unresolved imports.*/ - cfragNoPositionErr = -2808, /* The registration insertion point was not found.*/ - cfragNoPrivateMemErr = -2809, /* Out of memory for internal bookkeeping.*/ - cfragNoClientMemErr = -2810, /* Out of memory for fragment mapping or section instances.*/ - cfragNoIDsErr = -2811, /* No more CFM IDs for contexts, connections, etc.*/ - cfragInitOrderErr = -2812, /* */ - cfragImportTooOldErr = -2813, /* An import library was too old for a client.*/ - cfragImportTooNewErr = -2814, /* An import library was too new for a client.*/ - cfragInitLoopErr = -2815, /* Circularity in required initialization order.*/ - cfragInitAtBootErr = -2816, /* A boot library has an initialization function. (System 7 only)*/ - cfragLibConnErr = -2817, /* */ - cfragCFMStartupErr = -2818, /* Internal error during CFM initialization.*/ - cfragCFMInternalErr = -2819, /* An internal inconstistancy has been detected.*/ - cfragFragmentCorruptErr = -2820, /* A fragment's container was corrupt (known format).*/ - cfragInitFunctionErr = -2821, /* A fragment's initialization routine returned an error.*/ - cfragNoApplicationErr = -2822, /* No application member found in the cfrg resource.*/ - cfragArchitectureErr = -2823, /* A fragment has an unacceptable architecture.*/ - cfragFragmentUsageErr = -2824, /* A semantic error in usage of the fragment.*/ - cfragFileSizeErr = -2825, /* A file was too large to be mapped.*/ - cfragNotClosureErr = -2826, /* The closure ID was actually a connection ID.*/ - cfragNoRegistrationErr = -2827, /* The registration name was not found.*/ - cfragContainerIDErr = -2828, /* The fragment container ID was not valid.*/ - cfragClosureIDErr = -2829, /* The closure ID was not valid.*/ - cfragAbortClosureErr = -2830 /* Used by notification handlers to abort a closure.*/ -}; - -enum { - paramErr = -50, - unimpErr = -4 -}; - - -typedef UInt32 CFragVersionNumber; -enum { - kNullCFragVersion = 0, - kWildcardCFragVersion = 0xFFFFFFFF -}; - -typedef UInt8 CFragSymbolClass; -enum { - kCodeCFragSymbol = 0, - kDataCFragSymbol = 1, - kTVectorCFragSymbol = 2, - kTOCCFragSymbol = 3, - kGlueCFragSymbol = 4 -}; - -enum { - kUnresolvedCFragSymbolAddress = 0 -}; - -typedef UInt32 CFragShortVersionPair; -#define ComposeCFragShortVersionPair(current,older) (current << 16 | older) -#define GetCFragShortVersionCurrent(version) (version >> 16) -#define GetCFragShortVersionOlder(version) (version & 0xFFFF) - - -enum { - kMainCFragSymbolIndex = -1, - kInitCFragSymbolIndex = -2, - kTermCFragSymbolIndex = -3 -}; - -typedef void * PCodeInstance; - -OSStatus -PCodeOpen( LogicalAddress container, ByteCount containerSize, PCodeInstance * instance ); -OSStatus -PCodeClose( PCodeInstance instance ); -OSStatus -PCodeInstantiate( PCodeInstance instance, - IONDRVUndefinedSymbolHandler handler, void * self ); -OSStatus -PCodeFindExport( PCodeInstance instance, const char * symbolName, LogicalAddress * address, CFragSymbolClass * symbolClass ); -OSStatus -PCodeFindMain( PCodeInstance instance, LogicalAddress * mainAddress ); - -static __inline__ unsigned int get_R2(void) -{ - unsigned int result; - __asm__ volatile("mr %0, r2" : "=r" (result)); - return result; -} - -static __inline__ void set_R2(unsigned int val) -{ - __asm__ volatile("mr r2,%0" : : "r" (val)); - return; -} - -#ifdef __cplusplus -} -#endif - -#endif /* ! _IOKIT_IOPEFLOADER_H */ - diff --git a/iokit/Families/IONetworking/IOEthernetController.cpp b/iokit/Families/IONetworking/IOEthernetController.cpp deleted file mode 100644 index c664b67ca..000000000 --- a/iokit/Families/IONetworking/IOEthernetController.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOEthernetController.cpp - * - * Abstract Ethernet controller superclass. - * - * HISTORY - * - * Dec 3, 1998 jliu - C++ conversion. - */ - -#include <IOKit/assert.h> -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetInterface.h> - -extern "C" { -#include <sys/socket.h> -#include <net/if.h> -#include <net/etherdefs.h> -} - -//--------------------------------------------------------------------------- - -#define super IONetworkController - -OSDefineMetaClassAndAbstractStructors( IOEthernetController, IONetworkController) -OSMetaClassDefineReservedUnused( IOEthernetController, 0); -OSMetaClassDefineReservedUnused( IOEthernetController, 1); -OSMetaClassDefineReservedUnused( IOEthernetController, 2); -OSMetaClassDefineReservedUnused( IOEthernetController, 3); -OSMetaClassDefineReservedUnused( IOEthernetController, 4); -OSMetaClassDefineReservedUnused( IOEthernetController, 5); -OSMetaClassDefineReservedUnused( IOEthernetController, 6); -OSMetaClassDefineReservedUnused( IOEthernetController, 7); -OSMetaClassDefineReservedUnused( IOEthernetController, 8); -OSMetaClassDefineReservedUnused( IOEthernetController, 9); -OSMetaClassDefineReservedUnused( IOEthernetController, 10); -OSMetaClassDefineReservedUnused( IOEthernetController, 11); -OSMetaClassDefineReservedUnused( IOEthernetController, 12); -OSMetaClassDefineReservedUnused( IOEthernetController, 13); -OSMetaClassDefineReservedUnused( IOEthernetController, 14); -OSMetaClassDefineReservedUnused( IOEthernetController, 15); -OSMetaClassDefineReservedUnused( IOEthernetController, 16); -OSMetaClassDefineReservedUnused( IOEthernetController, 17); -OSMetaClassDefineReservedUnused( IOEthernetController, 18); -OSMetaClassDefineReservedUnused( IOEthernetController, 19); -OSMetaClassDefineReservedUnused( IOEthernetController, 20); -OSMetaClassDefineReservedUnused( IOEthernetController, 21); -OSMetaClassDefineReservedUnused( IOEthernetController, 22); -OSMetaClassDefineReservedUnused( IOEthernetController, 23); -OSMetaClassDefineReservedUnused( IOEthernetController, 24); -OSMetaClassDefineReservedUnused( IOEthernetController, 25); -OSMetaClassDefineReservedUnused( IOEthernetController, 26); -OSMetaClassDefineReservedUnused( IOEthernetController, 27); -OSMetaClassDefineReservedUnused( IOEthernetController, 28); -OSMetaClassDefineReservedUnused( IOEthernetController, 29); -OSMetaClassDefineReservedUnused( IOEthernetController, 30); -OSMetaClassDefineReservedUnused( IOEthernetController, 31); - -//------------------------------------------------------------------------- -// Macros - -#ifdef DEBUG -#define DLOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -//--------------------------------------------------------------------------- -// IOEthernetController class initializer. - -void IOEthernetController::initialize() -{ -} - -//--------------------------------------------------------------------------- -// Initialize an IOEthernetController instance. - -bool IOEthernetController::init(OSDictionary * properties) -{ - if (!super::init(properties)) - { - DLOG("IOEthernetController: super::init() failed\n"); - return false; - } - - return true; -} - -//--------------------------------------------------------------------------- -// Free the IOEthernetController instance. - -void IOEthernetController::free() -{ - // Any allocated resources should be released here. - - super::free(); -} - -//--------------------------------------------------------------------------- -// Publish Ethernet controller capabilites and properties. - -bool IOEthernetController::publishProperties() -{ - bool ret = false; - IOEthernetAddress addr; - OSDictionary * dict; - - do { - // Let the superclass publish properties first. - - if (super::publishProperties() == false) - break; - - // Publish the controller's Ethernet address. - - if ( (getHardwareAddress(&addr) != kIOReturnSuccess) || - (setProperty(kIOMACAddress, (void *) &addr, - kIOEthernetAddressSize) == false) ) - { - break; - } - - // Publish Ethernet defined packet filters. - - dict = OSDynamicCast(OSDictionary, getProperty(kIOPacketFilters)); - if ( dict ) - { - UInt32 filters; - OSNumber * num; - - if ( getPacketFilters(gIOEthernetWakeOnLANFilterGroup, - &filters) != kIOReturnSuccess ) - { - break; - } - - num = OSNumber::withNumber(filters, sizeof(filters) * 8); - if (num == 0) - break; - - ret = dict->setObject(gIOEthernetWakeOnLANFilterGroup, num); - num->release(); - } - } - while (false); - - return ret; -} - -//--------------------------------------------------------------------------- -// Set or change the station address used by the Ethernet controller. - -IOReturn -IOEthernetController::setHardwareAddress(const IOEthernetAddress * addr) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Enable or disable multicast mode. - -IOReturn IOEthernetController::setMulticastMode(bool active) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Enable or disable promiscuous mode. - -IOReturn IOEthernetController::setPromiscuousMode(bool active) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Enable or disable the wake on Magic Packet support. - -IOReturn IOEthernetController::setWakeOnMagicPacket(bool active) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Set the list of multicast addresses that the multicast filter should use -// to match against the destination address of an incoming frame. The frame -// should be accepted when a match occurs. - -IOReturn IOEthernetController::setMulticastList(IOEthernetAddress * /*addrs*/, - UInt32 /*count*/) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Allocate and return a new IOEthernetInterface instance. - -IONetworkInterface * IOEthernetController::createInterface() -{ - IOEthernetInterface * netif = new IOEthernetInterface; - - if ( netif && ( netif->init( this ) == false ) ) - { - netif->release(); - netif = 0; - } - return netif; -} - -//--------------------------------------------------------------------------- -// Returns all the packet filters supported by the Ethernet controller. -// This method will perform a bitwise OR of: -// -// kIOPacketFilterUnicast -// kIOPacketFilterBroadcast -// kIOPacketFilterMulticast -// kIOPacketFilterPromiscuous -// -// and write it to the argument provided if the group specified is -// gIONetworkFilterGroup, otherwise 0 is returned. Drivers that support -// a different set of filters should override this method. -// -// Returns kIOReturnSuccess. Drivers that override this method must return -// kIOReturnSuccess to indicate success, or an error code otherwise. - -IOReturn -IOEthernetController::getPacketFilters(const OSSymbol * group, - UInt32 * filters) const -{ - *filters = 0; - - if ( group == gIONetworkFilterGroup ) - { - return getPacketFilters(filters); - } - else - { - return kIOReturnSuccess; - } -} - -IOReturn IOEthernetController::getPacketFilters(UInt32 * filters) const -{ - *filters = ( kIOPacketFilterUnicast | - kIOPacketFilterBroadcast | - kIOPacketFilterMulticast | - kIOPacketFilterPromiscuous ); - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Enable a filter from the specified group. - -#define UCAST_BCAST_MASK \ - ( kIOPacketFilterUnicast | kIOPacketFilterBroadcast ) - -IOReturn IOEthernetController::enablePacketFilter( - const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0) -{ - IOReturn ret = kIOReturnUnsupported; - UInt32 newFilters = enabledFilters | aFilter; - - if ( group == gIONetworkFilterGroup ) - { - // The default action is to call setMulticastMode() or - // setPromiscuousMode() to handle multicast or promiscuous - // filter changes. - - if ( aFilter == kIOPacketFilterMulticast ) - { - ret = setMulticastMode(true); - } - else if ( aFilter == kIOPacketFilterPromiscuous ) - { - ret = setPromiscuousMode(true); - } - else if ( (newFilters ^ enabledFilters) & UCAST_BCAST_MASK ) - { - ret = kIOReturnSuccess; - } - } - else if ( group == gIOEthernetWakeOnLANFilterGroup ) - { - if ( aFilter == kIOEthernetWakeOnMagicPacket ) - { - ret = setWakeOnMagicPacket(true); - } - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Disable a filter from the specifed filter group. - -IOReturn IOEthernetController::disablePacketFilter( - const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0) -{ - IOReturn ret = kIOReturnUnsupported; - UInt32 newFilters = enabledFilters & ~aFilter; - - if ( group == gIONetworkFilterGroup ) - { - // The default action is to call setMulticastMode() or - // setPromiscuousMode() to handle multicast or promiscuous - // filter changes. - - if ( aFilter == kIOPacketFilterMulticast ) - { - ret = setMulticastMode(false); - } - else if ( aFilter == kIOPacketFilterPromiscuous ) - { - ret = setPromiscuousMode(false); - } - else if ( (newFilters ^ enabledFilters) & UCAST_BCAST_MASK ) - { - ret = kIOReturnSuccess; - } - } - else if ( group == gIOEthernetWakeOnLANFilterGroup ) - { - if ( aFilter == kIOEthernetWakeOnMagicPacket ) - { - ret = setWakeOnMagicPacket(false); - } - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Get the Ethernet controller's station address. -// Call the Ethernet specific (overloaded) form. - -IOReturn -IOEthernetController::getHardwareAddress(void * addr, - UInt32 * inOutAddrBytes) -{ - UInt32 bufBytes; - - if (inOutAddrBytes == 0) - return kIOReturnBadArgument; - - // Cache the size of the caller's buffer, and replace it with the - // number of bytes required. - - bufBytes = *inOutAddrBytes; - *inOutAddrBytes = kIOEthernetAddressSize; - - // Make sure the buffer is large enough for a single Ethernet - // hardware address. - - if ((addr == 0) || (bufBytes < kIOEthernetAddressSize)) - return kIOReturnNoSpace; - - return getHardwareAddress((IOEthernetAddress *) addr); -} - -//--------------------------------------------------------------------------- -// Set or change the station address used by the Ethernet controller. -// Call the Ethernet specific (overloaded) version of this method. - -IOReturn -IOEthernetController::setHardwareAddress(const void * addr, - UInt32 addrBytes) -{ - if ((addr == 0) || (addrBytes != kIOEthernetAddressSize)) - return kIOReturnBadArgument; - - return setHardwareAddress((const IOEthernetAddress *) addr); -} - -//--------------------------------------------------------------------------- -// Report the max/min packet sizes, including the frame header and FCS bytes. - -IOReturn IOEthernetController::getMaxPacketSize(UInt32 * maxSize) const -{ - *maxSize = kIOEthernetMaxPacketSize; - return kIOReturnSuccess; -} - -IOReturn IOEthernetController::getMinPacketSize(UInt32 * minSize) const -{ - *minSize = kIOEthernetMinPacketSize; - return kIOReturnSuccess; -} diff --git a/iokit/Families/IONetworking/IOEthernetInterface.cpp b/iokit/Families/IONetworking/IOEthernetInterface.cpp deleted file mode 100644 index 4b975a606..000000000 --- a/iokit/Families/IONetworking/IOEthernetInterface.cpp +++ /dev/null @@ -1,922 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOEthernetInterface.cpp - * - * HISTORY - * 8-Jan-1999 Joe Liu (jliu) created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <libkern/c++/OSData.h> -#include <IOKit/network/IOEthernetInterface.h> -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IONetworkUserClient.h> - -extern "C" { -#include <sys/param.h> -#include <sys/errno.h> -#include <sys/socket.h> -#include <net/if.h> -#include <net/etherdefs.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <sys/sockio.h> -#include <netinet/in_var.h> -#include <sys/malloc.h> -void arpwhohas(struct arpcom * ac, struct in_addr * addr); -} - -//--------------------------------------------------------------------------- - -#define super IONetworkInterface - -OSDefineMetaClassAndStructors( IOEthernetInterface, IONetworkInterface ) -OSMetaClassDefineReservedUnused( IOEthernetInterface, 0); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 1); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 2); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 3); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 4); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 5); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 6); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 7); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 8); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 9); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 10); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 11); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 12); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 13); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 14); -OSMetaClassDefineReservedUnused( IOEthernetInterface, 15); - -// The name prefix for all BSD Ethernet interfaces. -// -#define kIOEthernetInterfaceNamePrefix "en" - -//--------------------------------------------------------------------------- -// Macros - -#ifdef DEBUG -#define DLOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -UInt32 IOEthernetInterface::getFilters(const OSDictionary * dict, - const OSSymbol * group) -{ - OSNumber * num; - UInt32 filters = 0; - - assert( dict && group ); - - if (( num = (OSNumber *) dict->getObject(group) )) - { - filters = num->unsigned32BitValue(); - } - return filters; -} - -bool IOEthernetInterface::setFilters(OSDictionary * dict, - const OSSymbol * group, - UInt32 filters) -{ - OSNumber * num; - bool ret = false; - - assert( dict && group ); - - num = (OSNumber *) dict->getObject(group); - if ( num == 0 ) - { - if (( num = OSNumber::withNumber(filters, 32) )) - { - ret = dict->setObject(group, num); - num->release(); - } - } - else - { - num->setValue(filters); - ret = true; - } - return ret; -} - -#define GET_REQUIRED_FILTERS(g) getFilters(_requiredFilters, (g)) -#define GET_ACTIVE_FILTERS(g) getFilters(_activeFilters, (g)) -#define GET_SUPPORTED_FILTERS(g) getFilters(_supportedFilters, (g)) - -#define SET_REQUIRED_FILTERS(g, v) setFilters(_requiredFilters, (g), (v)) -#define SET_ACTIVE_FILTERS(g, v) setFilters(_activeFilters, (g), (v)) - -//--------------------------------------------------------------------------- -// Initialize an IOEthernetInterface instance. Instance variables are -// initialized, and an arpcom structure is allocated. - -bool IOEthernetInterface::init(IONetworkController * controller) -{ - // Allocate an arpcom structure, then call super::init(). - // We expect our superclass to call getIfnet() during its init() - // method, so arpcom must be allocated before calling super::init(). - - if ( (_arpcom = (struct arpcom *) IOMalloc(sizeof(*_arpcom))) == 0 ) - { - DLOG("IOEthernetInterface: arpcom allocation failed\n"); - return false; - } - - // Pass the init() call to our superclass. - - if ( super::init(controller) == false ) - return false; - - // Add an IONetworkData with room to hold an IOEthernetStats structure. - // This class does not reference the data object created, and no harm - // is done if the data object is released or replaced. - - IONetworkData * data = IONetworkData::withInternalBuffer( - kIOEthernetStatsKey, - sizeof(IOEthernetStats)); - if (data) - { - addNetworkData(data); - data->release(); - } - - // Create and initialize the filter dictionaries. - - _requiredFilters = OSDictionary::withCapacity(4); - _activeFilters = OSDictionary::withCapacity(4); - - if ( (_requiredFilters == 0) || (_activeFilters == 0) ) - return false; - - _supportedFilters = OSDynamicCast(OSDictionary, - controller->getProperty(kIOPacketFilters)); - if ( _supportedFilters == 0 ) return false; - _supportedFilters->retain(); - - // Controller's Unicast (directed) and Broadcast filters should always - // be enabled. Those bits should never be cleared. - - if ( !SET_REQUIRED_FILTERS( gIONetworkFilterGroup, - kIOPacketFilterUnicast | - kIOPacketFilterBroadcast ) - || !SET_REQUIRED_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) - || !SET_ACTIVE_FILTERS( gIONetworkFilterGroup, 0 ) - || !SET_ACTIVE_FILTERS( gIOEthernetWakeOnLANFilterGroup, 0 ) ) - { - return false; - } - - // Publish filter dictionaries to property table. - - setProperty( kIORequiredPacketFilters, _requiredFilters ); - setProperty( kIOActivePacketFilters, _activeFilters ); - - return true; -} - -//--------------------------------------------------------------------------- -// Initialize the given ifnet structure. The argument specified is a pointer -// to an ifnet structure obtained through getIfnet(). IOEthernetInterface -// will initialize this structure in a manner that is appropriate for most -// Ethernet interfaces, then call super::initIfnet() to allow the superclass -// to perform generic interface initialization. -// -// ifp: Pointer to the ifnet structure to be initialized. -// -// Returns true on success, false otherwise. - -bool IOEthernetInterface::initIfnet(struct ifnet * ifp) -{ - struct arpcom * ac = (struct arpcom *) ifp; - - assert(ac); - - lock(); - - bzero(ac, sizeof(*ac)); - - // Set defaults suitable for Ethernet interfaces. - - setInterfaceType( IFT_ETHER ); - setMaxTransferUnit( ETHERMTU ); - setMediaAddressLength( NUM_EN_ADDR_BYTES ); - setMediaHeaderLength( ETHERHDRSIZE ); - setFlags( IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS ); - - unlock(); - - return super::initIfnet(ifp); -} - -//--------------------------------------------------------------------------- -// Free the IOEthernetInterface instance. The memory allocated -// for the arpcom structure is released. - -void IOEthernetInterface::free() -{ - if ( _arpcom ) - { - IOFree(_arpcom, sizeof(*_arpcom)); - _arpcom = 0; - } - - if ( _requiredFilters ) - { - _requiredFilters->release(); - _requiredFilters = 0; - } - - if ( _activeFilters ) - { - _activeFilters->release(); - _activeFilters = 0; - } - - if ( _supportedFilters ) - { - _supportedFilters->release(); - _supportedFilters = 0; - } - - super::free(); -} - -//--------------------------------------------------------------------------- -// This method returns a pointer to an ifnet structure maintained -// by the family specific interface object. IOEthernetInterface -// allocates an arpcom structure in init(), and returns a pointer -// to that structure when this method is called. -// -// Returns a pointer to an ifnet structure. - -struct ifnet * IOEthernetInterface::getIfnet() const -{ - return (&(_arpcom->ac_if)); -} - -//--------------------------------------------------------------------------- -// The name of the interface advertised to the network layer -// is generated by concatenating the string returned by this method, -// and an unit number. -// -// Returns a pointer to a constant string "en". Thus Ethernet interfaces -// will be registered as en0, en1, etc. - -const char * IOEthernetInterface::getNamePrefix() const -{ - return kIOEthernetInterfaceNamePrefix; -} - -//--------------------------------------------------------------------------- -// Prepare the 'Ethernet' controller after it has been opened. This is called -// by IONetworkInterface after a controller has accepted an open from this -// interface. IOEthernetInterface uses this method to inspect the controller, -// and to cache certain controller properties, such as its hardware address. -// This method is called with the arbitration lock held. -// -// controller: The controller object that was opened. -// -// Returns true on success, false otherwise -// (which will cause the controller to be closed). - -bool IOEthernetInterface::controllerDidOpen(IONetworkController * ctr) -{ - bool ret = false; - OSData * addrData; - IOEthernetAddress * addr; - - do { - // Call the controllerDidOpen() in superclass first. - - if ( (ctr == 0) || (super::controllerDidOpen(ctr) == false) ) - break; - - // If the controller supports some form of multicast filtering, - // then set the ifnet IFF_MULTICAST flag. - - if ( GET_SUPPORTED_FILTERS(gIONetworkFilterGroup) & - (kIOPacketFilterMulticast | kIOPacketFilterMulticastAll) ) - { - setFlags(IFF_MULTICAST); - } - - // Get the controller's MAC/Ethernet address. - - addrData = OSDynamicCast(OSData, ctr->getProperty(kIOMACAddress)); - if ( (addrData == 0) || (addrData->getLength() != NUM_EN_ADDR_BYTES) ) - { - DLOG("%s: kIOMACAddress property access error (len %d)\n", - getName(), addrData ? addrData->getLength() : 0); - break; - } - - addr = (IOEthernetAddress *) addrData->getBytesNoCopy(); - -#if 1 // Print the address - IOLog("%s: Ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", - ctr->getName(), - addr->bytes[0], - addr->bytes[1], - addr->bytes[2], - addr->bytes[3], - addr->bytes[4], - addr->bytes[5]); -#endif - - // Copy the hardware address we obtained from the controller - // to the arpcom structure. - - bcopy(addr, _arpcom->ac_enaddr, NUM_EN_ADDR_BYTES); - - ret = true; - } - while (0); - - return ret; -} - -//--------------------------------------------------------------------------- -// When a close from our last client is received, the interface will -// close the controller. But before the controller is closed, this method -// will be called by our superclass to perform any final cleanup. This -// method is called with the arbitration lock held. -// -// IOEthernetInterface will ensure that the controller is disabled. -// -// controller: The currently opened controller object. - -void IOEthernetInterface::controllerWillClose(IONetworkController * ctr) -{ - super::controllerWillClose(ctr); -} - -//--------------------------------------------------------------------------- -// Handle ioctl commands originated from the network layer. -// Commands not handled by this method are passed to our superclass. -// -// Argument convention is: -// -// arg0 - (struct ifnet *) -// arg1 - (void *) -// -// The commands handled by IOEthernetInterface are: -// -// SIOCSIFADDR -// SIOCSIFFLAGS -// SIOCADDMULTI -// SIOCDELMULTI -// -// Returns an error code defined in errno.h (BSD). - -SInt32 IOEthernetInterface::performCommand( IONetworkController * ctr, - UInt32 cmd, - void * arg0, - void * arg1 ) -{ - SInt32 ret; - - assert( arg0 == _arpcom ); - - if ( ctr == 0 ) return EINVAL; - - switch ( cmd ) - { - case SIOCSIFFLAGS: - case SIOCADDMULTI: - case SIOCDELMULTI: - case SIOCSIFADDR: - - ret = (int) ctr->executeCommand( - this, /* client */ - (IONetworkController::Action) - &IOEthernetInterface::performGatedCommand, - this, /* target */ - ctr, /* param0 */ - (void *) cmd, /* param1 */ - arg0, /* param2 */ - arg1 ); /* param3 */ - break; - - default: - // Unknown command, let our superclass deal with it. - ret = super::performCommand(ctr, cmd, arg0, arg1); - break; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Handle an ioctl command on the controller's workloop context. - -int IOEthernetInterface::performGatedCommand(void * target, - void * arg1_ctr, - void * arg2_cmd, - void * arg3_0, - void * arg4_1) -{ - IOEthernetInterface * self = (IOEthernetInterface *) target; - IONetworkController * ctr = (IONetworkController *) arg1_ctr; - SInt ret = EOPNOTSUPP; - - // Refuse to perform controller I/O if the controller is in a - // low-power state that makes it "unusable". - - if ( self->_controllerLostPower ) return EPWROFF; - - self->lock(); - - switch ( (UInt32) arg2_cmd ) - { - case SIOCSIFADDR: - ret = self->syncSIOCSIFADDR(ctr); - break; - - case SIOCSIFFLAGS: - ret = self->syncSIOCSIFFLAGS(ctr); - break; - - case SIOCADDMULTI: - ret = self->syncSIOCADDMULTI(ctr); - break; - - case SIOCDELMULTI: - ret = self->syncSIOCDELMULTI(ctr); - break; - } - - self->unlock(); - - return ret; -} - -//--------------------------------------------------------------------------- -// enableController() is reponsible for calling the controller's enable() -// method and restoring the state of the controller. We assume that -// controllers can completely reset its state upon receiving a disable() -// method call. And when it is brought back up, the interface should -// assist in restoring the previous state of the Ethernet controller. - -IOReturn IOEthernetInterface::enableController(IONetworkController * ctr) -{ - IOReturn ret = kIOReturnSuccess; - bool enabled = false; - UInt32 filters; - - assert(ctr); - - do { - // Is controller already enabled? If so, exit and return success. - - if ( _ctrEnabled ) - break; - - // Send the controller an enable command. - - if ( (ret = ctr->enable((IOService *) this)) != kIOReturnSuccess ) - break; // unable to enable the controller. - - enabled = true; - - // Disable all Wake-On-LAN filters. - - filters = GET_ACTIVE_FILTERS(gIOEthernetWakeOnLANFilterGroup); - - for (UInt i = 0; i < (sizeof(filters) * 8); i++) - { - if ((1 << i) & filters) - { - disableFilter(ctr, gIOEthernetWakeOnLANFilterGroup, - (1 << i)); - } - } - - // Restore current filter selection. - - SET_ACTIVE_FILTERS(gIONetworkFilterGroup, 0); - filters = GET_REQUIRED_FILTERS(gIONetworkFilterGroup); - - for (UInt i = 0; i < (sizeof(filters) * 8); i++) - { - if ((1 << i) & filters) - { - if ( (ret = enableFilter(ctr, gIONetworkFilterGroup, - (1 << i))) - != kIOReturnSuccess ) - break; - } - } - if ( ret != kIOReturnSuccess ) - break; - - // Restore multicast filter settings. - - syncSIOCADDMULTI(ctr); - - _ctrEnabled = true; - - } while (false); - - // Disable the controller if a serious error has occurred after the - // controller has been enabled. - - if ( enabled && (ret != kIOReturnSuccess) ) - { - ctr->disable((IOService *) this); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Handles SIOCSIFFLAGS ioctl command for Ethernet interfaces. The network -// stack has changed the if_flags field in ifnet. Our job is to go -// through if_flags and see what has changed, and act accordingly. -// -// The fact that if_flags contains both generic and Ethernet specific bits -// means that we cannot move some of the default flag processing to the -// superclass. - -int IOEthernetInterface::syncSIOCSIFFLAGS(IONetworkController * ctr) -{ - UInt16 flags = getFlags(); - IOReturn ret = kIOReturnSuccess; - - if ( ( ((flags & IFF_UP) == 0) || _controllerLostPower ) && - ( flags & IFF_RUNNING ) ) - { - // If interface is marked down and it is currently running, - // then stop it. - - ctr->disable((IOService *) this); - flags &= ~IFF_RUNNING; - _ctrEnabled = false; - } - else if ( ( flags & IFF_UP ) && - ( _controllerLostPower == false ) && - ((flags & IFF_RUNNING) == 0) ) - { - // If interface is marked up and it is currently stopped, - // then start it. - - if ( (ret = enableController(ctr)) == kIOReturnSuccess ) - flags |= IFF_RUNNING; - } - - if ( flags & IFF_RUNNING ) - { - IOReturn rc; - - // We don't expect multiple flags to be changed for a given - // SIOCSIFFLAGS call. - - // Promiscuous mode - - rc = (flags & IFF_PROMISC) ? - enableFilter(ctr, gIONetworkFilterGroup, - kIOPacketFilterPromiscuous) : - disableFilter(ctr, gIONetworkFilterGroup, - kIOPacketFilterPromiscuous); - - if (ret == kIOReturnSuccess) ret = rc; - - // Multicast-All mode - - rc = (flags & IFF_ALLMULTI) ? - enableFilter(ctr, gIONetworkFilterGroup, - kIOPacketFilterMulticastAll) : - disableFilter(ctr, gIONetworkFilterGroup, - kIOPacketFilterMulticastAll); - - if (ret == kIOReturnSuccess) ret = rc; - } - - // Update the flags field to pick up any modifications. Also update the - // property table to reflect any flag changes. - - setFlags(flags, ~flags); - - return errnoFromReturn(ret); -} - -//--------------------------------------------------------------------------- -// Handles SIOCSIFADDR ioctl. - -SInt IOEthernetInterface::syncSIOCSIFADDR(IONetworkController * ctr) -{ - IOReturn ret = kIOReturnSuccess; - - // Interface is implicitly brought up by an SIOCSIFADDR ioctl. - - setFlags(IFF_UP); - - if ( (getFlags() & IFF_RUNNING) == 0 ) - { - if ( (ret = enableController(ctr)) == kIOReturnSuccess ) - setFlags(IFF_RUNNING); - } - - return errnoFromReturn(ret); -} - -//--------------------------------------------------------------------------- -// Handle SIOCADDMULTI ioctl command. - -SInt IOEthernetInterface::syncSIOCADDMULTI(IONetworkController * ctr) -{ - IOReturn ret; - - // Make sure multicast filter is active. - - ret = enableFilter(ctr, gIONetworkFilterGroup, kIOPacketFilterMulticast); - - if ( ret == kIOReturnSuccess ) - { - // Load multicast addresses only if the filter was activated. - - ret = setupMulticastFilter(ctr); - - // If the list is now empty, then deactivate the multicast filter. - - if ( _mcAddrCount == 0 ) - { - IOReturn dret = disableFilter(ctr, gIONetworkFilterGroup, - kIOPacketFilterMulticast); - - if (ret == kIOReturnSuccess) ret = dret; - } - } - - return errnoFromReturn(ret); -} - -//--------------------------------------------------------------------------- -// Handle SIOCDELMULTI ioctl command. - -SInt IOEthernetInterface::syncSIOCDELMULTI(IONetworkController * ctr) -{ - return syncSIOCADDMULTI(ctr); -} - -//--------------------------------------------------------------------------- -// Enable a packet filter. - -IOReturn -IOEthernetInterface::enableFilter(IONetworkController * ctr, - const OSSymbol * group, - UInt32 filter, - IOOptionBits options = 0) -{ - IOReturn ret; - UInt32 reqFilters; - UInt32 actFilters; - - // If the controller does not support the packet filter, - // there's no need to proceed. - - if (( GET_SUPPORTED_FILTERS(group) & filter ) == 0) - return kIOReturnUnsupported; - - do { - // Add specified filter to the set of required filters. - - reqFilters = GET_REQUIRED_FILTERS(group) | filter; - SET_REQUIRED_FILTERS(group, reqFilters); - - // Abort if no changes are needed. - - ret = kIOReturnSuccess; - - actFilters = GET_ACTIVE_FILTERS(group); - - if ( (( actFilters ^ reqFilters ) & filter) == 0 ) - break; - - // Send a command to the controller driver. - - ret = ctr->enablePacketFilter(group, filter, actFilters, options); - - if ( ret == kIOReturnSuccess ) - { - SET_ACTIVE_FILTERS(group, actFilters | filter); - } - } - while (false); - - return ret; -} - -//--------------------------------------------------------------------------- -// Disable a packet filter. - -IOReturn -IOEthernetInterface::disableFilter(IONetworkController * ctr, - const OSSymbol * group, - UInt32 filter, - IOOptionBits options = 0) -{ - IOReturn ret; - UInt32 reqFilters; - UInt32 actFilters; - - do { - // Remove specified filter from the set of required filters. - - reqFilters = GET_REQUIRED_FILTERS(group) & ~filter; - SET_REQUIRED_FILTERS(group, reqFilters); - - // Abort if no changes are needed. - - ret = kIOReturnSuccess; - - actFilters = GET_ACTIVE_FILTERS(group); - - if ( (( actFilters ^ reqFilters ) & filter) == 0 ) - break; - - // Send a command to the controller driver. - - ret = ctr->disablePacketFilter(group, filter, actFilters, options); - - if ( ret == kIOReturnSuccess ) - { - SET_ACTIVE_FILTERS(group, actFilters & ~filter); - } - } - while (false); - - return ret; -} - -//--------------------------------------------------------------------------- -// Cache the list of multicast addresses and send a command to the -// controller to update the multicast list. - -IOReturn -IOEthernetInterface::setupMulticastFilter(IONetworkController * ctr) -{ - void * multiAddrs = 0; - UInt mcount; - OSData * mcData = 0; - struct ifnet * ifp = (struct ifnet *) _arpcom; - struct ifmultiaddr * ifma; - IOReturn ret = kIOReturnSuccess; - bool ok; - - assert(ifp); - - // Update the multicast addresses count ivar. - - mcount = 0; - for (ifma = ifp->if_multiaddrs.lh_first; - ifma != NULL; - ifma = ifma->ifma_link.le_next) - { - if ((ifma->ifma_addr->sa_family == AF_UNSPEC) || - (ifma->ifma_addr->sa_family == AF_LINK)) - mcount++; - } - _mcAddrCount = mcount; - - if ( mcount ) - { - char * addrp; - - mcData = OSData::withCapacity(mcount * NUM_EN_ADDR_BYTES); - if (!mcData) - { - DLOG("%s: no memory for multicast address list\n", getName()); - return kIOReturnNoMemory; - } - - // Loop through the linked multicast structures and write the - // address to the OSData. - - for (ifma = ifp->if_multiaddrs.lh_first; - ifma != NULL; - ifma = ifma->ifma_link.le_next) - { - if (ifma->ifma_addr->sa_family == AF_UNSPEC) - addrp = &ifma->ifma_addr->sa_data[0]; - else - if (ifma->ifma_addr->sa_family == AF_LINK) - addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); - else - continue; - - ok = mcData->appendBytes((const void *) addrp, NUM_EN_ADDR_BYTES); - assert(ok); - } - - multiAddrs = (void *) mcData->getBytesNoCopy(); - assert(multiAddrs); - } - - // Issue a controller command to setup the multicast filter. - - ret = ((IOEthernetController *)ctr)->setMulticastList( - (IOEthernetAddress *) multiAddrs, - mcount); - if (mcData) - { - if (ret == kIOReturnSuccess) - setProperty(kIOMulticastAddressList, mcData); - - mcData->release(); - } - else { - removeProperty(kIOMulticastAddressList); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Power management support. -// -// Handlers called, with the controller's gate closed, in response to a -// controller power state change. - -IOReturn -IOEthernetInterface::controllerWillChangePowerState( - IONetworkController * ctr, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - if ( ( (flags & IOPMDeviceUsable ) == 0) && - ( _controllerLostPower == false ) ) - { - _controllerLostPower = true; - - // Enable Magic Packet if supported. - - if ( GET_SUPPORTED_FILTERS(gIOEthernetWakeOnLANFilterGroup) & - kIOEthernetWakeOnMagicPacket ) - { - enableFilter(ctr, gIOEthernetWakeOnLANFilterGroup, - kIOEthernetWakeOnMagicPacket); - } - - // Set _controllerLostPower, then call the SIOCSIFFLAGS handler to - // disable the controller, then mark the interface as Not Running. - - syncSIOCSIFFLAGS(ctr); - } - - return super::controllerWillChangePowerState( ctr, flags, - stateNumber, - policyMaker ); -} - -IOReturn -IOEthernetInterface::controllerDidChangePowerState( - IONetworkController * ctr, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - IOReturn ret = super::controllerDidChangePowerState( ctr, flags, - stateNumber, - policyMaker ); - - if ( ( flags & IOPMDeviceUsable ) && ( _controllerLostPower == true ) ) - { - _controllerLostPower = false; - - // Clear _controllerLostPower, then call the SIOCSIFFLAGS handler to - // perhaps enable the controller, restore all Ethernet controller - // state, then mark the interface as Running. - - syncSIOCSIFFLAGS(ctr); - } - - return ret; -} diff --git a/iokit/Families/IONetworking/IOKernelDebugger.cpp b/iokit/Families/IONetworking/IOKernelDebugger.cpp deleted file mode 100644 index daa450d8f..000000000 --- a/iokit/Families/IONetworking/IOKernelDebugger.cpp +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOKernelDebugger.cpp - * - * HISTORY - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOMessage.h> -#include <IOKit/IOLocks.h> -#include <IOKit/network/IONetworkController.h> -#include <IOKit/network/IOKernelDebugger.h> -#include <libkern/OSAtomic.h> - -//--------------------------------------------------------------------------- -// IOKDP - -#define kIOKDPEnableKDP "IOEnableKDP" -#define kIOKDPDriverMatch "IODriverMatch" -#define kIOKDPDriverNubMatch "IODriverNubMatch" - -class IOKDP : public IOService -{ - OSDeclareDefaultStructors( IOKDP ) - -public: - static void initialize(); - - virtual bool start( IOService * provider ); - - virtual void stop( IOService * provider ); - - virtual bool matchProvider( IOService * provider ); - - virtual bool matchServiceWithDictionary( IOService * service, - OSDictionary * match ); - - virtual IOReturn message( UInt32 type, - IOService * provider, - void * argument = 0 ); -}; - -//--------------------------------------------------------------------------- -// IOKDP defined globals. - -static IOLock * gIOKDPLock = 0; -static IOKDP * gIOKDP = 0; - -#define super IOService -OSDefineMetaClassAndStructorsWithInit( IOKDP, IOService, - IOKDP::initialize() ) - -//--------------------------------------------------------------------------- -// Match the provider with the matching dictionary in our property table. - -bool IOKDP::matchProvider(IOService * provider) -{ - IOService * driver = 0; - IOService * driverNub = 0; - OSBoolean * aBool; - - if ( provider ) driver = provider->getProvider(); - if ( driver ) driverNub = driver->getProvider(); - - if ( (driver == 0) || (driverNub == 0) ) - return false; - - if ( ( aBool = OSDynamicCast(OSBoolean, getProperty(kIOKDPEnableKDP)) ) && - ( aBool->isTrue() == false ) ) - return false; - - if ( matchServiceWithDictionary( driver, (OSDictionary *) - getProperty(kIOKDPDriverMatch)) ) - { - // IOLog("IOKDP: %s\n", kIOKDPDriverMatch); - return true; - } - - if ( matchServiceWithDictionary( driverNub, (OSDictionary *) - getProperty(kIOKDPDriverNubMatch)) ) - { - // IOLog("IOKDP: %s\n", kIOKDPDriverNubMatch); - return true; - } - - return false; -} - -//--------------------------------------------------------------------------- -// Match an IOService with a matching dictionary. - -bool IOKDP::matchServiceWithDictionary(IOService * service, - OSDictionary * match) -{ - OSCollectionIterator * matchIter; - OSCollectionIterator * arrayIter = 0; - OSCollection * array; - OSObject * objM; - OSObject * objP; - OSSymbol * sym; - bool isMatch = false; - - if ( ( OSDynamicCast(OSDictionary, match) == 0 ) || - ( match->getCount() == 0 ) || - ( (matchIter = OSCollectionIterator::withCollection(match)) == 0 ) ) - return false; - - while ( ( sym = OSDynamicCast(OSSymbol, matchIter->getNextObject()) ) ) - { - objM = match->getObject(sym); - objP = service->getProperty(sym); - - isMatch = false; - - if ( arrayIter ) - { - arrayIter->release(); - arrayIter = 0; - } - - if ( (array = OSDynamicCast( OSCollection, objM )) ) - { - arrayIter = OSCollectionIterator::withCollection( array ); - if ( arrayIter == 0 ) break; - } - - do { - if ( arrayIter && ((objM = arrayIter->getNextObject()) == 0) ) - break; - - if ( objM && objP && objM->isEqualTo(objP) ) - { - isMatch = true; - break; - } - } - while ( arrayIter ); - - if ( isMatch == false ) break; - } - - if ( arrayIter ) arrayIter->release(); - matchIter->release(); - - return isMatch; -} - -//--------------------------------------------------------------------------- -// IOKDP class initializer. - -void IOKDP::initialize() -{ - gIOKDPLock = IOLockAlloc(); - assert( gIOKDPLock ); -} - -//--------------------------------------------------------------------------- -// start/stop/message. - -bool IOKDP::start( IOService * provider ) -{ - bool ret = false; - - if ( super::start(provider) == false ) - return false; - - IOLockLock( gIOKDPLock ); - - do { - if ( gIOKDP ) - break; - - if ( matchProvider(provider) == false ) - break; - - if ( provider->open(this) == false ) - break; - - publishResource("kdp"); - - gIOKDP = this; - ret = true; - } - while ( false ); - - IOLockUnlock( gIOKDPLock ); - - return ret; -} - -void IOKDP::stop( IOService * provider ) -{ - provider->close(this); - - IOLockLock( gIOKDPLock ); - - if ( gIOKDP == this ) gIOKDP = 0; - - IOLockUnlock( gIOKDPLock ); - - super::stop(provider); -} - -IOReturn IOKDP::message( UInt32 type, - IOService * provider, - void * argument ) -{ - if ( type == kIOMessageServiceIsTerminated ) - { - provider->close(this); - } - return kIOReturnSuccess; -} - - -//--------------------------------------------------------------------------- -// IOKernelDebugger - -extern "C" { -// -// Defined in osfmk/kdp/kdp_en_debugger.h, but the header file is not -// exported, thus the definition is replicated here. -// -typedef void (*kdp_send_t)( void * pkt, UInt pkt_len ); -typedef void (*kdp_receive_t)( void * pkt, UInt * pkt_len, UInt timeout ); -void kdp_register_send_receive( kdp_send_t send, kdp_receive_t receive ); -} - -#undef super -#define super IOService -OSDefineMetaClassAndStructors( IOKernelDebugger, IOService ) -OSMetaClassDefineReservedUnused( IOKernelDebugger, 0); -OSMetaClassDefineReservedUnused( IOKernelDebugger, 1); -OSMetaClassDefineReservedUnused( IOKernelDebugger, 2); -OSMetaClassDefineReservedUnused( IOKernelDebugger, 3); - -// IOKernelDebugger global variables. -// -IOService * gIODebuggerDevice = 0; -IODebuggerTxHandler gIODebuggerTxHandler = 0; -IODebuggerRxHandler gIODebuggerRxHandler = 0; -UInt32 gIODebuggerTxBytes = 0; -UInt32 gIODebuggerRxBytes = 0; -SInt32 gIODebuggerSemaphore = 0; -UInt32 gIODebuggerFlag = 0; - -// Global debugger flags. -// -enum { - kIODebuggerFlagRegistered = 0x01, - kIODebuggerFlagWarnNullHandler = 0x02 -}; - -//--------------------------------------------------------------------------- -// The KDP receive dispatch function. Dispatches KDP receive requests to the -// registered receive handler. This function is registered with KDP via -// kdp_register_send_receive(). - -void IOKernelDebugger::kdpReceiveDispatcher( void * buffer, - UInt32 * length, - UInt32 timeout ) -{ - *length = 0; // return a zero length field by default. - - if ( gIODebuggerSemaphore ) return; // FIXME - Driver is busy! - - (*gIODebuggerRxHandler)( gIODebuggerDevice, buffer, length, timeout ); - - gIODebuggerRxBytes += *length; -} - -//--------------------------------------------------------------------------- -// The KDP transmit dispatch function. Dispatches KDP receive requests to the -// registered transmit handler. This function is registered with KDP via -// kdp_register_send_receive(). - -void IOKernelDebugger::kdpTransmitDispatcher( void * buffer, UInt32 length ) -{ - if ( gIODebuggerSemaphore ) return; // FIXME - Driver is busy! - - (*gIODebuggerTxHandler)( gIODebuggerDevice, buffer, length ); - - gIODebuggerTxBytes += length; -} - -//--------------------------------------------------------------------------- -// Null debugger handlers. - -void IOKernelDebugger::nullTxHandler( IOService * target, - void * buffer, - UInt32 length ) -{ -} - -void IOKernelDebugger::nullRxHandler( IOService * target, - void * buffer, - UInt32 * length, - UInt32 timeout ) -{ - if ( gIODebuggerFlag & kIODebuggerFlagWarnNullHandler ) - { - IOLog("IOKernelDebugger::%s no debugger device\n", __FUNCTION__); - gIODebuggerFlag &= ~kIODebuggerFlagWarnNullHandler; - } -} - -//--------------------------------------------------------------------------- -// Take the debugger lock conditionally. - -IODebuggerLockState IOKernelDebugger::lock( IOService * object ) -{ - if ( gIODebuggerDevice == object ) - { - OSIncrementAtomic( &gIODebuggerSemaphore ); - return kIODebuggerLockTaken; - } - return (IODebuggerLockState) 0; -} - -//--------------------------------------------------------------------------- -// Release the debugger lock if the kIODebuggerLockTaken flag is set. - -void IOKernelDebugger::unlock( IODebuggerLockState state ) -{ - if ( state & kIODebuggerLockTaken ) - OSDecrementAtomic( &gIODebuggerSemaphore ); -} - -//--------------------------------------------------------------------------- -// Initialize an IOKernelDebugger instance. - -bool IOKernelDebugger::init( IOService * target, - IODebuggerTxHandler txHandler, - IODebuggerRxHandler rxHandler ) -{ - if ( ( super::init() == false ) || - ( OSDynamicCast(IOService, target) == 0 ) || - ( txHandler == 0 ) || - ( rxHandler == 0 ) ) - { - return false; - } - - // Cache the target and handlers provided. - - _target = target; - _txHandler = txHandler; - _rxHandler = rxHandler; - - return true; -} - -//--------------------------------------------------------------------------- -// Factory method which performs allocation and initialization of an -// IOKernelDebugger instance. - -IOKernelDebugger * IOKernelDebugger::debugger( IOService * target, - IODebuggerTxHandler txHandler, - IODebuggerRxHandler rxHandler ) -{ - IOKernelDebugger * debugger = new IOKernelDebugger; - - if (debugger && (debugger->init( target, txHandler, rxHandler ) == false)) - { - debugger->release(); - debugger = 0; - } - - return debugger; -} - -//--------------------------------------------------------------------------- -// Register the debugger handlers. - -void IOKernelDebugger::registerHandler( IOService * target, - IODebuggerTxHandler txHandler, - IODebuggerRxHandler rxHandler ) -{ - bool doRegister; - - assert( ( target == gIODebuggerDevice ) || - ( target == 0 ) || - ( gIODebuggerDevice == 0 ) ); - - doRegister = ( target && ( txHandler != 0 ) && ( rxHandler != 0 ) ); - - if ( txHandler == 0 ) txHandler = &IOKernelDebugger::nullTxHandler; - if ( rxHandler == 0 ) rxHandler = &IOKernelDebugger::nullRxHandler; - - OSIncrementAtomic( &gIODebuggerSemaphore ); - - gIODebuggerDevice = target; - gIODebuggerTxHandler = txHandler; - gIODebuggerRxHandler = rxHandler; - gIODebuggerFlag |= kIODebuggerFlagWarnNullHandler; - - OSDecrementAtomic( &gIODebuggerSemaphore ); - - if ( doRegister && (( gIODebuggerFlag & kIODebuggerFlagRegistered ) == 0) ) - { - // Register dispatch function, these in turn will call the - // handlers when the debugger is active. - // - // Note: The following call may trigger an immediate break - // to the debugger. - - kdp_register_send_receive( (kdp_send_t) kdpTransmitDispatcher, - (kdp_receive_t) kdpReceiveDispatcher ); - - // Limit ourself to a single real KDP registration. - - gIODebuggerFlag |= kIODebuggerFlagRegistered; - } -} - -//--------------------------------------------------------------------------- -// Called by open() with the arbitration lock held. - -bool IOKernelDebugger::handleOpen( IOService * forClient, - IOOptionBits options, - void * arg ) -{ - IONetworkController * ctr = OSDynamicCast(IONetworkController, _target); - bool ret = false; - - do { - // Only a single client at a time. - - if ( _client ) break; - - // Register the target to prime the lock()/unlock() functionality - // before opening the target. - - registerHandler( _target ); - - // While the target is opened/enabled, it must block any thread - // which may acquire the debugger lock in its execution path. - - if ( _target->open( this ) == false ) - break; - - // Register interest in receiving notifications about controller - // power state changes. - // - // We are making an assumption that the controller is 'usable' and - // the next notification will inform this object that the controller - // has become unusable, there is no support for cases when the - // controller is already in an 'unusable' state. - - _pmDisabled = false; - - if ( ctr ) - { - // Register to receive PM notifications for controller power - // state changes. - - ctr->registerInterestedDriver( this ); - - if ( ctr->doEnable( this ) != kIOReturnSuccess ) - { - ctr->deRegisterInterestedDriver( this ); - break; - } - } - - // After the target has been opened, complete the registration. - - IOLog("%s: Debugger attached\n", getName()); - registerHandler( _target, _txHandler, _rxHandler ); - - // Remember the client. - - _client = forClient; - - ret = true; - } - while (0); - - if ( ret == false ) - { - registerHandler( 0 ); - _target->close( this ); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Called by IOService::close() with the arbitration lock held. - -void IOKernelDebugger::handleClose( IOService * forClient, - IOOptionBits options ) -{ - IONetworkController * ctr = OSDynamicCast(IONetworkController, _target); - - if ( _client && ( _client == forClient ) ) - { - // There is no KDP un-registration. The best we can do is to - // register dummy handlers. - - registerHandler( 0 ); - - if ( ctr ) - { - // Disable controller if it is not already disabled. - - if ( _pmDisabled == false ) - { - ctr->doDisable( this ); - } - - // Before closing the controller, remove interest in receiving - // notifications about controller power state changes. - - ctr->deRegisterInterestedDriver( this ); - } - - _client = 0; - - _target->close( this ); - } -} - -//--------------------------------------------------------------------------- -// Called by IOService::isOpen() with the arbitration lock held. - -bool IOKernelDebugger::handleIsOpen( const IOService * forClient ) const -{ - if ( forClient == 0 ) - return ( forClient != _client ); - else - return ( forClient == _client ); -} - -//--------------------------------------------------------------------------- -// Free the IOKernelDebugger object. - -void IOKernelDebugger::free() -{ - // IOLog("IOKernelDebugger::%s %p\n", __FUNCTION__, this); - super::free(); -} - -#define PM_SECS(x) ((x) * 1000 * 1000) - -//--------------------------------------------------------------------------- -// Handle controller's power state change notitifications. - -IOReturn -IOKernelDebugger::powerStateWillChangeTo( IOPMPowerFlags flags, - unsigned long stateNumber, - IOService * policyMaker ) -{ - IOReturn ret = IOPMAckImplied; - - if ( ( flags & IOPMDeviceUsable ) == 0 ) - { - // Controller is about to transition to an un-usable state. - // The debugger nub should be disabled. - - this->retain(); - - thread_call_func( (thread_call_func_t) pmDisableDebugger, - this, /* parameter */ - FALSE ); /* disable unique call filter */ - - ret = PM_SECS(3); /* Must ACK within 3 seconds */ - } - - return ret; -} - -IOReturn -IOKernelDebugger::powerStateDidChangeTo( IOPMPowerFlags flags, - unsigned long stateNumber, - IOService * policyMaker ) -{ - IOReturn ret = IOPMAckImplied; - - if ( flags & IOPMDeviceUsable ) - { - // Controller has transitioned to an usable state. - // The debugger nub should be enabled if necessary. - - this->retain(); - - thread_call_func( (thread_call_func_t) pmEnableDebugger, - this, /* parameter */ - FALSE ); /* disable unique call filter */ - - ret = PM_SECS(3); /* Must ACK within 3 seconds */ - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Static member function: Enable the debugger nub after the controller -// transitions into an usable state. - -void IOKernelDebugger::pmEnableDebugger( IOKernelDebugger * debugger ) -{ - IONetworkController * ctr; - assert( debugger ); - - ctr = OSDynamicCast( IONetworkController, debugger->_target ); - - debugger->lockForArbitration(); - - if ( debugger->_client && ( debugger->_pmDisabled == true ) ) - { - if ( ctr && ( ctr->doEnable( debugger ) != kIOReturnSuccess ) ) - { - // This is bad, unable to re-enable the controller after sleep. - IOLog("IOKernelDebugger: Unable to re-enable controller\n"); - } - else - { - registerHandler( debugger->_target, debugger->_txHandler, - debugger->_rxHandler ); - - debugger->_pmDisabled = false; - } - } - - debugger->unlockForArbitration(); - - // Ack the power state change. - debugger->_target->acknowledgePowerChange( debugger ); - - debugger->release(); -} - -//--------------------------------------------------------------------------- -// Static member function: Disable the debugger nub before the controller -// transitions into an unusable state. - -void IOKernelDebugger::pmDisableDebugger( IOKernelDebugger * debugger ) -{ - IONetworkController * ctr; - assert( debugger ); - - ctr = OSDynamicCast( IONetworkController, debugger->_target ); - - debugger->lockForArbitration(); - - if ( debugger->_client && ( debugger->_pmDisabled == false ) ) - { - // Keep an open on the controller, but inhibit access to the - // controller's debugger handlers, and disable controller's - // hardware support for the debugger. - - registerHandler( 0 ); - if ( ctr ) ctr->doDisable( debugger ); - - debugger->_pmDisabled = true; - } - - debugger->unlockForArbitration(); - - // Ack the power state change. - debugger->_target->acknowledgePowerChange( debugger ); - - debugger->release(); -} diff --git a/iokit/Families/IONetworking/IOMbufMemoryCursor.cpp b/iokit/Families/IONetworking/IOMbufMemoryCursor.cpp deleted file mode 100644 index 21360f1b2..000000000 --- a/iokit/Families/IONetworking/IOMbufMemoryCursor.cpp +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* IOMbufMemoryCursor.cpp created by gvdl on 1999-1-20 */ - -#include <sys/cdefs.h> - -__BEGIN_DECLS -#include <IOKit/assert.h> - -#include <sys/param.h> -#include <sys/mbuf.h> -#include <architecture/byte_order.h> -__END_DECLS - -#include <IOKit/network/IOMbufMemoryCursor.h> -#include <IOKit/IOLib.h> - -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif /* MIN */ - -#define next_page(x) trunc_page(x + PAGE_SIZE) - -/* Define the meta class stuff for the entire file here */ -OSDefineMetaClassAndAbstractStructors(IOMbufMemoryCursor, IOMemoryCursor) -OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 0); -OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 1); -OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 2); -OSMetaClassDefineReservedUnused( IOMbufMemoryCursor, 3); - -OSDefineMetaClassAndStructors(IOMbufNaturalMemoryCursor, IOMbufMemoryCursor) -OSDefineMetaClassAndStructors(IOMbufBigMemoryCursor, IOMbufMemoryCursor) -OSDefineMetaClassAndStructors(IOMbufLittleMemoryCursor, IOMbufMemoryCursor) - -#ifdef __ppc__ -OSDefineMetaClassAndStructors(IOMbufDBDMAMemoryCursor, IOMbufMemoryCursor) -#endif /* __ppc__ */ - -/*********************** class IOMbufMemoryCursor ***********************/ -#define super IOMemoryCursor - -bool IOMbufMemoryCursor::initWithSpecification(OutputSegmentFunc outSeg, - UInt32 maxSegmentSize, - UInt32 maxTransferSize, - UInt32 align) -{ - return false; -} - -bool IOMbufMemoryCursor::initWithSpecification(OutputSegmentFunc inOutSeg, - UInt32 inMaxSegmentSize, - UInt32 inMaxNumSegments) -{ - if (!super::initWithSpecification(inOutSeg, inMaxSegmentSize, 0, 1)) - return false; - -#if 0 - // It is too confusing to force the max segment size to be at least - // as large as a page. Most Enet devices only have 11-12 bit fields, - // enough for a full size frame, and also the PAGE_SIZE parameter - // may be architecture dependent. - - assert(inMaxSegmentSize >= PAGE_SIZE); - if (inMaxSegmentSize < PAGE_SIZE) - return false; -#else - if (!inMaxSegmentSize) - return false; -#endif - - maxSegmentSize = MIN(maxSegmentSize, PAGE_SIZE); - maxNumSegments = inMaxNumSegments; - coalesceCount = 0; - - return true; -} - -// -// Copy the src packet into the destination packet. The amount to copy is -// determined by the dstm->m_len, which is setup by analyseSegments, see below. -// The source mbuf is not freed nor modified. -// -#define BCOPY(s, d, l) do { bcopy((void *) s, (void *) d, l); } while(0) - -static inline void coalesceSegments(struct mbuf *srcm, struct mbuf *dstm) -{ - vm_offset_t src, dst; - SInt32 srcLen, dstLen; - struct mbuf *temp; - - srcLen = srcm->m_len; - src = mtod(srcm, vm_offset_t); - - dstLen = dstm->m_len; - dst = mtod(dstm, vm_offset_t); - - for (;;) { - if (srcLen < dstLen) { - - // Copy remainder of src mbuf to current dst. - BCOPY(src, dst, srcLen); - dst += srcLen; - dstLen -= srcLen; - - // Move on to the next source mbuf. - temp = srcm->m_next; assert(temp); - srcm = temp; - - srcLen = srcm->m_len; - src = mtod(srcm, vm_offset_t); - } - else if (srcLen > dstLen) { - - // Copy some of src mbuf to remaining space in dst mbuf. - BCOPY(src, dst, dstLen); - src += dstLen; - srcLen -= dstLen; - - // Move on to the next destination mbuf. - temp = dstm->m_next; assert(temp); - dstm = temp; - - dstLen = dstm->m_len; - dst = mtod(dstm, vm_offset_t); - } - else { /* (srcLen == dstLen) */ - - // copy remainder of src into remaining space of current dst - BCOPY(src, dst, srcLen); - - // Free current mbuf and move the current onto the next - srcm = srcm->m_next; - - // Do we have any data left to copy? - if (!dstm->m_next) - break; - dstm = dstm->m_next; - - assert(srcm); - dstLen = dstm->m_len; - dst = mtod(dstm, vm_offset_t); - srcLen = srcm->m_len; - src = mtod(srcm, vm_offset_t); - } - } -} - -static const UInt32 kMBufDataCacheSize = 16; - -static inline bool analyseSegments( - struct mbuf *packet, /* input packet mbuf */ - const UInt32 mbufsInCache, /* number of entries in segsPerMBuf[] */ - const UInt32 segsPerMBuf[], /* segments required per mbuf */ - SInt32 numSegs, /* total number of segments */ - const UInt32 maxSegs) /* max controller segments per mbuf */ -{ - struct mbuf *newPacket; // output mbuf chain. - struct mbuf *out; // current output mbuf link. - SInt32 outSize; // size of current output mbuf link. - SInt32 outSegs; // segments for current output mbuf link. - SInt32 doneSegs; // segments for output mbuf chain. - SInt32 outLen; // remaining length of input buffer. - - struct mbuf *in = packet; // save the original input packet pointer. - UInt32 inIndex = 0; - - // Allocate a mbuf (non header mbuf) to begin the output mbuf chain. - // - MGET(newPacket, M_DONTWAIT, MT_DATA); - if (!newPacket) { - IOLog("analyseSegments: MGET() 1 error\n"); - return false; - } - - /* Initialise outgoing packet controls */ - out = newPacket; - outSize = MLEN; - doneSegs = outSegs = outLen = 0; - - // numSegs stores the delta between the total and the max. For each - // input mbuf consumed, we decrement numSegs. - // - numSegs -= maxSegs; - - // Loop through the input packet mbuf 'in' and construct a new mbuf chain - // large enough to make (numSegs + doneSegs + outSegs) less than or - // equal to zero. - // - do { - vm_offset_t vmo; - - outLen += in->m_len; - - while (outLen > outSize) { - // Oh dear the current outgoing length is too big. - if (outSize != MCLBYTES) { - // Current mbuf is not yet a cluster so promote, then - // check for error. - - MCLGET(out, M_DONTWAIT); - if ( !(out->m_flags & M_EXT) ) { - IOLog("analyseSegments: MCLGET() error\n"); - goto bombAnalysis; - } - - outSize = MCLBYTES; - - continue; - } - - vmo = mtod(out, vm_offset_t); - out->m_len = MCLBYTES; /* Fill in target copy size */ - doneSegs += (round_page(vmo + MCLBYTES) - trunc_page(vmo)) - / PAGE_SIZE; - - // If the number of segments of the output chain, plus - // the segment for the mbuf we are about to allocate is greater - // than maxSegs, then abort. - // - if (doneSegs + 1 > (int) maxSegs) { - IOLog("analyseSegments: maxSegs limit 1 reached! %ld %ld\n", - doneSegs, maxSegs); - goto bombAnalysis; - } - - MGET(out->m_next, M_DONTWAIT, MT_DATA); - if (!out->m_next) { - IOLog("analyseSegments: MGET() error\n"); - goto bombAnalysis; - } - - out = out->m_next; - outSize = MLEN; - outLen -= MCLBYTES; - } - - // Compute number of segment in current outgoing mbuf. - vmo = mtod(out, vm_offset_t); - outSegs = (round_page(vmo + outLen) - trunc_page(vmo)) / PAGE_SIZE; - if (doneSegs + outSegs > (int) maxSegs) { - IOLog("analyseSegments: maxSegs limit 2 reached! %ld %ld %ld\n", - doneSegs, outSegs, maxSegs); - goto bombAnalysis; - } - - // Get the number of segments in the current inbuf - if (inIndex < mbufsInCache) - numSegs -= segsPerMBuf[inIndex]; // Yeah, in cache - else { - // Hmm, we have to recompute from scratch. Copy code from genPhys. - int thisLen = 0, mbufLen; - - vmo = mtod(in, vm_offset_t); - for (mbufLen = in->m_len; mbufLen; mbufLen -= thisLen) { - thisLen = MIN(next_page(vmo), vmo + mbufLen) - vmo; - vmo += thisLen; - numSegs--; - } - } - - // Walk the incoming buffer on one. - in = in->m_next; - inIndex++; - - // continue looping until the total number of segments has dropped - // to an acceptable level, or if we ran out of mbuf links. - - } while (in && ((numSegs + doneSegs + outSegs) > 0)); - - if ( (int) (numSegs + doneSegs + outSegs) <= 0) { // success - - out->m_len = outLen; // Set last mbuf with the remaining length. - - // The amount to copy is determine by the segment length in each - // mbuf linked to newPacket. The sum can be smaller than - // packet->pkthdr.len; - // - coalesceSegments(packet, newPacket); - - // Copy complete. - - // If 'in' is non zero, then it means that we only need to copy part - // of the input packet, beginning at the start. The mbuf chain - // beginning at 'in' must be preserved and linked to the new - // output packet chain. Everything before 'in', except for the - // header mbuf can be freed. - // - struct mbuf *m = packet->m_next; - while (m != in) - m = m_free(m); - - // The initial header mbuf is preserved, its length set to zero, and - // linked to the new packet chain. - - packet->m_len = 0; - packet->m_next = newPacket; - newPacket->m_next = in; - - return true; - } - -bombAnalysis: - - m_freem(newPacket); - return false; -} - -UInt32 IOMbufMemoryCursor::genPhysicalSegments(struct mbuf *packet, void *vector, - UInt32 maxSegs, bool doCoalesce) -{ - bool doneCoalesce = false; - - if (!packet || !(packet->m_flags & M_PKTHDR)) - return 0; - - if (!maxSegs) - maxSegs = maxNumSegments; - if (!maxSegs) - return 0; - - if ( packet->m_next == 0 ) - { - vm_offset_t src; - struct IOPhysicalSegment physSeg; - /* - * the packet consists of only 1 mbuf - * so if the data buffer doesn't span a page boundary - * we can take the simple way out - */ - src = mtod(packet, vm_offset_t); - - if ( trunc_page(src) == trunc_page(src+packet->m_len-1) ) - { - if ((physSeg.location = - (IOPhysicalAddress)mcl_to_paddr((char *)src)) == 0) - physSeg.location = (IOPhysicalAddress)pmap_extract(kernel_pmap, src); - if (!physSeg.location) - return 0; - physSeg.length = packet->m_len; - (*outSeg)(physSeg, vector, 0); - - return 1; - } - } - - if ( doCoalesce == true && maxSegs == 1 ) - { - vm_offset_t src; - vm_offset_t dst; - struct mbuf *m; - struct mbuf *mnext; - struct mbuf *out; - UInt32 len = 0; - struct IOPhysicalSegment physSeg; - - m = packet; - - MGET(out, M_DONTWAIT, MT_DATA); - if ( out == 0 ) return 0; - - MCLGET(out, M_DONTWAIT); - if ( !(out->m_flags & M_EXT) ) - { - m_free( out ); - return 0; - } - dst = mtod(out, vm_offset_t); - - do - { - src = mtod(m, vm_offset_t); - BCOPY( src, dst, m->m_len ); - dst += m->m_len; - len += m->m_len; - } while ( (m = m->m_next) != 0 ); - - out->m_len = len; - - dst = mtod(out, vm_offset_t); - if ((physSeg.location = (IOPhysicalAddress)mcl_to_paddr((char *)dst)) == 0) - physSeg.location = (IOPhysicalAddress)pmap_extract(kernel_pmap, dst); - if (!physSeg.location) - return 0; - physSeg.length = out->m_len; - (*outSeg)(physSeg, vector, 0); - - m = packet->m_next; - while (m != 0) - { - mnext = m->m_next; - m_free(m); - m = mnext; - } - - // The initial header mbuf is preserved, its length set to zero, and - // linked to the new packet chain. - - packet->m_len = 0; - packet->m_next = out; - out->m_next = 0; - - return 1; - } - - - // - // Iterate over the mbuf, translating segments were allowed. When we - // are not allowed to translate segments then accumulate segment - // statistics up to kMBufDataCacheSize of mbufs. Finally - // if we overflow our cache just count how many segments this - // packet represents. - // - UInt32 segsPerMBuf[kMBufDataCacheSize]; - -tryAgain: - UInt32 curMBufIndex = 0; - UInt32 curSegIndex = 0; - UInt32 lastSegCount = 0; - struct mbuf *m = packet; - - // For each mbuf in incoming packet. - do { - vm_size_t mbufLen, thisLen = 0; - vm_offset_t src; - - // Step through each segment in the current mbuf - for (mbufLen = m->m_len, src = mtod(m, vm_offset_t); - mbufLen; - src += thisLen, mbufLen -= thisLen) - { - // If maxSegmentSize is atleast PAGE_SIZE, then - // thisLen = MIN(next_page(src), src + mbufLen) - src; - - thisLen = MIN(mbufLen, maxSegmentSize); - thisLen = MIN(next_page(src), src + thisLen) - src; - - // If room left then find the current segment addr and output - if (curSegIndex < maxSegs) { - struct IOPhysicalSegment physSeg; - - if ((physSeg.location = - (IOPhysicalAddress)mcl_to_paddr((char *)src)) == 0) - physSeg.location = (IOPhysicalAddress)pmap_extract(kernel_pmap, src); - if (!physSeg.location) - return 0; - physSeg.length = thisLen; - (*outSeg)(physSeg, vector, curSegIndex); - } - // Count segments if we are coalescing. - curSegIndex++; - } - - // Cache the segment count data if room is available. - if (curMBufIndex < kMBufDataCacheSize) { - segsPerMBuf[curMBufIndex] = curSegIndex - lastSegCount; - lastSegCount = curSegIndex; - } - - // Move on to next imcoming mbuf - curMBufIndex++; - m = m->m_next; - } while (m); - - // If we finished cleanly return number of segments found - if (curSegIndex <= maxSegs) - return curSegIndex; - if (!doCoalesce) - return 0; // if !coalescing we've got a problem. - - - // If we are coalescing and it is possible then attempt coalesce, - if (!doneCoalesce - && (UInt) packet->m_pkthdr.len <= maxSegs * maxSegmentSize) { - // Hmm, we have to do some coalescing. - bool analysisRet; - - analysisRet = analyseSegments(packet, - MIN(curMBufIndex, kMBufDataCacheSize), - segsPerMBuf, - curSegIndex, maxSegs); - if (analysisRet) { - doneCoalesce = true; - coalesceCount++; - goto tryAgain; - } - } - - assert(!doneCoalesce); // Problem in Coalesce code. - packetTooBigErrors++; - return 0; -} - -/********************* class IOMbufBigMemoryCursor **********************/ -IOMbufBigMemoryCursor * -IOMbufBigMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) -{ - IOMbufBigMemoryCursor *me = new IOMbufBigMemoryCursor; - - if (me && !me->initWithSpecification(&bigOutputSegment, - maxSegSize, maxNumSegs)) { - me->release(); - return 0; - } - - return me; -} - - -/******************* class IOMbufNaturalMemoryCursor ********************/ -IOMbufNaturalMemoryCursor * -IOMbufNaturalMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) -{ - IOMbufNaturalMemoryCursor *me = new IOMbufNaturalMemoryCursor; - - if (me && !me->initWithSpecification(&naturalOutputSegment, - maxSegSize, maxNumSegs)) { - me->release(); - return 0; - } - - return me; -} - - -/******************** class IOMbufLittleMemoryCursor ********************/ -IOMbufLittleMemoryCursor * -IOMbufLittleMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) -{ - IOMbufLittleMemoryCursor *me = new IOMbufLittleMemoryCursor; - - if (me && !me->initWithSpecification(&littleOutputSegment, - maxSegSize, maxNumSegs)) { - me->release(); - return 0; - } - - return me; -} - - -/******************** class IOMbufDBDMAMemoryCursor *********************/ -#ifdef __ppc__ - -IOMbufDBDMAMemoryCursor * -IOMbufDBDMAMemoryCursor::withSpecification(UInt32 maxSegSize, UInt32 maxNumSegs) -{ - IOMbufDBDMAMemoryCursor *me = new IOMbufDBDMAMemoryCursor; - - if (me && !me->initWithSpecification(&dbdmaOutputSegment, - maxSegSize, maxNumSegs)) { - me->release(); - return 0; - } - - return me; -} -#endif /* __ppc__ */ diff --git a/iokit/Families/IONetworking/IOMbufQueue.h b/iokit/Families/IONetworking/IOMbufQueue.h deleted file mode 100644 index b5937ab36..000000000 --- a/iokit/Families/IONetworking/IOMbufQueue.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOMBUFQUEUE_H -#define _IOMBUFQUEUE_H - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -} - -struct IOMbufQueue { - struct mbuf * head; - struct mbuf * tail; - UInt32 size; - UInt32 capacity; -}; - -static __inline__ -UInt32 IOMbufFree(struct mbuf * m) -{ -/*LD#### - UInt32 count = 0; - struct mbuf * mn; - - while (( mn = m )) - { - m = mn->m_nextpkt; - mn->m_nextpkt = 0; - m_freem(mn); - count++; - } - return count; -*/ - return m_freem_list(m); -} - -static __inline__ -void IOMbufQueueInit(IOMbufQueue * q, UInt32 capacity) -{ - q->head = q->tail = 0; - q->size = 0; - q->capacity = capacity; -} - -static __inline__ -bool IOMbufQueueEnqueue(IOMbufQueue * q, struct mbuf * m) -{ - if (q->size >= q->capacity) return false; - - if (q->size++ > 0) - q->tail->m_nextpkt = m; - else - q->head = m; - - for (q->tail = m; - q->tail->m_nextpkt; - q->tail = q->tail->m_nextpkt, q->size++) - ; - - return true; -} - -static __inline__ -bool IOMbufQueueEnqueue(IOMbufQueue * q, IOMbufQueue * qe) -{ - if (qe->size) - { - if (q->size == 0) - q->head = qe->head; - else - q->tail->m_nextpkt = qe->head; - q->tail = qe->tail; - q->size += qe->size; - - qe->head = qe->tail = 0; - qe->size = 0; - } - return true; -} - -static __inline__ -void IOMbufQueuePrepend(IOMbufQueue * q, struct mbuf * m) -{ - struct mbuf * tail; - - for (tail = m, q->size++; - tail->m_nextpkt; - tail = tail->m_nextpkt, q->size++) - ; - - tail->m_nextpkt = q->head; - if (q->tail == 0) - q->tail = tail; - q->head = m; -} - -static __inline__ -void IOMbufQueuePrepend(IOMbufQueue * q, IOMbufQueue * qp) -{ - if (qp->size) - { - qp->tail->m_nextpkt = q->head; - if (q->tail == 0) - q->tail = qp->tail; - q->head = qp->head; - q->size += qp->size; - - qp->head = qp->tail = 0; - qp->size = 0; - } -} - -static __inline__ -struct mbuf * IOMbufQueueDequeue(IOMbufQueue * q) -{ - struct mbuf * m = q->head; - if (m) - { - if ((q->head = m->m_nextpkt) == 0) - q->tail = 0; - m->m_nextpkt = 0; - q->size--; - } - return m; -} - -static __inline__ -struct mbuf * IOMbufQueueDequeueAll(IOMbufQueue * q) -{ - struct mbuf * m = q->head; - q->head = q->tail = 0; - q->size = 0; - return m; -} - -static __inline__ -struct mbuf * IOMbufQueuePeek(IOMbufQueue * q) -{ - return q->head; -} - -static __inline__ -UInt32 IOMbufQueueGetSize(IOMbufQueue * q) -{ - return q->size; -} - -static __inline__ -UInt32 IOMbufQueueGetCapacity(IOMbufQueue * q) -{ - return q->capacity; -} - -static __inline__ -void IOMbufQueueSetCapacity(IOMbufQueue * q, UInt32 capacity) -{ - q->capacity = capacity; -} - -#endif /* !_IOMBUFQUEUE_H */ diff --git a/iokit/Families/IONetworking/IONetworkController.cpp b/iokit/Families/IONetworking/IONetworkController.cpp deleted file mode 100644 index 2b44e40f9..000000000 --- a/iokit/Families/IONetworking/IONetworkController.cpp +++ /dev/null @@ -1,2159 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkController.cpp - * - * HISTORY - * 9-Dec-1998 Joe Liu (jliu) created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOCommandGate.h> -#include <IOKit/network/IONetworkController.h> -#include <IOKit/network/IOOutputQueue.h> -#include <IOKit/network/IONetworkMedium.h> - -// IONetworkController (and its subclasses) needs to know about mbufs, -// but it shall have no further dependencies on BSD networking. -// -extern "C" { -#include <sys/param.h> // mbuf limits defined here. -#include <sys/mbuf.h> -#include <sys/kdebug.h> -// -// osfmk/kern/spl.h - Need splimp for mbuf macros. -// -typedef unsigned spl_t; -extern spl_t (splimp)(void); -} - -//------------------------------------------------------------------------- -// Macros. - -#define super IOService - -OSDefineMetaClassAndAbstractStructors( IONetworkController, IOService ) -OSMetaClassDefineReservedUnused( IONetworkController, 0); -OSMetaClassDefineReservedUnused( IONetworkController, 1); -OSMetaClassDefineReservedUnused( IONetworkController, 2); -OSMetaClassDefineReservedUnused( IONetworkController, 3); -OSMetaClassDefineReservedUnused( IONetworkController, 4); -OSMetaClassDefineReservedUnused( IONetworkController, 5); -OSMetaClassDefineReservedUnused( IONetworkController, 6); -OSMetaClassDefineReservedUnused( IONetworkController, 7); -OSMetaClassDefineReservedUnused( IONetworkController, 8); -OSMetaClassDefineReservedUnused( IONetworkController, 9); -OSMetaClassDefineReservedUnused( IONetworkController, 10); -OSMetaClassDefineReservedUnused( IONetworkController, 11); -OSMetaClassDefineReservedUnused( IONetworkController, 12); -OSMetaClassDefineReservedUnused( IONetworkController, 13); -OSMetaClassDefineReservedUnused( IONetworkController, 14); -OSMetaClassDefineReservedUnused( IONetworkController, 15); -OSMetaClassDefineReservedUnused( IONetworkController, 16); -OSMetaClassDefineReservedUnused( IONetworkController, 17); -OSMetaClassDefineReservedUnused( IONetworkController, 18); -OSMetaClassDefineReservedUnused( IONetworkController, 19); -OSMetaClassDefineReservedUnused( IONetworkController, 20); -OSMetaClassDefineReservedUnused( IONetworkController, 21); -OSMetaClassDefineReservedUnused( IONetworkController, 22); -OSMetaClassDefineReservedUnused( IONetworkController, 23); -OSMetaClassDefineReservedUnused( IONetworkController, 24); -OSMetaClassDefineReservedUnused( IONetworkController, 25); -OSMetaClassDefineReservedUnused( IONetworkController, 26); -OSMetaClassDefineReservedUnused( IONetworkController, 27); -OSMetaClassDefineReservedUnused( IONetworkController, 28); -OSMetaClassDefineReservedUnused( IONetworkController, 29); -OSMetaClassDefineReservedUnused( IONetworkController, 30); -OSMetaClassDefineReservedUnused( IONetworkController, 31); - -static bool isPowerOfTwo(UInt32 num) -{ - return (num == (num & ~(num - 1))); -} - -#define MEDIUM_LOCK IOTakeLock(_mediumLock); -#define MEDIUM_UNLOCK IOUnlock(_mediumLock); - -#ifdef DEBUG -#define DLOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -// OSSymbols for frequently used keys. -// -static const OSSymbol * gIOActiveMediumKey; -static const OSSymbol * gIOCurrentMediumKey; -static const OSSymbol * gIODefaultMediumKey; -static const OSSymbol * gIONullMediumName; -static const OSSymbol * gIOLinkDataKey; -static const OSData * gIONullLinkData; - -// Global symbols. -// -const OSSymbol * gIONetworkFilterGroup; -const OSSymbol * gIOEthernetWakeOnLANFilterGroup; - -// Constants for handleCommand(). -// -enum { - kCommandEnable = 1, - kCommandDisable = 2, - kCommandPrepare = 3 -}; - -//--------------------------------------------------------------------------- -// IONetworkController class initializer. Create often used OSSymbol objects -// that are used as keys. This method is called explicitly by a line in -// IOStartIOKit.cpp and not by the OSDefineMetaClassAndInit() mechanism, to -// ensure that this method is called after the OSSymbol class is initialized. - -void IONetworkController::initialize() -{ - gIOActiveMediumKey = OSSymbol::withCStringNoCopy(kIOActiveMedium); - gIOCurrentMediumKey = OSSymbol::withCStringNoCopy(kIOSelectedMedium); - gIODefaultMediumKey = OSSymbol::withCStringNoCopy(kIODefaultMedium); - gIONullMediumName = OSSymbol::withCStringNoCopy(""); - gIOLinkDataKey = OSSymbol::withCStringNoCopy(kIOLinkData); - gIONullLinkData = OSData::withCapacity(0); - gIONetworkFilterGroup - = OSSymbol::withCStringNoCopy(kIONetworkFilterGroup); - - gIOEthernetWakeOnLANFilterGroup - = OSSymbol::withCStringNoCopy("IOEthernetWakeOnLANFilterGroup"); - - assert( gIOEthernetWakeOnLANFilterGroup ); - - assert(gIOActiveMediumKey && - gIOCurrentMediumKey && - gIODefaultMediumKey && - gIONullMediumName && - gIOLinkDataKey && - gIONullLinkData && - gIONetworkFilterGroup); - - IONetworkData::initialize(); -} - -//--------------------------------------------------------------------------- -// Initialize the IONetworkController instance. Instance variables are -// set to their default values, then super::init() is called. -// -// properties: A dictionary object containing a property table -// associated with this instance. -// -// Returns true on success, false otherwise. - -bool IONetworkController::init(OSDictionary * properties) -{ - // Initialize instance variables. - // - _workLoop = 0; - _cmdGate = 0; - _outputQueue = 0; - _clientSet = 0; - _clientSetIter = 0; - _cmdClient = 0; - _propertiesPublished = false; - _mediumLock = 0; - _lastLinkData = gIONullLinkData; - _lastActiveMediumName = gIONullMediumName; - _lastCurrentMediumName = gIONullMediumName; - - if (super::init(properties) == false) - { - DLOG("IONetworkController: super::init() failed\n"); - return false; - } - - return true; -} - -//------------------------------------------------------------------------- -// Called after the controller driver was successfully matched to a provider, -// to start running. IONetworkController will allocate resources and gather -// controller properties. No I/O will be performed until the subclass -// attaches a client object from its start() method. Subclasses must override -// this method and call super::start() at the beginning of its implementation. -// Then check the return value to make sure the superclass was started -// successfully before continuing. The resources allocated by -// IONetworkController include: -// -// - An IOCommandGate object to handle client commands. -// - An OSSet to track our clients. -// - An optional IOOutputQueue object for output queueing. -// -// Tasks that are usually performed by a typical network driver in start -// include: -// -// - Resource allocation -// - Hardware initialization -// - Allocation of IOEventSources and attaching them to an IOWorkLoop object. -// - Publishing a medium dictionary. -// - And finally, attaching an interface object after the driver is ready -// to handle client requests. -// -// provider: The provider that the controller was matched -// (and attached) to. -// -// Returns true on success, false otherwise. - -bool IONetworkController::start(IOService * provider) -{ - // Most drivers will probably want to wait for BSD due to their - // dependency on mbufs, which is not available until BSD is - // initialized. - - if ((getFeatures() & kIONetworkFeatureNoBSDWait) == 0) - waitForService(resourceMatching( "IOBSD" )); - - // Start our superclass. - - if (!super::start(provider)) - return false; - - // Create an OSSet to store our clients. - - _clientSet = OSSet::withCapacity(2); - if (_clientSet == 0) - return false; - - _clientSetIter = OSCollectionIterator::withCollection(_clientSet); - if (_clientSetIter == 0) - return false; - - // Initialize link status properties. - - if (!setProperty(gIOActiveMediumKey, (OSSymbol *) gIONullMediumName) || - !setProperty(gIOCurrentMediumKey, (OSSymbol *) gIONullMediumName)) - return false; - - _linkStatus = OSNumber::withNumber((UInt64) 0, 32); - if (!_linkStatus || !setProperty(kIOLinkStatus, _linkStatus)) - { - return false; - } - - _linkSpeed = OSNumber::withNumber((UInt64) 0, 64); - if (!_linkSpeed || !setProperty(kIOLinkSpeed, _linkSpeed)) - { - return false; - } - - // Allocate a mutex lock to serialize access to the medium dictionary. - - _mediumLock = IOLockAlloc(); - if (!_mediumLock) - return false; - IOLockInitWithState(_mediumLock, kIOLockStateUnlocked); - - // Tell the driver that now is the time to create a work loop - // (if it wants one). - - if ( createWorkLoop() != true ) - { - DLOG("%s: createWorkLoop() error\n", getName()); - return false; - } - - // Get the workloop. - - _workLoop = getWorkLoop(); - if ( _workLoop == 0 ) - { - DLOG("%s: IOWorkLoop allocation failed\n", getName()); - return false; - } - _workLoop->retain(); - - // Create a 'private' IOCommandGate object and attach it to - // our workloop created above. This is used by executeCommand(). - - _cmdGate = IOCommandGate::commandGate(this); - if (!_cmdGate || - (_workLoop->addEventSource(_cmdGate) != kIOReturnSuccess)) - { - DLOG("%s: IOCommandGate initialization failed\n", getName()); - return false; - } - - // Try to allocate an IOOutputQueue instance. This is optional and - // _outputQueue may be 0. - - _outputQueue = createOutputQueue(); - - // Query the controller's mbuf buffer restrictions. - - IOPacketBufferConstraints constraints; - getPacketBufferConstraints(&constraints); - if ((constraints.alignStart > kIOPacketBufferAlign32) || - (constraints.alignLength > kIOPacketBufferAlign32) || - !isPowerOfTwo(constraints.alignStart) || - !isPowerOfTwo(constraints.alignLength)) - { - IOLog("%s: Invalid alignment: start:%ld, length:%ld\n", - getName(), - constraints.alignStart, - constraints.alignLength); - return false; - } - - // Make it easier to satisfy both constraints. - - if (constraints.alignStart < constraints.alignLength) - constraints.alignStart = constraints.alignLength; - - // Convert to alignment masks. - - _alignStart = (constraints.alignStart) ? constraints.alignStart - 1 : 0; - _alignLength = (constraints.alignLength) ? constraints.alignLength - 1 : 0; - _alignPadding = _alignStart + _alignLength; - - // Called by a policy-maker to initialize itself for power-management. - // IONetworkController is the policy-maker. - - PMinit(); - - // Called by a policy-maker on its nub, to be attached into the - // power management hierarchy. - - provider->joinPMtree(this); - - return true; -} - -//--------------------------------------------------------------------------- -// The opposite of start(). The controller has been instructed to stop running. -// This method should release resources and undo actions performed by start(). -// Subclasses must override this method and call super::stop() at the end of -// its implementation. -// -// provider: The provider that the controller was matched -// (and attached) to. - -void IONetworkController::stop(IOService * provider) -{ - // Called by a policy-maker to resign its responsibilities as the - // policy-maker. - - PMstop(); - - super::stop(provider); -} - -//--------------------------------------------------------------------------- -// Power-management hooks for subclasses. - -IOReturn IONetworkController::registerWithPolicyMaker(IOService * policyMaker) -{ - // An opportunity for subclasses to call - // policyMaker->registerPowerDriver(...) - // and other future PM requirements. - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Catch calls to createWorkLoop() for drivers that choose not implement this -// method. - -bool IONetworkController::createWorkLoop() -{ - return true; -} - -//--------------------------------------------------------------------------- -// Get the IOCommandGate object created by IONetworkController. -// An IOCommandGate is created and attached to the internal workloop by -// the start() method. -// This IOCommandGate object is used to handle client commands sent to -// executeCommand(). Subclasses that need an IOCommandGate should use the -// object returned by this method, rather than creating -// a new instance. See IOCommandGate. -// -// Returns the IOCommandGate object created by IONetworkController. - -IOCommandGate * IONetworkController::getCommandGate() const -{ - return _cmdGate; -} - -//--------------------------------------------------------------------------- -// Get the address of the method designated to handle output packets. -// -// Returns the address of the outputPacket() method. - -IOOutputAction IONetworkController::getOutputHandler() const -{ - return (IOOutputAction) &IONetworkController::outputPacket; -} - -//--------------------------------------------------------------------------- -// Create a new interface object and attach it to the controller. -// The createInterface() method is called to perform the allocation and -// initialization, followed by a call to configureInterface() to configure -// the interface. Subclasses can override those methods to customize the -// interface client attached. Drivers will usually call this method from -// their start() implementation, after they are ready to process client -// requests. -// -// interfaceP: If successful (return value is true), then the interface -// object will be written to the handle provided. -// -// doRegister: If true, then registerService() is called to register -// the interface, which will trigger the matching process, -// and cause the interface to become registered with the network -// layer. For drivers that wish to delay the registration, and -// hold off servicing requests and data packets from the network -// layer, set doRegister to false and call registerService() on -// the interface object when the controller becomes ready. -// This allows the driver to attach an interface but without -// making it available to the rest of the system. -// -// Returns true on success, false otherwise. - -bool -IONetworkController::attachInterface(IONetworkInterface ** interfaceP, - bool doRegister = true) -{ - IONetworkInterface * netif; - - *interfaceP = 0; - - // We delay some initialization until the first time that - // attachInterface() is called by the subclass. - - if (executeCommand(this, &IONetworkController::handleCommand, - this, (void *) kCommandPrepare) != kIOReturnSuccess) - { - return false; - } - - do { - // Allocate a concrete subclass of IONetworkInterface - // by calling createInterface(). - - netif = createInterface(); - if (!netif) - break; - - // Configure the interface instance by calling - // configureInterface(), then attach it as our client. - - if ( !configureInterface(netif) || !netif->attach(this) ) - { - netif->release(); - break; - } - - *interfaceP = netif; - - // Register the interface nub. Spawns a matching thread. - - if (doRegister) - netif->registerService(); - - return true; // success - } - while (0); - - return false; // failure -} - -//--------------------------------------------------------------------------- -// Detach the interface object. This method will check that the object -// provided is indeed an IONetworkInterface, and if so its terminate() -// method is called. Note that a registered interface object will close -// and detach from its controller only after the network layer has removed -// all references to the data structures exposed by the interface. -// -// interface: An interface object to be detached. -// sync: If true, the interface is terminated synchronously. -// Note that this may cause detachInterface() to block -// for an indeterminate of time. - -void -IONetworkController::detachInterface(IONetworkInterface * interface, - bool sync = false) -{ - IOOptionBits options = kIOServiceRequired; - - if (OSDynamicCast(IONetworkInterface, interface) == 0) - return; - - if (sync) - options |= kIOServiceSynchronous; - - interface->terminate(options); -} - -//--------------------------------------------------------------------------- -// This method is called by attachInterface() or attachDebuggerClient() on -// the workloop context, to prepare the controller before attaching the client -// object. This method will call publishProperties() to publish controller -// capabilities and properties that may be used by client objects. However, -// publishProperties() will be called only once, even if prepare() is called -// multiple times. -// -// kIOReturnSuccess on success, or an error code otherwise. -// Returning an error will cause the client attach to fail. - -IOReturn IONetworkController::prepare() -{ - IOReturn ret = kIOReturnSuccess; - - if ( _propertiesPublished == false ) - { - if ( publishProperties() == true ) - { - _propertiesPublished = true; - - if (pm_vars != 0) - { - registerWithPolicyMaker( this ); - } - } - else - { - ret = kIOReturnError; - } - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Handle a client open on the controller object. IOService calls this method -// with the arbitration lock held. Subclasses are not expected to override -// this method. -// -// client: The client that is attempting to open the controller. -// options: See IOService. -// argument: See IOService. -// -// Returns true to accept the client open, false to refuse it. - -bool IONetworkController::handleOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - assert(client); - return _clientSet->setObject(client); -} - -//--------------------------------------------------------------------------- -// Handle a close from one of the client objects. IOService calls this method -// with the arbitration lock held. Subclasses are not expected to override this -// method. -// -// client: The client that is closing the controller. -// options: See IOService. - -void IONetworkController::handleClose(IOService * client, IOOptionBits options) -{ - _clientSet->removeObject(client); -} - -//--------------------------------------------------------------------------- -// This method is always called by IOService with the arbitration lock held. -// Subclasses should not override this method. -// -// Returns true if the specified client, or any client if none is -// specified, presently has an open on this object. - -bool IONetworkController::handleIsOpen(const IOService * client) const -{ - if (client) - return _clientSet->containsObject(client); - else - return (_clientSet->getCount() > 0); -} - -//--------------------------------------------------------------------------- -// Free the IONetworkController instance by releasing all allocated resources, -// then call super::free(). - -void IONetworkController::free() -{ -#define RELEASE(x) do { if (x) { (x)->release(); (x) = 0; } } while (0) - - // We should have no clients at this point. If we do, - // then something is very wrong! It means that a client - // has an open on us, and yet we are being freed. - - if (_clientSet) assert(_clientSet->getCount() == 0); - - RELEASE( _outputQueue ); - RELEASE( _cmdGate ); - RELEASE( _workLoop ); - RELEASE( _clientSetIter ); - RELEASE( _clientSet ); - RELEASE( _linkStatus ); - RELEASE( _linkSpeed ); - - if (_mediumLock) { IOLockFree(_mediumLock); _mediumLock = 0; } - - super::free(); -} - -//--------------------------------------------------------------------------- -// Handle an enable request from a client. - -IOReturn IONetworkController::enable(IOService * client) -{ - if (OSDynamicCast(IONetworkInterface, client)) - return enable((IONetworkInterface *) client); - - if (OSDynamicCast(IOKernelDebugger, client)) - return enable((IOKernelDebugger *) client); - - IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__); - return kIOReturnBadArgument; -} - -//--------------------------------------------------------------------------- -// Handle a disable request from a client. - -IOReturn IONetworkController::disable(IOService * client) -{ - if (OSDynamicCast(IONetworkInterface, client)) - return disable((IONetworkInterface *) client); - - if (OSDynamicCast(IOKernelDebugger, client)) - return disable((IOKernelDebugger *) client); - - IOLog("%s::%s Unknown client type\n", getName(), __FUNCTION__); - return kIOReturnBadArgument; -} - -//--------------------------------------------------------------------------- -// Called by an interface client to enable the controller. - -IOReturn IONetworkController::enable(IONetworkInterface * interface) -{ - IOLog("IONetworkController::%s\n", __FUNCTION__); - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Called by an interface client to disable the controller. - -IOReturn IONetworkController::disable(IONetworkInterface * interface) -{ - IOLog("IONetworkController::%s\n", __FUNCTION__); - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Discover and publish controller capabilities to the property table. -// This method is called by prepare() on the workloop context. -// -// Returns true if all capabilities were discovered and published -// successfully, false otherwise. Returning false will prevent client -// objects from attaching to the controller since a vital property that -// a client requires may be missing. - -bool IONetworkController::publishProperties() -{ - bool ret = false; - const OSString * string; - UInt32 num; - OSDictionary * dict = 0; - OSNumber * numObj = 0; - - do { - bool status; - - string = newVendorString(); - if (string) { - status = setProperty(kIOVendor, (OSObject *) string); - string->release(); - if (status != true) break; - } - - string = newModelString(); - if (string) { - status = setProperty(kIOModel, (OSObject *) string); - string->release(); - if (status != true) break; - } - - string = newRevisionString(); - if (string) { - status = setProperty(kIORevision, (OSObject *) string); - string->release(); - if (status != true) break; - } - - // Publish controller feature flags. - - num = getFeatures(); - if ( !setProperty(kIOFeatures, num, sizeof(num) * 8) ) - break; - - // Publish max/min packet size. - - if ( ( getMaxPacketSize(&num) != kIOReturnSuccess ) || - ( !setProperty(kIOMaxPacketSize, num, sizeof(num) * 8) ) ) - break; - - if ( ( getMinPacketSize(&num) != kIOReturnSuccess ) || - ( !setProperty(kIOMinPacketSize, num, sizeof(num) * 8) ) ) - break; - - // Publish supported packet filters. - - if (getPacketFilters(gIONetworkFilterGroup, &num) != kIOReturnSuccess) - break; - - dict = OSDictionary::withCapacity(4); - numObj = OSNumber::withNumber(num, sizeof(num) * 8); - if ( (dict == 0) || (numObj == 0) ) break; - - if ( !dict->setObject(gIONetworkFilterGroup, numObj) || - !setProperty(kIOPacketFilters, dict) ) - break; - - ret = true; - } - while (false); - - if (ret == false) { - DLOG("IONetworkController::%s error\n", __FUNCTION__); - } - if ( dict ) dict->release(); - if ( numObj ) numObj->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Send a network event to all attached interface objects. - -bool IONetworkController::_broadcastEvent(UInt32 type, void * data = 0) -{ - IONetworkInterface * netif; - - lockForArbitration(); // locks open/close/state changes. - - if (_clientSet->getCount()) - { - _clientSetIter->reset(); - - while ((netif = (IONetworkInterface *)_clientSetIter->getNextObject())) - { - if (OSDynamicCast(IONetworkInterface, netif) == 0) - continue; // only send events to IONetworkInterface objects. - netif->inputEvent(type, data); - } - } - - unlockForArbitration(); - - return true; -} - -//--------------------------------------------------------------------------- -// A client request for the controller to change to a new MTU size. - -IOReturn IONetworkController::setMaxPacketSize(UInt32 maxSize) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Transmit a packet mbuf. - -UInt32 IONetworkController::outputPacket(struct mbuf * m, void * param) -{ - // The implementation here is simply a sink-hole, all packets are - // dropped. - - if (m) freePacket(m); - return 0; -} - -//--------------------------------------------------------------------------- -// Report features supported by the controller and/or driver. - -UInt32 IONetworkController::getFeatures() const -{ - return 0; -} - -//--------------------------------------------------------------------------- -// Create default description strings. - -const OSString * IONetworkController::newVendorString() const -{ - return 0; -} - -const OSString * IONetworkController::newModelString() const -{ - return 0; -} - -const OSString * IONetworkController::newRevisionString() const -{ - return 0; -} - -//--------------------------------------------------------------------------- -// Encode a client command received by executeCommand(). - -struct cmdStruct { - OSObject * client; - void * target; - IONetworkController::Action action; - void * param0; - void * param1; - void * param2; - void * param3; - IOReturn ret; -}; - -//--------------------------------------------------------------------------- -// Get the command client object. - -OSObject * IONetworkController::getCommandClient() const -{ - return ( _workLoop->inGate() ? _cmdClient : 0 ); -} - -//--------------------------------------------------------------------------- -// Configure an interface object created through createInterface(). -// IONetworkController will register its output handler with the interface -// object provided. After the interface is registered and opened by its -// client, it will refuse requests to change its properties through its -// public methods. Since this method is called before the interface object -// is published and registered, subclasses of IONetworkController may override -// this method to configure and customize the interface object. -// -// interface: The interface object to be configured. -// -// Returns true if configuration was successful, false otherwise (this -// will cause attachInterface() to fail). - -bool IONetworkController::configureInterface(IONetworkInterface * interface) -{ - IOOutputAction handler; - OSObject * target; - bool ret; - IONetworkData * stats; - - if (!OSDynamicCast(IONetworkInterface, interface)) - return false; - - IOOutputQueue * outQueue = getOutputQueue(); - - // Must register an output handler with the interface object. - // The interface will send output packets, to its registered - // output handler. If we allocated an output queue, then we - // register the queue as the output handler, otherwise, we - // become the output handler. - - if (outQueue) - { - target = outQueue; - handler = outQueue->getOutputHandler(); - - stats = outQueue->getStatisticsData(); - interface->addNetworkData(stats); - } - else - { - target = this; - handler = getOutputHandler(); - } - ret = interface->registerOutputHandler(target, handler); - - return ret; -} - -//--------------------------------------------------------------------------- -// Called by start() to create an optional IOOutputQueue instance to handle -// output queueing. The default implementation will always return 0, hence -// no output queue will be created. A driver may override this method and -// return a subclass of IOOutputQueue. IONetworkController will keep a -// reference to the queue created, and will release the object when -// IONetworkController is freed. Also see getOutputQueue(). -// -// Returns a newly allocated and initialized IOOutputQueue instance. - -IOOutputQueue * IONetworkController::createOutputQueue() -{ - return 0; -} - -//--------------------------------------------------------------------------- -// Return the output queue allocated though createOutputQueue(). - -IOOutputQueue * IONetworkController::getOutputQueue() const -{ - return _outputQueue; -} - -//--------------------------------------------------------------------------- -// Called by start() to obtain the constraints on the memory buffer -// associated with each mbuf allocated through allocatePacket(). -// Drivers can override this method to specify their buffer constraints -// imposed by their bus master hardware. Note that outbound packets, -// those that originate from the network stack, are not subject -// to the constraints reported here. -// -// constraintsP: A pointer to an IOPacketBufferConstraints structure -// that that this method is expected to initialize. -// See IOPacketBufferConstraints structure definition. - -void IONetworkController::getPacketBufferConstraints( - IOPacketBufferConstraints * constraintsP) const -{ - assert(constraintsP); - constraintsP->alignStart = kIOPacketBufferAlign1; - constraintsP->alignLength = kIOPacketBufferAlign1; -} - -//--------------------------------------------------------------------------- -// Allocates a mbuf chain. Each mbuf in the chain is aligned according to -// the constraints from IONetworkController::getPacketBufferConstraints(). -// The last mbuf in the chain will be guaranteed to be length aligned if -// the 'size' argument is a multiple of the length alignment. -// -// The m->m_len and m->pkthdr.len fields are updated by this function. -// This allows the driver to pass the mbuf chain obtained through this -// function to the IOMbufMemoryCursor object directly. -// -// If (size + alignments) is smaller than MCLBYTES, then this function -// will always return a single mbuf header or cluster. -// -// The allocation is guaranteed not to block. If a packet cannot be -// allocated, this function will return NULL. - -#define IO_APPEND_MBUF(head, tail, m) { \ - if (tail) { \ - (tail)->m_next = (m); \ - (tail) = (m); \ - } \ - else { \ - (head) = (tail) = (m); \ - (head)->m_pkthdr.len = 0; \ - } \ -} - -#define IO_ALIGN_MBUF_START(m, mask) { \ - if ( (mask) & mtod((m), vm_address_t) ) { \ - (m)->m_data = (caddr_t) (( mtod((m), vm_address_t) + (mask) ) \ - & ~(mask)); \ - } \ -} - -#define IO_ALIGN_MBUF(m, size, smask, lmask) { \ - IO_ALIGN_MBUF_START((m), (smask)); \ - (m)->m_len = ((size) - (smask)) & ~(lmask); \ -} - -static struct mbuf * allocateMbuf( UInt32 size, UInt32 smask, UInt32 lmask ) -{ - struct mbuf * m; - struct mbuf * head = 0; - struct mbuf * tail = 0; - UInt32 capacity; - - while ( size ) - { - // Allocate a mbuf. For the initial mbuf segment, allocate a - // mbuf header. - - if ( head == 0 ) - { - MGETHDR( m, M_DONTWAIT, MT_DATA ); - capacity = MHLEN; - } - else - { - MGET( m, M_DONTWAIT, MT_DATA ); - capacity = MLEN; - } - - if ( m == 0 ) goto error; // mbuf allocation error - - // Append the new mbuf to the tail of the mbuf chain. - - IO_APPEND_MBUF( head, tail, m ); - - // If the remaining size exceed the buffer size of a normal mbuf, - // then promote it to a cluster. Currently, the cluster size is - // fixed to MCLBYTES bytes. - - if ( ( size + smask + lmask ) > capacity ) - { - MCLGET( m, M_DONTWAIT ); - if ( (m->m_flags & M_EXT) == 0 ) goto error; - capacity = MCLBYTES; - } - - // Align the mbuf per driver's specifications. - - IO_ALIGN_MBUF( m, capacity, smask, lmask ); - - // Compute the number of bytes needed after accounting for the - // current mbuf allocation. - - if ( (UInt) m->m_len > size ) - m->m_len = size; - - size -= m->m_len; - - // Update the total length in the packet header. - - head->m_pkthdr.len += m->m_len; - } - - return head; - -error: - if ( head ) m_freem(head); - return 0; -} - -struct mbuf * IONetworkController::allocatePacket( UInt32 size ) -{ - struct mbuf * m; - - do { - // Handle the simple case where the requested size - // is small enough for a single mbuf. Otherwise, - // go to the more costly route and call the - // generic mbuf allocation routine. - - if ( ( size + _alignStart ) <= MCLBYTES ) { - if ( ( size + _alignStart ) > MHLEN ) { - m = m_getpacket(); /* MGETHDR+MCLGET under one single lock */ - if ( m == 0 ) break; - } - else - { - MGETHDR( m, M_DONTWAIT, MT_DATA ); - if ( m == 0 ) break; - } - - // Align start of mbuf buffer. - - IO_ALIGN_MBUF_START( m, _alignStart ); - - // No length adjustment for single mbuf. - // Driver gets what it asked for. - - m->m_pkthdr.len = m->m_len = size; - } - else - { - m = allocateMbuf(size, _alignStart, _alignLength); - } - } while ( false ); - - return m; -} - -//--------------------------------------------------------------------------- -// Release the mbuf back to the free pool. - -void IONetworkController::freePacket(struct mbuf * m, IOOptionBits options) -{ - assert(m); - - if ( options & kDelayFree ) - { - m->m_nextpkt = _freeList; - _freeList = m; - } - else - { - m_freem_list(m); - } -} - -UInt32 IONetworkController::releaseFreePackets() -{ - UInt32 count = 0; - - if ( _freeList ) - { - count = m_freem_list( _freeList ); - _freeList = 0; - } - return count; -} - -static inline bool IO_COPY_MBUF( - const struct mbuf * src, - struct mbuf * dst, - int length) -{ - caddr_t src_dat, dst_dat; - int dst_len, src_len; - - assert(src && dst); - - dst_len = dst->m_len; - dst_dat = dst->m_data; - - while (src) { - - src_len = src->m_len; - src_dat = src->m_data; - - if (src_len > length) - src_len = length; - - while (src_len) { - - if (dst_len >= src_len) { - // copy entire src mbuf to dst mbuf. - - bcopy(src_dat, dst_dat, src_len); - length -= src_len; - dst_len -= src_len; - dst_dat += src_len; - src_len = 0; - } - else { - // fill up dst mbuf with some portion of the data in - // the src mbuf. - - bcopy(src_dat, dst_dat, dst_len); // dst_len = 0? - length -= dst_len; - dst_len = 0; - src_len -= dst_len; - } - - // Go to the next destination mbuf segment. - - if (dst_len == 0) { - if (!(dst = dst->m_next)) - return (length == 0); - dst_len = dst->m_len; - dst_dat = dst->m_data; - } - - } /* while (src_len) */ - - src = src->m_next; - - } /* while (src) */ - - return (length == 0); // returns true on success. -} - -//--------------------------------------------------------------------------- -// Replace the mbuf pointed by the given pointer with another mbuf. -// Drivers can call this method to replace a mbuf before passing the -// original mbuf, which contains a received frame, to the network layer. -// -// mp: A pointer to the original mbuf that shall be updated by this -// method to point to the new mbuf. -// size: If size is 0, then the new mbuf shall have the same size -// as the original mbuf that is being replaced. Otherwise, the new -// mbuf shall have the size specified here. -// -// If mbuf allocation was successful, then the replacement will -// take place and the original mbuf will be returned. Otherwise, -// a NULL is returned. - -struct mbuf * IONetworkController::replacePacket(struct mbuf ** mp, - UInt32 size = 0) -{ - assert((mp != NULL) && (*mp != NULL)); - - struct mbuf * m = *mp; - - // If size is zero, then size is taken from the source mbuf. - - if (size == 0) size = m->m_pkthdr.len; - - // Allocate a new packet to replace the current packet. - - if ( (*mp = allocatePacket(size)) == 0 ) - { - *mp = m; m = 0; - } - - return m; -} - -//--------------------------------------------------------------------------- -// Make a copy of a mbuf, and return the copy. The source mbuf is not modified. -// -// m: The source mbuf. -// size: The number of bytes to copy. If set to 0, then the entire -// source mbuf is copied. -// -// Returns a new mbuf created from the source packet. - -struct mbuf * IONetworkController::copyPacket(const struct mbuf * m, - UInt32 size = 0) -{ - struct mbuf * mn; - - assert(m != NULL); - - // If size is zero, then size is taken from the source mbuf. - - if (size == 0) size = m->m_pkthdr.len; - - // Copy the current mbuf to the new mbuf, and return the new mbuf. - // The input mbuf is left intact. - - if ( (mn = allocatePacket(size)) == 0 ) return 0; - - if (!IO_COPY_MBUF(m, mn, size)) - { - freePacket(mn); mn = 0; - } - - return mn; -} - -//--------------------------------------------------------------------------- -// Either replace or copy the source mbuf given depending on the amount of -// data in the source mbuf. This method will either perform a copy or replace -// the source mbuf, whichever is more time efficient. If replaced, then the -// original mbuf is returned, and a new mbuf is allocated to take its place. -// If copied, the source mbuf is left intact, while a copy is returned that -// is just big enough to hold all the data from the source mbuf. -// -// mp: A pointer to the source mbuf that may be updated by this -// method to point to the new mbuf if replaced. -// rcvlen: The number of data bytes in the source mbuf. -// replacedP: Pointer to a bool that is set to true if the -// source mbuf was replaced, or set to false if the -// source mbuf was copied. -// -// Returns a replacement or a copy of the source mbuf, 0 if mbuf -// allocation failed. - -struct mbuf * IONetworkController::replaceOrCopyPacket(struct mbuf ** mp, - UInt32 rcvlen, - bool * replacedP) -{ - struct mbuf * m; - - assert((mp != NULL) && (*mp != NULL)); - - if ( (rcvlen + _alignPadding) > MHLEN ) - { - // Large packet, it is more efficient to allocate a new mbuf - // to replace the original mbuf than to make a copy. The new - // packet shall have exactly the same size as the original - // mbuf being replaced. - - m = *mp; - - if ( (*mp = allocatePacket(m->m_pkthdr.len)) == 0 ) - { - *mp = m; m = 0; // error recovery - } - - *replacedP = true; - } - else - { - // The copy will fit within a header mbuf. Fine, make a copy - // of the original mbuf instead of replacing it. We only copy - // the rcvlen bytes, not the entire source mbuf. - - if ( (m = allocatePacket(rcvlen)) == 0 ) return 0; - - if (!IO_COPY_MBUF(*mp, m, rcvlen)) - { - freePacket(m); m = 0; - } - - *replacedP = false; - } - - return m; -} - -//--------------------------------------------------------------------------- -// Get hardware support of network/transport layer checksums. - -IOReturn -IONetworkController::getChecksumSupport( UInt32 * checksumMask, - UInt32 checksumFamily, - bool isOutput ) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Update a mbuf with the result from the hardware checksum engine. - -#define kTransportLayerPartialChecksums \ - ( kChecksumTCPNoPseudoHeader | \ - kChecksumUDPNoPseudoHeader | \ - kChecksumTCPSum16 ) - -#define kTransportLayerFullChecksums \ - ( kChecksumTCP | kChecksumUDP ) - -bool -IONetworkController::setChecksumResult( struct mbuf * m, - UInt32 family, - UInt32 result, - UInt32 valid, - UInt32 param0 = 0, - UInt32 param1 = 0 ) -{ -#ifdef HW_CSUM_SUPPORT - // Reporting something that is valid without checking for it - // is forbidden. - - valid &= result; - - // Initialize checksum result fields in the packet. - - m->m_pkthdr.csum_flags = 0; - - if ( family != kChecksumFamilyTCPIP ) - { - return false; - } - - // Set the result for the network layer (IP) checksum. - - if ( result & kChecksumIP ) - { - m->m_pkthdr.csum_flags = CSUM_IP_CHECKED; - if ( valid & kChecksumIP ) - m->m_pkthdr.csum_flags |= CSUM_IP_VALID; - } - - // Now examine the transport layer checksum flags. - - if ( valid & kTransportLayerFullChecksums ) - { - // Excellent, hardware did account for the pseudo-header - // and no "partial" checksum value is required. - - m->m_pkthdr.csum_flags |= ( CSUM_DATA_VALID | CSUM_PSEUDO_HDR ); - m->m_pkthdr.csum_data = 0xffff; // fake a valid checksum value - } - else if ( result & kTransportLayerPartialChecksums ) - { - // Hardware does not account for the pseudo-header. - // Driver must pass up the partial TCP/UDP checksum, - // and the transport layer must adjust for the missing - // 12-byte pseudo-header. - - m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; - m->m_pkthdr.csum_data = (UInt16) param0; - - if ( result & kChecksumTCPSum16 ) - { - // A very simple engine that only computes a ones complement - // sum of 16-bit words (UDP/TCP style checksum), from a fixed - // offset, without the ability to scan for the IP or UDP/TCP - // headers. Must pass up the offset to the packet data where - // the checksum computation started from. - - m->m_pkthdr.csum_flags |= CSUM_TCP_SUM; // XXX - fake constant - m->m_pkthdr.csum_data |= (((UInt16) param1) << 16); - } - } - return true; -#else - return false; -#endif HW_CSUM_SUPPORT -} - -//--------------------------------------------------------------------------- -// Get the checksums that must be performed by the hardware for the -// given packet, before it is sent on the network. - -void -IONetworkController::getChecksumDemand( const struct mbuf * m, - UInt32 checksumFamily, - UInt32 * demandMask, - void * param0 = 0, - void * param1 = 0 ) -{ -#ifdef HW_CSUM_SUPPORT - if ( checksumFamily != kChecksumFamilyTCPIP ) - { - *demandMask = 0; return; - } - - *demandMask = m->m_pkthdr.csum_flags & ( kChecksumIP | - kChecksumTCP | - kChecksumUDP | - kChecksumTCPSum16 ); - - if ( m->m_pkthdr.csum_flags & kChecksumTCPSum16 ) - { - // param0 is start offset (XXX - range?) - // param1 is stuff offset (XXX - range?) - - if (param0) - *((UInt16 *) param0) = (UInt16) (m->m_pkthdr.csum_data); - if (param1) - *((UInt16 *) param1) = (UInt16) (m->m_pkthdr.csum_data >> 16); - } -#else - *demandMask = 0; - return; -#endif HW_CSUM_SUPPORT -} - -#if 0 -//--------------------------------------------------------------------------- -// Used for debugging only. Log the mbuf fields. - -static void _logMbuf(struct mbuf * m) -{ - if (!m) { - IOLog("logMbuf: NULL mbuf\n"); - return; - } - - while (m) { - IOLog("m_next : %08x\n", (UInt) m->m_next); - IOLog("m_nextpkt: %08x\n", (UInt) m->m_nextpkt); - IOLog("m_len : %d\n", (UInt) m->m_len); - IOLog("m_data : %08x\n", (UInt) m->m_data); - IOLog("m_type : %08x\n", (UInt) m->m_type); - IOLog("m_flags : %08x\n", (UInt) m->m_flags); - - if (m->m_flags & M_PKTHDR) - IOLog("m_pkthdr.len : %d\n", (UInt) m->m_pkthdr.len); - - if (m->m_flags & M_EXT) { - IOLog("m_ext.ext_buf : %08x\n", (UInt) m->m_ext.ext_buf); - IOLog("m_ext.ext_size: %d\n", (UInt) m->m_ext.ext_size); - } - - m = m->m_next; - } - IOLog("\n"); -} -#endif /* 0 */ - -//--------------------------------------------------------------------------- -// Allocate and attache a new IOKernelDebugger client object. -// -// debuggerP: A handle that is updated by this method -// with the allocated IOKernelDebugger instance. -// -// Returns true on success, false otherwise. - -bool IONetworkController::attachDebuggerClient(IOKernelDebugger ** debugger) -{ - IOKernelDebugger * client; - bool ret = false; - - // Prepare the controller. - - if (executeCommand(this, &IONetworkController::handleCommand, - this, (void *) kCommandPrepare) != kIOReturnSuccess) - { - return false; - } - - // Create a debugger client nub and register the static - // member functions as the polled-mode handlers. - - client = IOKernelDebugger::debugger( this, - &debugTxHandler, - &debugRxHandler ); - - if ( client && !client->attach(this) ) - { - // Unable to attach the client object. - client->terminate( kIOServiceRequired | kIOServiceSynchronous ); - client->release(); - client = 0; - } - - *debugger = client; - - if ( client ) - { - client->registerService(); - ret = true; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Detach and terminate the IOKernelDebugger client object provided. -// A synchronous termination is issued, and this method returns after -// the debugger client has been terminated. -// -// debugger: The IOKernelDebugger instance to be detached and terminated. -// If the argument provided is NULL or is not an IOKernelDebugger, -// this method will return immediately. - -void IONetworkController::detachDebuggerClient(IOKernelDebugger * debugger) -{ - if (OSDynamicCast(IOKernelDebugger, debugger) == 0) - return; - - // Terminate the debugger client and return after the client has - // been terminated. - - debugger->terminate(kIOServiceRequired | kIOServiceSynchronous); -} - -//--------------------------------------------------------------------------- -// An enable request from an IOKernelDebugger client. - -IOReturn IONetworkController::enable(IOKernelDebugger * debugger) -{ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// A disable request from an IOKernelDebugger client. - -IOReturn IONetworkController::disable(IOKernelDebugger * debugger) -{ - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Take and release the debugger lock. - -void IONetworkController::reserveDebuggerLock() -{ - if ( _debugLockCount++ == 0 ) - { - _debugLockState = IODebuggerLock( this ); - } -} - -void IONetworkController::releaseDebuggerLock() -{ - if ( --_debugLockCount == 0 ) - { - IODebuggerUnlock( _debugLockState ); - } - assert( _debugLockCount >= 0 ); -} - -//--------------------------------------------------------------------------- -// This static C++ member function is registered by attachDebuggerClient() -// as the debugger receive handler. IOKernelDebugger will call this -// function when KDP is polling for a received packet. This function will -// in turn will call the receivePacket() member function implemented by -// a driver with debugger support. - -void IONetworkController::debugRxHandler(IOService * handler, - void * buffer, - UInt32 * length, - UInt32 timeout) -{ - ((IONetworkController *) handler)->receivePacket(buffer, - length, - timeout); -} - -//--------------------------------------------------------------------------- -// This static C++ member function is registered by attachDebuggerClient() -// as the debugger transmit handler. IOKernelDebugger will call this -// function when KDP sends an outgoing packet. This function will in turn -// call the sendPacket() member function implemented by a driver with -// debugger support. - -void IONetworkController::debugTxHandler(IOService * handler, - void * buffer, - UInt32 length) -{ - ((IONetworkController *) handler)->sendPacket(buffer, length); -} - -//--------------------------------------------------------------------------- -// This method must be implemented by a driver that supports kernel debugging. -// After a debugger client is attached through attachDebuggerClient(), this -// method will be called by the debugger client to poll for a incoming packet -// when the debugger session is active. This method may be called from the -// primary interrupt context, implementation must avoid any memory allocation, -// and must never block. The receivePacket() method in IONetworkController is -// used as a placeholder and should not be called. A driver that attaches -// a debugger client must override this method. -// -// pkt: Pointer to a receive buffer where the received packet should -// be stored to. The buffer has enough space for 1518 bytes. -// pkt_len: The length of the received packet must be written to the -// integer pointed by pkt_len. -// timeout: The maximum amount of time in milliseconds to poll for -// a packet to arrive before this method must return. - -void IONetworkController::receivePacket(void * /*pkt*/, - UInt32 * /*pkt_len*/, - UInt32 /*timeout*/) -{ - IOLog("IONetworkController::%s()\n", __FUNCTION__); -} - -//--------------------------------------------------------------------------- -// Debugger polled-mode transmit handler. This method must be implemented -// by a driver that supports kernel debugging. After a debugger client is -// attached through attachDebuggerClient(), this method will be called by the -// debugger to send an outbound packet when the kernel debugger is active. -// This method may be called from the primary interrupt context, and the -// implementation must avoid any memory allocation, and must never block. -// sendPacket() method in IONetworkController is used as a placeholder -// and should not be called. A driver that attaches a debugger client -// must override this method. -// -// pkt: Pointer to a transmit buffer containing the packet to be sent. -// pkt_len: The amount of data in the transmit buffer. - -void IONetworkController::sendPacket(void * /*pkt*/, UInt32 /*pkt_len*/) -{ - IOLog("IONetworkController::%s()\n", __FUNCTION__); -} - -//--------------------------------------------------------------------------- -// Report the link status and the active medium. - -bool IONetworkController::setLinkStatus( - UInt32 status, - const IONetworkMedium * activeMedium, - UInt64 speed, - OSData * data) -{ - bool success = true; - bool changed = false; - UInt32 linkEvent = 0; - const OSSymbol * name = activeMedium ? activeMedium->getName() : - gIONullMediumName; - - if (data == 0) - data = (OSData *) gIONullLinkData; - - if ((speed == 0) && activeMedium) - speed = activeMedium->getSpeed(); - - MEDIUM_LOCK; - - // Update kIOActiveMedium property. - - if (name != _lastActiveMediumName) - { - if ( setProperty(gIOActiveMediumKey, (OSSymbol *) name) ) - { - changed = true; - _lastActiveMediumName = name; - } - else - success = false; - } - - // Update kIOLinkData property. - - if (data != _lastLinkData) - { - if ( setProperty(gIOLinkDataKey, data) ) - { - changed = true; - _lastLinkData = data; - } - else - success = false; - } - - // Update kIOLinkStatus property. - - if (status != _linkStatus->unsigned32BitValue()) - { - if (status & kIONetworkLinkValid) - { - linkEvent = (status & kIONetworkLinkActive) ? - kIONetworkEventTypeLinkUp : - kIONetworkEventTypeLinkDown; - } - _linkStatus->setValue(status); - changed = true; - } - - // Update kIOLinkSpeed property. - - if (speed != _linkSpeed->unsigned64BitValue()) - { - _linkSpeed->setValue(speed); - changed = true; - } - - MEDIUM_UNLOCK; - - // Broadcast a link event to interface objects. - - if (linkEvent) - _broadcastEvent(linkEvent); - - return success; -} - -//--------------------------------------------------------------------------- -// Returns the medium dictionary published by the driver through -// publishMediumDictionary(). Use copyMediumDictionary() to get a copy -// of the medium dictionary. -// -// Returns the published medium dictionary, or 0 if the driver has not -// yet published a medium dictionary through publishMediumDictionary(). - -const OSDictionary * IONetworkController::getMediumDictionary() const -{ - return (OSDictionary *) getProperty(kIOMediumDictionary); -} - -//--------------------------------------------------------------------------- -// Returns a copy of the medium dictionary published by the driver. -// The caller is responsible for releasing the dictionary object returned. -// Use getMediumDictionary() to get a reference to the published medium -// dictionary instead of creating a copy. -// -// Returns a copy of the medium dictionary, or 0 if the driver has not -// published a medium dictionary through publishMediumDictionary(). - -OSDictionary * IONetworkController::copyMediumDictionary() const -{ - const OSDictionary * mediumDict; - OSDictionary * copy = 0; - - MEDIUM_LOCK; - - mediumDict = getMediumDictionary(); - - if (mediumDict) - { - copy = OSDictionary::withDictionary(mediumDict, - mediumDict->getCount()); - } - - MEDIUM_UNLOCK; - - return copy; -} - -//--------------------------------------------------------------------------- -// A client request to change the media selection. - -IOReturn IONetworkController::selectMedium(const IONetworkMedium * medium) -{ - return kIOReturnUnsupported; -} - -//--------------------------------------------------------------------------- -// Private function to lookup a key in the medium dictionary and call -// setMedium() if a match is found. This function is called by our -// clients to change the medium selection by passing a name for the desired -// medium. - -IOReturn IONetworkController::selectMediumWithName(const OSSymbol * mediumName) -{ - OSSymbol * currentMediumName; - IONetworkMedium * newMedium = 0; - bool doChange = true; - IOReturn ret = kIOReturnSuccess; - - if (OSDynamicCast(OSSymbol, mediumName) == 0) - return kIOReturnBadArgument; - - MEDIUM_LOCK; - - do { - const OSDictionary * mediumDict = getMediumDictionary(); - if (!mediumDict) - { - // no medium dictionary, bail out. - ret = kIOReturnUnsupported; - break; - } - - // Lookup the new medium in the dictionary. - - newMedium = (IONetworkMedium *) mediumDict->getObject(mediumName); - if (!newMedium) - { - ret = kIOReturnBadArgument; - break; // not found, invalid mediumName. - } - - newMedium->retain(); - - // Lookup the current medium key to avoid unnecessary - // medium changes. - - currentMediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey); - - // Is change necessary? - - if (currentMediumName && mediumName->isEqualTo(currentMediumName)) - doChange = false; - } - while (0); - - MEDIUM_UNLOCK; - - if (newMedium) - { - // Call the driver's selectMedium() without holding the medium lock. - - if (doChange) - ret = selectMedium(newMedium); - - // Remove the earlier retain. - - newMedium->release(); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Designate an entry in the published medium dictionary as -// the current selected medium. - -bool IONetworkController::setSelectedMedium(const IONetworkMedium * medium) -{ - bool success = true; - bool changed = false; - const OSSymbol * name = medium ? medium->getName() : gIONullMediumName; - - MEDIUM_LOCK; - - if (name != _lastCurrentMediumName) - { - if ( setProperty(gIOCurrentMediumKey, (OSSymbol *) name) ) - { - changed = true; - _lastCurrentMediumName = name; - } - else - success = false; - } - - MEDIUM_UNLOCK; - -#if 0 - if (changed) - _broadcastEvent(kIONetworkEventTypeLinkChange); -#endif - - return success; -} - -//--------------------------------------------------------------------------- -// Get the current selected medium. - -const IONetworkMedium * IONetworkController::getSelectedMedium() const -{ - IONetworkMedium * medium = 0; - OSSymbol * mediumName; - - MEDIUM_LOCK; - - do { - const OSDictionary * mediumDict = getMediumDictionary(); - if (!mediumDict) // no medium dictionary, bail out. - break; - - // Fetch the current medium name from the property table. - - mediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey); - - // Make sure the current medium name points to an entry in - // the medium dictionary. - - medium = (IONetworkMedium *) mediumDict->getObject(mediumName); - - // Invalid current medium, try the default medium. - - if ( medium == 0 ) - { - OSString * aString; - - // This comes from the driver's property list. - // More checking is done to avoid surprises. - - aString = OSDynamicCast( OSString, - getProperty(gIODefaultMediumKey) ); - - medium = (IONetworkMedium *) mediumDict->getObject(aString); - } - } - while (0); - - MEDIUM_UNLOCK; - - return medium; -} - -//--------------------------------------------------------------------------- -// A private function to verify a medium dictionary. Returns true if the -// dictionary is OK. - -static bool verifyMediumDictionary(const OSDictionary * mediumDict) -{ - OSCollectionIterator * iter; - bool verifyOk = true; - OSSymbol * key; - - if (!OSDynamicCast(OSDictionary, mediumDict)) - return false; // invalid argument - - if (mediumDict->getCount() == 0) - return false; // empty dictionary - - iter = OSCollectionIterator::withCollection((OSDictionary *) mediumDict); - if (!iter) - return false; // cannot allocate iterator - - while ((key = (OSSymbol *) iter->getNextObject())) - { - if ( !OSDynamicCast(IONetworkMedium, mediumDict->getObject(key)) ) - { - verifyOk = false; // non-medium object in dictionary - break; - } - } - - iter->release(); - - return verifyOk; -} - -//--------------------------------------------------------------------------- -// Publish a dictionary of IONetworkMedium objects. - -bool -IONetworkController::publishMediumDictionary(const OSDictionary * mediumDict) -{ - OSDictionary * cloneDict; - bool ret = false; - - if (!verifyMediumDictionary(mediumDict)) - return false; // invalid dictionary - - // Create a clone of the source dictionary. This prevents the driver - // from adding/removing entries after the medium dictionary is added - // to the property table. - - cloneDict = OSDictionary::withDictionary(mediumDict, - mediumDict->getCount()); - if (!cloneDict) - return false; // unable to create a copy - - MEDIUM_LOCK; - - // Add the dictionary to the property table. - - if (setProperty(kIOMediumDictionary, cloneDict)) - { - const OSSymbol * mediumName; - - // Update kIOSelectedMedium property. - - mediumName = (OSSymbol *) getProperty(gIOCurrentMediumKey); - if (cloneDict->getObject(mediumName) == 0) - { - mediumName = gIONullMediumName; - } - setProperty(gIOCurrentMediumKey, (OSSymbol *) mediumName); - _lastCurrentMediumName = mediumName; - - // Update kIOActiveMedium property. - - mediumName = (OSSymbol *) getProperty(gIOActiveMediumKey); - if (cloneDict->getObject(mediumName) == 0) - { - mediumName = gIONullMediumName; - } - setProperty(gIOActiveMediumKey, (OSSymbol *) mediumName); - _lastActiveMediumName = mediumName; - - ret = true; - } - - MEDIUM_UNLOCK; - - // Retained by the property table. drop our retain count. - - cloneDict->release(); - -#if 0 - // Broadcast a link change event. - - _broadcastEvent(kIONetworkEventTypeLinkChange); -#endif - - return ret; -} - -//--------------------------------------------------------------------------- -// Static function called by the internal IOCommandGate object to -// handle a runAction() request invoked by executeCommand(). - -IOReturn IONetworkController::executeCommandAction(OSObject * owner, - void * arg0, - void * /* arg1 */, - void * /* arg2 */, - void * /* arg3 */) -{ - IONetworkController * self = (IONetworkController *) owner; - cmdStruct * cmdP = (cmdStruct *) arg0; - IOReturn ret; - bool accept = true; - OSObject * oldClient; - - assert(cmdP && self); - - oldClient = self->_cmdClient; - - if (accept != true) - { - // Command rejected. - ret = kIOReturnNotPermitted; - } - else - { - self->_cmdClient = cmdP->client; - - cmdP->ret = (*cmdP->action)( cmdP->target, - cmdP->param0, - cmdP->param1, - cmdP->param2, - cmdP->param3 ); - - self->_cmdClient = oldClient; - - ret = kIOReturnSuccess; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Perform an "action" that is synchronized by the command gate. - -IOReturn IONetworkController::executeCommand(OSObject * client, - Action action, - void * target, - void * param0, - void * param1, - void * param2, - void * param3) -{ - cmdStruct cmd; - IOReturn ret; - - cmd.client = client; - cmd.action = action; - cmd.target = target; - cmd.param0 = param0; - cmd.param1 = param1; - cmd.param2 = param2; - cmd.param3 = param3; - - // Execute the client command through the command gate. Client commands - // are thus synchronized with the workloop returned by getWorkLoop(). - - ret = _cmdGate->runAction( (IOCommandGate::Action) - &IONetworkController::executeCommandAction, - (void *) &cmd ); /* arg0 - cmdStruct */ - - // If executeCommandAction() executed successfully, then return the - // status from the client command that was executed. - - if (ret == kIOReturnSuccess) - ret = cmd.ret; - - return ret; -} - -//--------------------------------------------------------------------------- -// Called by executeCommand() to handle the client command on the -// workloop context. - -IOReturn IONetworkController::handleCommand(void * target, - void * param0, - void * param1, - void * param2, - void * param3) -{ - - IONetworkController * self = (IONetworkController *) target; - UInt32 command = (UInt32) param0; - IOService * client = (IOService *) param1; - IOReturn ret; - - switch (command) - { - case kCommandEnable: - ret = self->enable(client); - break; - - case kCommandDisable: - ret = self->disable(client); - break; - - case kCommandPrepare: - ret = self->prepare(); - break; - - default: - ret = kIOReturnUnsupported; - break; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Issue an kCommandEnable command to handleCommand(). - -IOReturn IONetworkController::doEnable(IOService * client) -{ - return executeCommand( client, - &IONetworkController::handleCommand, - this, - (void *) kCommandEnable, - (void *) client); -} - -//--------------------------------------------------------------------------- -// Issue an kCommandDisable command to handleCommand(). - -IOReturn IONetworkController::doDisable(IOService * client) -{ - return executeCommand( client, - &IONetworkController::handleCommand, - this, - (void *) kCommandDisable, - (void *) client); -} diff --git a/iokit/Families/IONetworking/IONetworkData.cpp b/iokit/Families/IONetworking/IONetworkData.cpp deleted file mode 100644 index 821f02b60..000000000 --- a/iokit/Families/IONetworking/IONetworkData.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkData.cpp - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <libkern/c++/OSDictionary.h> -#include <libkern/c++/OSNumber.h> -#include <libkern/c++/OSData.h> -#include <IOKit/network/IONetworkData.h> - -#define super OSObject -OSDefineMetaClassAndStructors( IONetworkData, OSObject ) -OSMetaClassDefineReservedUnused( IONetworkData, 0); -OSMetaClassDefineReservedUnused( IONetworkData, 1); -OSMetaClassDefineReservedUnused( IONetworkData, 2); -OSMetaClassDefineReservedUnused( IONetworkData, 3); - -#define TAP_IS_VALID (_tapAction) - -// All access method are serialized by a single global lock, -// shared among all IONetworkData instances. -// -static IOLock * gIONDLock = 0; -#define LOCK IOTakeLock(gIONDLock) -#define UNLOCK IOUnlock(gIONDLock) - -static const OSSymbol * gIONDDataKey; -static const OSSymbol * gIONDAccessKey; -static const OSSymbol * gIONDSizeKey; - -//--------------------------------------------------------------------------- -// IONetworkData class initializer. - -void IONetworkData::initialize() -{ - // Allocates the global data lock. - // - gIONDLock = IOLockAlloc(); - assert(gIONDLock); - IOLockInitWithState(gIONDLock, kIOLockStateUnlocked); - - gIONDDataKey = OSSymbol::withCStringNoCopy( kIONetworkDataBytes ); - gIONDAccessKey = OSSymbol::withCStringNoCopy( kIONetworkDataAccessTypes ); - gIONDSizeKey = OSSymbol::withCStringNoCopy( kIONetworkDataSize ); - - assert(gIONDDataKey && gIONDAccessKey && gIONDSizeKey); -} - -//--------------------------------------------------------------------------- -// Initialize an IONetworkData instance. - -bool -IONetworkData::init(const char * name, - UInt32 bufferType, - UInt32 bufferSize, - void * extBuffer = 0, - UInt32 accessTypes = kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0) -{ - if ((bufferType == kIONetworkDataBufferTypeInternal) || - (bufferType == kIONetworkDataBufferTypeExternal)) - { - _buffer = (bufferType == kIONetworkDataBufferTypeInternal) ? - (void *) kalloc(bufferSize) : extBuffer; - - if (_buffer == 0) - return false; - - if (bufferType == kIONetworkDataBufferTypeInternal) - bzero(_buffer, bufferSize); - } - - _bufType = bufferType; - _access = accessTypes; - _tapTarget = target; - _tapAction = action; - _tapParam = param; - _size = bufferSize; - - // Generate a key for this object based on its assigned name. - // - if ((_key = OSSymbol::withCString(name)) == 0) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Factory method that will construct and initialize an IONetworkData -// instance with an internal buffer. - -IONetworkData * -IONetworkData::withInternalBuffer( - const char * name, - UInt32 bufferSize, - UInt32 accessTypes = kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0) -{ - IONetworkData * aData = new IONetworkData; - - if (aData && !aData->init(name, - kIONetworkDataBufferTypeInternal, - bufferSize, - 0, - accessTypes, - target, - action, - param)) - { - aData->release(); - aData = 0; - } - return aData; -} - -//--------------------------------------------------------------------------- -// Factory method that will construct and initialize an IONetworkData -// instance with an external buffer. - -IONetworkData * -IONetworkData::withExternalBuffer( - const char * name, - UInt32 bufferSize, - void * buffer, - UInt32 accessTypes = kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0) -{ - IONetworkData * aData = new IONetworkData; - - if (aData && !aData->init(name, - kIONetworkDataBufferTypeExternal, - bufferSize, - buffer, - accessTypes, - target, - action, - param)) - { - aData->release(); - aData = 0; - } - return aData; -} - -//--------------------------------------------------------------------------- -// Factory method that will construct and initialize an IONetworkData -// instance with no data buffer. The notification handler must intervene -// when the IONetworkData is accessed. - -IONetworkData * -IONetworkData::withNoBuffer(const char * name, - UInt32 bufferSize, - UInt32 accessTypes, - void * target, - Action action, - void * param = 0) -{ - IONetworkData * aData = new IONetworkData; - - if (aData && !aData->init(name, - kIONetworkDataBufferTypeNone, - bufferSize, - 0, - accessTypes, - target, - action, - param)) - { - aData->release(); - aData = 0; - } - return aData; -} - -//--------------------------------------------------------------------------- -// Free the IONetworkData instance. - -void IONetworkData::free() -{ - if (_key) - _key->release(); - - if (_buffer && (_bufType == kIONetworkDataBufferTypeInternal)) - kfree((vm_offset_t) _buffer, _size); - - super::free(); -} - -//--------------------------------------------------------------------------- -// Return the type of buffer managed by this instance. -// See IONetworkDataBufferType enum definition - -UInt32 IONetworkData::getBufferType() const -{ - return _bufType; -} - -//--------------------------------------------------------------------------- -// Change the supported access types. - -#define kIONetworkDataImmutableAccessTypes 0 - -void IONetworkData::setAccessTypes(UInt32 types) -{ - LOCK; - _access = (_access & kIONetworkDataImmutableAccessTypes) | - (types & ~kIONetworkDataImmutableAccessTypes); - UNLOCK; -} - -//--------------------------------------------------------------------------- -// Register a target/action to handle access notification. - -void IONetworkData::setNotificationTarget(void * target, - Action action, - void * param) -{ - LOCK; - _tapTarget = target; - _tapAction = action; - _tapParam = param; - UNLOCK; -} - -//--------------------------------------------------------------------------- -// Return the supported access types. - -UInt32 IONetworkData::getAccessTypes() const -{ - return _access; -} - -//--------------------------------------------------------------------------- -// Return the notification target. - -void * IONetworkData::getNotificationTarget() const -{ - return _tapTarget; -} - -//--------------------------------------------------------------------------- -// Return the notification action. - -IONetworkData::Action IONetworkData::getNotificationAction() const -{ - return _tapAction; -} - -//--------------------------------------------------------------------------- -// Return the notification parameter. - -void * IONetworkData::getNotificationParameter() const -{ - return _tapParam; -} - -//--------------------------------------------------------------------------- -// Get an OSSymbol key associated with this instance. -// During initialization, IONetworkData will create an OSSymbol -// key based on its assigned name. -// -// Return an OSSymbol key generated from the assigned name. - -const OSSymbol * IONetworkData::getKey() const -{ - return _key; -} - -//--------------------------------------------------------------------------- -// Return the size of the data managed by this instance in bytes. - -UInt32 IONetworkData::getSize() const -{ - return _size; -} - -//--------------------------------------------------------------------------- -// Write to the data buffer with data from a source buffer provided -// by the caller. - -bool IONetworkData::writeBytes(const void * srcBuffer, - UInt32 srcBufferSize, - UInt32 writeOffset) -{ - if ( _buffer == 0 ) return false; - - if ( srcBufferSize && - (writeOffset < _size) && - ((writeOffset + srcBufferSize) <= _size) ) - { - bcopy(srcBuffer, (char *) _buffer + writeOffset, srcBufferSize); - return true; - } - - return false; -} - -//--------------------------------------------------------------------------- -// Return a pointer to the data buffer. - -const void * IONetworkData::getBuffer() const -{ - return (_buffer) ? _buffer : 0; -} - -//--------------------------------------------------------------------------- -// Copy the data buffer to a destination buffer provided by the caller. - -bool IONetworkData::readBytes(void * dstBuffer, - UInt32 * dstBufferSize, - UInt32 readOffset) const -{ - if ( _buffer == 0 ) return false; - - if ( *dstBufferSize && (readOffset < _size) ) - { - UInt32 bytesCopied = min((_size - readOffset), *dstBufferSize); - - bcopy((char *) _buffer + readOffset, dstBuffer, bytesCopied); - - *dstBufferSize = bytesCopied; - - return true; - } - - return false; -} - -//--------------------------------------------------------------------------- -// Clear the entire data buffer by filling it with zeroes. - -bool IONetworkData::clearBuffer() -{ - if ( _buffer ) - { - bzero((void *) _buffer, _size); - return true; - } - return false; -} - -//--------------------------------------------------------------------------- -// Handle a user space request to reset the data buffer. - -IOReturn IONetworkData::reset() -{ - IOReturn ret = kIOReturnUnsupported; - - LOCK; - - do { - // Check access. - - if ( (_access & kIONetworkDataAccessTypeReset) == 0 ) - { - ret = kIOReturnNotWritable; - break; - } - - // Default action is to bzero the entire buffer. - - if ( clearBuffer() ) - { - ret = kIOReturnSuccess; - } - - // Notify our target. - - if ( TAP_IS_VALID ) - { - ret = (*_tapAction)(_tapTarget, _tapParam, - this, - (UInt32) kIONetworkDataAccessTypeReset, - 0, 0, 0); - } - } - while (0); - - UNLOCK; - - return ret; -} - -//--------------------------------------------------------------------------- -// Handle an external request to read from the data buffer -// and copy it to the destination buffer provided by the accessor. - -IOReturn IONetworkData::read(void * dstBuffer, - UInt32 * dstBufferSize, - UInt32 readOffset) -{ - IOReturn ret = kIOReturnUnsupported; - - LOCK; - - do { - // Check the arguments. - - if ( !dstBuffer || !dstBufferSize ) - { - ret = kIOReturnBadArgument; - break; - } - - // Check access. - - if ( (_access & kIONetworkDataAccessTypeRead) == 0 ) - { - ret = kIOReturnNotReadable; - break; - } - - // Notify the target before the read operation. - // The target can take this opportunity to update the - // data buffer. If the target returns an error, - // abort and return the error. - - if ( TAP_IS_VALID ) - { - ret = (*_tapAction)(_tapTarget, _tapParam, - this, - (UInt32) kIONetworkDataAccessTypeRead, - dstBuffer, - dstBufferSize, - readOffset); - if (ret != kIOReturnSuccess) - break; - } - - if ( _buffer ) - { - ret = readBytes(dstBuffer, dstBufferSize, readOffset) ? - kIOReturnSuccess : kIOReturnBadArgument; - } - } - while (0); - - UNLOCK; - - return ret; -} - -//--------------------------------------------------------------------------- -// Handle an external request to write to the data buffer -// from a source buffer provided by the accessor. - -IOReturn IONetworkData::write(void * srcBuffer, - UInt32 srcBufferSize, - UInt32 writeOffset) -{ - IOReturn ret = kIOReturnUnsupported; - - LOCK; - - do { - // Check the arguments. - - if ( srcBuffer == 0 ) - { - ret = kIOReturnBadArgument; - break; - } - - // Check access. - - if ( (_access & kIONetworkDataAccessTypeWrite) == 0 ) - { - ret = kIOReturnNotWritable; - break; - } - - // Update the data buffer. - - if ( _buffer && - (writeBytes(srcBuffer, srcBufferSize, writeOffset) == false) ) - { - ret = kIOReturnBadArgument; - break; - } - - // Notify the target after a successful write operation. - - if ( TAP_IS_VALID ) - { - ret = (*_tapAction)(_tapTarget, _tapParam, - this, - (UInt32) kIONetworkDataAccessTypeWrite, - srcBuffer, - &srcBufferSize, - writeOffset); - } - } - while (0); - - UNLOCK; - - return ret; -} - -//--------------------------------------------------------------------------- -// Serialize the IONetworkData object. If notification is enabled, -// then the notification handler is called before the data buffer is -// serialized. - -bool IONetworkData::serialize(OSSerialize * s) const -{ - bool ok; - OSDictionary * dictToSerialize; - OSData * dataEntry; - OSNumber * numberEntry; - - dictToSerialize = OSDictionary::withCapacity(3); - if (!dictToSerialize) - return false; - - numberEntry = OSNumber::withNumber(_access, sizeof(_access) * 8); - if (numberEntry) { - dictToSerialize->setObject(gIONDAccessKey, numberEntry); - numberEntry->release(); - } - - numberEntry = OSNumber::withNumber(_size, sizeof(_size) * 8); - if (numberEntry) { - dictToSerialize->setObject(gIONDSizeKey, numberEntry); - numberEntry->release(); - } - - LOCK; - - do { - // Check access. - - if ((_access & kIONetworkDataAccessTypeSerialize) == 0) - break; - - if (_buffer == 0) - break; - - // Notify the target before the read operation. - // The target can take this opportunity to update the - // data buffer. If the target returns an error, - // then the data buffer is not serialized. - - if (TAP_IS_VALID && - ((*_tapAction)(_tapTarget, _tapParam, - (IONetworkData *) this, - kIONetworkDataAccessTypeSerialize, - 0, 0, 0) != kIOReturnSuccess)) - { - break; - } - - dataEntry = OSData::withBytesNoCopy(_buffer, _size); - if (dataEntry) { - dictToSerialize->setObject(gIONDDataKey, dataEntry); - dataEntry->release(); - } - } - while (0); - - ok = dictToSerialize->serialize(s); - dictToSerialize->release(); - - UNLOCK; - - return ok; -} diff --git a/iokit/Families/IONetworking/IONetworkInterface.cpp b/iokit/Families/IONetworking/IONetworkInterface.cpp deleted file mode 100644 index 849752297..000000000 --- a/iokit/Families/IONetworking/IONetworkInterface.cpp +++ /dev/null @@ -1,1531 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkInterface.cpp - * - * HISTORY - * 8-Jan-1999 Joe Liu (jliu) created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOBSD.h> -#include <IOKit/network/IONetworkInterface.h> -#include <IOKit/network/IONetworkController.h> -#include <IOKit/network/IONetworkUserClient.h> -#include <IOKit/network/IONetworkStack.h> - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <net/bpf.h> -#include <net/if.h> -#include <netinet/if_ether.h> -#include <net/if_media.h> -#include <net/dlil.h> -int copyout(void *kaddr, void *udaddr, size_t len); - -#ifdef KEV_DL_LINK_ON -#include <sys/kern_event.h> -int dlil_event(struct ifnet *ifp, struct kern_event_msg *event); -#endif -} - -//--------------------------------------------------------------------------- - -#define super IOService - -OSDefineMetaClassAndAbstractStructors( IONetworkInterface, IOService ) -OSMetaClassDefineReservedUnused( IONetworkInterface, 0); -OSMetaClassDefineReservedUnused( IONetworkInterface, 1); -OSMetaClassDefineReservedUnused( IONetworkInterface, 2); -OSMetaClassDefineReservedUnused( IONetworkInterface, 3); -OSMetaClassDefineReservedUnused( IONetworkInterface, 4); -OSMetaClassDefineReservedUnused( IONetworkInterface, 5); -OSMetaClassDefineReservedUnused( IONetworkInterface, 6); -OSMetaClassDefineReservedUnused( IONetworkInterface, 7); -OSMetaClassDefineReservedUnused( IONetworkInterface, 8); -OSMetaClassDefineReservedUnused( IONetworkInterface, 9); -OSMetaClassDefineReservedUnused( IONetworkInterface, 10); -OSMetaClassDefineReservedUnused( IONetworkInterface, 11); -OSMetaClassDefineReservedUnused( IONetworkInterface, 12); -OSMetaClassDefineReservedUnused( IONetworkInterface, 13); -OSMetaClassDefineReservedUnused( IONetworkInterface, 14); -OSMetaClassDefineReservedUnused( IONetworkInterface, 15); - -//--------------------------------------------------------------------------- -// Macros - -#ifdef DEBUG -#define DLOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -//--------------------------------------------------------------------------- -// Initialize an IONetworkInterface instance. -// -// Returns true if initialized successfully, false otherwise. - -bool IONetworkInterface::init(IONetworkController * controller) -{ - // Propagate the init() call to our superclass. - - if ( super::init() == false ) - return false; - - // The controller object provided must be valid. - - if ( OSDynamicCast(IONetworkController, controller) == 0 ) - return false; - - _controller = controller; - - // Create interface lock to serialize ifnet updates. - - _ifLock = IORecursiveLockAlloc(); - if ( _ifLock == 0 ) - return false; - - // Create an OSNumber to store interface state bits. - - _stateBits = OSNumber::withNumber((UInt64) 0, 32); - if ( _stateBits == 0 ) - return false; - setProperty( kIOInterfaceState, _stateBits ); - - // Create an OSSet to store client objects. Initial capacity - // (which can grow) is set at 2 clients. - - _clientSet = OSSet::withCapacity(2); - if ( _clientSet == 0 ) - return false; - - // Get the ifnet structure of the network interface. Subclasses must - // implement getIfnet() and expect this function to be called when - // they call IONetworkInterface::init(). - - _ifp = getIfnet(); - if ( _ifp == 0 ) - { - DLOG("%s: getIfnet() returned NULL\n", getName()); - return false; - } - - // Intialize the ifnet structure. - - if ( initIfnet(_ifp) == false ) - return false; - - // Create a data dictionary. - - if ( (_dataDict = OSDictionary::withCapacity(5)) == 0 ) - return false; - - IONetworkData * data = IONetworkData::withExternalBuffer( - kIONetworkStatsKey, - sizeof(IONetworkStats), - (UInt8 *) &(_ifp->if_data.ifi_ipackets)); - if ( data ) - { - addNetworkData(data); - data->release(); - } - - // Register default output handler. - - if ( registerOutputHandler( controller, - controller->getOutputHandler() ) == false ) - { - return false; - } - - // Set the kIOInterfaceNamePrefix and kIOPrimaryInterface properties. - // These may be used by an user space agent as hints when assigning a - // BSD name for the interface. - - setProperty( kIOInterfaceNamePrefix, getNamePrefix() ); - setProperty( kIOPrimaryInterface, isPrimaryInterface() ); - - return true; -} - -//--------------------------------------------------------------------------- -// Destroy the interface. Release all allocated resources. - -void IONetworkInterface::free() -{ - DLOG("IONetworkInterface::free()\n"); - - if ( _clientSet ) - { - // Should not have any clients. - assert(_clientSet->getCount() == 0); - _clientSet->release(); - _clientSet = 0; - } - - if ( _dataDict ) { _dataDict->release(); _dataDict = 0; } - if ( _stateBits ) { _stateBits->release(); _stateBits = 0; } - - if ( _ifLock ) - { - IORecursiveLockFree(_ifLock); - _ifLock = 0; - } - - clearInputQueue(); - - super::free(); -} - -//--------------------------------------------------------------------------- -// Returns true if the receiver of this method is the system's primary -// network interface. - -bool IONetworkInterface::isPrimaryInterface() const -{ - IOService * provider = getController(); - bool isPrimary = false; - - if ( provider ) provider = provider->getProvider(); - - // FIXME: Should rely on a single property, and the platform - // expert should patch the device tree if necessary to make - // it so. - - if ( provider && - ( provider->getProperty( "AAPL,slot-name" ) == 0 ) && - ( provider->getProperty( "built-in" ) || - provider->getProperty( "AAPL,connector" ) || - ( strcmp( provider->getName(), "ethernet" ) == 0 ) ) ) - { - isPrimary = true; - } - - return isPrimary; -} - -//--------------------------------------------------------------------------- -// Get the IONetworkCotroller object that is servicing this interface. - -IONetworkController * IONetworkInterface::getController() const -{ - return _controller; -} - -#ifdef HW_CSUM_SUPPORT -//--------------------------------------------------------------------------- -// Get the value that should be set in the hwassist field in the ifnet -// structure. Currently, this field is solely used for advertising the -// hardware checksumming support. - -static UInt32 getIfnetHardwareAssistValue( IONetworkController * ctr ) -{ - UInt32 input; - UInt32 output; - UInt32 hwassist = 0; - - do { - if ( ctr->getChecksumSupport( - &input, - IONetworkController::kChecksumFamilyTCPIP, - false ) != kIOReturnSuccess ) break; - - if ( ctr->getChecksumSupport( - &output, - IONetworkController::kChecksumFamilyTCPIP, - true ) != kIOReturnSuccess ) break; - - if ( input & output & IONetworkController::kChecksumIP ) - { - hwassist |= CSUM_IP; - } - - if ( ( input & ( IONetworkController::kChecksumTCP | - IONetworkController::kChecksumTCPNoPseudoHeader ) ) - && ( output & ( IONetworkController::kChecksumTCP | - IONetworkController::kChecksumTCPSum16 ) ) ) - { - hwassist |= CSUM_TCP; - } - - if ( ( input & ( IONetworkController::kChecksumUDP | - IONetworkController::kChecksumUDPNoPseudoHeader ) ) - && ( output & ( IONetworkController::kChecksumUDP | - IONetworkController::kChecksumTCPSum16 ) ) ) - { - hwassist |= CSUM_UDP; - } - } - while ( false ); - - return hwassist; -} -#endif HW_CSUM_SUPPORT - -//--------------------------------------------------------------------------- -// Initialize the ifnet structure. - -bool IONetworkInterface::initIfnet(struct ifnet * ifp) -{ - lock(); - - // Register our 'shim' functions. These function pointers - // points to static member functions inside this class. - - ifp->if_output = output_shim; - ifp->if_ioctl = ioctl_shim; - ifp->if_set_bpf_tap = set_bpf_tap_shim; - ifp->if_private = this; - ifp->if_free = &IONetworkStack::bsdInterfaceWasUnregistered; - ifp->if_name = (char *) getNamePrefix(); - - unlock(); - - return true; -} - -//--------------------------------------------------------------------------- -// Implement family specific matching. - -bool IONetworkInterface::matchPropertyTable(OSDictionary * table, - SInt32 * score) -{ - return super::matchPropertyTable(table, score); -} - -//--------------------------------------------------------------------------- -// Take the interface lock. - -void IONetworkInterface::lock() -{ - IORecursiveLockLock(_ifLock); -} - -//--------------------------------------------------------------------------- -// Release the interface lock. - -void IONetworkInterface::unlock() -{ - IORecursiveLockUnlock(_ifLock); -} - -//--------------------------------------------------------------------------- -// Inspect the controller after it has been opened. - -bool IONetworkInterface::controllerDidOpen(IONetworkController * controller) -{ - return true; // by default, always accept the controller open. -} - -//--------------------------------------------------------------------------- -// Perform cleanup before the controller is closed. - -void IONetworkInterface::controllerWillClose(IONetworkController * controller) -{ -} - -//--------------------------------------------------------------------------- -// Handle a client open on the interface. - -bool IONetworkInterface::handleOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - bool accept = false; - bool controllerOpen = false; - - do { - // Was this object already registered as our client? - - if ( _clientSet->containsObject(client) ) - { - DLOG("%s: multiple opens from client %lx\n", - getName(), (UInt32) client); - accept = true; - break; - } - - // If the interface has not received a client open, which also - // implies that the interface has not yet opened the controller, - // then open the controller upon receiving the first open from - // a client. If the controller open fails, the client open will - // be rejected. - - if ( ( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0 ) - { - if ( ( (controllerOpen = _controller->open(this)) == false ) || - ( controllerDidOpen(_controller) == false ) ) - break; - } - - // Qualify the client. - - if ( handleClientOpen(client, options, argument) == false ) - break; - - // Add the new client object to our client set. - - if ( _clientSet->setObject(client) == false ) - { - handleClientClose(client, 0); - break; - } - - accept = true; - } - while (false); - - // If provider was opened above, but an error has caused us to refuse - // the client open, then close our provider. - - if ( controllerOpen ) - { - if (accept) - { - setInterfaceState( kIONetworkInterfaceOpenedState ); - _controller->registerInterestedDriver( this ); - } - else { - controllerWillClose(_controller); - _controller->close(this); - } - } - - return accept; -} - -//--------------------------------------------------------------------------- -// Handle a client close on the interface. - -void IONetworkInterface::handleClose(IOService * client, IOOptionBits options) -{ - // Remove the object from the client OSSet. - - if ( _clientSet->containsObject(client) ) - { - // Call handleClientClose() to handle the client close. - - handleClientClose( client, options ); - - // If this is the last client, then close our provider. - - if ( _clientSet->getCount() == 1 ) - { - _controller->deRegisterInterestedDriver( this ); - controllerWillClose( _controller ); - _controller->close( this ); - setInterfaceState( 0, kIONetworkInterfaceOpenedState ); - } - - // Remove the client from our OSSet. - - _clientSet->removeObject(client); - } -} - -//--------------------------------------------------------------------------- -// Query whether a client has an open on the interface. - -bool IONetworkInterface::handleIsOpen(const IOService * client) const -{ - if (client) - return _clientSet->containsObject(client); - else - return (_clientSet->getCount() > 0); -} - -//--------------------------------------------------------------------------- -// Handle a client open on the interface. - -bool IONetworkInterface::handleClientOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - if ( OSDynamicCast(IONetworkStack, client) ) - { - // Transition state to registered interface. - - setInterfaceState( kIONetworkInterfaceRegisteredState ); - } - return true; -} - -//--------------------------------------------------------------------------- -// Handle a client close on the interface. - -void IONetworkInterface::handleClientClose(IOService * client, - IOOptionBits options) -{ - if ( OSDynamicCast(IONetworkStack, client) ) - { - // Transition state to unregistered interface. - - setInterfaceState( 0, kIONetworkInterfaceRegisteredState ); - } -} - -//--------------------------------------------------------------------------- -// Register the output packet handler. - -bool IONetworkInterface::registerOutputHandler(OSObject * target, - IOOutputAction action) -{ - lock(); - - // Sanity check on the arguments. - - if ( (getInterfaceState() & kIONetworkInterfaceRegisteredState) || - !target || !action ) - { - unlock(); - return false; - } - - _outTarget = target; - _outAction = action; - - unlock(); - - return true; -} - -//--------------------------------------------------------------------------- -// Feed packets to the input/output BPF packet filter taps. - -static inline void _feedPacketTap(struct ifnet * ifp, - struct mbuf * m, - BPF_FUNC func, - int mode) -{ - if (func) func(ifp, m); -} - -//--------------------------------------------------------------------------- -// Called by a network controller to submit a single packet received from -// the network to the data link layer. - -#define IN_Q_ENQUEUE(m) \ -{ \ - if (_inputQHead == 0) { \ - _inputQHead = _inputQTail = (m); \ - } \ - else { \ - _inputQTail->m_nextpkt = (m) ; \ - _inputQTail = (m); \ - } \ - _inputQCount++; \ -} - -#define DLIL_INPUT(m_head, m_tail) \ -{ \ - if ( m_head ) { \ - dlil_input(_ifp, (m_head), (m_tail)); \ - } \ -} - -UInt32 IONetworkInterface::flushInputQueue() -{ - UInt32 count = _inputQCount; - - DLIL_INPUT(_inputQHead, _inputQTail); - _inputQHead = _inputQTail = 0; - _inputQCount = 0; - - return count; -} - -UInt32 IONetworkInterface::clearInputQueue() -{ - UInt32 count = _inputQCount; - - m_freem_list( _inputQHead ); - - _inputQHead = _inputQTail = 0; - _inputQCount = 0; - - return count; -} - -UInt32 IONetworkInterface::inputPacket(struct mbuf * pkt, - UInt32 length = 0, - IOOptionBits options = 0, - void * param = 0) -{ - UInt32 count; - - assert(pkt); - - // Set the source interface and length of the received frame. - - if ( length ) - { - if ( pkt->m_next == 0 ) - { - pkt->m_pkthdr.len = pkt->m_len = length; - } - else - { - struct mbuf * m = pkt; - pkt->m_pkthdr.len = length; - do { - if (length < (UInt32) m->m_len) - m->m_len = length; - length -= m->m_len; - } while (( m = m->m_next )); - assert(length == 0); - } - } - - pkt->m_pkthdr.rcvif = _ifp; - - // Increment input byte count. - - _ifp->if_ibytes += pkt->m_pkthdr.len; - - // Feed BPF tap. - - _feedPacketTap(_ifp, pkt, _inputFilterFunc, BPF_TAP_INPUT); - - pkt->m_pkthdr.header = pkt->m_data; - pkt->m_pkthdr.len -= sizeof(struct ether_header); - pkt->m_len -= sizeof(struct ether_header); - pkt->m_data += sizeof(struct ether_header); - - if ( options & kInputOptionQueuePacket ) - { - IN_Q_ENQUEUE(pkt); - count = 0; - } - else - { - if ( _inputQHead ) // queue is not empty - { - IN_Q_ENQUEUE(pkt); - - count = _inputQCount; - - DLIL_INPUT(_inputQHead, _inputQTail); - - _inputQHead = _inputQTail = 0; - _inputQCount = 0; - } - else - { - DLIL_INPUT(pkt, pkt); - count = 1; - } - } - return count; -} - -//--------------------------------------------------------------------------- -// Deliver an event to the network layer. - -bool IONetworkInterface::inputEvent(UInt32 type, void * data) -{ - bool success = true; - -#ifdef KEV_DL_LINK_ON - struct { - kern_event_msg header; - u_long unit; - char if_name[IFNAMSIZ]; - } event; - - switch (type) - { - // Deliver an IOKit defined event. - - case kIONetworkEventTypeLinkUp: - case kIONetworkEventTypeLinkDown: - - if ( ( _ifp->if_flags & IFF_UP ) == 0 ) - { - break; - } - - bzero((void *) &event, sizeof(event)); - - event.header.total_size = sizeof(event); - event.header.vendor_code = KEV_VENDOR_APPLE; - event.header.kev_class = KEV_NETWORK_CLASS; - event.header.kev_subclass = KEV_DL_SUBCLASS; - event.header.event_code = (type == kIONetworkEventTypeLinkUp) ? - KEV_DL_LINK_ON : KEV_DL_LINK_OFF; - event.header.event_data[0] = _ifp->if_family; - event.unit = (u_long) _ifp->if_unit; - strncpy(&event.if_name[0], _ifp->if_name, IFNAMSIZ); - - dlil_event(_ifp, &event.header); - break; - - // Deliver a raw kernel event to DLIL. - // The data argument must point to a kern_event_msg structure. - - case kIONetworkEventTypeDLIL: - dlil_event(_ifp, (struct kern_event_msg *) data); - break; - - default: - IOLog("IONetworkInterface: unknown event type %lx\n", type); - success = false; - break; - } -#endif - - return success; -} - -//--------------------------------------------------------------------------- -// SIOCSIFMTU (set interface MTU) ioctl handler. - -SInt32 IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctr, - struct ifreq * ifr) -{ - SInt32 error; - UInt32 newMTU = ifr->ifr_mtu; - - // If change is not necessary, return success without getting the - // controller involved. - - if ( getMaxTransferUnit() == newMTU ) - return 0; - - // Request the controller to switch MTU size. - - error = errnoFromReturn( ctr->setMaxPacketSize(newMTU) ); - - if ( error == 0 ) - { - // Controller reports success. Update the interface MTU size - // property. - - setMaxTransferUnit(newMTU); - } - - return error; -} - -//--------------------------------------------------------------------------- -// SIOCSIFMEDIA (SET interface media) ioctl handler. - -SInt32 IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctr, - struct ifreq * ifr) -{ - OSDictionary * mediumDict; - IONetworkMedium * medium; - SInt32 error; - - mediumDict = ctr->copyMediumDictionary(); // creates a copy - if ( mediumDict == 0 ) - { - // unable to allocate memory, or no medium dictionary. - return EOPNOTSUPP; - } - - medium = IONetworkMedium::getMediumWithType(mediumDict, ifr->ifr_media); - if ( medium == 0 ) - { - // Exact type was not found. Try a partial match. - // ifconfig program sets the media type and media - // options separately. This should not be allowed! - - medium = IONetworkMedium::getMediumWithType(mediumDict, - ifr->ifr_media, - ~(IFM_TMASK | IFM_NMASK)); - if ( medium == 0 ) - { - mediumDict->release(); - return EINVAL; // requested medium not found. - } - } - - // It may be possible for the controller to update the medium - // dictionary and perhaps delete the medium entry that we have - // selected from our copy of the stale dictionary. This is - // harmless since IONetworkController will filter out invalid - // selections before calling the driver. - - error = errnoFromReturn( ctr->selectMediumWithName(medium->getName()) ); - - mediumDict->release(); - - return error; -} - -//--------------------------------------------------------------------------- -// SIOCGIFMEDIA (GET interface media) ioctl handler. - -SInt32 IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctr, - struct ifreq * ifr) -{ - OSDictionary * mediumDict = 0; - UInt mediumCount = 0; - UInt maxCount; - OSCollectionIterator * iter = 0; - UInt32 * typeList; - UInt typeListSize; - OSSymbol * keyObject; - SInt32 error = 0; - struct ifmediareq * ifmr = (struct ifmediareq *) ifr; - - // Maximum number of medium types that the caller will accept. - // - maxCount = ifmr->ifm_count; - - do { - mediumDict = ctr->copyMediumDictionary(); // creates a copy - if (mediumDict == 0) - { - break; // unable to allocate memory, or no medium dictionary. - } - - if ((mediumCount = mediumDict->getCount()) == 0) - break; // no medium in the medium dictionary - - if (maxCount == 0) - break; // caller is only probing for support and media count. - - if (maxCount < mediumCount) - { - // user buffer is too small to hold all medium entries. - error = E2BIG; - - // Proceed with partial copy on E2BIG. This follows the - // SIOCGIFMEDIA handling practice in bsd/net/if_media.c. - // - // break; - } - - // Create an iterator to loop through the medium entries in the - // dictionary. - // - iter = OSCollectionIterator::withCollection(mediumDict); - if (!iter) - { - error = ENOMEM; - break; - } - - // Allocate memory for the copyout buffer. - // - typeListSize = maxCount * sizeof(UInt32); - typeList = (UInt32 *) IOMalloc(typeListSize); - if (!typeList) - { - error = ENOMEM; - break; - } - bzero(typeList, typeListSize); - - // Iterate through the medium dictionary and copy the type of - // each medium entry to typeList[]. - // - mediumCount = 0; - while ( (keyObject = (OSSymbol *) iter->getNextObject()) && - (mediumCount < maxCount) ) - { - IONetworkMedium * medium = (IONetworkMedium *) - mediumDict->getObject(keyObject); - if (!medium) - continue; // should not happen! - - typeList[mediumCount++] = medium->getType(); - } - - if (mediumCount) - { - error = copyout((caddr_t) typeList, - (caddr_t) ifmr->ifm_ulist, - typeListSize); - } - - IOFree(typeList, typeListSize); - } - while (0); - - ifmr->ifm_active = ifmr->ifm_current = IFM_NONE; - ifmr->ifm_status = 0; - ifmr->ifm_count = mediumCount; - - // Get a copy of the controller's property table and read the - // link status, current, and active medium. - - OSDictionary * pTable = ctr->dictionaryWithProperties(); - if (pTable) - { - OSNumber * linkStatus = (OSNumber *) - pTable->getObject(kIOLinkStatus); - if (linkStatus) - ifmr->ifm_status = linkStatus->unsigned32BitValue(); - - if (mediumDict) - { - IONetworkMedium * medium; - OSSymbol * mediumName; - - if ((mediumName = (OSSymbol *) pTable->getObject(kIOSelectedMedium)) - && (medium = (IONetworkMedium *) - mediumDict->getObject(mediumName))) - { - ifmr->ifm_current = medium->getType(); - } - - if ((mediumName = (OSSymbol *) pTable->getObject(kIOActiveMedium)) - && (medium = (IONetworkMedium *) - mediumDict->getObject(mediumName))) - { - ifmr->ifm_active = medium->getType(); - } - } - pTable->release(); - } - - if (iter) - iter->release(); - - if (mediumDict) - mediumDict->release(); - - return error; -} - -//--------------------------------------------------------------------------- -// Handle ioctl commands sent to the network interface. - -SInt32 IONetworkInterface::performCommand(IONetworkController * ctr, - UInt32 cmd, - void * arg0, - void * arg1) -{ - struct ifreq * ifr = (struct ifreq *) arg1; - SInt32 ret = EOPNOTSUPP; - - if ( (ifr == 0) || (ctr == 0) ) - return EINVAL; - - switch ( cmd ) - { - // Get interface MTU. - - case SIOCGIFMTU: - ifr->ifr_mtu = getMaxTransferUnit(); - ret = 0; // no error - break; - - // Get interface media type and status. - - case SIOCGIFMEDIA: - ret = syncSIOCGIFMEDIA(ctr, ifr); - break; - - case SIOCSIFMTU: - case SIOCSIFMEDIA: - ret = (int) ctr->executeCommand( - this, /* client */ - (IONetworkController::Action) - &IONetworkInterface::performGatedCommand, - this, /* target */ - ctr, /* param0 */ - (void *) cmd, /* param1 */ - arg0, /* param2 */ - arg1 ); /* param3 */ - break; - - default: - // DLOG(%s: command not handled (%08lx), getName(), cmd); - break; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Perform an ioctl command on the controller's workloop context. - -int IONetworkInterface::performGatedCommand(void * target, - void * arg1_ctr, - void * arg2_cmd, - void * arg3_0, - void * arg4_1) -{ - IONetworkInterface * self = (IONetworkInterface *) target; - IONetworkController * ctr = (IONetworkController *) arg1_ctr; - struct ifreq * ifr = (struct ifreq *) arg4_1; - SInt32 ret = EOPNOTSUPP; - - // Refuse to issue I/O to the controller if it is in a power state - // that renders it "unusable". - - if ( self->getInterfaceState() & kIONetworkInterfaceDisabledState ) - return EPWROFF; - - switch ( (UInt32) arg2_cmd ) - { - // Set interface MTU. - - case SIOCSIFMTU: - ret = self->syncSIOCSIFMTU(ctr, ifr); - break; - - // Set interface (controller) media type. - - case SIOCSIFMEDIA: - ret = self->syncSIOCSIFMEDIA(ctr, ifr); - break; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// if_ioctl() handler - Calls performCommand() when we receive an ioctl -// from DLIL. - -int -IONetworkInterface::ioctl_shim(struct ifnet * ifp, u_long cmd, caddr_t data) -{ - assert(ifp && ifp->if_private); - - IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; - - assert(ifp == self->_ifp); - - return self->performCommand( self->_controller, - cmd, - (void *) ifp, - (void *) data ); -} - -//--------------------------------------------------------------------------- -// if_output() handler. -// -// Handle a call from the network stack to transmit the given mbuf. -// For now, we can assume that the mbuf is singular, and never chained. - -int IONetworkInterface::output_shim(struct ifnet * ifp, struct mbuf * m) -{ - assert(ifp && ifp->if_private); - - IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; - - assert(ifp == self->_ifp); - - if ( m == 0 ) - { - DLOG("IONetworkInterface: NULL output mbuf\n"); - return EINVAL; - } - - if ( (m->m_flags & M_PKTHDR) == 0 ) - { - DLOG("IONetworkInterface: M_PKTHDR bit not set\n"); - m_freem(m); - return EINVAL; - } - - // Increment output byte counter. - - ifp->if_obytes += m->m_pkthdr.len; - - // Feed the output filter tap. - - _feedPacketTap(ifp, m, self->_outputFilterFunc, BPF_TAP_OUTPUT); - - // Forward the packet to the registered output packet handler. - - return ((self->_outTarget)->*(self->_outAction))(m, 0); -} - -//--------------------------------------------------------------------------- -// if_set_bpf_tap() handler. Handles request from the DLIL to enable or -// disable the input/output filter taps. -// -// FIXME - locking may be needed. - -int IONetworkInterface::set_bpf_tap_shim(struct ifnet * ifp, - int mode, - BPF_FUNC func) -{ - assert(ifp && ifp->if_private); - - IONetworkInterface * self = (IONetworkInterface *) ifp->if_private; - - assert(ifp == self->_ifp); - - self->lock(); - - switch ( mode ) - { - case BPF_TAP_DISABLE: - self->_inputFilterFunc = self->_outputFilterFunc = 0; - break; - - case BPF_TAP_INPUT: - assert(func); - self->_inputFilterFunc = func; - break; - - case BPF_TAP_OUTPUT: - assert(func); - self->_outputFilterFunc = func; - break; - - case BPF_TAP_INPUT_OUTPUT: - assert(func); - self->_inputFilterFunc = self->_outputFilterFunc = func; - break; - - default: - DLOG("IONetworkInterface: Unknown BPF tap mode %d\n", mode); - break; - } - - self->unlock(); - - return 0; -} - -//--------------------------------------------------------------------------- -// As the name implies, this function does nothing. This will get called -// if the network layer tries to call the if_watchdog function pointer -// in ifnet. This should not happen. IOKit does not use this watchdog -// timer facility. - -void IONetworkInterface::null_shim(struct ifnet * /*ifp*/) -{ - IOLog("IONetworkInterface::null_shim called!\n"); -} - -//--------------------------------------------------------------------------- -// ifnet field (and property table) getter/setter. - -bool IONetworkInterface::_setInterfaceProperty(UInt32 value, - UInt32 mask, - UInt32 bytes, - void * addr, - char * key) -{ - bool updateOk = false; - UInt32 newValue; - OSNumber * number; - - lock(); - - // Update the property in ifnet. - - switch (bytes) - { - case 1: - newValue = (*((UInt8 *) addr) & mask) | value; - *((UInt8 *) addr) = (UInt8) newValue; - break; - case 2: - newValue = (*((UInt16 *) addr) & mask) | value; - *((UInt16 *) addr) = (UInt16) newValue; - break; - case 4: - newValue = (*((UInt32 *) addr) & mask) | value; - *((UInt32 *) addr) = (UInt32) newValue; - break; - default: - goto abort; - } - - // Update the OSNumber in the property table. - - if ( key ) - { - if ( (number = (OSNumber *) getProperty(key)) ) - { - number->setValue(newValue); - updateOk = true; - } - else - { - updateOk = setProperty(key, newValue, bytes * 8); - } - } -abort: - unlock(); - return updateOk; -} - -#define IO_IFNET_GET(func, type, field) \ -type IONetworkInterface:: ## func() const \ -{ \ - type ret; \ - ((IONetworkInterface *) this)->lock(); \ - ret = _ifp ? _ifp-> ## field : 0; \ - ((IONetworkInterface *) this)->unlock(); \ - return ret; \ -} - -#define IO_IFNET_SET(func, type, field, propName) \ -bool IONetworkInterface:: ## func(type value) \ -{ \ - return _setInterfaceProperty( \ - (UInt32) value, \ - 0, \ - sizeof(type), \ - (void *) &_ifp-> ## field, \ - propName); \ -} - -#define IO_IFNET_RMW(func, type, field, propName) \ -bool IONetworkInterface:: ## func(type value, type clear = 0) \ -{ \ - return _setInterfaceProperty( \ - (UInt32) value, \ - (UInt32) ~clear, \ - sizeof(type), \ - (void *) &_ifp-> ## field, \ - propName); \ -} - -//--------------------------------------------------------------------------- -// Interface type accessors (ifp->if_type). The list of interface types is -// defined in <bsd/net/if_types.h>. - -IO_IFNET_SET(setInterfaceType, UInt8, if_type, kIOInterfaceType) -IO_IFNET_GET(getInterfaceType, UInt8, if_type) - -//--------------------------------------------------------------------------- -// Mtu (MaxTransferUnit) accessors (ifp->if_mtu). - -IO_IFNET_SET(setMaxTransferUnit, UInt32, if_mtu, kIOMaxTransferUnit) -IO_IFNET_GET(getMaxTransferUnit, UInt32, if_mtu) - -//--------------------------------------------------------------------------- -// Flags accessors (ifp->if_flags). This is a read-modify-write operation. - -IO_IFNET_RMW(setFlags, UInt16, if_flags, kIOInterfaceFlags) -IO_IFNET_GET(getFlags, UInt16, if_flags) - -//--------------------------------------------------------------------------- -// EFlags accessors (ifp->if_eflags). This is a read-modify-write operation. - -IO_IFNET_RMW(setExtraFlags, UInt32, if_eflags, kIOInterfaceExtraFlags) -IO_IFNET_GET(getExtraFlags, UInt32, if_eflags) - -//--------------------------------------------------------------------------- -// MediaAddressLength accessors (ifp->if_addrlen) - -IO_IFNET_SET(setMediaAddressLength, UInt8, if_addrlen, kIOMediaAddressLength) -IO_IFNET_GET(getMediaAddressLength, UInt8, if_addrlen) - -//--------------------------------------------------------------------------- -// MediaHeaderLength accessors (ifp->if_hdrlen) - -IO_IFNET_SET(setMediaHeaderLength, UInt8, if_hdrlen, kIOMediaHeaderLength) -IO_IFNET_GET(getMediaHeaderLength, UInt8, if_hdrlen) - -//--------------------------------------------------------------------------- -// Interface unit number. The unit number for the interface is assigned -// by our client. - -IO_IFNET_SET(setUnitNumber, UInt16, if_unit, kIOInterfaceUnit) -IO_IFNET_GET(getUnitNumber, UInt16, if_unit) - -//--------------------------------------------------------------------------- -// Return true if the interface has been registered with the network layer, -// false otherwise. - -bool IONetworkInterface::isRegistered() const -{ - return (bool)(getInterfaceState() & kIONetworkInterfaceRegisteredState); -} - -//--------------------------------------------------------------------------- -// Return the interface state flags. - -UInt32 IONetworkInterface::getInterfaceState() const -{ - return _stateBits->unsigned32BitValue(); -} - -//--------------------------------------------------------------------------- -// Set (or clear) the interface state flags. - -UInt32 IONetworkInterface::setInterfaceState( UInt32 set, - UInt32 clear ) -{ - UInt32 val; - - assert( _stateBits ); - - lock(); - - val = ( _stateBits->unsigned32BitValue() | set ) & ~clear; - _stateBits->setValue( val ); - - unlock(); - - return val; -} - -//--------------------------------------------------------------------------- -// Perform a lookup of the dictionary kept by the interface, -// and return an entry that matches the specified string key. -// -// key: Search for an IONetworkData entry with this key. -// -// Returns the matching entry, or 0 if no match was found. - -IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const -{ - return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); -} - -IONetworkData * IONetworkInterface::getNetworkData(const char * key) const -{ - return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); -} - -//--------------------------------------------------------------------------- -// A private function to copy the data dictionary to the property table. - -bool IONetworkInterface::_syncNetworkDataDict() -{ - OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict); - bool ret = false; - - if (aCopy) { - ret = setProperty(kIONetworkData, aCopy); - aCopy->release(); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Remove an entry from the IONetworkData dictionary managed by the interface. -// The removed object is released. - -bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey) -{ - bool ret = false; - - lock(); - - do { - if ( getInterfaceState() & kIONetworkInterfaceOpenedState ) - break; - - _dataDict->removeObject(aKey); - ret = _syncNetworkDataDict(); - } - while (0); - - unlock(); - - return ret; -} - -bool IONetworkInterface::removeNetworkData(const char * aKey) -{ - bool ret = false; - - lock(); - - do { - if ( getInterfaceState() & kIONetworkInterfaceOpenedState ) - break; - - _dataDict->removeObject(aKey); - ret = _syncNetworkDataDict(); - } - while (0); - - unlock(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Add an IONetworkData object to a dictionary managed by the interface. - -bool IONetworkInterface::addNetworkData(IONetworkData * aData) -{ - bool ret = false; - - if (OSDynamicCast(IONetworkData, aData) == 0) - return false; - - lock(); - - if (( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0) - { - if ((ret = _dataDict->setObject(aData->getKey(), aData))) - ret = _syncNetworkDataDict(); - } - - unlock(); - - return ret; -} - -//--------------------------------------------------------------------------- -// Create a new IOUserClient to handle client requests. The default -// implementation will create an IONetworkUserClient instance if -// the type given is kIONUCType. - -IOReturn IONetworkInterface::newUserClient(task_t owningTask, - void * /*security_id*/, - UInt32 type, - IOUserClient ** handler) -{ - IOReturn err = kIOReturnSuccess; - IONetworkUserClient * client; - - if (type != kIONUCType) - return kIOReturnBadArgument; - - client = IONetworkUserClient::withTask(owningTask); - - if (!client || !client->attach(this) || !client->start(this)) - { - if (client) - { - client->detach(this); - client->release(); - client = 0; - } - err = kIOReturnNoMemory; - } - - *handler = client; - - return err; -} - -//--------------------------------------------------------------------------- -// Handle controller's power state transitions. - -IOReturn -IONetworkInterface::controllerWillChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - if ( ( flags & IOPMDeviceUsable ) == 0 ) - { - setInterfaceState( kIONetworkInterfaceDisabledState ); - } - return kIOReturnSuccess; -} - -IOReturn -IONetworkInterface::controllerDidChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - if ( flags & IOPMDeviceUsable ) - { - setInterfaceState( 0, kIONetworkInterfaceDisabledState ); - } - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Static member functions called by power-management notification handlers. -// Act as stub functions that will simply forward the call to virtual member -// functions. - -IOReturn -IONetworkInterface::sControllerWillChangePowerState( - IONetworkInterface * netif, - void * param0, - void * param1, - void * param2, - void * param3 ) -{ - return netif->controllerWillChangePowerState( - (IONetworkController *) param0, - (IOPMPowerFlags) param1, - (UInt32) param2, - (IOService *) param3 ); -} - -IOReturn -IONetworkInterface::sControllerDidChangePowerState( - IONetworkInterface * netif, - void * param0, - void * param1, - void * param2, - void * param3 ) -{ - return netif->controllerDidChangePowerState( - (IONetworkController *) param0, - (IOPMPowerFlags) param1, - (UInt32) param2, - (IOService *) param3 ); -} - -//--------------------------------------------------------------------------- -// Handle notitifications triggered by controller's power state change. - -IOReturn -IONetworkInterface::powerStateWillChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - _controller->executeCommand( - this, /* client */ - (IONetworkController::Action) - &IONetworkInterface::sControllerWillChangePowerState, - this, /* target */ - (void *) _controller, /* param0 */ - (void *) flags, /* param1 */ - (void *) stateNumber, /* param2 */ - (void *) policyMaker); /* param3 */ - - return IOPMAckImplied; -} - -IOReturn -IONetworkInterface::powerStateDidChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ) -{ - _controller->executeCommand( - this, /* client */ - (IONetworkController::Action) - &IONetworkInterface::sControllerDidChangePowerState, - this, /* target */ - (void *) _controller, /* param0 */ - (void *) flags, /* param1 */ - (void *) stateNumber, /* param2 */ - (void *) policyMaker); /* param3 */ - - return IOPMAckImplied; -} diff --git a/iokit/Families/IONetworking/IONetworkMedium.cpp b/iokit/Families/IONetworking/IONetworkMedium.cpp deleted file mode 100644 index 7a10de58b..000000000 --- a/iokit/Families/IONetworking/IONetworkMedium.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkMedium.cpp - * - * HISTORY - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <libkern/c++/OSObject.h> -#include <libkern/c++/OSNumber.h> -#include <libkern/c++/OSCollectionIterator.h> -#include <libkern/c++/OSDictionary.h> -#include <libkern/c++/OSSerialize.h> -#include <IOKit/network/IONetworkMedium.h> - -//--------------------------------------------------------------------------- -// OSMetaClass macros. - -#define super OSObject -OSDefineMetaClassAndStructors( IONetworkMedium, OSObject ) -OSMetaClassDefineReservedUnused( IONetworkMedium, 0); -OSMetaClassDefineReservedUnused( IONetworkMedium, 1); -OSMetaClassDefineReservedUnused( IONetworkMedium, 2); -OSMetaClassDefineReservedUnused( IONetworkMedium, 3); - -//--------------------------------------------------------------------------- -// Initialize an IONetworkMedium instance. -// -// type: The medium type, the fields are encoded with bits defined in -// IONetworkMedium.h. -// -// speed: The maximum (or the only) link speed supported over this medium -// in units of bits per second. -// -// flags: An optional flag for the medium object. -// See IONetworkMedium.h for defined flags. -// -// index: An optional 32-bit index assigned by the caller. Drivers can use -// this to store an index or a pointer to a media table inside the -// driver, or it may map to a driver defined media type. -// -// name: An name to assign to this medium object. If 0, then a name -// will be created based on the medium type given using nameForType(). -// -// Returns true on success, false otherwise. - -bool IONetworkMedium::init(IOMediumType type, - UInt64 speed, - UInt32 flags = 0, - UInt32 index = 0, - const char * name = 0) -{ - if ( super::init() == false ) - return false; - - _type = type; - _flags = flags; - _speed = speed; - _index = index; - - if (name) - _name = OSSymbol::withCString(name); - else - _name = IONetworkMedium::nameForType(type); - - if (!_name) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Factory method which performs allocation and initialization -// of an IONetworkMedium instance. -// -// Returns an IONetworkMedium instance on success, or 0 otherwise. - -IONetworkMedium * IONetworkMedium::medium(IOMediumType type, - UInt64 speed, - UInt32 flags = 0, - UInt32 index = 0, - const char * name = 0) -{ - IONetworkMedium * medium = new IONetworkMedium; - - if (medium && !medium->init(type, speed, flags, index, name)) - { - medium->release(); - medium = 0; - } - - return medium; -} - -//--------------------------------------------------------------------------- -// Free the IONetworkMedium instance. - -void IONetworkMedium::free() -{ - if (_name) - { - _name->release(); - _name = 0; - } - super::free(); -} - -//--------------------------------------------------------------------------- -// Return the assigned medium type. - -IOMediumType IONetworkMedium::getType() const -{ - return _type; -} - -//--------------------------------------------------------------------------- -// Return the medium flags. - -UInt32 IONetworkMedium::getFlags() const -{ - return _flags; -} - -//--------------------------------------------------------------------------- -// Return the maximum medium speed. - -UInt64 IONetworkMedium::getSpeed() const -{ - return _speed; -} - -//--------------------------------------------------------------------------- -// Return the assigned index. - -UInt32 IONetworkMedium::getIndex() const -{ - return _index; -} - -//--------------------------------------------------------------------------- -// Return the name for this instance. - -const OSSymbol * IONetworkMedium::getName() const -{ - return _name; -} - -//--------------------------------------------------------------------------- -// Given a medium type, create an unique OSymbol name for the medium. -// The caller is responsible for releasing the OSSymbol object returned. -// -// type: A medium type. See IONetworkMedium.h for type encoding. -// -// Returns an OSSymbol created based on the type provided. - -const OSSymbol * IONetworkMedium::nameForType(IOMediumType type) -{ - char buffer[10]; - - sprintf(buffer, "%08lx", type); - - // Caller must remember to free the OSSymbol! - // - return OSSymbol::withCString(buffer); -} - -//--------------------------------------------------------------------------- -// Test for equality between two IONetworkMedium objects. -// Two IONetworkMedium objects are considered equal if -// they have similar properties assigned to them during initialization. -// -// medium: An IONetworkMedium to test against the IONetworkMedium -// object being called. -// -// Returns true if equal, false otherwise. - -bool IONetworkMedium::isEqualTo(const IONetworkMedium * medium) const -{ - return ( (medium->_name == _name) && - (medium->_type == _type) && - (medium->_flags == _flags) && - (medium->_speed == _speed) && - (medium->_index == _index) ); -} - -//--------------------------------------------------------------------------- -// Test for equality between a IONetworkMedium object and an OSObject. -// The OSObject is considered equal to the IONetworkMedium object if the -// OSObject is an IONetworkMedium, and they have similar properties assigned -// to them during initialization. -// -// obj: An OSObject to test against the IONetworkMedium object being called. -// -// Returns true if equal, false otherwise. - -bool IONetworkMedium::isEqualTo(const OSMetaClassBase * obj) const -{ - IONetworkMedium * medium; - if ((medium = OSDynamicCast(IONetworkMedium, obj))) - return isEqualTo(medium); - else - return false; -} - -//--------------------------------------------------------------------------- -// Create an OSData containing an IOMediumDescriptor structure (not copied), -// and ask the OSData to serialize. -// -// s: An OSSerialize object to handle the serialization. -// -// Returns true on success, false otherwise. - -static bool addNumberToDict(OSDictionary * dict, - const char * key, - UInt32 val, - UInt32 bits = 32) -{ - OSNumber * num = OSNumber::withNumber(val, bits); - bool ret; - - if ( num == 0 ) return false; - ret = dict->setObject( key, num ); - num->release(); - return ret; -} - -bool IONetworkMedium::serialize(OSSerialize * s) const -{ - bool ret; - OSDictionary * dict; - - dict = OSDictionary::withCapacity(4); - if ( dict == 0 ) return false; - - addNumberToDict(dict, kIOMediumType, getType()); - addNumberToDict(dict, kIOMediumSpeed, getSpeed(), 64); - addNumberToDict(dict, kIOMediumIndex, getIndex()); - addNumberToDict(dict, kIOMediumFlags, getFlags()); - - ret = dict->serialize(s); - dict->release(); - - return ret; -} - -//--------------------------------------------------------------------------- -// A helper function to add an IONetworkMedium object to a given dictionary. -// The name of the medium is used as the key for the new dictionary entry. -// -// dict: An OSDictionary object where the medium object should be added to. -// medium: The IONetworkMedium object to add to the dictionary. -// -// Returns true on success, false otherwise. - -bool IONetworkMedium::addMedium(OSDictionary * dict, - const IONetworkMedium * medium) -{ - // Arguments type checking. - // - if (!OSDynamicCast(OSDictionary, dict) || - !OSDynamicCast(IONetworkMedium, medium)) - return false; - - return dict->setObject(medium->getName(), medium); -} - -//--------------------------------------------------------------------------- -// A helper function to remove an entry in a dictionary with a key that -// matches the name of the IONetworkMedium object provided. -// -// dict: An OSDictionary object where the medium object should be removed -// from. -// medium: The name of this medium object is used as the removal key. - -void IONetworkMedium::removeMedium(OSDictionary * dict, - const IONetworkMedium * medium) -{ - // Arguments type checking. - // - if (!OSDynamicCast(OSDictionary, dict) || - !OSDynamicCast(IONetworkMedium, medium)) - return; - - dict->removeObject(medium->getName()); -} - -//--------------------------------------------------------------------------- -// Iterate through a dictionary and return an IONetworkMedium entry that -// satisfies the matching criteria. Returns 0 if there is no match. - -IONetworkMedium * IONetworkMedium::getMediumWithType( - const OSDictionary * dict, - IOMediumType type, - IOMediumType mask = 0) -{ - OSCollectionIterator * iter; - OSSymbol * key; - IONetworkMedium * medium; - IONetworkMedium * match = 0; - - if (!dict) return 0; - - // Shouldn't withCollection take an (const OSDictionary *) argument? - - iter = OSCollectionIterator::withCollection((OSDictionary *) dict); - if (!iter) - return 0; - - while ( (key = (OSSymbol *) iter->getNextObject()) ) - { - medium = OSDynamicCast(IONetworkMedium, dict->getObject(key)); - if (medium == 0) continue; - - if ( ( (medium->getType() ^ type) & ~mask) == 0 ) - { - match = medium; - break; - } - } - - iter->release(); - - return match; -} - -IONetworkMedium * IONetworkMedium::getMediumWithIndex( - const OSDictionary * dict, - UInt32 index, - UInt32 mask = 0) -{ - OSCollectionIterator * iter; - OSSymbol * key; - IONetworkMedium * medium; - IONetworkMedium * match = 0; - - if (!dict) return 0; - - // Shouldn't withCollection take an (const OSDictionary *) argument? - - iter = OSCollectionIterator::withCollection((OSDictionary *) dict); - if (!iter) - return 0; - - while ( (key = (OSSymbol *) iter->getNextObject()) ) - { - medium = OSDynamicCast(IONetworkMedium, dict->getObject(key)); - if (medium == 0) continue; - - if ( ( (medium->getIndex() ^ index) & ~mask) == 0 ) - { - match = medium; - break; - } - } - - iter->release(); - - return match; -} diff --git a/iokit/Families/IONetworking/IONetworkStack.cpp b/iokit/Families/IONetworking/IONetworkStack.cpp deleted file mode 100644 index 3f5dbc05e..000000000 --- a/iokit/Families/IONetworking/IONetworkStack.cpp +++ /dev/null @@ -1,1124 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkStack.cpp - An IOKit proxy for the BSD network stack. - * - * HISTORY - * - * IONetworkStack abstracts essential network stack services. These - * include registering/unregistering network interfaces, and interface - * name space management. - * - * Only a single IONetworkStack object is instantiated. This object will - * register to receive a notification when a network interface object is - * first published. The notification handler is responsible for attaching - * the network stack object to the interface object as a client. When the - * interface is terminated, this linkage is severed. - * - * This object does not participate in the data/packet flow. The interface - * object will interact directly with DLIL to send and to receive packets. - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOBSD.h> -#include <IOKit/IOMessage.h> -#include <IOKit/IOKitKeys.h> -#include <IOKit/network/IONetworkInterface.h> -#include <IOKit/network/IONetworkStack.h> -#include <libkern/c++/OSDictionary.h> - -extern "C" { -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <net/bpf.h> -#include <net/if.h> -#include <netinet/if_ether.h> -#include <net/dlil.h> -#include <sys/sockio.h> -void ether_ifattach(struct ifnet * ifp); // FIXME -} - -#define super IOService -OSDefineMetaClassAndStructors( IONetworkStack, IOService ) -OSMetaClassDefineReservedUnused( IONetworkStack, 0); -OSMetaClassDefineReservedUnused( IONetworkStack, 1); -OSMetaClassDefineReservedUnused( IONetworkStack, 2); -OSMetaClassDefineReservedUnused( IONetworkStack, 3); - -#ifdef DEBUG_XXX -#define __LOG(class, fn, fmt, args...) IOLog(class "::%s " fmt, fn, ## args) -#define DLOG(fmt, args...) __LOG("IONetworkStack", __FUNCTION__, fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -#define NETIF_FLAGS(n) ((n)->_clientVar[0]) -#define SET_NETIF_FLAGS(n, x) (NETIF_FLAGS(n) |= (x)) -#define CLR_NETIF_FLAGS(n, x) (NETIF_FLAGS(n) &= ~(x)) - -static IONetworkStack * gIONetworkStack = 0; - -// Flags encoded on the interface object. -// -enum { - kInterfaceFlagActive = 0x01, // Interface is awaiting registration - kInterfaceFlagRegistered = 0x02, // Interface has registered with DLIL - kInterfaceFlagRegistering = 0x04 // Interface is registering with DLIL -}; - -// IONetworkStackUserClient definition. -// -#include <IOKit/IOUserClient.h> - -class IONetworkStackUserClient : public IOUserClient -{ - OSDeclareDefaultStructors( IONetworkStackUserClient ) - -protected: - IONetworkStack * _provider; - -public: - static IONetworkStackUserClient * withTask( task_t owningTask ); - virtual bool start( IOService * provider ); - virtual IOReturn clientClose(); - virtual IOReturn clientDied(); - virtual IOReturn setProperties( OSObject * properties ); -}; - -//--------------------------------------------------------------------------- -// Initialize the IONetworkStack object. - -bool IONetworkStack::init( OSDictionary * properties ) -{ - // Init our superclass first. - - if ( super::init(properties) == false ) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// IONetworkStack was matched to its provider (IOResources), now start it up. - -bool IONetworkStack::start( IOService * provider ) -{ - DLOG("%p\n", provider); - - if ( super::start(provider) == false ) - return false; - - // Only a single IONetworkStack object is created, and a reference - // to this object is stored in a global variable. - - // When the boot process is VERY VERY slow for some unknown reason - // we get two instances of IONetworkStack and theassert below fires. - // so I am commenting the assert and replacing it with an if statement. - // assert( gIONetworkStack == 0 ); - - if ( gIONetworkStack != 0 ) - return false; - - gIONetworkStack = this; - - // Create containers to store interface objects. - - _ifSet = OSOrderedSet::withCapacity(10); - if ( _ifSet == 0 ) - return false; - - _ifDict = OSDictionary::withCapacity(4); - if ( _ifDict == 0 ) - return false; - - // Create a notification object to call a 'C' function, every time an - // interface object is first published. - - _interfaceNotifier = addNotification( - /* type */ gIOFirstPublishNotification, - /* match */ serviceMatching("IONetworkInterface"), - /* action */ interfacePublished, - /* param */ this ); - - if ( _interfaceNotifier == 0 ) return false; - - // Register the IONetworkStack object. - - registerService(); - - // Success. - - DLOG("success\n"); - - return true; -} - -//--------------------------------------------------------------------------- -// Stop is called by a terminated provider, after being closed, but before -// this client object is detached from it. - -void IONetworkStack::stop( IOService * provider ) -{ - DLOG("%p\n", provider); - super::stop(provider); -} - -//--------------------------------------------------------------------------- -// Release allocated resources. - -void IONetworkStack::free() -{ - DLOG("\n"); - - // IONotifier::remove() will remove the notification request - // and release the object. - - if ( _interfaceNotifier ) - { - _interfaceNotifier->remove(); - _interfaceNotifier = 0; - } - - // Free interface containers. - - if ( _ifDict ) - { - _ifDict->release(); - _ifDict = 0; - } - - if ( _ifSet ) - { - _ifSet->release(); - _ifSet = 0; - } - - gIONetworkStack = 0; - - // Propagate the free to superclass. - - super::free(); -} - -//--------------------------------------------------------------------------- -// A static method to get the global network stack object. - -IONetworkStack * IONetworkStack::getNetworkStack() -{ - return (IONetworkStack *) IOService::waitForService( - IOService::serviceMatching("IONetworkStack") ); -} - - -//=========================================================================== -// -// Interface object container helpers. -// -//=========================================================================== - -//--------------------------------------------------------------------------- -// Add the new interface object to an OSOrderedSet. - -bool IONetworkStack::addInterface( IONetworkInterface * netif ) -{ - return _ifSet->setObject(netif); -} - -//--------------------------------------------------------------------------- -// Remove an interface object from an OSOrderedSet. - -void IONetworkStack::removeInterface( IONetworkInterface * netif ) -{ - _ifSet->removeObject(netif); - DLOG("count = %d\n", _ifSet->getCount()); -} - -//--------------------------------------------------------------------------- -// Get an interface object at a given index. - -IONetworkInterface * IONetworkStack::getInterface( UInt32 index ) -{ - return (IONetworkInterface *) _ifSet->getObject(index); -} - -//--------------------------------------------------------------------------- -// Query whether the specified interface object is a member of the Set. - -bool IONetworkStack::containsInterface( IONetworkInterface * netif ) -{ - return _ifSet->containsObject(netif); -} - -//--------------------------------------------------------------------------- -// Add an interface object to the set of registered interfaces. - -bool IONetworkStack::addRegisteredInterface( IONetworkInterface * netif ) -{ - bool success = true; - OSOrderedSet * set; - const char * prefix = netif->getNamePrefix(); - - if (prefix == 0) return false; - - // Look for a Set object in the dictionary. - - set = (OSOrderedSet *) _ifDict->getObject(prefix); - - // If not found, then create one and add it to the dictionary. - - if ( (set == 0) && - ((set = OSOrderedSet::withCapacity(10, orderRegisteredInterfaces))) ) - { - success = _ifDict->setObject(prefix, set); - set->release(); - } - - // Add the interface object to its corresponding set. - // All objects in a set will have the same name prefix. - - success = (set && success) ? set->setObject(netif) : false; - - return success; -} - -//--------------------------------------------------------------------------- -// Remove an interface object from the set of registered interfaces. - -void IONetworkStack::removeRegisteredInterface( IONetworkInterface * netif ) -{ - OSOrderedSet * set; - const char * prefix = netif->getNamePrefix(); - - if ( prefix ) - { - set = (OSOrderedSet *) _ifDict->getObject(prefix); - - if ( set ) - { - // Remove interface from set. - - set->removeObject(netif); - DLOG("set:%s count = %d\n", prefix, set->getCount()); - - // Remove (also release) the set from the dictionary. - - if ( set->getCount() == 0 ) _ifDict->removeObject(prefix); - } - } -} - -//--------------------------------------------------------------------------- -// Get an registered interface with the given prefix and unit number. - -IONetworkInterface * -IONetworkStack::getRegisteredInterface( const char * prefix, - UInt32 unit ) -{ - OSOrderedSet * set; - IONetworkInterface * netif = 0; - - set = (OSOrderedSet *) _ifDict->getObject(prefix); - - for ( UInt32 index = 0; - ( set && (netif = (IONetworkInterface *) set->getObject(index)) ); - index++ ) - { - if ( netif->getUnitNumber() == unit ) - break; - } - - return netif; -} - -//--------------------------------------------------------------------------- -// Get the last object (with largest index) in the set of registered -// interfaces with the specified prefix. - -IONetworkInterface * -IONetworkStack::getLastRegisteredInterface( const char * prefix ) -{ - OSOrderedSet * set; - - set = (OSOrderedSet *) _ifDict->getObject(prefix); - - return ( set ) ? (IONetworkInterface *) set->getLastObject() : 0; -} - -//--------------------------------------------------------------------------- -// Get the next available unit number in the set of registered interfaces -// with the specified prefix. - -UInt32 -IONetworkStack::getNextAvailableUnitNumber( const char * prefix, - UInt32 startingUnit ) -{ - IONetworkInterface * netif = getLastRegisteredInterface(prefix); - - if ( ( netif == 0 ) || ( netif->getUnitNumber() < startingUnit ) ) - { - // The unit number provided is acceptable. - } - else if ( netif->getUnitNumber() == startingUnit ) - { - // Conflict, bump proposed unit number by one. - startingUnit++; - } - else - { - OSOrderedSet * set = (OSOrderedSet *) _ifDict->getObject(prefix); - - for ( UInt32 index = 0; set; index++ ) - { - netif = (IONetworkInterface *) set->getObject(index); - - if ( ( netif == 0 ) || - ( netif->getUnitNumber() > startingUnit ) ) - break; - else if ( netif->getUnitNumber() < startingUnit ) - continue; - else - startingUnit = netif->getUnitNumber() + 1; - } - } - - return startingUnit; -} - - -//=========================================================================== -// -// Interface Management. -// -//=========================================================================== - - -//--------------------------------------------------------------------------- -// A static member function that is called by a notification object when an -// interface is published. This function is called with arbitration lock of -// the interface object held. - -bool IONetworkStack::interfacePublished( void * /* target */, - void * /* param */, - IOService * service ) -{ - IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, service); - bool success = false; - - DLOG("%p\n", netif); - - if ( gIONetworkStack == 0 ) - return false; - - gIONetworkStack->lockForArbitration(); - - do { - if ( netif == 0 ) break; - - // Early exit from redundant notifications. - - if ( gIONetworkStack->containsInterface(netif) == true ) - { - success = true; - break; - } - - // Add the interface to a collection. - - if ( gIONetworkStack->addInterface(netif) == false ) - break; - - // Attach the stack object to the interface object as its client. - - if ( gIONetworkStack->attach(netif) == false ) - break; - - // Initialize the interface flags. These flags are used only - // by IONetworkStack. - - NETIF_FLAGS(netif) = kInterfaceFlagActive; - - // No outside intervention is required for the primary interface - // to be registered at unit 0. This is to assure that we have 'en0' - // even if something is really fouled up. Ideally, this should be - // removed in the future and have a single entity manage the - // naming responsibility. And on Intel, there is no concept of a - // "built-in" interface, so this will do nothing for Intel. - - if ( gIONetworkStack->_registerPrimaryInterface && - netif->isPrimaryInterface() ) - { - const char * prefix = netif->getNamePrefix(); - const UInt32 unit = 0; - - // If another interface already took unit 0, do nothing. - - if ( gIONetworkStack->getRegisteredInterface(prefix, unit) == 0 ) - { - OSArray * array = OSArray::withCapacity(1); - if ( array ) - { - gIONetworkStack->preRegisterInterface( netif, - prefix, - unit, - array ); - - completeRegistration( array, false ); // Async - } - } - } - - success = true; - } - while ( false ); - - // Remove interface on failure. - - if (success == false) gIONetworkStack->removeInterface(netif); - - gIONetworkStack->unlockForArbitration(); - - return success; -} - -//--------------------------------------------------------------------------- -// Handle termination messages sent from the interface object (provider). - -IOReturn IONetworkStack::message( UInt32 type, - IOService * provider, - void * /* argument */ ) -{ - IONetworkInterface * netif = (IONetworkInterface *) provider; - IOReturn ret = kIOReturnBadArgument; - - DLOG("%lx %p\n", type, provider); - - if ( type == kIOMessageServiceIsTerminated ) - { - lockForArbitration(); - - do { - // Verify that the provider object given is known. - - if ( containsInterface(netif) == false ) - break; - - ret = kIOReturnSuccess; - - // Interface has become inactive, it is no longer possible - // to open or to attach to the interface object. - // Mark the interface as Inactive. - - CLR_NETIF_FLAGS( netif, kInterfaceFlagActive ); - - // Interface is registering with DLIL. Postpone termination until - // the interface has completed the registration. - - if ( NETIF_FLAGS(netif) & kInterfaceFlagRegistering ) - break; - - // Remove the interface object. Don't worry, it is still retained. - - removeInterface(netif); - - // If interface was never registered with BSD, no additional - // action is required. - - if ( (NETIF_FLAGS(netif) & kInterfaceFlagRegistered) == 0 ) - break; - - // Need to unregister the interface. Do this asynchronously. - // The interface will be waiting for a close before advancing - // to the next stage in the termination process. - - thread_call_func( (thread_call_func_t) unregisterBSDInterface, - netif, - TRUE ); /* unique call desired */ - } - while ( false ); - - unlockForArbitration(); - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Detach an inactive interface that is currently registered with BSD. - -void IONetworkStack::unregisterBSDInterface( IONetworkInterface * netif ) -{ - assert( netif ); - - // If dlil_if_detach() returns DLIL_WAIT_FOR_FREE, then we - // must not close the interface until we receive a callback - // from DLIL. Otherwise, proceed with the close. - - DLOG("%p\n", netif); - - if ( dlil_if_detach(netif->getIfnet()) != DLIL_WAIT_FOR_FREE ) - { - bsdInterfaceWasUnregistered( netif->getIfnet() ); - } -} - -//--------------------------------------------------------------------------- -// Handle a callback from DLIL to signal that an interface can now be safely -// destroyed. DLIL will issue this call only if the dlil_if_detach() function -// returned DLIL_WAIT_FOR_FREE. - -int IONetworkStack::bsdInterfaceWasUnregistered( struct ifnet * ifp ) -{ - IONetworkInterface * netif; - - assert( ifp ); - - netif = (IONetworkInterface *) ifp->if_private; - DLOG("%p\n", netif); - - assert( netif && gIONetworkStack ); - - // An interface was detached from DLIL. It is now safe to close the - // interface object. - - gIONetworkStack->lockForArbitration(); - - assert( NETIF_FLAGS(netif) == kInterfaceFlagRegistered ); - - // Update state. - - CLR_NETIF_FLAGS( netif, kInterfaceFlagRegistered ); - - // Drop interface from list of registered interfaces, - // and decrement interface retain count. - - gIONetworkStack->removeRegisteredInterface(netif); - - gIONetworkStack->unlockForArbitration(); - - // Make sure the interface is brought down before it is closed. - - netif->setFlags( 0, IFF_UP ); // clear IFF_UP flag. - (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, 0); - - // Close interface and allow it to proceed with termination. - - netif->close(gIONetworkStack); - - return 0; -} - -//--------------------------------------------------------------------------- -// Pre-register a network interface. This function assumes that the -// caller is holding the arbitration lock. - -bool IONetworkStack::preRegisterInterface( IONetworkInterface * netif, - const char * prefix, - UInt32 unit, - OSArray * array ) -{ - bool success = false; - - DLOG("%p %s %d\n", netif, prefix ? prefix : "", unit); - - assert( netif && array ); - - do { - if ( prefix == 0 ) break; - - // Verify that the interface object given is known. - - if ( containsInterface(netif) == false ) - break; - - // Interface must be in Active state. - - if ( NETIF_FLAGS(netif) != kInterfaceFlagActive ) - { - break; - } - - // The unit argument provided is a hint to indicate the lowest unit - // number that can be assigned to the interface. We are allowed to - // increment the unit number provided if the number is already - // taken. - - unit = getNextAvailableUnitNumber(prefix, unit); - - // Open the interface object. This will fail if the interface - // object has become inactive. Beware of reverse lock acquisition - // sequence, which is interface then stack arbitration lock. - // Must avoid taking locks in that order to avoid deadlocks. - // The only exception is when handling the "First Publish" - // notification, which is safe since the stack object does not - // yet have a reference to the new interface. - - if ( netif->open(this) == false ) - { - break; - } - - // Update interface name properties and add the interface object - // to a collection of registered interfaces. The chosen name will - // be reserved until the interface is removed from the collection - // of registered interfaces. - - if ( ( netif->setUnitNumber(unit) == false ) || - ( addRegisteredInterface(netif) == false ) ) - { - netif->close(this); - break; - } - - success = true; - } - while ( false ); - - if ( success ) - { - // Mark the interface as in the process of registering. - - SET_NETIF_FLAGS( netif, kInterfaceFlagRegistering ); - - // Add interface to pre-registration array. - // We assume the array has enough storage space for the new entry. - - success = array->setObject( netif ); - assert( success ); - } - - return success; -} - -//--------------------------------------------------------------------------- -// Complete the registration of interface objects stored in the array provided. -// The arbitration lock should not be held when the 'isSync' flag is true. - -void -IONetworkStack::completeRegistration( OSArray * array, bool isSync ) -{ - if ( isSync ) - { - completeRegistrationUsingArray( array ); - } - else - { - thread_call_func( (thread_call_func_t) completeRegistrationUsingArray, - array, - TRUE ); /* unique call desired */ - } -} - -void -IONetworkStack::completeRegistrationUsingArray( OSArray * array ) -{ - IONetworkInterface * netif; - - assert( array ); - - for ( UInt32 i = 0; i < array->getCount(); i++ ) - { - netif = (IONetworkInterface *) array->getObject(i); - assert( netif ); - - registerBSDInterface( netif ); - } - - array->release(); // consumes a ref count -} - -//--------------------------------------------------------------------------- -// Call DLIL functions to register the BSD interface. - -void IONetworkStack::registerBSDInterface( IONetworkInterface * netif ) -{ - char ifname[20]; - bool doTermination = false; - - assert( netif ); - - // Attach the interface to DLIL. - - bpfattach( netif->getIfnet(), DLT_EN10MB, sizeof(struct ether_header) ); - ether_ifattach( netif->getIfnet() ); - - // Add a kIOBSDNameKey property to the interface AFTER the interface - // has registered with DLIL. The order is very important to avoid - // rooting from an interface which is not yet known by BSD. - - sprintf(ifname, "%s%d", netif->getNamePrefix(), netif->getUnitNumber()); - netif->setProperty(kIOBSDNameKey, ifname); - - // Update state bits and detect for untimely interface termination. - - gIONetworkStack->lockForArbitration(); - - assert( ( NETIF_FLAGS(netif) & - ( kInterfaceFlagRegistering | kInterfaceFlagRegistered ) ) == - kInterfaceFlagRegistering ); - - CLR_NETIF_FLAGS( netif, kInterfaceFlagRegistering ); - SET_NETIF_FLAGS( netif, kInterfaceFlagRegistered ); - - if ( ( NETIF_FLAGS(netif) & kInterfaceFlagActive ) == 0 ) - { - doTermination = true; - } - else - { - // Re-register interface after the interface has registered with BSD. - // Is there a danger in calling registerService while holding the - // gIONetworkStack's arbitration lock? - - netif->registerService(); - } - - gIONetworkStack->unlockForArbitration(); - - // In the unlikely event that an interface was terminated before - // being registered, re-issue the termination message and tear it - // all down. - - if ( doTermination ) - { - gIONetworkStack->message(kIOMessageServiceIsTerminated, netif); - } -} - -//--------------------------------------------------------------------------- -// External/Public API - Register all interfaces. - -IOReturn -IONetworkStack::registerAllInterfaces() -{ - IONetworkInterface * netif; - const UInt32 unit = 0; - OSArray * array; - - lockForArbitration(); - - // Allocate array to hold pre-registered interface objects. - - array = OSArray::withCapacity( _ifSet->getCount() ); - if ( array == 0 ) - { - unlockForArbitration(); - return kIOReturnNoMemory; - } - - // Iterate through all interface objects. - - for ( UInt32 index = 0; ( netif = getInterface(index) ); index++ ) - { - // Interface must be Active and not yet registered. - - if ( NETIF_FLAGS(netif) != kInterfaceFlagActive ) - { - continue; - } - - // Pre-register the interface. - - preRegisterInterface( netif, - netif->getNamePrefix(), - unit, - array ); - } - - unlockForArbitration(); - - // Complete registration without holding the arbitration lock. - - completeRegistration( array, true ); - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// External/Public API - Register primary interface. - -IOReturn IONetworkStack::registerPrimaryInterface( bool enable ) -{ - IONetworkInterface * netif; - const UInt32 unit = 0; - OSArray * array; - - lockForArbitration(); - - _registerPrimaryInterface = enable; - - if ( _registerPrimaryInterface == false ) - { - unlockForArbitration(); - return kIOReturnSuccess; - } - - // Allocate array to hold pre-registered interface objects. - - array = OSArray::withCapacity( _ifSet->getCount() ); - if ( array == 0 ) - { - unlockForArbitration(); - return kIOReturnNoMemory; - } - - // Iterate through all interface objects. - - for ( UInt32 index = 0; ( netif = getInterface(index) ); index++ ) - { - const char * prefix = netif->getNamePrefix(); - - // Interface must be Active and not yet registered. - - if ( NETIF_FLAGS(netif) != kInterfaceFlagActive ) - { - continue; - } - - // Primary only. - - if ( netif->isPrimaryInterface() != true ) - { - continue; - } - - // If the unit slot is already taken, forget it. - - if ( getRegisteredInterface( prefix, unit ) ) - { - continue; - } - - // Pre-register the interface. - - preRegisterInterface( netif, prefix, unit, array ); - } - - unlockForArbitration(); - - // Complete registration without holding the arbitration lock. - - completeRegistration( array, true ); - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// External/Public API - Register a single interface. - -IOReturn IONetworkStack::registerInterface( IONetworkInterface * netif, - const char * prefix, - UInt32 unit, - bool isSync ) -{ - bool ret; - OSArray * array; - - // Create pre-registration array. - - array = OSArray::withCapacity( 1 ); - if ( array == 0 ) - { - return kIOReturnNoMemory; - } - - // Pre-registration has to be serialized, but the registration can - // (and should) be completed without holding a lock. If the interface - // has already been registered, or cannot be registered, then the - // return value will be false. - - lockForArbitration(); - ret = preRegisterInterface( netif, prefix, unit, array ); - unlockForArbitration(); - - // Complete the registration synchronously or asynchronously. - // If synchronous, then this call will return after the interface - // object in the array has registered with DLIL. - - completeRegistration( array, isSync ); - - return ret ? kIOReturnSuccess : kIOReturnError; -} - -//--------------------------------------------------------------------------- -// Registered interfaces are ordered by their assigned unit number. Those with -// larger unit numbers will be placed behind those with smaller unit numbers. -// This ordering makes it easier to hunt for an available unit number slot for -// a new interface. - -SInt32 IONetworkStack:: -orderRegisteredInterfaces( const OSMetaClassBase * obj1, - const OSMetaClassBase * obj2, - void * ref ) -{ - const IONetworkInterface * netif1 = (const IONetworkInterface *) obj1; - const IONetworkInterface * netif2 = (const IONetworkInterface *) obj2; - - assert( netif1 && netif2 ); - - return ( netif2->getUnitNumber() - netif1->getUnitNumber() ); -} - -//--------------------------------------------------------------------------- -// Create a user-client object to manage user space access. - -IOReturn IONetworkStack::newUserClient( task_t owningTask, - void * /* security_id */, - UInt32 /* type */, - IOUserClient ** handler ) -{ - IOReturn err = kIOReturnSuccess; - IOUserClient * client; - - client = IONetworkStackUserClient::withTask(owningTask); - - if (!client || !client->attach(this) || !client->start(this)) - { - if (client) - { - client->detach(this); - client->release(); - client = 0; - err = kIOReturnExclusiveAccess; - } - else - { - err = kIOReturnNoMemory; - } - } - - *handler = client; - - return err; -} - -//--------------------------------------------------------------------------- -// IONetworkStackUserClient implementation. - -#undef super -#define super IOUserClient -OSDefineMetaClassAndStructors( IONetworkStackUserClient, IOUserClient ) - -IONetworkStackUserClient * IONetworkStackUserClient::withTask( task_t task ) -{ - IONetworkStackUserClient * me = new IONetworkStackUserClient; - - if ( me && me->init() == false ) - { - me->release(); - return 0; - } - return me; -} - -bool IONetworkStackUserClient::start( IOService * provider ) -{ - if ( super::start(provider) == false ) - return false; - - if ( provider->open(this) == false ) - return false; - - _provider = (IONetworkStack *) provider; - - return true; -} - -IOReturn IONetworkStackUserClient::clientClose() -{ - if (_provider) - { - _provider->close(this); - detach(_provider); - } - return kIOReturnSuccess; -} - -IOReturn IONetworkStackUserClient::clientDied() -{ - return clientClose(); -} - -IOReturn IONetworkStackUserClient::setProperties( OSObject * properties ) -{ - IONetworkInterface * netif; - OSDictionary * dict = OSDynamicCast(OSDictionary, properties); - IOReturn ret = kIOReturnBadArgument; - OSString * path = 0; - OSNumber * unit; - OSNumber * cmd; - - do { - // Sanity check. - - if ( (_provider == 0) || (dict == 0) ) - break; - - // Switch on the specified user command. - - cmd = OSDynamicCast( OSNumber, - dict->getObject( kIONetworkStackUserCommand ) ); - if ( cmd == 0 ) - break; - - switch ( cmd->unsigned32BitValue() ) - { - // Register one interface. - - case kIORegisterOne: - path = OSDynamicCast( OSString, - dict->getObject( kIOPathMatchKey )); - unit = OSDynamicCast( OSNumber, - dict->getObject( kIOInterfaceUnit )); - - if ( (path == 0) || (unit == 0) ) - { - break; - } - - netif = OSDynamicCast( IONetworkInterface, - IORegistryEntry::fromPath( path->getCStringNoCopy()) ); - - if ( netif == 0 ) break; - - ret = _provider->registerInterface( netif, - netif->getNamePrefix(), - unit->unsigned32BitValue() ); - - netif->release(); // offset the retain by fromPath(). - - break; - - // Register all interfaces. - - case kIORegisterAll: - ret = _provider->registerAllInterfaces(); - break; - } - } - while ( false ); - - return ret; -} diff --git a/iokit/Families/IONetworking/IONetworkUserClient.cpp b/iokit/Families/IONetworking/IONetworkUserClient.cpp deleted file mode 100644 index 8641d4b5a..000000000 --- a/iokit/Families/IONetworking/IONetworkUserClient.cpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * - */ - -#include <IOKit/assert.h> -#include <IOKit/network/IONetworkInterface.h> -#include <IOKit/network/IONetworkUserClient.h> -#include <IOKit/network/IONetworkData.h> - -//------------------------------------------------------------------------ - -#define super IOUserClient -OSDefineMetaClassAndStructors( IONetworkUserClient, IOUserClient ) - -#ifdef DEBUG -#define DLOG(fmt, args...) IOLog(fmt, ## args) -#else -#define DLOG(fmt, args...) -#endif - -//--------------------------------------------------------------------------- -// Factory method that performs allocation and initialization -// of an IONetworkUserClient instance. - -IONetworkUserClient * IONetworkUserClient::withTask(task_t owningTask) -{ - IONetworkUserClient * me; - - me = new IONetworkUserClient; - if (me) - { - if (!me->init()) - { - me->release(); - return 0; - } - me->_task = owningTask; - } - return me; -} - -//--------------------------------------------------------------------------- -// Start the IONetworkUserClient. - -bool IONetworkUserClient::start(IOService * provider) -{ - UInt32 i; - - _owner = OSDynamicCast(IONetworkInterface, provider); - assert(_owner); - - if (!super::start(_owner)) - return false; - - if (!_owner->open(this)) - return false; - - // Initialize the call structures. - // - i = kIONUCResetNetworkDataIndex; - _methods[i].object = this; - _methods[i].func = (IOMethod) &IONetworkUserClient::resetNetworkData; - _methods[i].count0 = kIONUCResetNetworkDataInputs; - _methods[i].count1 = kIONUCResetNetworkDataOutputs; - _methods[i].flags = kIONUCResetNetworkDataFlags; - - i = kIONUCWriteNetworkDataIndex; - _methods[i].object = this; - _methods[i].func = (IOMethod) &IONetworkUserClient::writeNetworkData; - _methods[i].count0 = kIONUCWriteNetworkDataInput0; - _methods[i].count1 = kIONUCWriteNetworkDataInput1; - _methods[i].flags = kIONUCWriteNetworkDataFlags; - - i = kIONUCReadNetworkDataIndex; - _methods[i].object = this; - _methods[i].func = (IOMethod) &IONetworkUserClient::readNetworkData; - _methods[i].count0 = kIONUCReadNetworkDataInputs; - _methods[i].count1 = kIONUCReadNetworkDataOutputs; - _methods[i].flags = kIONUCReadNetworkDataFlags; - - i = kIONUCGetNetworkDataCapacityIndex; - _methods[i].object = this; - _methods[i].func = (IOMethod) - &IONetworkUserClient::getNetworkDataCapacity; - _methods[i].count0 = kIONUCGetNetworkDataCapacityInputs; - _methods[i].count1 = kIONUCGetNetworkDataCapacityOutputs; - _methods[i].flags = kIONUCGetNetworkDataCapacityFlags; - - i = kIONUCGetNetworkDataHandleIndex; - _methods[i].object = this; - _methods[i].func = (IOMethod) &IONetworkUserClient::getNetworkDataHandle; - _methods[i].count0 = kIONUCGetNetworkDataHandleInputs; - _methods[i].count1 = kIONUCGetNetworkDataHandleOutputs; - _methods[i].flags = kIONUCGetNetworkDataHandleFlags; - - return true; -} - -//--------------------------------------------------------------------------- -// Free the IONetworkUserClient instance. - -void IONetworkUserClient::free() -{ - super::free(); -} - -//--------------------------------------------------------------------------- -// Handle a client close. Close and detach from our owner (provider). - -IOReturn IONetworkUserClient::clientClose() -{ - if (_owner) { - _owner->close(this); - detach(_owner); - } - - return kIOReturnSuccess; -} - -//--------------------------------------------------------------------------- -// Handle client death. Close and detach from our owner (provider). - -IOReturn IONetworkUserClient::clientDied() -{ - return clientClose(); -} - -//--------------------------------------------------------------------------- -// Look up an entry from the method array. - -IOExternalMethod * -IONetworkUserClient::getExternalMethodForIndex(UInt32 index) -{ - if (index >= kIONUCLastIndex) - return 0; - else - return &_methods[index]; -} - -//--------------------------------------------------------------------------- -// Fill the data buffer in an IONetworkData object with zeroes. - -IOReturn IONetworkUserClient::resetNetworkData(OSSymbol * key) -{ - IONetworkData * data; - IOReturn ret; - - data = _owner->getNetworkData(key); - ret = data ? data->reset() : kIOReturnBadArgument; - - return ret; -} - -//--------------------------------------------------------------------------- -// Write to the data buffer in an IONetworkData object with data from a -// source buffer provided by the caller. - -IOReturn -IONetworkUserClient::writeNetworkData(OSSymbol * key, - void * srcBuffer, - IOByteCount srcBufferSize) -{ - IONetworkData * data; - IOReturn ret; - - if (!srcBuffer || (srcBufferSize == 0)) - return kIOReturnBadArgument; - - data = _owner->getNetworkData(key); - ret = data ? data->write(srcBuffer, srcBufferSize) : kIOReturnBadArgument; - - return ret; -} - -//--------------------------------------------------------------------------- -// Read the data buffer in an IONetworkData object and copy -// this data to a destination buffer provided by the caller. - -IOReturn -IONetworkUserClient::readNetworkData(OSSymbol * key, - void * dstBuffer, - IOByteCount * dstBufferSize) -{ - IONetworkData * data; - IOReturn ret ; - - if (!dstBuffer || !dstBufferSize) - return kIOReturnBadArgument; - - data = _owner->getNetworkData(key); - ret = data ? data->read(dstBuffer, dstBufferSize) : - kIOReturnBadArgument; - - return ret; -} - -//--------------------------------------------------------------------------- -// Get the capacity of an IONetworkData object. - -IOReturn -IONetworkUserClient::getNetworkDataCapacity(OSSymbol * key, - UInt32 * capacity) -{ - IOReturn ret = kIOReturnBadArgument; - IONetworkData * data; - - data = _owner->getNetworkData(key); - - if (data) { - *capacity = data->getSize(); - ret = kIOReturnSuccess; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Called to obtain a handle that maps to an IONetworkData object. -// This handle can be later passed to other methods in this class -// to refer to the same object. - -IOReturn -IONetworkUserClient::getNetworkDataHandle(char * name, - OSSymbol ** handle, - IOByteCount nameSize, - IOByteCount * handleSizeP) -{ - IOReturn ret = kIOReturnBadArgument; - const OSSymbol * key; - - if (!name || !nameSize || (name[nameSize - 1] != '\0') || - (*handleSizeP != sizeof(*handle))) - return kIOReturnBadArgument; - - key = OSSymbol::withCStringNoCopy(name); - if (!key) - return kIOReturnNoMemory; - - if (_owner->getNetworkData(key)) - { - *handle = (OSSymbol *) key; - ret = kIOReturnSuccess; - } - - if (key) - key->release(); - - return ret; -} diff --git a/iokit/Families/IONetworking/IOOutputQueue.cpp b/iokit/Families/IONetworking/IOOutputQueue.cpp deleted file mode 100644 index 44349b770..000000000 --- a/iokit/Families/IONetworking/IOOutputQueue.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * IOOutputQueue.cpp - * - * HISTORY - * 2-Feb-1999 Joe Liu (jliu) created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/network/IOOutputQueue.h> -#include <IOKit/network/IOBasicOutputQueue.h> -#include <IOKit/network/IOGatedOutputQueue.h> -#include <IOKit/network/IONetworkStats.h> -#include <IOKit/network/IONetworkController.h> -#include "IOMbufQueue.h" -#include <libkern/OSAtomic.h> - -//=========================================================================== -// IOOutputQueue -//=========================================================================== - -#define STATE_IS(bits) (_state == (bits)) -#define STATE_HAS(bits) ((_state & (bits)) == (bits)) -#define STATE_SET(bits) (_state |= (bits)) -#define STATE_CLR(bits) (_state &= ~(bits)) - -#undef super -#define super OSObject -OSDefineMetaClassAndAbstractStructors( IOOutputQueue, OSObject ) -OSMetaClassDefineReservedUnused( IOOutputQueue, 0); -OSMetaClassDefineReservedUnused( IOOutputQueue, 1); -OSMetaClassDefineReservedUnused( IOOutputQueue, 2); -OSMetaClassDefineReservedUnused( IOOutputQueue, 3); -OSMetaClassDefineReservedUnused( IOOutputQueue, 4); -OSMetaClassDefineReservedUnused( IOOutputQueue, 5); -OSMetaClassDefineReservedUnused( IOOutputQueue, 6); -OSMetaClassDefineReservedUnused( IOOutputQueue, 7); -OSMetaClassDefineReservedUnused( IOOutputQueue, 8); -OSMetaClassDefineReservedUnused( IOOutputQueue, 9); -OSMetaClassDefineReservedUnused( IOOutputQueue, 10); -OSMetaClassDefineReservedUnused( IOOutputQueue, 11); -OSMetaClassDefineReservedUnused( IOOutputQueue, 12); -OSMetaClassDefineReservedUnused( IOOutputQueue, 13); -OSMetaClassDefineReservedUnused( IOOutputQueue, 14); -OSMetaClassDefineReservedUnused( IOOutputQueue, 15); - -//--------------------------------------------------------------------------- -// Initialize an IOOutputQueue object. - -bool IOOutputQueue::init() -{ - if (super::init() == false) - return false; - - // Allocate and initialize the callout entry for async service. - - _callEntry = thread_call_allocate((thread_call_func_t) &runServiceThread, - (void *) this); /* param0 */ - if (_callEntry == 0) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Frees the IOOutputQueue object. - -void IOOutputQueue::free() -{ - if (_callEntry) - { - cancelServiceThread(); - thread_call_free(_callEntry); - _callEntry = 0; - } - - super::free(); -} - -//--------------------------------------------------------------------------- -// Schedule a service thread callout, which will run the -// serviceThread() method. - -bool IOOutputQueue::scheduleServiceThread(void * param = 0) -{ - return thread_call_enter1(_callEntry, (thread_call_param_t) param); -} - -//--------------------------------------------------------------------------- -// Cancel any pending service thread callout. - -bool IOOutputQueue::cancelServiceThread() -{ - if (_callEntry == 0) - return false; - else - return thread_call_cancel(_callEntry); -} - -//--------------------------------------------------------------------------- -// A 'C' glue function that is registered as the service thread callout -// handler. This function in turn will call the serviceThread() method. - -void -IOOutputQueue::runServiceThread(thread_call_param_t param0, /* this */ - thread_call_param_t param1) /* param */ -{ - assert(param0); - ((IOOutputQueue *) param0)->serviceThread(param1); -} - -//--------------------------------------------------------------------------- -// Must be implemented by a subclass that calls scheduleServiceThread(). -// The default implementation is a placeholder and performs no action. - -void IOOutputQueue::serviceThread(void * param) -{ -} - -//--------------------------------------------------------------------------- -// Return an address of a method that is designated to handle -// packets sent to the queue object. - -IOOutputAction IOOutputQueue::getOutputHandler() const -{ - return (IOOutputAction) &IOOutputQueue::enqueue; -} - -//--------------------------------------------------------------------------- -// Return an IONetworkData object containing statistics counters. - -IONetworkData * IOOutputQueue::getStatisticsData() const -{ - return 0; -} - - -//=========================================================================== -// IOBasicOutputQueue -//=========================================================================== - -#undef super -#define super IOOutputQueue -OSDefineMetaClassAndStructors( IOBasicOutputQueue, IOOutputQueue ) - -#define QUEUE_LOCK IOSimpleLockLock(_spinlock) -#define QUEUE_UNLOCK IOSimpleLockUnlock(_spinlock) - -#define kIOOutputQueueSignature ((void *) 0xfacefeed) - -//--------------------------------------------------------------------------- -// 'C' function glue to dispatch the IONetworkData notification. - -IOReturn -IOBasicOutputQueue::dispatchNetworkDataNotification(void * target, - void * param, - IONetworkData * data, - UInt32 type) -{ - IOBasicOutputQueue * self = (IOBasicOutputQueue *) target; - return self->handleNetworkDataAccess(data, type, param); -} - -//--------------------------------------------------------------------------- -// Initialize an IOBasicOutputQueue object. - -bool IOBasicOutputQueue::init(OSObject * target, - IOOutputAction action, - UInt32 capacity = 0) -{ - if (super::init() == false) - return false; - - if ((target == 0) || (action == 0)) - return false; - - _target = target; - _action = action; - - // Create a data object for queue statistics. - - _statsData = IONetworkData::withInternalBuffer( - kIOOutputQueueStatsKey, - sizeof(IOOutputQueueStats), - kIONetworkDataBasicAccessTypes, - this, - (IONetworkData::Action) - &IOBasicOutputQueue::dispatchNetworkDataNotification, - kIOOutputQueueSignature); - - if (_statsData == 0) - return false; - - _stats = (IOOutputQueueStats *) _statsData->getBuffer(); - assert(_stats); - - _stats->capacity = capacity; - - // Create two queue objects. - - _queues[0] = IONew(IOMbufQueue, 1); - _queues[1] = IONew(IOMbufQueue, 1); - - IOMbufQueueInit(_queues[0], capacity); - IOMbufQueueInit(_queues[1], capacity); - - if ( (_queues[0] == 0) || (_queues[1] == 0) ) - return false; - - _inQueue = _queues[0]; - - // Create a spinlock to protect the queue. - - _spinlock = IOSimpleLockAlloc(); - if (_spinlock == 0) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Factory methods that will construct and initialize an IOBasicOutputQueue -// object. - -IOBasicOutputQueue * -IOBasicOutputQueue::withTarget(IONetworkController * target, - UInt32 capacity = 0) -{ - IOBasicOutputQueue * queue = new IOBasicOutputQueue; - - if (queue && !queue->init(target, target->getOutputHandler(), capacity)) - { - queue->release(); - queue = 0; - } - return queue; -} - -IOBasicOutputQueue * -IOBasicOutputQueue::withTarget(OSObject * target, - IOOutputAction action, - UInt32 capacity = 0) -{ - IOBasicOutputQueue * queue = new IOBasicOutputQueue; - - if (queue && !queue->init(target, action, capacity)) - { - queue->release(); - queue = 0; - } - return queue; -} - -//--------------------------------------------------------------------------- -// Release all resources previously allocated before calling super::free(). - -void IOBasicOutputQueue::free() -{ - cancelServiceThread(); - - if (_spinlock) - { - flush(); - IOSimpleLockFree(_spinlock); - _spinlock = 0; - } - - if (_queues[0]) IODelete(_queues[0], IOMbufQueue, 1); - if (_queues[1]) IODelete(_queues[1], IOMbufQueue, 1); - _queues[0] = _queues[1] = 0; - - if (_statsData) - { - _statsData->release(); - _statsData = 0; - } - - super::free(); -} - -//--------------------------------------------------------------------------- -// Provide an implementation for the serviceThread() method defined in -// IOOutputQueue. This method is called by a callout thread after an -// asynchronous service was scheduled. - -void IOBasicOutputQueue::serviceThread(void * param) -{ - QUEUE_LOCK; - STATE_CLR((UInt32) param); - STATE_SET(kStateOutputActive); - dequeue(); - QUEUE_UNLOCK; -} - -//--------------------------------------------------------------------------- -// Add a single packet, or a chain of packets, to the queue object. -// This method can support multiple clients threads. - -UInt32 IOBasicOutputQueue::enqueue(struct mbuf * m, void * param) -{ - bool success; - - QUEUE_LOCK; - - success = IOMbufQueueEnqueue(_inQueue, m); - - if ( STATE_IS( kStateRunning ) ) - { - STATE_SET( kStateOutputActive ); - dequeue(); - } - - QUEUE_UNLOCK; - - // Drop the packet if the packet(s) were not queued. - // But avoid calling m_free() while holding a simple lock. - // This will not be necessary in the future when m_free() - // is no longer funneled. - - if (success == false) - { - OSAddAtomic( IOMbufFree(m), - (SInt32 *) &_stats->dropCount ); - } - - return 0; -} - -//--------------------------------------------------------------------------- -// Responsible for removing all packets from the queue and pass each packet -// removed to our target. This method returns when the queue becomes empty -// or if the queue is stalled by the target. This method is called with the -// spinlock held. - -void IOBasicOutputQueue::dequeue() -{ - IOMbufQueue * outQueue = _queues[0]; - UInt32 newState = 0; - UInt32 myServiceCount; - - // Switch the input queue. Work on the real queue, while allowing - // clients to continue to queue packets to the "shadow" queue. - - _inQueue = _queues[1]; - - // While dequeue is allowed, and incoming queue has packets. - - while ( STATE_IS( kStateRunning | kStateOutputActive ) && - IOMbufQueueGetSize(outQueue) ) - { - myServiceCount = _serviceCount; - - QUEUE_UNLOCK; - - output( outQueue, &newState ); - - QUEUE_LOCK; - - // If service() was called during the interval when the - // spinlock was released, then refuse to honor any - // stall requests. - - if ( newState ) - { - if ( myServiceCount != _serviceCount ) - newState &= ~kStateOutputStalled; - - STATE_SET( newState ); - } - - // Absorb new packets added to the shadow queue. - - IOMbufQueueEnqueue( outQueue, _inQueue ); - } - - _inQueue = _queues[0]; - - STATE_CLR( kStateOutputActive ); - - if ( newState & kStateOutputServiceMask ) - { - scheduleServiceThread((void *)(newState & kStateOutputServiceMask)); - } - - if (_waitDequeueDone) - { - // A stop() request is waiting for the transmit thread to - // complete transmission. Wake up the waiting thread. - - _waitDequeueDone = false; - thread_wakeup((void *) &_waitDequeueDone); - } -} - -//--------------------------------------------------------------------------- -// Transfer all packets from the given queue to the target. Continue until -// the queue becomes empty, or if the target throttle the queue. - -void IOBasicOutputQueue::output(IOMbufQueue * queue, UInt32 * state) -{ - struct mbuf * pkt; - UInt32 status; - - do { - pkt = IOMbufQueueDequeue(queue); - assert(pkt); - - // Handoff each packet to the controller driver. - - status = (_target->*_action)( pkt, 0 ); - - if ( status == ( kIOOutputStatusAccepted | kIOOutputCommandNone ) ) - { - // Fast-path the typical code path. - _stats->outputCount++; - } - else - { - // Look at the return status and update statistics counters. - - switch (status & kIOOutputStatusMask) - { - default: - case kIOOutputStatusAccepted: - _stats->outputCount++; - break; - - case kIOOutputStatusRetry: - IOMbufQueuePrepend(queue, pkt); - _stats->retryCount++; - break; - } - - // Handle the requested action. - - switch (status & kIOOutputCommandMask) - { - case kIOOutputCommandStall: - *state = kStateOutputStalled; - _stats->stallCount++; - break; - - default: - break; - } - } - } - while ( IOMbufQueueGetSize(queue) && (*state == 0) ); -} - -//--------------------------------------------------------------------------- -// Start or enable the queue. - -bool IOBasicOutputQueue::start() -{ - QUEUE_LOCK; - - STATE_SET( kStateRunning ); - STATE_CLR( kStateOutputStalled ); - _serviceCount++; - - if ( STATE_IS( kStateRunning ) ) - { - STATE_SET( kStateOutputActive ); - dequeue(); - } - - QUEUE_UNLOCK; - - return true; /* always return true */ -} - -//--------------------------------------------------------------------------- -// Stop or disable the queue. - -bool IOBasicOutputQueue::stop() -{ - bool wasRunning; - - QUEUE_LOCK; - - wasRunning = STATE_HAS( kStateRunning ); - - STATE_CLR( kStateRunning ); - - if ( STATE_HAS( kStateOutputActive ) ) - { - // If dequeue is active, it means that: - // 1. A thread is about to call dequeue(). - // 2. A thread is in dequeue() and calling the target. - // - // Wait for the dequeue thread to complete processing. - - _waitDequeueDone = true; - - assert_wait((void *) &_waitDequeueDone, false); - } - - QUEUE_UNLOCK; - - thread_block((void (*)(void)) 0); - - return wasRunning; -} - -//--------------------------------------------------------------------------- -// If the queue becomes stalled, then service() must be called by the target -// to restart the queue when the target is ready to accept more packets. - -bool IOBasicOutputQueue::service(UInt32 options = 0) -{ - bool doDequeue = false; - bool async = (options & kServiceAsync); - UInt32 oldState; - - QUEUE_LOCK; - - oldState = _state; - - // Clear the stall condition. - - STATE_CLR( kStateOutputStalled ); - _serviceCount++; - - if ( ( oldState & kStateOutputStalled ) && - STATE_IS( kStateRunning ) && - IOMbufQueueGetSize(_queues[0]) ) - { - doDequeue = true; - STATE_SET( kStateOutputActive ); - if (async == false) dequeue(); - } - - QUEUE_UNLOCK; - - if ( doDequeue && async ) - { - scheduleServiceThread(); - } - - return doDequeue; -} - -//--------------------------------------------------------------------------- -// Release all packets held by the queue. - -UInt32 IOBasicOutputQueue::flush() -{ - UInt32 flushCount; - - QUEUE_LOCK; - flushCount = IOMbufFree( IOMbufQueueDequeueAll( _inQueue ) ); - OSAddAtomic(flushCount, (SInt32 *) &_stats->dropCount); - QUEUE_UNLOCK; - - return flushCount; -} - -//--------------------------------------------------------------------------- -// Change the capacity of the queue. - -bool IOBasicOutputQueue::setCapacity(UInt32 capacity) -{ - QUEUE_LOCK; - IOMbufQueueSetCapacity(_queues[1], capacity); - IOMbufQueueSetCapacity(_queues[0], capacity); - _stats->capacity = capacity; - QUEUE_UNLOCK; - return true; -} - -//--------------------------------------------------------------------------- -// Returns the current queue capacity. - -UInt32 IOBasicOutputQueue::getCapacity() const -{ - return _stats->capacity; -} - -//--------------------------------------------------------------------------- -// Returns the current queue size. - -UInt32 IOBasicOutputQueue::getSize() const -{ - UInt32 size; - QUEUE_LOCK; - size = IOMbufQueueGetSize(_queues[0]) + IOMbufQueueGetSize(_queues[1]); - QUEUE_UNLOCK; - return size; -} - -//--------------------------------------------------------------------------- -// Returns the number of packets dropped by the queue due to over-capacity. - -UInt32 IOBasicOutputQueue::getDropCount() -{ - return _stats->dropCount; -} - -//--------------------------------------------------------------------------- -// Returns the number of packet passed to the target. - -UInt32 IOBasicOutputQueue::getOutputCount() -{ - return _stats->outputCount; -} - -//--------------------------------------------------------------------------- -// Returns the number of times that a kIOOutputStatusRetry status code -// is received from the target. - -UInt32 IOBasicOutputQueue::getRetryCount() -{ - return _stats->retryCount; -} - -//--------------------------------------------------------------------------- -// Returns the number of times that a kIOOutputCommandStall action code -// is received from the target. - -UInt32 IOBasicOutputQueue::getStallCount() -{ - return _stats->stallCount; -} - -//--------------------------------------------------------------------------- -// Returns the current state of the queue object. - -UInt32 IOBasicOutputQueue::getState() const -{ - return _state; -} - -//--------------------------------------------------------------------------- -// This method is called by our IONetworkData object when it receives -// a read or a reset request. We need to be notified to intervene in -// the request handling. - -IOReturn -IOBasicOutputQueue::handleNetworkDataAccess(IONetworkData * data, - UInt32 accessType, - void * arg) -{ - IOReturn ret = kIOReturnSuccess; - - assert(data && (arg == kIOOutputQueueSignature)); - - // Check the type of data request. - - switch (accessType) - { - case kIONetworkDataAccessTypeRead: - case kIONetworkDataAccessTypeSerialize: - _stats->size = getSize(); - break; - - default: - ret = kIOReturnNotWritable; - break; - } - - return ret; -} - -//--------------------------------------------------------------------------- -// Return an IONetworkData object containing an IOOutputQueueStats structure. - -IONetworkData * IOBasicOutputQueue::getStatisticsData() const -{ - return _statsData; -} - -//=========================================================================== -// IOGatedOutputQueue -//=========================================================================== - -#undef super -#define super IOBasicOutputQueue -OSDefineMetaClassAndStructors( IOGatedOutputQueue, IOBasicOutputQueue ) - -//--------------------------------------------------------------------------- -// Initialize an IOGatedOutputQueue object. - -bool IOGatedOutputQueue::init(OSObject * target, - IOOutputAction action, - IOWorkLoop * workloop, - UInt32 capacity = 0) -{ - if (super::init(target, action, capacity) == false) - return false; - - // Verify that the IOWorkLoop provided is valid. - - if (OSDynamicCast(IOWorkLoop, workloop) == 0) - return false; - - // Allocate and attach an IOCommandGate object to the workloop. - - _gate = IOCommandGate::commandGate(this); - - if (!_gate || (workloop->addEventSource(_gate) != kIOReturnSuccess)) - return false; - - // Allocate and attach an IOInterruptEventSource object to the workloop. - - _interruptSrc = IOInterruptEventSource::interruptEventSource( - this, - (IOInterruptEventSource::Action) restartDeferredOutput - ); - - if ( !_interruptSrc || - (workloop->addEventSource(_interruptSrc) != kIOReturnSuccess) ) - return false; - - return true; -} - -//--------------------------------------------------------------------------- -// Factory methods that will construct and initialize an IOGatedOutputQueue -// object. - -IOGatedOutputQueue * -IOGatedOutputQueue::withTarget(IONetworkController * target, - IOWorkLoop * workloop, - UInt32 capacity = 0) -{ - IOGatedOutputQueue * queue = new IOGatedOutputQueue; - - if (queue && !queue->init(target, target->getOutputHandler(), workloop, - capacity)) - { - queue->release(); - queue = 0; - } - return queue; -} - -IOGatedOutputQueue * -IOGatedOutputQueue::withTarget(OSObject * target, - IOOutputAction action, - IOWorkLoop * workloop, - UInt32 capacity = 0) -{ - IOGatedOutputQueue * queue = new IOGatedOutputQueue; - - if (queue && !queue->init(target, action, workloop, capacity)) - { - queue->release(); - queue = 0; - } - return queue; -} - -//--------------------------------------------------------------------------- -// Free the IOGatedOutputQueue object. - -void IOGatedOutputQueue::free() -{ - cancelServiceThread(); - - if (_gate) - { - _gate->release(); - _gate = 0; - } - - if (_interruptSrc) - { - IOWorkLoop * wl = _interruptSrc->getWorkLoop(); - if (wl) wl->removeEventSource(_interruptSrc); - _interruptSrc->release(); - _interruptSrc = 0; - } - - super::free(); -} - -//--------------------------------------------------------------------------- -// Called by an IOCommandGate object. - -void IOGatedOutputQueue::gatedOutput(OSObject * /* owner */, - IOGatedOutputQueue * self, - IOMbufQueue * queue, - UInt32 * state) -{ - struct mbuf * pkt; - UInt32 status; - - do { - pkt = IOMbufQueueDequeue(queue); - assert(pkt); - - // Handoff the packet to the controller driver. - - status = ((self->_target)->*(self->_action))( pkt, 0 ); - - if ( status == ( kIOOutputStatusAccepted | kIOOutputCommandNone ) ) - { - // Fast-path the typical code path. - self->_stats->outputCount++; - } - else - { - // Look at the return status and update statistics counters. - - switch (status & kIOOutputStatusMask) - { - default: - case kIOOutputStatusAccepted: - self->_stats->outputCount++; - break; - - case kIOOutputStatusRetry: - IOMbufQueuePrepend(queue, pkt); - self->_stats->retryCount++; - break; - } - - // Handle the requested action. - - switch (status & kIOOutputCommandMask) - { - case kIOOutputCommandStall: - *state = kStateOutputStalled; - self->_stats->stallCount++; - break; - - default: - break; - } - } - } - while ( IOMbufQueueGetSize(queue) && (*state == 0) ); -} - -//--------------------------------------------------------------------------- -// Called by our superclass to output all packets in the packet queue given. - -enum { - kStateOutputDeferred = 0x100 -}; - -void IOGatedOutputQueue::output(IOMbufQueue * queue, UInt32 * state) -{ - if ( _gate->attemptAction((IOCommandGate::Action) - &IOGatedOutputQueue::gatedOutput, - (void *) this, - (void *) queue, - (void *) state) == kIOReturnCannotLock ) - { - *state = kStateOutputDeferred; - } -} - -bool IOGatedOutputQueue::scheduleServiceThread(void * param) -{ - if ( ((UInt32) param) & kStateOutputDeferred ) - { - _interruptSrc->interruptOccurred(0, 0, 0); - return true; - } - else - { - return super::scheduleServiceThread(param); - } -} - -void IOGatedOutputQueue::restartDeferredOutput( - OSObject * owner, - IOInterruptEventSource * sender, - int count) -{ - IOGatedOutputQueue * self = (IOGatedOutputQueue *) owner; - self->serviceThread((void *) kStateOutputDeferred); -} diff --git a/iokit/Families/IONetworking/IOPacketQueue.cpp b/iokit/Families/IONetworking/IOPacketQueue.cpp deleted file mode 100644 index dd5a223bd..000000000 --- a/iokit/Families/IONetworking/IOPacketQueue.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * IOPacketQueue.cpp - Implements a FIFO mbuf packet queue. - * - * HISTORY - * 9-Dec-1998 Joe Liu (jliu) created. - * - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> // IOLog -#include <IOKit/network/IOPacketQueue.h> -#include "IOMbufQueue.h" - -#define super OSObject -OSDefineMetaClassAndStructors( IOPacketQueue, OSObject ) -OSMetaClassDefineReservedUnused( IOPacketQueue, 0); -OSMetaClassDefineReservedUnused( IOPacketQueue, 1); -OSMetaClassDefineReservedUnused( IOPacketQueue, 2); -OSMetaClassDefineReservedUnused( IOPacketQueue, 3); -OSMetaClassDefineReservedUnused( IOPacketQueue, 4); -OSMetaClassDefineReservedUnused( IOPacketQueue, 5); -OSMetaClassDefineReservedUnused( IOPacketQueue, 6); -OSMetaClassDefineReservedUnused( IOPacketQueue, 7); -OSMetaClassDefineReservedUnused( IOPacketQueue, 8); -OSMetaClassDefineReservedUnused( IOPacketQueue, 9); -OSMetaClassDefineReservedUnused( IOPacketQueue, 10); -OSMetaClassDefineReservedUnused( IOPacketQueue, 11); -OSMetaClassDefineReservedUnused( IOPacketQueue, 12); -OSMetaClassDefineReservedUnused( IOPacketQueue, 13); -OSMetaClassDefineReservedUnused( IOPacketQueue, 14); -OSMetaClassDefineReservedUnused( IOPacketQueue, 15); - - -//--------------------------------------------------------------------------- -// Lock macros - -#define LOCK IOSimpleLockLock(_lock) -#define UNLOCK IOSimpleLockUnlock(_lock) - -//--------------------------------------------------------------------------- -// Initialize an IOPacketQueue object. - -bool IOPacketQueue::initWithCapacity(UInt32 capacity) -{ - if (super::init() == false) - { - IOLog("IOPacketQueue: super::init() failed\n"); - return false; - } - - _queue = IONew(IOMbufQueue, 1); - if (_queue == 0) - return false; - - IOMbufQueueInit(_queue, capacity); - - if ((_lock = IOSimpleLockAlloc()) == 0) - return false; - - IOSimpleLockInit(_lock); - - return true; -} - -//--------------------------------------------------------------------------- -// Factory method that will construct and initialize an IOPacketQueue object. - -IOPacketQueue * IOPacketQueue::withCapacity(UInt32 capacity) -{ - IOPacketQueue * queue = new IOPacketQueue; - - if (queue && !queue->initWithCapacity(capacity)) - { - queue->release(); - queue = 0; - } - return queue; -} - -//--------------------------------------------------------------------------- -// Frees the IOPacketQueue instance. - -void IOPacketQueue::free() -{ - if (_lock) - { - IOSimpleLockFree(_lock); - _lock = 0; - } - - if (_queue) - { - flush(); - IODelete(_queue, IOMbufQueue, 1); - _queue = 0; - } - - super::free(); -} - -//--------------------------------------------------------------------------- -// Get the current size of the queue. - -UInt32 IOPacketQueue::getSize() const -{ - return IOMbufQueueGetSize(_queue); -} - -//--------------------------------------------------------------------------- -// Change the capacity of the queue. - -bool IOPacketQueue::setCapacity(UInt32 capacity) -{ - IOMbufQueueSetCapacity(_queue, capacity); - return true; -} - -//--------------------------------------------------------------------------- -// Get the capacity of the queue. - -UInt32 IOPacketQueue::getCapacity() const -{ - return IOMbufQueueGetCapacity(_queue); -} - -//--------------------------------------------------------------------------- -// Peek at the head of the queue without dequeueing the packet. - -const struct mbuf * IOPacketQueue::peek() const -{ - return IOMbufQueuePeek(_queue); -} - -//--------------------------------------------------------------------------- -// Add a packet chain to the head of the queue. - -void IOPacketQueue::prepend(struct mbuf * m) -{ - IOMbufQueuePrepend(_queue, m); -} - -void IOPacketQueue::prepend(IOPacketQueue * queue) -{ - IOMbufQueuePrepend(_queue, queue->_queue); -} - -//--------------------------------------------------------------------------- -// Add a packet chain to the tail of the queue. - -bool IOPacketQueue::enqueue(struct mbuf * m) -{ - return IOMbufQueueEnqueue(_queue, m); -} - -bool IOPacketQueue::enqueue(IOPacketQueue * queue) -{ - return IOMbufQueueEnqueue(_queue, queue->_queue); -} - -UInt32 IOPacketQueue::enqueueWithDrop(struct mbuf * m) -{ - return IOMbufQueueEnqueue(_queue, m) ? 0 : IOMbufFree(m); -} - -//--------------------------------------------------------------------------- -// Remove a single packet from the head of the queue. - -struct mbuf * IOPacketQueue::dequeue() -{ - return IOMbufQueueDequeue(_queue); -} - -//--------------------------------------------------------------------------- -// Remove all packets from the queue and return the chain of packet(s). - -struct mbuf * IOPacketQueue::dequeueAll() -{ - return IOMbufQueueDequeueAll(_queue); -} - -//--------------------------------------------------------------------------- -// Remove all packets from the queue and put them back to the free mbuf -// pool. The size of the queue will be cleared to zero. - -UInt32 IOPacketQueue::flush() -{ - return IOMbufFree(IOMbufQueueDequeueAll(_queue)); -} - -//--------------------------------------------------------------------------- -// Locked forms of prepend/enqueue/dequeue/dequeueAll methods. -// A spinlock will enforce mutually exclusive queue access. - -void IOPacketQueue::lockPrepend(struct mbuf * m) -{ - LOCK; - IOMbufQueuePrepend(_queue, m); - UNLOCK; -} - -bool IOPacketQueue::lockEnqueue(struct mbuf * m) -{ - bool ok; - LOCK; - ok = IOMbufQueueEnqueue(_queue, m); - UNLOCK; - return ok; -} - -UInt32 IOPacketQueue::lockEnqueueWithDrop(struct mbuf * m) -{ - bool ok; - LOCK; - ok = IOMbufQueueEnqueue(_queue, m); - UNLOCK; - return ok ? 0 : IOMbufFree(m); -} - -struct mbuf * IOPacketQueue::lockDequeue() -{ - struct mbuf * m; - LOCK; - m = IOMbufQueueDequeue(_queue); - UNLOCK; - return m; -} - -struct mbuf * IOPacketQueue::lockDequeueAll() -{ - struct mbuf * m; - LOCK; - m = IOMbufQueueDequeueAll(_queue); - UNLOCK; - return m; -} - -UInt32 IOPacketQueue::lockFlush() -{ - struct mbuf * m; - LOCK; - m = IOMbufQueueDequeueAll(_queue); - UNLOCK; - return IOMbufFree(m); -} diff --git a/iokit/Families/IOPCIBus/IOPCIBridge.cpp b/iokit/Families/IOPCIBus/IOPCIBridge.cpp deleted file mode 100644 index 3e990785a..000000000 --- a/iokit/Families/IOPCIBus/IOPCIBridge.cpp +++ /dev/null @@ -1,1187 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - * 23 Nov 98 sdouglas created from objc version. - * - */ - -#include <IOKit/system.h> - -#include <IOKit/pci/IOPCIBridge.h> -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/pci/IOAGPDevice.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IORangeAllocator.h> -#include <IOKit/IOPlatformExpert.h> -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> -#include <IOKit/IOCatalogue.h> - -#include <libkern/c++/OSContainers.h> - -extern "C" { -#include <machine/machine_routines.h> -}; - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOService - -OSDefineMetaClassAndAbstractStructors( IOPCIBridge, IOService ) -OSMetaClassDefineReservedUnused(IOPCIBridge, 0); -OSMetaClassDefineReservedUnused(IOPCIBridge, 1); -OSMetaClassDefineReservedUnused(IOPCIBridge, 2); -OSMetaClassDefineReservedUnused(IOPCIBridge, 3); -OSMetaClassDefineReservedUnused(IOPCIBridge, 4); -OSMetaClassDefineReservedUnused(IOPCIBridge, 5); -OSMetaClassDefineReservedUnused(IOPCIBridge, 6); -OSMetaClassDefineReservedUnused(IOPCIBridge, 7); -OSMetaClassDefineReservedUnused(IOPCIBridge, 8); -OSMetaClassDefineReservedUnused(IOPCIBridge, 9); -OSMetaClassDefineReservedUnused(IOPCIBridge, 10); -OSMetaClassDefineReservedUnused(IOPCIBridge, 11); -OSMetaClassDefineReservedUnused(IOPCIBridge, 12); -OSMetaClassDefineReservedUnused(IOPCIBridge, 13); -OSMetaClassDefineReservedUnused(IOPCIBridge, 14); -OSMetaClassDefineReservedUnused(IOPCIBridge, 15); -OSMetaClassDefineReservedUnused(IOPCIBridge, 16); -OSMetaClassDefineReservedUnused(IOPCIBridge, 17); -OSMetaClassDefineReservedUnused(IOPCIBridge, 18); -OSMetaClassDefineReservedUnused(IOPCIBridge, 19); -OSMetaClassDefineReservedUnused(IOPCIBridge, 20); -OSMetaClassDefineReservedUnused(IOPCIBridge, 21); -OSMetaClassDefineReservedUnused(IOPCIBridge, 22); -OSMetaClassDefineReservedUnused(IOPCIBridge, 23); -OSMetaClassDefineReservedUnused(IOPCIBridge, 24); -OSMetaClassDefineReservedUnused(IOPCIBridge, 25); -OSMetaClassDefineReservedUnused(IOPCIBridge, 26); -OSMetaClassDefineReservedUnused(IOPCIBridge, 27); -OSMetaClassDefineReservedUnused(IOPCIBridge, 28); -OSMetaClassDefineReservedUnused(IOPCIBridge, 29); -OSMetaClassDefineReservedUnused(IOPCIBridge, 30); -OSMetaClassDefineReservedUnused(IOPCIBridge, 31); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// 1 log, 2 disable DT -int gIOPCIDebug = 0; - -#ifdef __I386__ -static void setupIntelPIC(IOPCIDevice * nub); -#endif - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// stub driver has two power states, off and on - -enum { kIOPCIBridgePowerStateCount = 2 }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOPCIBridge::start( IOService * provider ) -{ - static const IOPMPowerState powerStates[ kIOPCIBridgePowerStateCount ] = { - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } - }; - - if( !super::start( provider)) - return( false); - - // empty ranges to start - bridgeMemoryRanges = IORangeAllocator::withRange( 0, 1, 8, - IORangeAllocator::kLocking ); - assert( bridgeMemoryRanges ); - setProperty( "Bridge Memory Ranges", bridgeMemoryRanges ); - - bridgeIORanges = IORangeAllocator::withRange( 0, 1, 8, - IORangeAllocator::kLocking ); - assert( bridgeIORanges ); - setProperty( "Bridge IO Ranges", bridgeIORanges ); - - if( !configure( provider)) - return( false); - - // initialize superclass variables - PMinit(); - // register as controlling driver - registerPowerDriver( this, (IOPMPowerState *) powerStates, - kIOPCIBridgePowerStateCount); - // join the tree - provider->joinPMtree( this); - // clamp power on - temporaryPowerClampOn(); - - probeBus( provider, firstBusNum() ); - - return( true ); -} - -IOReturn IOPCIBridge::setDevicePowerState( IOPCIDevice * device, - unsigned long powerState ) -{ - if( powerState) - return( restoreDeviceState( device)); - else - return( saveDeviceState( device)); -} - -enum { kSavedConfigSize = 64 }; -enum { kSavedConfigs = 16 }; - -IOReturn IOPCIBridge::saveDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ) -{ - int i; - - if( !device->savedConfig) - device->savedConfig = IONew( UInt32, kSavedConfigSize ); - if( !device->savedConfig) - return( kIOReturnNotReady ); - - for( i = 1; i < kSavedConfigs; i++) - device->savedConfig[i] = device->configRead32( i * 4 ); - - return( kIOReturnSuccess ); -} - -IOReturn IOPCIBridge::restoreDeviceState( IOPCIDevice * device, - IOOptionBits options = 0 ) -{ - int i; - - if( !device->savedConfig) - return( kIOReturnNotReady ); - - for( i = 2; i < kSavedConfigs; i++) - device->configWrite32( i * 4, device->savedConfig[ i ]); - - device->configWrite32( kIOPCIConfigCommand, device->savedConfig[1]); - - IODelete( device->savedConfig, UInt32, kSavedConfigSize); - device->savedConfig = 0; - - return( kIOReturnSuccess ); -} - - -bool IOPCIBridge::configure( IOService * provider ) -{ - return( true ); -} - -static SInt32 PCICompare( UInt32 /* cellCount */, UInt32 cleft[], UInt32 cright[] ) -{ - IOPCIPhysicalAddress * left = (IOPCIPhysicalAddress *) cleft; - IOPCIPhysicalAddress * right = (IOPCIPhysicalAddress *) cright; - static const UInt8 spacesEq[] = { 0, 1, 2, 2 }; - - if( spacesEq[ left->physHi.s.space ] != spacesEq[ right->physHi.s.space ]) - return( -1); - - return( left->physLo - right->physLo ); -} - -void IOPCIBridge::nvLocation( IORegistryEntry * entry, - UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum ) -{ - IOPCIDevice * nub; - - nub = OSDynamicCast( IOPCIDevice, entry ); - assert( nub ); - - *busNum = nub->space.s.busNum; - *deviceNum = nub->space.s.deviceNum; - *functionNum = nub->space.s.functionNum; -} - -void IOPCIBridge::spaceFromProperties( OSDictionary * propTable, - IOPCIAddressSpace * space ) -{ - OSData * regProp; - IOPCIAddressSpace * inSpace; - - space->bits = 0; - - if( (regProp = (OSData *) propTable->getObject("reg"))) { - - inSpace = (IOPCIAddressSpace *) regProp->getBytesNoCopy(); - space->s.busNum = inSpace->s.busNum; - space->s.deviceNum = inSpace->s.deviceNum; - space->s.functionNum = inSpace->s.functionNum; - } -} - -IORegistryEntry * IOPCIBridge::findMatching( OSIterator * kids, - IOPCIAddressSpace space ) -{ - IORegistryEntry * found = 0; - IOPCIAddressSpace regSpace; - - if( kids) { - kids->reset(); - while( (0 == found) - && (found = (IORegistryEntry *) kids->getNextObject())) { - - spaceFromProperties( found->getPropertyTable(), ®Space); - if( space.bits != regSpace.bits) - found = 0; - } - } - return( found ); -} - -OSDictionary * IOPCIBridge::constructProperties( IOPCIAddressSpace space ) -{ - OSDictionary * propTable; - UInt32 value; - UInt8 byte; - UInt16 vendor, device; - OSData * prop; - const char * name; - const OSSymbol * nameProp; - char * nameStr; - char * compatBuf; - char * nextCompat; - - struct IOPCIGenericNames { - const char * name; - UInt32 mask; - UInt32 classCode; - }; - static const IOPCIGenericNames genericNames[] = { - { "display", 0xffffff, 0x000100 }, - { "scsi", 0xffff00, 0x010000 }, - { "ethernet", 0xffff00, 0x020000 }, - { "display", 0xff0000, 0x030000 }, - { "pci-bridge", 0xffff00, 0x060400 }, - { 0, 0, 0 } - }; - const IOPCIGenericNames * nextName; - - compatBuf = (char *) IOMalloc( 256 ); - - propTable = OSDictionary::withCapacity( 8 ); - - if( compatBuf && propTable) { - - prop = OSData::withBytes( &space, sizeof( space) ); - if( prop) { - propTable->setObject("reg", prop ); - prop->release(); - } - - value = configRead32( space, kIOPCIConfigVendorID ); - vendor = value; - device = value >> 16; - - prop = OSData::withBytes( &vendor, 2 ); - if( prop) { - propTable->setObject("vendor-id", prop ); - prop->release(); - } - - prop = OSData::withBytes( &device, 2 ); - if( prop) { - propTable->setObject("device-id", prop ); - prop->release(); - } - - value = configRead32( space, kIOPCIConfigRevisionID ); - byte = value & 0xff; - prop = OSData::withBytes( &byte, 1 ); - if( prop) { - propTable->setObject("revision-id", prop ); - prop->release(); - } - - // make generic name - value >>= 8; - name = 0; - for( nextName = genericNames; - (0 == name) && nextName->name; - nextName++ ) { - if( (value & nextName->mask) == nextName->classCode) - name = nextName->name; - } - - // start compatible list - nextCompat = compatBuf; - sprintf( nextCompat, "pci%x,%x", vendor, device); - nameStr = nextCompat; - - value = configRead32( space, kIOPCIConfigSubSystemVendorID ); - if( value) { - vendor = value; - device = value >> 16; - - prop = OSData::withBytes( &vendor, 2 ); - if( prop) { - propTable->setObject("subsystem-vendor-id", prop ); - prop->release(); - } - prop = OSData::withBytes( &device, 2 ); - if( prop) { - propTable->setObject("subsystem-id", prop ); - prop->release(); - } - - nextCompat += strlen( nextCompat ) + 1; - sprintf( nextCompat, "pci%x,%x", vendor, device); - nameStr = nextCompat; - } - - nextCompat += strlen( nextCompat ) + 1; - prop = OSData::withBytes( compatBuf, nextCompat - compatBuf); - if( prop) { - propTable->setObject( "compatible", prop ); - prop->release(); - } - - if( 0 == name) - name = nameStr; - - nameProp = OSSymbol::withCString( name ); - if( nameProp) { - propTable->setObject( gIONameKey, (OSSymbol *) nameProp); - nameProp->release(); - } - } - - if( compatBuf) - IOFree( compatBuf, 256 ); - - return( propTable ); -} - -IOPCIDevice * IOPCIBridge::createNub( OSDictionary * from ) -{ - return( new IOPCIDevice ); -} - -bool IOPCIBridge::initializeNub( IOPCIDevice * nub, - OSDictionary * from ) -{ - spaceFromProperties( from, &nub->space); - nub->parent = this; - if( ioDeviceMemory()) - nub->ioMap = ioDeviceMemory()->map(); - - return( true ); -} - -bool IOPCIBridge::publishNub( IOPCIDevice * nub, UInt32 /* index */ ) -{ - char location[ 24 ]; - bool ok; - OSData * data; - OSData * driverData; - UInt32 *regData, expRomReg; - IOMemoryMap * memoryMap; - IOVirtualAddress virtAddr; - - if( nub) { - if( nub->space.s.functionNum) - sprintf( location, "%X,%X", nub->space.s.deviceNum, - nub->space.s.functionNum ); - else - sprintf( location, "%X", nub->space.s.deviceNum ); - nub->setLocation( location ); - IODTFindSlotName( nub, nub->space.s.deviceNum ); - - // Look for a "driver-reg,AAPL,MacOSX,PowerPC" property. - if( (data = (OSData *)nub->getProperty( "driver-reg,AAPL,MacOSX,PowerPC"))) { - if( data->getLength() == (2 * sizeof(UInt32))) { - regData = (UInt32 *)data->getBytesNoCopy(); - - getNubResources(nub); - memoryMap = nub->mapDeviceMemoryWithRegister(kIOPCIConfigExpansionROMBase); - if( memoryMap != 0) { - virtAddr = memoryMap->getVirtualAddress(); - virtAddr += regData[0]; - - nub->setMemoryEnable(true); - - expRomReg = nub->configRead32(kIOPCIConfigExpansionROMBase); - nub->configWrite32(kIOPCIConfigExpansionROMBase, expRomReg | 1); - - driverData = OSData::withBytesNoCopy((void *)virtAddr, regData[1]); - if ( driverData != 0) { - gIOCatalogue->addExtensionsFromArchive(driverData); - - driverData->release(); - } - - nub->configWrite32(kIOPCIConfigExpansionROMBase, expRomReg); - - nub->setMemoryEnable(false); - - memoryMap->release(); - } - } - } - - ok = nub->attach( this ); - if( ok) - nub->registerService(); - } else - ok = false; - - return( ok ); -} - -void IOPCIBridge::publishNubs( OSIterator * kids, UInt32 index ) -{ - IORegistryEntry * found; - IOPCIDevice * nub; - OSDictionary * propTable; - - if( kids) { - kids->reset(); - while( (found = (IORegistryEntry *) kids->getNextObject())) { - - propTable = found->getPropertyTable(); - nub = createNub( propTable ); - if( !nub) - continue; - if( !initializeNub( nub, propTable)) - continue; - if( !nub->init( found, gIODTPlane)) - continue; - - publishNub( nub, index++ ); - -if( 1 & gIOPCIDebug) - IOLog("%08lx = 0:%08lx 4:%08lx ", nub->space.bits, - nub->configRead32(kIOPCIConfigVendorID), - nub->configRead32(kIOPCIConfigCommand) ); - - } - } -} - -UInt8 IOPCIBridge::firstBusNum( void ) -{ - return( 0 ); -} - -UInt8 IOPCIBridge::lastBusNum( void ) -{ - return( 255 ); -} - -void IOPCIBridge::probeBus( IOService * provider, UInt8 busNum ) -{ - IORegistryEntry * regEntry; - OSDictionary * propTable; - IOPCIDevice * nub = 0; - IOPCIAddressSpace space; - UInt32 vendor; - UInt8 scanDevice, scanFunction, lastFunction; - OSIterator * kidsIter; - UInt32 index = 0; - - IODTSetResolving( provider, PCICompare, nvLocation ); - - if( 2 & gIOPCIDebug) - kidsIter = 0; - else - kidsIter = provider->getChildIterator( gIODTPlane ); - - space.bits = 0; - space.s.busNum = busNum; - - for( scanDevice = 0; scanDevice <= 31; scanDevice++ ) { - - lastFunction = 0; - for( scanFunction = 0; scanFunction <= lastFunction; scanFunction++ ) { - - space.s.deviceNum = scanDevice; - space.s.functionNum = scanFunction; - - if( (regEntry = findMatching( kidsIter, space ))) { - - - } else { - /* probe - should guard exceptions */ -#ifdef __ppc__ - // DEC bridge really needs safe probe - continue; -#endif - vendor = configRead32( space, kIOPCIConfigVendorID ); - vendor &= 0x0000ffff; - if( (0 == vendor) || (0xffff == vendor)) - continue; - - // look in function 0 for multi function flag - if( (0 == scanFunction) - && (0x00800000 & configRead32( space, - kIOPCIConfigCacheLineSize ))) - lastFunction = 7; - - propTable = constructProperties( space ); - if( propTable - && (nub = createNub( propTable)) - && (initializeNub( nub, propTable)) - && nub->init( propTable )) { -#ifdef __I386__ - setupIntelPIC(nub); -#endif - publishNub( nub, index++); - } - } - } - } - - if( kidsIter) { - publishNubs( kidsIter, index ); - kidsIter->release(); - } -} - -bool IOPCIBridge::addBridgeMemoryRange( IOPhysicalAddress start, - IOPhysicalLength length, bool host ) -{ - IORangeAllocator * platformRanges; - bool ok = true; - - if( host ) { - - platformRanges = getPlatform()->getPhysicalRangeAllocator(); - assert( platformRanges ); - - // out of the platform - ok = platformRanges->allocateRange( start, length ); - if( !ok) - kprintf("%s: didn't get host range (%08lx:%08lx)\n", getName(), - start, length); - } - - // and into the bridge - bridgeMemoryRanges->deallocate( start, length ); - - return( ok ); -} - -bool IOPCIBridge::addBridgeIORange( IOByteCount start, IOByteCount length ) -{ - bool ok = true; - - // into the bridge - bridgeIORanges->deallocate( start, length ); - - return( ok ); -} - -bool IOPCIBridge::constructRange( IOPCIAddressSpace * flags, - IOPhysicalAddress phys, - IOPhysicalLength len, - OSArray * array ) -{ - IODeviceMemory * range; - IODeviceMemory * ioMemory; - IORangeAllocator * bridgeRanges; - bool ok; - - if( !array) - return( false ); - - if( kIOPCIIOSpace == flags->s.space) { - - bridgeRanges = bridgeIORanges; - if( (ioMemory = ioDeviceMemory())) { - - phys &= 0x00ffffff; // seems bogus - range = IODeviceMemory::withSubRange( ioMemory, phys, len ); - if( range == 0) - /* didn't fit */ - range = IODeviceMemory::withRange( - phys + ioMemory->getPhysicalAddress(), len ); - - } else - range = 0; - - } else { - bridgeRanges = bridgeMemoryRanges; - range = IODeviceMemory::withRange( phys, len ); - } - - - if( range) { - -#ifdef i386 - // Do nothing for Intel -- I/O ports are not accessed through - // memory on this platform, but through I/O port instructions -#else - - ok = bridgeRanges->allocateRange( phys, len ); - if( !ok) - IOLog("%s: bad range %d(%08lx:%08lx)\n", getName(), flags->s.space, - phys, len); -#endif - - range->setTag( flags->bits ); - ok = array->setObject( range ); - range->release(); - - } else - ok = false; - - return( ok ); -} - - -IOReturn IOPCIBridge::getDTNubAddressing( IOPCIDevice * regEntry ) -{ - OSArray * array; - IORegistryEntry * parentEntry; - OSData * addressProperty; - IOPhysicalAddress phys; - IOPhysicalLength len; - UInt32 cells = 5; - int i, num; - UInt32 * reg; - - addressProperty = (OSData *) regEntry->getProperty( "assigned-addresses" ); - if( 0 == addressProperty) - return( kIOReturnSuccess ); - - parentEntry = regEntry->getParentEntry( gIODTPlane ); - if( 0 == parentEntry) - return( kIOReturnBadArgument ); - - array = OSArray::withCapacity( 1 ); - if( 0 == array) - return( kIOReturnNoMemory ); - - reg = (UInt32 *) addressProperty->getBytesNoCopy(); - num = addressProperty->getLength() / (4 * cells); - - for( i = 0; i < num; i++) { - - if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) - - constructRange( (IOPCIAddressSpace *) reg, phys, len, array ); - - reg += cells; - } - - if( array->getCount()) - regEntry->setProperty( gIODeviceMemoryKey, array); - - array->release(); - - return( kIOReturnSuccess); -} - -IOReturn IOPCIBridge::getNubAddressing( IOPCIDevice * nub ) -{ - OSArray * array; - IOPhysicalAddress phys; - IOPhysicalLength len; - UInt32 save, value; - IOPCIAddressSpace reg; - UInt8 regNum; - bool memEna, ioEna; - boolean_t s; - - value = nub->configRead32( kIOPCIConfigVendorID ); - if( 0x0003106b == value ) // control doesn't play well - return( kIOReturnSuccess ); - - // only header type 0 - value = nub->configRead32( kIOPCIConfigCacheLineSize ); - if( value & 0x007f0000) - return( kIOReturnSuccess ); - - array = OSArray::withCapacity( 1 ); - if( 0 == array) - return( kIOReturnNoMemory ); - - for( regNum = 0x10; regNum < 0x28; regNum += 4) { - - // begin scary - s = ml_set_interrupts_enabled(FALSE); - memEna = nub->setMemoryEnable( false ); - ioEna = nub->setIOEnable( false ); - - save = nub->configRead32( regNum ); - - nub->configWrite32( regNum, 0xffffffff ); - value = nub->configRead32( regNum ); - - nub->configWrite32( regNum, save ); - nub->setMemoryEnable( memEna ); - nub->setIOEnable( ioEna ); - ml_set_interrupts_enabled( s ); - // end scary - - if( 0 == value) - continue; - - reg = nub->space; - reg.s.registerNum = regNum; - - if( value & 1) { - reg.s.space = kIOPCIIOSpace; - - } else { - reg.s.prefetch = (0 != (value & 8)); - - switch( value & 6) { - case 2: /* below 1Mb */ - reg.s.t = 1; - /* fall thru */ - case 0: /* 32-bit mem */ - case 6: /* reserved */ - reg.s.space = kIOPCI32BitMemorySpace; - break; - - case 4: /* 64-bit mem */ - reg.s.space = kIOPCI64BitMemorySpace; - regNum += 4; - break; - } - } - - value &= 0xfffffff0; - phys = IOPhysical32( 0, save & value ); - len = IOPhysical32( 0, -value ); - -if( 1 & gIOPCIDebug) - IOLog("Space %08lx : %08lx, %08lx\n", reg.bits, phys, len); - - constructRange( ®, phys, len, array ); - } - - if( array->getCount()) - nub->setProperty( gIODeviceMemoryKey, array); - - array->release(); - - return( kIOReturnSuccess); -} - -bool IOPCIBridge::isDTNub( IOPCIDevice * nub ) -{ - return( 0 != nub->getParentEntry( gIODTPlane )); -} - -IOReturn IOPCIBridge::getNubResources( IOService * service ) -{ - IOPCIDevice * nub = (IOPCIDevice *) service; - IOReturn err; - - if( service->getDeviceMemory()) - return( kIOReturnSuccess ); - - if( isDTNub( nub)) - err = getDTNubAddressing( nub ); - else - err = getNubAddressing( nub ); - - return( err); -} - -bool IOPCIBridge::matchKeys( IOPCIDevice * nub, const char * keys, - UInt32 defaultMask, UInt8 regNum ) -{ - const char * next; - UInt32 mask, value, reg; - bool found = false; - - do { - value = strtoul( keys, (char **) &next, 16); - if( next == keys) - break; - - while( (*next) == ' ') - next++; - - if( (*next) == '&') - mask = strtoul( next + 1, (char **) &next, 16); - else - mask = defaultMask; - - reg = nub->configRead32( regNum ); - found = ((value & mask) == (reg & mask)); - keys = next; - - } while( !found); - - return( found ); -} - - -bool IOPCIBridge::pciMatchNub( IOPCIDevice * nub, - OSDictionary * table, - SInt32 * score ) -{ - OSString * prop; - const char * keys; - bool match = true; - UInt8 regNum; - int i; - - struct IOPCIMatchingKeys { - const char * propName; - UInt8 regs[ 4 ]; - UInt32 defaultMask; - }; - IOPCIMatchingKeys * look; - static IOPCIMatchingKeys matching[] = { - { kIOPCIMatchKey, - { 0x00 + 1, 0x2c }, 0xffffffff }, - { kIOPCIPrimaryMatchKey, - { 0x00 }, 0xffffffff }, - { kIOPCISecondaryMatchKey, - { 0x2c }, 0xffffffff }, - { kIOPCIClassMatchKey, - { 0x08 }, 0xffffff00 }}; - - for( look = matching; - (match && (look < (&matching[4]))); - look++ ) { - - prop = (OSString *) table->getObject( look->propName ); - if( prop) { - keys = prop->getCStringNoCopy(); - match = false; - for( i = 0; - ((false == match) && (i < 4)); - i++ ) { - - regNum = look->regs[ i ]; - match = matchKeys( nub, keys, - look->defaultMask, regNum & 0xfc ); - if( 0 == (1 & regNum)) - break; - } - } - } - - return( match ); -} - -bool IOPCIBridge::matchNubWithPropertyTable( IOService * nub, - OSDictionary * table, - SInt32 * score ) -{ - bool matches; - - matches = pciMatchNub( (IOPCIDevice *) nub, table, score); - - return( matches ); -} - -bool IOPCIBridge::compareNubName( const IOService * nub, - OSString * name, OSString ** matched ) const -{ - return( IODTCompareNubName( nub, name, matched )); -} - -UInt32 IOPCIBridge::findPCICapability( IOPCIAddressSpace space, - UInt8 capabilityID, UInt8 * found ) -{ - UInt32 data = 0; - UInt8 offset = 0; - - if( found) - *found = 0; - - if( 0 == ((kIOPCIStatusCapabilities << 16) - & (configRead32( space, kIOPCIConfigCommand)))) - return( 0 ); - - offset = configRead32( space, kIOPCIConfigCapabilitiesPtr ); - while( offset) { - data = configRead32( space, offset ); - if( capabilityID == (data & 0xff)) { - if( found) - *found = offset; - break; - } - offset = (data >> 8) & 0xfc; - } - - return( data ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOPCIBridge::createAGPSpace( IOAGPDevice * master, - IOOptionBits options, - IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - return( kIOReturnUnsupported ); -} - -IOReturn IOPCIBridge::destroyAGPSpace( IOAGPDevice * master ) -{ - return( kIOReturnUnsupported ); -} - -IORangeAllocator * IOPCIBridge::getAGPRangeAllocator( IOAGPDevice * master ) -{ - return( 0 ); -} - -IOOptionBits IOPCIBridge::getAGPStatus( IOAGPDevice * master, - IOOptionBits options = 0 ) -{ - return( 0 ); -} - -IOReturn IOPCIBridge::commitAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options ) -{ - return( kIOReturnUnsupported ); -} - -IOReturn IOPCIBridge::releaseAGPMemory( IOAGPDevice * master, - IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options ) -{ - return( kIOReturnUnsupported ); -} - -IOReturn IOPCIBridge::resetAGPDevice( IOAGPDevice * master, - IOOptionBits options = 0 ) -{ - return( kIOReturnUnsupported ); -} - -IOReturn IOPCIBridge::getAGPSpace( IOAGPDevice * master, - IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - return( kIOReturnUnsupported ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOPCIBridge - -OSDefineMetaClassAndStructors(IOPCI2PCIBridge, IOPCIBridge) -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 0); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 1); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 2); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 3); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 4); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 5); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 6); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 7); -OSMetaClassDefineReservedUnused(IOPCI2PCIBridge, 8); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOService * IOPCI2PCIBridge::probe( IOService * provider, - SInt32 * score ) -{ - - if( 0 == (bridgeDevice = OSDynamicCast( IOPCIDevice, provider))) - return( 0 ); - - *score -= 100; - - return( this ); -} - -enum { - kPCI2PCIBusNumbers = 0x18, - kPCI2PCIIORange = 0x1c, - kPCI2PCIMemoryRange = 0x20, - kPCI2PCIPrefetchMemoryRange = 0x24, - kPCI2PCIUpperIORange = 0x30 -}; - -bool IOPCI2PCIBridge::configure( IOService * provider ) -{ - UInt32 end; - UInt32 start; - bool ok; - - end = bridgeDevice->configRead32( kPCI2PCIMemoryRange ); - if( end ) { - start = (end & 0xfff0) << 16; - end |= 0x000fffff; - ok = addBridgeMemoryRange( start, end - start + 1, false ); - } - - end = bridgeDevice->configRead32( kPCI2PCIPrefetchMemoryRange ); - if( end) { - start = (end & 0xfff0) << 16; - end |= 0x000fffff; - ok = addBridgeMemoryRange( start, end - start + 1, false ); - } - - end = bridgeDevice->configRead32( kPCI2PCIIORange ); - if( end) { - start = (end & 0xf0) << 8; - end = (end & 0xffff) | 0xfff; - ok = addBridgeIORange( start, end - start + 1 ); - } - - saveBridgeState(); - - return( super::configure( provider )); -} - -void IOPCI2PCIBridge::saveBridgeState( void ) -{ - long cnt; - - for (cnt = 0; cnt < kIOPCIBridgeRegs; cnt++) { - bridgeState[cnt] = bridgeDevice->configRead32(cnt * 4); - } -} - -void IOPCI2PCIBridge::restoreBridgeState( void ) -{ - long cnt; - - for (cnt = 0; cnt < kIOPCIBridgeRegs; cnt++) { - bridgeDevice->configWrite32(cnt * 4, bridgeState[cnt]); - } -} - -UInt8 IOPCI2PCIBridge::firstBusNum( void ) -{ - UInt32 value; - - value = bridgeDevice->configRead32( kPCI2PCIBusNumbers ); - - return( (value >> 8) & 0xff ); -} - -UInt8 IOPCI2PCIBridge::lastBusNum( void ) -{ - UInt32 value; - - value = bridgeDevice->configRead32( kPCI2PCIBusNumbers ); - - return( (value >> 16) & 0xff ); -} - -IOPCIAddressSpace IOPCI2PCIBridge::getBridgeSpace( void ) -{ - return( bridgeDevice->space ); -} - -UInt32 IOPCI2PCIBridge::configRead32( IOPCIAddressSpace space, - UInt8 offset ) -{ - return( bridgeDevice->configRead32( space, offset )); -} - -void IOPCI2PCIBridge::configWrite32( IOPCIAddressSpace space, - UInt8 offset, UInt32 data ) -{ - bridgeDevice->configWrite32( space, offset, data ); -} - -UInt16 IOPCI2PCIBridge::configRead16( IOPCIAddressSpace space, - UInt8 offset ) -{ - return( bridgeDevice->configRead16( space, offset )); -} - -void IOPCI2PCIBridge::configWrite16( IOPCIAddressSpace space, - UInt8 offset, UInt16 data ) -{ - bridgeDevice->configWrite16( space, offset, data ); -} - -UInt8 IOPCI2PCIBridge::configRead8( IOPCIAddressSpace space, - UInt8 offset ) -{ - return( bridgeDevice->configRead8( space, offset )); -} - -void IOPCI2PCIBridge::configWrite8( IOPCIAddressSpace space, - UInt8 offset, UInt8 data ) -{ - bridgeDevice->configWrite8( space, offset, data ); -} - -IODeviceMemory * IOPCI2PCIBridge::ioDeviceMemory( void ) -{ - return( bridgeDevice->ioDeviceMemory()); -} - -bool IOPCI2PCIBridge::publishNub( IOPCIDevice * nub, UInt32 index ) -{ - if( nub) - nub->setProperty( "IOChildIndex" , index, 32 ); - - return( super::publishNub( nub, index ) ); -} - -#ifdef __I386__ - -static void setupIntelPIC(IOPCIDevice *nub) -{ - OSDictionary *propTable; - OSArray *controller; - OSArray *specifier; - OSData *tmpData; - long irq; - extern OSSymbol *gIntelPICName; - - propTable = nub->getPropertyTable(); - if (!propTable) return; - - do { - // Create the interrupt specifer array. - specifier = OSArray::withCapacity(1); - if ( !specifier ) - break; - irq = nub->configRead32(kIOPCIConfigInterruptLine) & 0xf; - tmpData = OSData::withBytes(&irq, sizeof(irq)); - if ( tmpData ) { - specifier->setObject(tmpData); - tmpData->release(); - } - - controller = OSArray::withCapacity(1); - if ( controller ) { - controller->setObject(gIntelPICName); - - // Put the two arrays into the property table. - propTable->setObject(gIOInterruptControllersKey, controller); - controller->release(); - } - propTable->setObject(gIOInterruptSpecifiersKey, specifier); - specifier->release(); - } while( false ); -} - -#endif diff --git a/iokit/Families/IOPCIBus/IOPCIDevice.cpp b/iokit/Families/IOPCIBus/IOPCIDevice.cpp deleted file mode 100644 index 0212aa67e..000000000 --- a/iokit/Families/IOPCIBus/IOPCIDevice.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - */ - -#include <IOKit/system.h> - -#include <IOKit/pci/IOPCIBridge.h> -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/pci/IOAGPDevice.h> -#include <IOKit/IOPlatformExpert.h> - -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> - -#include <libkern/c++/OSContainers.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#define super IOService - -OSDefineMetaClassAndStructors(IOPCIDevice, IOService) -OSMetaClassDefineReservedUnused(IOPCIDevice, 0); -OSMetaClassDefineReservedUnused(IOPCIDevice, 1); -OSMetaClassDefineReservedUnused(IOPCIDevice, 2); -OSMetaClassDefineReservedUnused(IOPCIDevice, 3); -OSMetaClassDefineReservedUnused(IOPCIDevice, 4); -OSMetaClassDefineReservedUnused(IOPCIDevice, 5); -OSMetaClassDefineReservedUnused(IOPCIDevice, 6); -OSMetaClassDefineReservedUnused(IOPCIDevice, 7); -OSMetaClassDefineReservedUnused(IOPCIDevice, 8); -OSMetaClassDefineReservedUnused(IOPCIDevice, 9); -OSMetaClassDefineReservedUnused(IOPCIDevice, 10); -OSMetaClassDefineReservedUnused(IOPCIDevice, 11); -OSMetaClassDefineReservedUnused(IOPCIDevice, 12); -OSMetaClassDefineReservedUnused(IOPCIDevice, 13); -OSMetaClassDefineReservedUnused(IOPCIDevice, 14); -OSMetaClassDefineReservedUnused(IOPCIDevice, 15); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -// stub driver has two power states, off and on - -enum { kIOPCIDevicePowerStateCount = 2 }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// attach -// -// We clamp power on. The effect is -// to prevent system sleep. If a driver is loaded which can -// power manage the device, it will become our child and we -// will remove the clamp. This prevents the system -// from sleeping when there are non-power-managed -// PCI cards installed. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOPCIDevice::attach( IOService * provider ) -{ - static const IOPMPowerState powerStates[ kIOPCIDevicePowerStateCount ] = { - { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, IOPMPowerOn, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } - }; - - // initialize superclass variables - PMinit(); - // register as controlling driver - registerPowerDriver( this, (IOPMPowerState *) powerStates, - kIOPCIDevicePowerStateCount ); - // join the tree - provider->joinPMtree( this); - - // clamp power on if this is a slot device - slotNameProperty = provider->getProperty ("AAPL,slot-name"); - if (slotNameProperty != NULL) - changePowerStateToPriv (1); - - return super::attach(provider); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// maxCapabilityForDomainState -// -// If the power domain is supplying power, the device -// can be on. If there is no power it can only be off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -unsigned long IOPCIDevice::maxCapabilityForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn ) - return( kIOPCIDevicePowerStateCount - 1); - else - return( 0); -} - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// initialPowerStateForDomainState -// -// This is our first information about the power domain state. -// If power is on in the new state, the device is on. -// If domain power is off, the device is also off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -unsigned long IOPCIDevice::initialPowerStateForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn) - return( kIOPCIDevicePowerStateCount - 1); - else - return( 0); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// powerStateForDomainState -// -// The power domain may be changing state. -// If power is on in the new state, the device will be on. -// If domain power is off, the device will be off. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -unsigned long IOPCIDevice::powerStateForDomainState( - IOPMPowerFlags domainState ) -{ - if( domainState & IOPMPowerOn) - return( pm_vars->myCurrentState); - else - return( 0); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// setPowerState -// -// Saves and restores PCI config space if power is going down or up. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOPCIDevice::setPowerState( unsigned long powerState, - IOService * whatDevice ) -{ - parent->setDevicePowerState( this, powerState ); - - return( IOPMAckImplied); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// addPowerChild -// -// -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOPCIDevice::addPowerChild ( IOService * theChild ) -{ - IOReturn result = IOPMNoErr; - - result = super::addPowerChild (theChild); - - if ((slotNameProperty != NULL) && (result == IOPMNoErr)) - changePowerStateToPriv(0); - - return result; -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// joinPMtree -// -// A policy-maker for our PCI device calls here when initializing, -// to be attached into the power management hierarchy. -// We attach this driver as our child so we can save and restore its config -// space across power cycles. -// -// This overrides the default function of the IOService joinPMtree. -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -void IOPCIDevice::joinPMtree( IOService * driver ) -{ - // hook it into the tree - pm_vars->thePlatform->PMRegisterDevice( this, driver); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -bool IOPCIDevice::matchPropertyTable( OSDictionary * table, SInt32 * score ) -{ - return( parent->matchNubWithPropertyTable( this, table, score )); -} - -bool IOPCIDevice::compareName( OSString * name, OSString ** matched = 0 ) const -{ - return( parent->compareNubName( this, name, matched )); -} - -IOReturn IOPCIDevice::getResources( void ) -{ - return( parent->getNubResources( this )); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -UInt32 IOPCIDevice::configRead32( IOPCIAddressSpace _space, - UInt8 offset ) -{ - return( parent->configRead32( _space, offset )); -} - -void IOPCIDevice::configWrite32( IOPCIAddressSpace _space, - UInt8 offset, UInt32 data ) -{ - parent->configWrite32( _space, offset, data ); -} - -UInt16 IOPCIDevice::configRead16( IOPCIAddressSpace _space, - UInt8 offset ) -{ - return( parent->configRead16( _space, offset )); -} - -void IOPCIDevice::configWrite16( IOPCIAddressSpace _space, - UInt8 offset, UInt16 data ) -{ - parent->configWrite16( _space, offset, data ); -} - -UInt8 IOPCIDevice::configRead8( IOPCIAddressSpace _space, - UInt8 offset ) -{ - return( parent->configRead8( _space, offset )); -} - -void IOPCIDevice::configWrite8( IOPCIAddressSpace _space, - UInt8 offset, UInt8 data ) -{ - parent->configWrite8( _space, offset, data ); -} - -UInt32 IOPCIDevice::configRead32( UInt8 offset ) -{ - return( parent->configRead32( space, offset )); -} - -void IOPCIDevice::configWrite32( UInt8 offset, UInt32 data ) -{ - parent->configWrite32( space, offset, data ); -} - -UInt16 IOPCIDevice::configRead16( UInt8 offset ) -{ - return( parent->configRead16( space, offset )); -} - -void IOPCIDevice::configWrite16( UInt8 offset, UInt16 data ) -{ - parent->configWrite16( space, offset, data ); -} - -UInt8 IOPCIDevice::configRead8( UInt8 offset ) -{ - return( parent->configRead8( space, offset )); -} - -void IOPCIDevice::configWrite8( UInt8 offset, UInt8 data ) -{ - parent->configWrite8( space, offset, data ); -} - -IOReturn IOPCIDevice::saveDeviceState( IOOptionBits options = 0 ) -{ - return( parent->saveDeviceState( this, options ) ); -} - -IOReturn IOPCIDevice::restoreDeviceState( IOOptionBits options = 0 ) -{ - return( parent->restoreDeviceState( this, options ) ); -} - -UInt32 IOPCIDevice::findPCICapability( UInt8 capabilityID, UInt8 * offset = 0 ) -{ - return( parent->findPCICapability( space, capabilityID, offset )); -} - -UInt32 IOPCIDevice::setConfigBits( UInt8 reg, UInt32 mask, UInt32 value ) -{ - UInt32 was; - UInt32 bits; - - bits = configRead32( reg ); - was = (bits & mask); - bits &= ~mask; - bits |= (value & mask); - configWrite32( reg, bits ); - - return( was ); -} - -bool IOPCIDevice::setBusMasterEnable( bool enable ) -{ - return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandBusMaster, - enable ? kIOPCICommandBusMaster : 0)); -} - -bool IOPCIDevice::setMemoryEnable( bool enable ) -{ - return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandMemorySpace, - enable ? kIOPCICommandMemorySpace : 0)); -} - -bool IOPCIDevice::setIOEnable( bool enable, bool /* exclusive = false */ ) -{ - // exclusive is TODO. - return( 0 != setConfigBits( kIOPCIConfigCommand, kIOPCICommandIOSpace, - enable ? kIOPCICommandIOSpace : 0)); -} - -UInt8 IOPCIDevice::getBusNumber( void ) -{ - return( space.s.busNum ); -} - -UInt8 IOPCIDevice::getDeviceNumber( void ) -{ - return( space.s.deviceNum ); -} - -UInt8 IOPCIDevice::getFunctionNumber( void ) -{ - return( space.s.functionNum ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IODeviceMemory * IOPCIDevice::getDeviceMemoryWithRegister( UInt8 reg ) -{ - OSArray * array; - IODeviceMemory * range; - unsigned int i = 0; - - array = (OSArray *) getProperty( gIODeviceMemoryKey); - if( 0 == array) - return( 0); - - while( (range = (IODeviceMemory *) array->getObject( i++ ))) { - if( reg == (range->getTag() & 0xff)) - break; - } - - return( range); -} - -IOMemoryMap * IOPCIDevice:: mapDeviceMemoryWithRegister( UInt8 reg, - IOOptionBits options = 0 ) -{ - IODeviceMemory * range; - IOMemoryMap * map; - - range = getDeviceMemoryWithRegister( reg ); - if( range) - map = range->map( options ); - else - map = 0; - - return( map ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IODeviceMemory * IOPCIDevice::ioDeviceMemory( void ) -{ - return( parent->ioDeviceMemory() ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOService * IOPCIDevice::matchLocation( IOService * /* client */ ) -{ - return( this ); -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#undef super -#define super IOPCIDevice - -OSDefineMetaClassAndStructors(IOAGPDevice, IOPCIDevice) -OSMetaClassDefineReservedUnused(IOAGPDevice, 0); -OSMetaClassDefineReservedUnused(IOAGPDevice, 1); -OSMetaClassDefineReservedUnused(IOAGPDevice, 2); -OSMetaClassDefineReservedUnused(IOAGPDevice, 3); -OSMetaClassDefineReservedUnused(IOAGPDevice, 4); -OSMetaClassDefineReservedUnused(IOAGPDevice, 5); -OSMetaClassDefineReservedUnused(IOAGPDevice, 6); -OSMetaClassDefineReservedUnused(IOAGPDevice, 7); -OSMetaClassDefineReservedUnused(IOAGPDevice, 8); -OSMetaClassDefineReservedUnused(IOAGPDevice, 9); -OSMetaClassDefineReservedUnused(IOAGPDevice, 10); -OSMetaClassDefineReservedUnused(IOAGPDevice, 11); -OSMetaClassDefineReservedUnused(IOAGPDevice, 12); -OSMetaClassDefineReservedUnused(IOAGPDevice, 13); -OSMetaClassDefineReservedUnused(IOAGPDevice, 14); -OSMetaClassDefineReservedUnused(IOAGPDevice, 15); -OSMetaClassDefineReservedUnused(IOAGPDevice, 16); - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -IOReturn IOAGPDevice::createAGPSpace( IOOptionBits options, - IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - return( parent->createAGPSpace( this, options, address, length )); -} - -IOReturn IOAGPDevice::destroyAGPSpace( void ) -{ - return( parent->destroyAGPSpace( this )); -} - -IORangeAllocator * IOAGPDevice::getAGPRangeAllocator( void ) -{ - return( parent->getAGPRangeAllocator( this )); -} - -IOOptionBits IOAGPDevice::getAGPStatus( IOOptionBits options = 0 ) -{ - return( parent->getAGPStatus( this, options )); -} - -IOReturn IOAGPDevice::resetAGP( IOOptionBits options = 0 ) -{ - return( parent->resetAGPDevice( this, options )); -} - -IOReturn IOAGPDevice::getAGPSpace( IOPhysicalAddress * address, - IOPhysicalLength * length ) -{ - return( parent->getAGPSpace( this, address, length )); -} - -IOReturn IOAGPDevice::commitAGPMemory( IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options = 0 ) -{ - return( parent->commitAGPMemory( this, memory, agpOffset, options )); -} - -IOReturn IOAGPDevice::releaseAGPMemory( IOMemoryDescriptor * memory, - IOByteCount agpOffset, - IOOptionBits options = 0 ) -{ - return( parent->releaseAGPMemory( this, memory, agpOffset, options )); -} - - diff --git a/iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp b/iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp deleted file mode 100644 index 172b1a2e1..000000000 --- a/iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - */ - -#include <IOKit/system.h> - -#include <IOKit/pci/IOPCIBridge.h> -#include <IOKit/pci/IOPCIDevice.h> -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> - -#include <libkern/c++/OSContainers.h> - -#include <architecture/i386/pio.h> - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -UInt32 IOPCIDevice::ioRead32( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt32 value; - - if( 0 == map) - map = ioMap; - - value = inl( map->getPhysicalAddress() + offset ); - - return( value ); -} - -UInt16 IOPCIDevice::ioRead16( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt16 value; - - if( 0 == map) - map = ioMap; - - value = inw( map->getPhysicalAddress() + offset ); - - return( value ); -} - -UInt8 IOPCIDevice::ioRead8( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt32 value; - - if( 0 == map) - map = ioMap; - - value = inb( map->getPhysicalAddress() + offset ); - - return( value ); -} - -void IOPCIDevice::ioWrite32( UInt16 offset, UInt32 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) - map = ioMap; - - outl( map->getPhysicalAddress() + offset, value ); -} - -void IOPCIDevice::ioWrite16( UInt16 offset, UInt16 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) - map = ioMap; - - outw( map->getPhysicalAddress() + offset, value ); -} - -void IOPCIDevice::ioWrite8( UInt16 offset, UInt8 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) - map = ioMap; - - outb( map->getPhysicalAddress() + offset, value ); -} - diff --git a/iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp b/iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp deleted file mode 100644 index 8730695e6..000000000 --- a/iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 23 Nov 98 sdouglas created from objc version. - */ - -#include <IOKit/system.h> - -#include <IOKit/pci/IOPCIBridge.h> -#include <IOKit/pci/IOPCIDevice.h> - -#include <IOKit/IOLib.h> -#include <IOKit/assert.h> - -#include <libkern/OSByteOrder.h> -#include <libkern/c++/OSContainers.h> - - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -UInt32 IOPCIDevice::ioRead32( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt32 value; - - if( 0 == map) { - map = ioMap; - if( 0 == map) - return( 0 ); - } - - value = OSReadSwapInt32( (volatile void *)map->getVirtualAddress(), offset); - eieio(); - - return( value ); -} - -UInt16 IOPCIDevice::ioRead16( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt16 value; - - if( 0 == map) { - map = ioMap; - if( 0 == map) - return( 0 ); - } - - value = OSReadSwapInt16( (volatile void *)map->getVirtualAddress(), offset); - eieio(); - - return( value ); -} - -UInt8 IOPCIDevice::ioRead8( UInt16 offset, IOMemoryMap * map = 0 ) -{ - UInt32 value; - - if( 0 == map) { - map = ioMap; - if( 0 == map) - return( 0 ); - } - - value = ((volatile UInt8 *) map->getVirtualAddress())[ offset ]; - eieio(); - - return( value ); -} - -void IOPCIDevice::ioWrite32( UInt16 offset, UInt32 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) { - map = ioMap; - if( 0 == map) - return; - } - - OSWriteSwapInt32( (volatile void *)map->getVirtualAddress(), offset, value); - eieio(); -} - -void IOPCIDevice::ioWrite16( UInt16 offset, UInt16 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) { - map = ioMap; - if( 0 == map) - return; - } - - OSWriteSwapInt16( (volatile void *)map->getVirtualAddress(), offset, value); - eieio(); -} - -void IOPCIDevice::ioWrite8( UInt16 offset, UInt8 value, - IOMemoryMap * map = 0 ) -{ - if( 0 == map) { - map = ioMap; - if( 0 == map) - return; - } - - ((volatile UInt8 *) map->getVirtualAddress())[ offset ] = value; - eieio(); - -} - diff --git a/iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp b/iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp deleted file mode 100644 index 52691d032..000000000 --- a/iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOLib.h> -#include <IOKit/IOReturn.h> -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/scsi/IOSCSICDDrive.h> -#include <IOKit/storage/scsi/IOSCSICDDriveNub.h> - -#define super IOSCSIHDDrive -OSDefineMetaClassAndStructors(IOSCSICDDrive,IOSCSIHDDrive) - -static void __inline ConvertBCDToHex(UInt8 *value) -{ - *value = (((*value) >> 4) * 10) + ((*value) & 0x0f); -} - -/* The Callback (C) entry from the SCSI provider. We just glue - * right into C++. - */ - -void -IOSCSICDDrive_gc_glue(IOService *object,void *param) -{ - IOSCSICDDrive *self; - struct IOBasicSCSI::context *cx; - - self = (IOSCSICDDrive *)object; - cx = (struct IOBasicSCSI::context *)param; - self->genericCompletion(cx); /* do it in C++ */ -} - -IOReturn -IOSCSICDDrive::audioPause(bool pause) -{ - struct context *cx; - SCSICDBInfo scsiCmd; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 10; - scsiCmd.cdb[0] = kIOSCSICommandPauseResume; - scsiCmd.cdb[8] = pause ? 0x00 : 0x01; - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, 0, false); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSICDDrive::audioPlay(CDMSF timeStart,CDMSF timeStop) -{ - return(doAudioPlayCommand(timeStart,timeStop)); -} - -IOReturn -IOSCSICDDrive::audioScan(CDMSF timeStart,bool reverse) -{ - struct context *cx; - SCSICDBInfo scsiCmd; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 10; - scsiCmd.cdb[0] = 0xCD; /* AUDIO SCAN (10) */ - scsiCmd.cdb[1] = reverse ? 0x10 : 0x00; - scsiCmd.cdb[3] = timeStart.minute; - scsiCmd.cdb[4] = timeStart.second; - scsiCmd.cdb[5] = timeStart.frame; - scsiCmd.cdb[9] = 0x40; /* MSF */ - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, 0, false); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSICDDrive::audioStop() -{ - struct context *cx; - SCSICDBInfo scsiCmd; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 6; - scsiCmd.cdb[0] = 0x01; /* REZERO UNIT (6) */ - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, 0, false); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -bool -IOSCSICDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score) -{ - if ((inqBuf[0] & 0x1f) == kIOSCSIDeviceTypeCDROM) { -// IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning TRUE\n",getName()); - *score = 0; - return(true); - } else { -// IOLog("%s[IOSCSICDDrive]::deviceTypeMatches, returning FALSE\n",getName()); - return(false); /* we don't handle other devices */ - } -} - -IOReturn -IOSCSICDDrive::doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - struct context *cx; - SCSICDBInfo scsiCmd; - - assert(buffer->getDirection() == kIODirectionIn); - - bzero(&scsiCmd, sizeof(scsiCmd)); - - if (sectorArea == kCDSectorAreaUser) { - if (sectorType == kCDSectorTypeCDDA) { - scsiCmd.cdbLength = 12; - scsiCmd.cdb[ 0] = 0xD8; /* READ CD-DA */ - scsiCmd.cdb[ 2] = (block >> 24) & 0xFF; - scsiCmd.cdb[ 3] = (block >> 16) & 0xFF; - scsiCmd.cdb[ 4] = (block >> 8) & 0xFF; - scsiCmd.cdb[ 5] = (block ) & 0xFF; - scsiCmd.cdb[ 6] = (nblks >> 24) & 0xFF; - scsiCmd.cdb[ 7] = (nblks >> 16) & 0xFF; - scsiCmd.cdb[ 8] = (nblks >> 8) & 0xFF; - scsiCmd.cdb[ 9] = (nblks ) & 0xFF; - } else if (sectorType == kCDSectorTypeMode1 || - sectorType == kCDSectorTypeMode2Form1) { - return doAsyncReadWrite(buffer,block,nblks,completion); - } - } - - if (scsiCmd.cdbLength == 0) { - return(kIOReturnUnsupported); - } - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - buffer->retain(); /* bump the retain count */ - cx->memory = buffer; - cx->completion = completion; - cx->state = kAsyncReadWrite; - - cx->scsireq->setCallback(this, (CallbackFn)IOSCSICDDrive_gc_glue, cx); - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(buffer, buffer->getLength(), false); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(60000); - - /* Queue the request awaiting power and return. When power comes up, - * the request will be passed to standardAsyncReadWriteExecute. - */ - queueCommand(cx,kAsync,getReadWritePowerState()); /* queue and possibly wait for power */ - - return(kIOReturnSuccess); -} - -IOReturn -IOSCSICDDrive::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - if (buffer->getDirection() == kIODirectionOut) { - return(kIOReturnNotWritable); - } - - return(super::doAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSICDDrive::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - if (buffer->getDirection() == kIODirectionOut) { - return(kIOReturnNotWritable); - } - - return(super::doSyncReadWrite(buffer,block,nblks)); -} - -IOReturn -IOSCSICDDrive::doAudioPlayCommand(CDMSF timeStart,CDMSF timeStop) -{ - struct context *cx; - struct IOAudioPlayMSFcdb *p; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - p = (struct IOAudioPlayMSFcdb *)scsiCDB.cdb; /* use PlayAudioMSF */ - p->opcode = kIOSCSICommandPlayAudioMSF; - p->lunbits = 0; - p->reserved1 = 0; - p->start_m = timeStart.minute; - p->start_s = timeStart.second; - p->start_f = timeStart.frame; - p->end_m = timeStop.minute; - p->end_s = timeStop.second; - p->end_f = timeStop.frame; - p->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - req->setPointers(cx->senseDataDesc, 255, false, true); - - req->setPointers( cx->memory, 0, false ); - req->setTimeout( 5000 ); - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSICDDrive::doFormatMedia(UInt64 /* byteCapacity */) -{ - return(kIOReturnUnsupported); -} - -UInt32 -IOSCSICDDrive::doGetFormatCapacities(UInt64 * /* capacities */,UInt32 /* capacitiesMaxCount */) const -{ - return(kIOReturnUnsupported); -} - -IOReturn -IOSCSICDDrive::doSynchronizeCache(void) -{ - return(kIOReturnUnsupported); -} - -IOReturn -IOSCSICDDrive::getAudioStatus(CDAudioStatus *status) -{ - IOReturn result; - UInt8 *tempBuf; - - /* Get a buffer for the returned data: */ - - result = allocateTempBuffer(&tempBuf,16); - if (result != kIOReturnSuccess) { - return(kIOReturnNoMemory); - } - - result = readSubChannel(tempBuf,16,IORSCcdb::kCurrentPosition,0); - - if (result == kIOReturnSuccess) { /* we got the data */ - assert(tempBuf[2] == 0); - assert(tempBuf[3] == 12); - assert(tempBuf[4] == 1); - - status->status = tempBuf[ 1]; - - status->position.track.number = tempBuf[ 6]; - status->position.track.index = tempBuf[ 7]; - - status->position.time.minute = tempBuf[ 9]; - status->position.time.second = tempBuf[10]; - status->position.time.frame = tempBuf[11]; - - status->position.track.time.minute = tempBuf[13]; - status->position.track.time.second = tempBuf[14]; - status->position.track.time.frame = tempBuf[15]; - } - deleteTempBuffer(tempBuf,16); - - return(result); -} - -IOReturn -IOSCSICDDrive::getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) -{ - struct context *cx; - SCSICDBInfo scsiCmd; - IOReturn result; - UInt8 audio_control[28]; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - cx->memory = IOMemoryDescriptor::withAddress(audio_control, - sizeof(audio_control), - kIODirectionIn); - if (cx->memory == NULL) { - deleteContext(cx); - return(kIOReturnNoMemory); - } - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 6; - scsiCmd.cdb[0] = 0x1a; /* MODE SENSE (6) */ - scsiCmd.cdb[2] = 0x0e; /* PAGE CODE E */ - scsiCmd.cdb[4] = sizeof(audio_control); - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, sizeof(audio_control), true); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - - if (result == kIOReturnSuccess) { - assert((audio_control[ 0] ) == 28-1); - assert((audio_control[ 3] ) == 0x08); - assert((audio_control[12] & 0x3f) == 0x0e); - assert((audio_control[13] ) == 0x0e); - - *leftVolume = audio_control[21]; - *rightVolume = audio_control[23]; - } - - deleteContext(cx); - - return(result); -} - -const char * -IOSCSICDDrive::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeCDROM); -} - -bool -IOSCSICDDrive::init(OSDictionary * properties) -{ - return(super::init(properties)); -} - -IOService * -IOSCSICDDrive::instantiateNub(void) -{ - IOService *nub; - - /* Instantiate a generic CDROM nub so a generic driver can match above us. */ - - nub = new IOSCSICDDriveNub; - return(nub); -} - -void -IOSCSICDDrive::mediaArrived(void) -{ -} - -void -IOSCSICDDrive::mediaGone(void) -{ -} - -IOReturn -IOSCSICDDrive::readISRC(UInt8 track,CDISRC isrc) -{ - IOReturn result; - UInt8 *tempBuf; - - /* Get a buffer for the returned data: */ - - result = allocateTempBuffer(&tempBuf,24); - if (result != kIOReturnSuccess) { - return(kIOReturnNoMemory); - } - - result = readSubChannel(tempBuf,24,IORSCcdb::kISRC,track); - if (result == kIOReturnSuccess) { - assert(tempBuf[2] == 0); - assert(tempBuf[3] == 20); - assert(tempBuf[4] == 3); - - if ((tempBuf[8] & 0x80)) { /* return the ISRC */ - bcopy(&tempBuf[9],isrc,kCDISRCMaxLength); - isrc[kCDISRCMaxLength] = '\0'; - } else { - result = kIOReturnNotFound; - } - } - - deleteTempBuffer(tempBuf,24); - - return(result); -} - -IOReturn -IOSCSICDDrive::readMCN(CDMCN mcn) -{ - IOReturn result; - UInt8 *tempBuf; - - /* Get a buffer for the returned data: */ - - result = allocateTempBuffer(&tempBuf,24); - if (result != kIOReturnSuccess) { - return(kIOReturnNoMemory); - } - - result = readSubChannel(tempBuf,24,IORSCcdb::kMCN,0); - if (result == kIOReturnSuccess) { - assert(tempBuf[2] == 0); - assert(tempBuf[3] == 20); - assert(tempBuf[4] == 2); - - if ((tempBuf[8] & 0x80)) { /* return the MCN */ - bcopy(&tempBuf[9],mcn,kCDMCNMaxLength); - mcn[kCDMCNMaxLength] = '\0'; - } else { - result = kIOReturnNotFound; - } - } - - deleteTempBuffer(tempBuf,24); - - return(result); -} - - -IOReturn -IOSCSICDDrive::readSubChannel(UInt8 *buffer,UInt32 length,UInt8 dataFormat,UInt8 trackNumber) -{ - struct context *cx; - struct IORSCcdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - bzero(buffer,length); - - c = (struct IORSCcdb *)(scsiCDB.cdb); - - c->opcode = kIOSCSICommandReadSubChannel; - c->lunbits = 0; - c->lunbits |= IORSCcdb::kMSF; - c->subq = IORSCcdb::kSubq; - c->dataformat = dataFormat; - c->track = trackNumber; /* any valid track will do */ - c->reserved1 = 0; - c->reserved2 = 0; - c->len_hi = length >> 8; - c->len_lo = length & 0xff; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - req->setPointers(cx->senseDataDesc, 255, false, true); - - cx->memory = IOMemoryDescriptor::withAddress((void *)buffer, - length, - kIODirectionIn); - req->setPointers( cx->memory, length, false ); - - req->setTimeout( 5000 ); - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSICDDrive::readTOC(IOMemoryDescriptor *buffer) -{ - struct context *cx; - struct IOReadToccdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IOReadToccdb *)scsiCDB.cdb; - - c->opcode = kIOSCSICommandReadTOC; - c->lunbits = IOReadToccdb::kMSF; - c->reserved1 = 0; - c->reserved2 = 0; - c->reserved3 = 0; - c->reserved4 = 0; - c->start_trk_session = 0; - c->len_hi = buffer->getLength() >> 8; - c->len_lo = buffer->getLength() & 0xff; - c->ctlbyte = IOReadToccdb::kFullTOC << 6; /* old format field */ - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - req->setPointers(cx->senseDataDesc, 255, false, true); - - buffer->retain(); /* bump the retain count */ - cx->memory = buffer; - - req->setPointers( cx->memory, cx->memory->getLength(), false ); - - req->setTimeout( 5000 ); - - result = simpleSynchIO(cx); - - deleteContext(cx); - -#ifdef HOLLYWOOD_BCD_TO_HEX_SUPPORT - IOByteCount tocMaxSize; - CDTOC *toc = buffer->getVirtualSegment(0, &tocMaxSize); - - /* Convert BCD-encoded values in TOC to hex values. */ - if (toc && tocMaxSize >= sizeof(UInt32)) { - UInt32 count = (tocMaxSize - sizeof(UInt32)) / sizeof(CDTOCDescriptor); - for (UInt32 index = 0; index < count; index++) { - if (toc->descriptors[index].point <= 0x99) { - ConvertBCDToHex(&toc->descriptors[index].point); - } - if ((toc->descriptors[index].point & 0xf0) == 0xb0) { - ConvertBCDToHex(&toc->descriptors[index].address.minute); - ConvertBCDToHex(&toc->descriptors[index].address.second); - ConvertBCDToHex(&toc->descriptors[index].address.frame); - ConvertBCDToHex(&toc->descriptors[index].zero); - } - if ( toc->descriptors[index].point <= 0x99 || - ( toc->descriptors[index].point >= 0xa0 && - toc->descriptors[index].point <= 0xc0 ) ) { - ConvertBCDToHex(&toc->descriptors[index].p.minute); - if (toc->descriptors[index].point != 0xa0) { - ConvertBCDToHex(&toc->descriptors[index].p.second); - } - ConvertBCDToHex(&toc->descriptors[index].p.frame); - } - } - } -#endif HOLLYWOOD_BCD_TO_HEX_SUPPORT - - return(result); -} - -IOReturn -IOSCSICDDrive::reportMaxWriteTransfer(UInt64 /* blockSize */,UInt64 * /* max */) -{ - return(0); -} - -IOReturn -IOSCSICDDrive::reportMediaState(bool *mediaPresent,bool *changed) -{ - IOReturn result; - - result = super::reportMediaState(mediaPresent,changed); - - if (result != kIOReturnSuccess) { - IOLog("%s[IOSCSICDDrive]::reportMediaState; result=%s, changed = %s, present = %s\n", - getName(),stringFromReturn(result),*changed ? "Y" : "N", *mediaPresent ? "Y" : "N"); - } - - if ((result == kIOReturnSuccess) && *changed) { /* the media state changed */ - if (*mediaPresent) { /* new media inserted */ - mediaArrived(); - } else { /* media went away */ - mediaGone(); - } - } - - /* We don't return the result of our internal operations. But since they - * indicate a problem, we probably should report some kind of problem, - * or maybe just ignore the media change. - */ - - return(result); -} - -IOReturn -IOSCSICDDrive::reportWriteProtection(bool *isWriteProtected) -{ - *isWriteProtected = true; - return(kIOReturnSuccess); -} - -IOReturn -IOSCSICDDrive::setAudioVolume(UInt8 leftVolume,UInt8 rightVolume) -{ - struct context *cx; - SCSICDBInfo scsiCmd; - IOReturn result; - UInt8 audio_control[28]; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - cx->memory = IOMemoryDescriptor::withAddress(audio_control, - sizeof(audio_control), - kIODirectionIn); - if (cx->memory == NULL) { - deleteContext(cx); - return(kIOReturnNoMemory); - } - - /* Get current values. */ - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 6; - scsiCmd.cdb[0] = 0x1a; /* MODE SENSE (6) */ - scsiCmd.cdb[2] = 0x0e; /* PAGE CODE E */ - scsiCmd.cdb[4] = sizeof(audio_control); - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, sizeof(audio_control), true); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - - if (result == kIOReturnSuccess) { - assert((audio_control[ 0] ) == 28-1); - assert((audio_control[ 3] ) == 0x08); - assert((audio_control[12] & 0x3f) == 0x0e); - assert((audio_control[13] ) == 0x0e); - - /* Set new values. */ - - audio_control[21] = audio_control[25] = leftVolume; - audio_control[23] = audio_control[27] = rightVolume; - - deleteContext(cx); - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - cx->memory = IOMemoryDescriptor::withAddress(audio_control, - sizeof(audio_control), - kIODirectionOut); - if (cx->memory == NULL) { - deleteContext(cx); - return(kIOReturnNoMemory); - } - - bzero(&scsiCmd, sizeof(scsiCmd)); - - scsiCmd.cdbLength = 6; - scsiCmd.cdb[0] = 0x15; /* MODE SELECT (6) */ - scsiCmd.cdb[4] = sizeof(audio_control); - - cx->scsireq->setCDB(&scsiCmd); - cx->scsireq->setPointers(cx->memory, sizeof(audio_control), true); - cx->scsireq->setPointers(cx->senseDataDesc, 255, false, true); - cx->scsireq->setTimeout(5000); - - result = simpleSynchIO(cx); - } - - deleteContext(cx); - - return(result); -} diff --git a/iokit/Families/IOSCSICDDrive/IOSCSICDDriveNub.cpp b/iokit/Families/IOSCSICDDrive/IOSCSICDDriveNub.cpp deleted file mode 100644 index 94104d038..000000000 --- a/iokit/Families/IOSCSICDDrive/IOSCSICDDriveNub.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/scsi/IOSCSICDDriveNub.h> -#include <IOKit/storage/scsi/IOSCSICDDrive.h> - -#define super IOCDBlockStorageDevice -OSDefineMetaClassAndStructors(IOSCSICDDriveNub,IOCDBlockStorageDevice) - -bool -IOSCSICDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) { - return(false); - } - - _provider = OSDynamicCast(IOSCSICDDrive,provider); - if (_provider == NULL) { - return(false); - } else { - return(true); - } -} - -IOReturn -IOSCSICDDriveNub::audioPause(bool pause) -{ - return(_provider->audioPause(pause)); -} - -IOReturn -IOSCSICDDriveNub::audioPlay(CDMSF timeStart,CDMSF timeStop) -{ - return(_provider->audioPlay(timeStart,timeStop)); -} - -IOReturn -IOSCSICDDriveNub::audioScan(CDMSF timeStart,bool reverse) -{ - return(_provider->audioScan(timeStart,reverse)); -} - -IOReturn -IOSCSICDDriveNub::audioStop() -{ - return(_provider->audioStop()); -} - -IOReturn -IOSCSICDDriveNub::doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - return(_provider->doAsyncReadCD(buffer,block,nblks, - sectorArea,sectorType, - completion)); -} - -IOReturn -IOSCSICDDriveNub::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - return(_provider->doAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSICDDriveNub::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - return(_provider->doSyncReadWrite(buffer,block,nblks)); -} - -IOReturn -IOSCSICDDriveNub::doEjectMedia(void) -{ - return(_provider->doEjectMedia()); -} - -IOReturn -IOSCSICDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return(_provider->doFormatMedia(byteCapacity)); -} - -UInt32 -IOSCSICDDriveNub::doGetFormatCapacities(UInt64 * capacities,UInt32 capacitiesMaxCount) const -{ - return(_provider->doGetFormatCapacities(capacities,capacitiesMaxCount)); -} - -IOReturn -IOSCSICDDriveNub::doLockUnlockMedia(bool doLock) -{ - return(_provider->doLockUnlockMedia(doLock)); -} - -IOReturn -IOSCSICDDriveNub::doSynchronizeCache(void) -{ - return(_provider->doSynchronizeCache()); -} - -IOReturn -IOSCSICDDriveNub::getAudioStatus(CDAudioStatus *status) -{ - return(_provider->getAudioStatus(status)); -} - -IOReturn -IOSCSICDDriveNub::getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) -{ - return(_provider->getAudioVolume(leftVolume,rightVolume)); -} - -UInt32 -IOSCSICDDriveNub::getMediaType(void) -{ - return(kCDMediaTypeROM); -} - -char * -IOSCSICDDriveNub::getVendorString(void) -{ - return(_provider->getVendorString()); -} - -char * -IOSCSICDDriveNub::getProductString(void) -{ - return(_provider->getProductString()); -} - -char * -IOSCSICDDriveNub::getRevisionString(void) -{ - return(_provider->getRevisionString()); -} - -char * -IOSCSICDDriveNub::getAdditionalDeviceInfoString(void) -{ - return(_provider->getAdditionalDeviceInfoString()); -} - -IOReturn -IOSCSICDDriveNub::readISRC(UInt8 track,CDISRC isrc) -{ - return(_provider->readISRC(track,isrc)); -} - -IOReturn -IOSCSICDDriveNub::readMCN(CDMCN mcn) -{ - return(_provider->readMCN(mcn)); -} - -IOReturn -IOSCSICDDriveNub::readTOC(IOMemoryDescriptor *buffer) -{ - return(_provider->readTOC(buffer)); -} - -IOReturn -IOSCSICDDriveNub::reportBlockSize(UInt64 *blockSize) -{ - return(_provider->reportBlockSize(blockSize)); -} - -IOReturn -IOSCSICDDriveNub::reportEjectability(bool *isEjectable) -{ - return(_provider->reportEjectability(isEjectable)); -} - -IOReturn -IOSCSICDDriveNub::reportLockability(bool *isLockable) -{ - return(_provider->reportLockability(isLockable)); -} - -IOReturn -IOSCSICDDriveNub::reportPollRequirements(bool *pollIsRequired,bool *pollIsExpensive) -{ - return(_provider-> reportPollRequirements(pollIsRequired,pollIsExpensive)); -} - -IOReturn -IOSCSICDDriveNub::reportMaxReadTransfer (UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxReadTransfer(blockSize,max)); -} - -IOReturn -IOSCSICDDriveNub::reportMaxValidBlock(UInt64 *maxBlock) -{ - return(_provider->reportMaxValidBlock(maxBlock)); -} - -IOReturn -IOSCSICDDriveNub::reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxWriteTransfer(blockSize,max)); -} - -IOReturn -IOSCSICDDriveNub::reportMediaState(bool *mediaPresent,bool *changed) -{ - return(_provider-> reportMediaState(mediaPresent,changed)); -} - -IOReturn -IOSCSICDDriveNub::reportRemovability(bool *isRemovable) -{ - return(_provider->reportRemovability(isRemovable)); -} - -IOReturn -IOSCSICDDriveNub::reportWriteProtection(bool *isWriteProtected) -{ - return(_provider->reportWriteProtection(isWriteProtected)); -} - -IOReturn -IOSCSICDDriveNub::setAudioVolume(UInt8 leftVolume,UInt8 rightVolume) -{ - return(_provider->setAudioVolume(leftVolume,rightVolume)); -} - diff --git a/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDrive.cpp b/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDrive.cpp deleted file mode 100644 index 3c8db1bd1..000000000 --- a/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDrive.cpp +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -// ============================================================================= -// Copyright (c) 2000 Apple Computer, Inc. All rights reserved. -// -// IOSCSIDVDDrive.cpp -// -#include <IOKit/IOLib.h> -#include <IOKit/IOReturn.h> -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/scsi/IOSCSIDVDDrive.h> -#include <IOKit/storage/scsi/IOSCSIDVDDriveNub.h> -#include <IOKit/storage/IODVDTypes.h> -#include <libkern/OSByteOrder.h> - -#define super IOSCSICDDrive -OSDefineMetaClassAndStructors(IOSCSIDVDDrive,IOSCSICDDrive) - -/*----------------*/ -const int kFeatureProfileList = 0x0000; -const int kFeatureCore = 0x0001; -const int kFeatureMorphing = 0x0002; -const int kFeatureRemovableMedium = 0x0003; -const int kFeatureRandomReadable = 0x0010; -const int kFeatureMultiRead = 0x001d; -const int kFeatureCDRead = 0x001e; -const int kFeatureDVDRead = 0x001f; -const int kFeatureRandomWrite = 0x0020; -const int kFeatureIncrStreamWrite = 0x0021; -const int kFeatureSectorErasable = 0x0022; -const int kFeatureFormattable = 0x0023; -const int kFeatureDefectManagement = 0x0024; -const int kFeatureWriteOnce = 0x0025; -const int kFeatureRestrictedOverwrite = 0x0026; -const int kFeatureDVDRWRestrictedOverwrite = 0x002c; -const int kFeatureCDTrackAtOnce = 0x002d; -const int kFeatureCDMastering = 0x002e; -const int kFeatureDVDR_RWWrite = 0x002f; -const int kFeaturePowerManagement = 0x0100; -const int kFeatureSMART = 0x0101; -const int kFeatureEmbeddedChanger = 0x0102; -const int kFeatureCDAudioAnalogPlay = 0x0103; -const int kFeatureMicrocodeUpgrade = 0x0104; -const int kFeatureTimeout = 0x0105; -const int kFeatureDVDCSS = 0x0106; -const int kFeatureRealTimeStreaming = 0x0107; -const int kFeatureLUNSerialNumber = 0x0108; -const int kFeatureDiskControlBlocks = 0x010a; -const int kFeatureDVDCPRM = 0x010b; - -void -IOSCSIDVDDrive::checkConfig(UInt8 *buf,UInt32 actual) -{ - struct featureHdr { - UInt32 totalLen; - UInt8 reserved1[2]; - UInt16 currentProfile; - }; - struct featureDescriptor { - UInt16 featureCode; - UInt8 versionPC; - UInt8 additionalLength; - }; - - int len; - struct featureHdr *fh; - struct featureDescriptor *fdp; - - fh = (struct featureHdr *)buf; - len = OSSwapBigToHostInt32(fh->totalLen); - - fdp = (struct featureDescriptor *)(&buf[8]); - - do { - - switch (OSSwapBigToHostInt16(fdp->featureCode)) { - - case kFeatureDVDRead : - _isDVDDrive = true; - break; - case kFeatureDVDCSS : - _canDoCSS = true; - break; - } - fdp = (struct featureDescriptor *)((char *)fdp + - sizeof(struct featureDescriptor) + - fdp->additionalLength); - } while ((UInt8 *)fdp < &buf[len]); -} - -IOReturn -IOSCSIDVDDrive::determineMediaType(void) -{ - struct featureHdr { - UInt32 totalLen; - UInt8 reserved1[2]; - UInt16 currentProfile; - }; - struct featureDescriptor { - UInt16 featureCode; - UInt8 versionPC; - UInt8 additionalLength; - }; - - int len; - struct featureHdr *fh; - struct featureDescriptor *fdp; - IOReturn result; - UInt32 configSize; - UInt8 configBuf[kMaxConfigLength]; - - /* Get the *current* configuration information, relating to the media. */ - - result = getConfiguration(configBuf,kMaxConfigLength,&configSize,true); - if (result != kIOReturnSuccess) { - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; result = '%s'\n", - getName(),stringFromReturn(result)); - return(result); - } - - fh = (struct featureHdr *)configBuf; - len = OSSwapBigToHostInt32(fh->totalLen); - - fdp = (struct featureDescriptor *)(&configBuf[8]); - - _mediaType = kDVDMediaTypeUnknown; /* assume there is no media inserted */ - - do { - - switch (OSSwapBigToHostInt16(fdp->featureCode)) { - - case kFeatureCDRead : - _mediaType = kCDMediaTypeROM; - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; media is %s.\n",getName(),"CD"); - break; - case kFeatureDVDRead : - _mediaType = kDVDMediaTypeROM; - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; media is %s.\n",getName(),"DVDROM"); - break; - case kFeatureFormattable : - _mediaType = kDVDMediaTypeRAM; - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; media is %s.\n",getName(),"DVDRam"); - break; - case kFeatureRandomWrite : - _isWriteProtected = false; - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; write-enabled.\n",getName()); - break; - } - fdp = (struct featureDescriptor *)((char *)fdp + - sizeof(struct featureDescriptor) + - fdp->additionalLength); - } while ((UInt8 *)fdp < &configBuf[len]); - - if (_mediaType == kDVDMediaTypeUnknown) { - IOLog("%s[IOSCSIDVDDrive]::determineMediaType; drive is empty.\n",getName()); - } - - return(kIOReturnSuccess); -} - -bool -IOSCSIDVDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score) -{ - IOReturn result; - UInt8 type; - - type = inqBuf[0] & 0x1f; - - if (type == kIOSCSIDeviceTypeCDROM) { - // IOLog("%s[IOSCSIDVDDrive]::deviceTypeMatches; device type %d is CD/DVD\n",getName(),type); - - /* Try to get the device configuration. If we can, then it must be a DVD - * drive since it follows the MtFuji command set (so far). If we cannot - * get the configuration, then the device must be a plain CDROM drive. - */ - result = getConfiguration(_configBuf,kMaxConfigLength,&_configSize,false); - if (result == kIOReturnSuccess) { - // IOLog("%s[IOSCSIDVDDrive]::deviceTypeMatches getConfig OK; returning true\n",getName()); - checkConfig(_configBuf,_configSize); - if (_isDVDDrive) { - // IOLog("---isDVDDrive\n"); - *score = 16; /* override any CD driver match */ - return(true); - } else { /* not DVD */ - return(false); - } - } else { - // IOLog("%s[IOSCSIDVDDrive]::deviceTypeMatches getConfig fail; returning false\n",getName()); - return(false); - } - } else { - /** - IOLog("%s[IOSCSIDVDDrive]::deviceTypeMatches; device type %d not CD/DVD, returning FALSE\n", - getName(),type); - **/ - return(false); /* we don't handle other devices */ - } -} - -IOReturn -IOSCSIDVDDrive::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - return(standardAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSIDVDDrive::doFormatMedia(UInt64 byteCapacity) -{ - return(standardFormatMedia(byteCapacity)); -} - -UInt32 -IOSCSIDVDDrive::doGetFormatCapacities(UInt64 *capacities,UInt32 capacitiesMaxCount) const -{ - if (capacitiesMaxCount > 0) { - *capacities = (UInt64)((UInt64)2600 * (UInt64)1048576); /* DVD-RAM V1.0 is 2.6GB */ - return(1); - } else { - return(0); - } -} - -IOReturn -IOSCSIDVDDrive::doSynchronizeCache(void) -{ - return(standardSynchronizeCache()); -} - -IOReturn -IOSCSIDVDDrive::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - return(standardSyncReadWrite(buffer,block,nblks)); -} - -IOReturn -IOSCSIDVDDrive::getConfiguration(UInt8 *buffer,UInt32 length,UInt32 *actualLength,bool current) -{ - struct context *cx; - struct IOGCCdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - SCSIResults scsiResults; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - bzero(buffer,length); - - c = (struct IOGCCdb *)(scsiCDB.cdb); - - c->opcode = kIOSCSICommandGetConfiguration; - c->lunRT = 0; - if (current) { /* only get current features */ - c->lunRT |= 0x01; - } - c->startFeature_lo = 0; - c->startFeature_hi = 0; - c->len_hi = length >> 8; - c->len_lo = length & 0xff; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - - cx->memory = IOMemoryDescriptor::withAddress((void *)buffer, - length, - kIODirectionIn); - req->setPointers( cx->memory, length, false ); - req->setPointers( cx->senseDataDesc, 255, false, true ); - req->setTimeout( 5000 ); - - queueCommand(cx,kSync,getGetConfigurationPowerState()); - result = simpleSynchIO(cx); - - req->getResults(&scsiResults); - if (result == kIOReturnUnderrun) { - result = kIOReturnSuccess; - } - *actualLength = scsiResults.bytesTransferred; - - deleteContext(cx); - - return(result); -} - -const char * -IOSCSIDVDDrive::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeDVD); -} - -UInt32 -IOSCSIDVDDrive::getGetConfigurationPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIDVDDrive::getReportKeyPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIDVDDrive::getSendKeyPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIDVDDrive::getMediaType(void) -{ - return(_mediaType); -} - -bool -IOSCSIDVDDrive::init(OSDictionary * properties) -{ - _isDVDDrive = false; - _canDoCSS = false; - _configSize = 0; - _mediaType = kDVDMediaTypeUnknown; - _isWriteProtected = true; - - return(super::init(properties)); -} - -IOService * -IOSCSIDVDDrive::instantiateNub(void) -{ - IOService *nub; - - /* Instantiate a generic DVD nub so a generic driver can match above us. */ - - nub = new IOSCSIDVDDriveNub; - return(nub); -} - -IOReturn -IOSCSIDVDDrive::reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat) -{ - struct context *cx; - struct IORKCdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IORKCdb *)(scsiCDB.cdb); - - c->opcode = kIOSCSICommandReportKey; - if (keyFormat == kTitleKey) { - c->lba_0 = lba >> 24; - c->lba_1 = lba >> 16; - c->lba_2 = lba >> 8; - c->lba_3 = lba & 0xff; - } - c->keyClass = keyClass; - c->len_hi = buffer->getLength() >> 8; - c->len_lo = buffer->getLength() & 0xff; - c->agidKeyFormat = agid << 6 | keyFormat; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - - cx->memory = buffer; - - req->setPointers( cx->memory, cx->memory->getLength(), false ); - req->setPointers( cx->senseDataDesc, 255, false, true ); - req->setTimeout( 5000 ); - - queueCommand(cx,kSync,getReportKeyPowerState()); - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSIDVDDrive::reportMediaState(bool *mediaPresent,bool *changed) -{ - IOReturn result; - - /* Let the superclass check for media in the standard way: */ - - result = super::reportMediaState(mediaPresent,changed); - - if (result != kIOReturnSuccess) { - IOLog("%s[IOSCSIDVDDrive]:: reportMediaState; result = '%s' from super\n", - getName(),stringFromReturn(result)); - return(result); - } - - /* If we have newly-inserted media, determine its type: */ - - if (*mediaPresent && *changed) { - result = determineMediaType(); - } - - return(result); -} - -IOReturn -IOSCSIDVDDrive::reportWriteProtection(bool *isWriteProtected) -{ - *isWriteProtected = _isWriteProtected; - return(kIOReturnSuccess); -} - -IOReturn -IOSCSIDVDDrive::sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat) -{ - struct context *cx; - struct IOSKCdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IOSKCdb *)(scsiCDB.cdb); - - c->opcode = kIOSCSICommandSendKey; - c->keyClass = keyClass; - c->len_hi = buffer->getLength() >> 8; - c->len_lo = buffer->getLength() & 0xff; - c->agidKeyFormat = agid << 6 | keyFormat; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - req->setCDB( &scsiCDB ); - - cx->memory = buffer; - - req->setPointers( cx->memory, cx->memory->getLength(), false ); - req->setPointers( cx->senseDataDesc, 255, false, true ); - req->setTimeout( 5000 ); - - queueCommand(cx,kSync,getSendKeyPowerState()); - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} diff --git a/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp b/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp deleted file mode 100644 index 9061f004d..000000000 --- a/iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/scsi/IOSCSIDVDDriveNub.h> -#include <IOKit/storage/scsi/IOSCSIDVDDrive.h> - -#define super IODVDBlockStorageDevice -OSDefineMetaClassAndStructors(IOSCSIDVDDriveNub,IODVDBlockStorageDevice) - -bool -IOSCSIDVDDriveNub::attach(IOService * provider) -{ - if (!super::attach(provider)) { - return(false); - } - - _provider = OSDynamicCast(IOSCSIDVDDrive,provider); - if (_provider == NULL) { - return(false); - } else { - return(true); - } -} - -IOReturn -IOSCSIDVDDriveNub::audioPause(bool pause) -{ - return(_provider->audioPause(pause)); -} - -IOReturn -IOSCSIDVDDriveNub::audioPlay(CDMSF timeStart,CDMSF timeStop) -{ - return(_provider->audioPlay(timeStart,timeStop)); -} - -IOReturn -IOSCSIDVDDriveNub::audioScan(CDMSF timeStart,bool reverse) -{ - return(_provider->audioScan(timeStart,reverse)); -} - -IOReturn -IOSCSIDVDDriveNub::audioStop() -{ - return(_provider->audioStop()); -} - -IOReturn -IOSCSIDVDDriveNub::doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) -{ - return(_provider->doAsyncReadCD(buffer,block,nblks, - sectorArea,sectorType, - completion)); -} - -IOReturn -IOSCSIDVDDriveNub::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - return(_provider->doAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSIDVDDriveNub::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - return(_provider->doSyncReadWrite(buffer,block,nblks)); -} - -IOReturn -IOSCSIDVDDriveNub::doEjectMedia(void) -{ - return(_provider->doEjectMedia()); -} - -IOReturn -IOSCSIDVDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return(_provider->doFormatMedia(byteCapacity)); -} - -UInt32 -IOSCSIDVDDriveNub::doGetFormatCapacities(UInt64 * capacities,UInt32 capacitiesMaxCount) const -{ - return(_provider->doGetFormatCapacities(capacities,capacitiesMaxCount)); -} - -IOReturn -IOSCSIDVDDriveNub::doLockUnlockMedia(bool doLock) -{ - return(_provider->doLockUnlockMedia(doLock)); -} - -IOReturn -IOSCSIDVDDriveNub::doSynchronizeCache(void) -{ - return(_provider->doSynchronizeCache()); -} - -IOReturn -IOSCSIDVDDriveNub::getAudioStatus(CDAudioStatus *status) -{ - return(_provider->getAudioStatus(status)); -} - -IOReturn -IOSCSIDVDDriveNub::getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) -{ - return(_provider->getAudioVolume(leftVolume,rightVolume)); -} - -UInt32 -IOSCSIDVDDriveNub::getMediaType(void) -{ - return(_provider->getMediaType()); -} - -char * -IOSCSIDVDDriveNub::getVendorString(void) -{ - return(_provider->getVendorString()); -} - -char * -IOSCSIDVDDriveNub::getProductString(void) -{ - return(_provider->getProductString()); -} - -char * -IOSCSIDVDDriveNub::getRevisionString(void) -{ - return(_provider->getRevisionString()); -} - -char * -IOSCSIDVDDriveNub::getAdditionalDeviceInfoString(void) -{ - return(_provider->getAdditionalDeviceInfoString()); -} - -IOReturn -IOSCSIDVDDriveNub::readISRC(UInt8 track,CDISRC isrc) -{ - return(_provider->readISRC(track,isrc)); -} - -IOReturn -IOSCSIDVDDriveNub::readMCN(CDMCN mcn) -{ - return(_provider->readMCN(mcn)); -} - -IOReturn -IOSCSIDVDDriveNub::readTOC(IOMemoryDescriptor *buffer) -{ - return(_provider->readTOC(buffer)); -} - -IOReturn -IOSCSIDVDDriveNub::reportBlockSize(UInt64 *blockSize) -{ - return(_provider->reportBlockSize(blockSize)); -} - -IOReturn -IOSCSIDVDDriveNub::reportEjectability(bool *isEjectable) -{ - return(_provider->reportEjectability(isEjectable)); -} - -IOReturn -IOSCSIDVDDriveNub::reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat) -{ - return(_provider->reportKey(buffer,keyClass,lba,agid,keyFormat)); -} - -IOReturn -IOSCSIDVDDriveNub::reportLockability(bool *isLockable) -{ - return(_provider->reportLockability(isLockable)); -} - -IOReturn -IOSCSIDVDDriveNub::reportPollRequirements(bool *pollIsRequired,bool *pollIsExpensive) -{ - return(_provider-> reportPollRequirements(pollIsRequired,pollIsExpensive)); -} - -IOReturn -IOSCSIDVDDriveNub::reportMaxReadTransfer (UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxReadTransfer(blockSize,max)); -} - -IOReturn -IOSCSIDVDDriveNub::reportMaxValidBlock(UInt64 *maxBlock) -{ - return(_provider->reportMaxValidBlock(maxBlock)); -} - -IOReturn -IOSCSIDVDDriveNub::reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxWriteTransfer(blockSize,max)); -} - -IOReturn -IOSCSIDVDDriveNub::reportMediaState(bool *mediaPresent,bool *changed) -{ - return(_provider->reportMediaState(mediaPresent,changed)); -} - -IOReturn -IOSCSIDVDDriveNub::reportRemovability(bool *isRemovable) -{ - return(_provider->reportRemovability(isRemovable)); -} - -IOReturn -IOSCSIDVDDriveNub::reportWriteProtection(bool *isWriteProtected) -{ - return(_provider->reportWriteProtection(isWriteProtected)); -} - -IOReturn -IOSCSIDVDDriveNub::sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat) -{ - return(_provider->sendKey(buffer,keyClass,agid,keyFormat)); -} - -IOReturn -IOSCSIDVDDriveNub::setAudioVolume(UInt8 leftVolume,UInt8 rightVolume) -{ - return(_provider->setAudioVolume(leftVolume,rightVolume)); -} diff --git a/iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp b/iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp deleted file mode 100644 index dcfdc159c..000000000 --- a/iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp +++ /dev/null @@ -1,1331 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOLib.h> -#include <IOKit/IOReturn.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/scsi/scsi-device/SCSIDevice.h> -#include <IOKit/storage/scsi/IOBasicSCSI.h> - -#define super IOService -OSDefineMetaClass(IOBasicSCSI,IOService) -OSDefineAbstractStructors(IOBasicSCSI,IOService) - -void IOBasicSCSI_gc_glue(void *object,void *param); - -/* Allocate a new context struct. A return of NULL means we couldn't - * allocate either the context itself or one of its members. - */ -struct IOBasicSCSI::context * -IOBasicSCSI::allocateContext(void) -{ - struct context *cx; - - //xxx IOLog("allocateContext entered\n"); - - /* First, the context structure itself. */ - - cx = IONew(struct context,1); - if (cx == NULL) { - return(NULL); - } - - bzero(cx,sizeof(struct context)); - - /* Allocate all the structs and objects we need. If any allocation - * fails, we can simply call deleteContext() to free anything - * allocated so far. - */ - - cx->scsireq = _provider->allocCommand(kIOSCSIDevice, 0); - if (cx->scsireq == NULL) { - deleteContext(cx); - return(NULL); - } - - - /* Preset the completion parameters, which are the same for - * all SCSI requests we issue. Only the target function changes. - */ - - cx->senseData = (SCSISenseData *)IOMalloc(256); - if (cx-> senseData == NULL) { - deleteContext(cx); - return(NULL); - } - - bzero(cx->senseData, 256 ); - - cx->senseDataDesc = IOMemoryDescriptor::withAddress(cx->senseData, - 256, - kIODirectionIn); - - - cx->sync = IOSyncer::create(false); - if (cx->sync == NULL) { - deleteContext(cx); - return(NULL); - } - - cx->retryInProgress = false; - - /* We defer allocation of the Memory Descriptor till later; - * it will be allocated where it's needed. - */ - - // IOLog("allocateContext returning cx = %08x\n",(unsigned int)cx); - - return(cx); -} - -IOReturn -IOBasicSCSI::allocateInquiryBuffer(UInt8 **buf,UInt32 size) -{ - *buf = (UInt8 *)IOMalloc(size); - if (*buf == NULL) { - return(kIOReturnNoMemory); - } - - bzero(*buf,size); - - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::allocateTempBuffer(UInt8 **buf,UInt32 size) -{ - *buf = (UInt8 *)IOMalloc(size); - if (*buf == NULL) { - return(kIOReturnNoMemory); - } - - bzero(*buf,size); - - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::allocateReadCapacityBuffer(UInt8 **buf,UInt8 size) -{ - *buf = (UInt8 *)IOMalloc(size); - if (*buf == NULL) { - return(kIOReturnNoMemory); - } - - bzero(*buf,size); - - return(kIOReturnSuccess); -} - -UInt32 -IOBasicSCSI::createReadCdb(UInt8 *cdb,UInt32 *cdbLength, - UInt32 block,UInt32 nblks, - UInt32 *maxAutoSenseLength, - UInt32 *timeoutSeconds) -{ - struct IORWcdb *c; - - c = (struct IORWcdb *)cdb; - - c->opcode = SOP_READ10; - c->lunbits = 0; - - c->lba_3 = block >> 24; - c->lba_2 = block >> 16; - c->lba_1 = block >> 8; - c->lba_0 = block & 0xff; - - c->reserved = 0; - - c->count_msb = nblks >> 8; - c->count_lsb = nblks & 0xff; - - c->ctlbyte = 0; - - *cdbLength = 10; - *maxAutoSenseLength = 8; /* do the sense */ - *timeoutSeconds = 60; - return(0); -} - -UInt32 -IOBasicSCSI::createWriteCdb(UInt8 *cdb,UInt32 *cdbLength, - UInt32 block,UInt32 nblks, - UInt32 *maxAutoSenseLength, - UInt32 *timeoutSeconds) -{ - struct IORWcdb *c; - - c = (struct IORWcdb *)cdb; - - c->opcode = SOP_WRITE10; - c->lunbits = 0; - - c->lba_3 = block >> 24; - c->lba_2 = block >> 16; - c->lba_1 = block >> 8; - c->lba_0 = block & 0xff; - - c->reserved = 0; - - c->count_msb = nblks >> 8; - c->count_lsb = nblks & 0xff; - - c->ctlbyte = 0; - - *cdbLength = 10; - *maxAutoSenseLength = sizeof( SCSISenseData ); /* do the sense */ - *timeoutSeconds = 60; - return(0); -} - -void -IOBasicSCSI::deleteContext(struct context *cx) -{ - // IOLog("deleteContext %08x\n",(unsigned int)cx); - - if (cx->scsireq) { - cx->scsireq->release(); - } - -// if (cx->scsiresult) { -// IODelete(cx->scsiresult,struct IOSCSIResult,1); -// } - - if (cx->senseData) - { - IOFree( cx->senseData, 256 ); - } - - if ( cx->senseDataDesc ) - { - cx->senseDataDesc->release(); - } - - if (cx->memory) { - cx->memory->release(); - } - - if (cx->sync) { - cx->sync->release(); - } - - IODelete(cx,struct context,1); -} - -void -IOBasicSCSI::deleteInquiryBuffer(UInt8 *buf,UInt32 size) -{ - IOFree((void *)buf,size); -} - -void -IOBasicSCSI::deleteTempBuffer(UInt8 *buf,UInt32 len) -{ - IOFree((void *)buf,len); -} - -void -IOBasicSCSI::deleteReadCapacityBuffer(UInt8 *buf,UInt32 len) -{ - IOFree((void *)buf,len); -} - -IOReturn -IOBasicSCSI::doInquiry(UInt8 *inqBuf,UInt32 maxLen,UInt32 *actualLen) -{ - _provider->getInquiryData( inqBuf, maxLen, actualLen ); - return kIOReturnSuccess; -} - -IOReturn -IOBasicSCSI::doReadCapacity(UInt64 *blockSize,UInt64 *maxBlock) -{ - struct context *cx; - struct IOReadCapcdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - UInt8 *buf; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(SCSICDBInfo) ); - - c = (struct IOReadCapcdb *)&scsiCDB.cdb; - c->opcode = SOP_READCAP; - c->lunbits = 0; - c->lba_3 = 0; - c->lba_2 = 0; - c->lba_1 = 0; - c->lba_0 = 0; - c->reserved1 = 0; - c->reserved2 = 0; - c->reserved3 = 0; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - - req->setCDB( &scsiCDB ); - req->setPointers( cx->senseDataDesc, sizeof(SCSISenseData), false, true ); - - req->setTimeout( 30000 ); - - *blockSize = 0; - *maxBlock = 0; - - result = allocateReadCapacityBuffer(&buf,kReadCapSize); - - if (result == kIOReturnSuccess) { - - cx->memory = IOMemoryDescriptor::withAddress((void *)buf, - kReadCapSize, - kIODirectionIn); - - req->setPointers( cx->memory, kReadCapSize, false ); - - /* We force the drive to be completely powered-up, including the mechanical - * components, because some drives (e.g. CDs) access the media. - */ - - queueCommand(cx,kSync,getReadCapacityPowerState()); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); - - if (result == kIOReturnSuccess) { - - *blockSize = (buf[4] << 24) | /* endian-neutral */ - (buf[5] << 16) | - (buf[6] << 8) | - (buf[7] ); - - *maxBlock = (buf[0] << 24) | /* endian-neutral */ - (buf[1] << 16) | - (buf[2] << 8) | - (buf[3] ); - } - - deleteReadCapacityBuffer(buf,kReadCapSize); - } - - deleteContext(cx); - - return(result); -} - -void -IOBasicSCSI::free(void) -{ - if (_inqBuf) { - deleteInquiryBuffer(_inqBuf,_inqBufSize); - _inqBuf = NULL; - } - -#ifdef DISKPM - if (_powerQueue.lock) { - IOLockFree(_powerQueue.lock); - } -#endif - - if (_busResetContext) { - deleteContext(_busResetContext); - } - if (_unitAttentionContext) { - deleteContext(_unitAttentionContext); - } - - super::free(); -} - -/* The Callback (C) entry from the SCSI provider. We just glue - * right into C++. - */ - -void -IOBasicSCSI_gc_glue(void *object,void *param) -{ - IOBasicSCSI *self; - struct IOBasicSCSI::context *cx; - - self = (IOBasicSCSI *)object; - cx = (struct IOBasicSCSI::context *)param; - self->genericCompletion(cx); /* do it in C++ */ -} - -void -IOBasicSCSI::setupBusResetRecovery(void) -{ - IOLog("%s[IOBasicSCSI]: SCSI bus reset occurred; begin recovery.\n",getName()); - - _busResetContext->step = 1; - _busResetRecoveryInProgress = true; - _provider->holdQueue(kQTypeNormalQ); - // _provider->flushQueue(kQTypeNormalQ,kIOReturnAborted); -} - -void -IOBasicSCSI::beginBusResetRecovery(void) -{ - /* In this method, we issue the first command necessary to recover - * from the Bus Reset condition. Its completion will call - * busResetRecoveryCommandComplete, which is respnsible for starting - * the next command, until all have been executed. - * - * The default implementation of this method does nothing, except - * to call finishBusResetRecovery immediately. - */ - - // IOLog("%s[IOBasicSCSI]: beginBusReset\n",getName()); - finishBusResetRecovery(); -} - -void -IOBasicSCSI::busResetRecoveryCommandComplete(struct IOBasicSCSI::context *cx) -{ - /* We are entered for each command completion during bus reset recovery. - * - * Do whatever we have to upon completion of one of our commands. - * - * Typically we would increment "step" then start another asynchronous - * command. When we have finished running off the whole set of required - * operations then we call finishBusResetRecovery. - * - * The default implementation does nothing. - */ -} - -void -IOBasicSCSI::finishBusResetRecovery(void) -{ - /* Release the IO queue so that any pending commands can start. */ - - IOLog("%s[IOBasicSCSI]: SCSI bus reset recovery complete.\n",getName()); - _provider->releaseQueue(kQTypeNormalQ); - _busResetRecoveryInProgress = false; -} - -bool -IOBasicSCSI::unitAttentionDetected(struct IOBasicSCSI::context *cx) -{ - SCSIResults scsiResults; - - /* We're not currently handling a Unit Attention: see if - * we just got a one to handle. Note that we do NOT have to - * detect Bus Reset here, because we receive notification of - * that event asynchronously via the message() method. - */ - - cx->scsireq->getResults(&scsiResults); - - /* A special case is Unit Attention, which can happen at any time. We begin - * the Unit Attention recovery procedure which issues multiple asynch commands - * to restore the device condition. After the recovery procedure completes, - * it causes a retry of the original command. - */ - - if (scsiResults.requestSenseDone == true) { /* an error occurred */ - - // IOLog("%s[IOBasicSCSI]::unitAttentionDetected: sense code %02x\n", - // getName(),cx->scsiresult->scsiSense[02]); - - if ((cx->senseData->senseKey & 0x0f) == kUnitAttention) { /* it's a UA */ - - // IOLog("%s[IOBasicSCSI]::unitAttentionDetected: detected UnitAttention\n", - // getName()); - - return(true); - } - - } /* no sense data, therefore NOT a Unit Attention */ - - return(false); -} - -void -IOBasicSCSI::setupUnitAttentionRecovery(struct IOBasicSCSI::context *cx) -{ - if (!_unitAttentionRecoveryInProgress) { - - /* Save original IO context and set step. */ - - _unitAttentionContext->originalIOContext = cx; - - _unitAttentionContext->step = 1; - - _unitAttentionRecoveryInProgress = true; - - beginUnitAttentionRecovery(); - } -} - -void -IOBasicSCSI::beginUnitAttentionRecovery(void) -{ - /* In this method, we issue the first command necessary to recover - * from the Unit Attention condition. Its completion will call - * unitAttentionCommandComplete, which is respnsible for starting - * the next command, until all have been executed. - * - * The default implementation of this method does nothing, except - * to call finishUnitAttentionRecovery immediately. - */ - - finishUnitAttentionRecovery(); -} - -void -IOBasicSCSI::unitAttentionRecoveryCommandComplete(struct IOBasicSCSI::context *cx) -{ - /* We are entered for each command completion during Unit Attention recovery. - * - * Do whatever we have to upon completion of one of our commands. - * - * Typically we would increment "step" then start another asynchronous - * command. When we have finished running off the whole set of required - * operations then we call finishUnitAttentionRecovery. - * - * The default implementation does nothing. - */ -} - -void -IOBasicSCSI::finishUnitAttentionRecovery(void) -{ - /* When we're done, we reissue the command that caught the Unit Attention. */ - - _unitAttentionRecoveryInProgress = false; - _unitAttentionContext->originalIOContext->scsireq->execute(); -} - -bool -IOBasicSCSI::automaticRetry(struct IOBasicSCSI::context *cx) -{ - SCSIResults scsiResults; - - if (unitAttentionDetected(cx)) { /* do an automatic retry for Unit Attention */ - setupUnitAttentionRecovery(cx); - return(true); - } - - cx->scsireq->getResults(&scsiResults); - - if (scsiResults.returnCode != kIOReturnSuccess && - scsiResults.returnCode != kIOReturnError) { - /** - IOLog("%s[IOBasicSCSI]: retcode = %08lx / %s\n", - getName(),scsiResults.returnCode,stringFromReturn(scsiResults.returnCode)); - **/ - } - - if (scsiResults.returnCode == kIOReturnAborted || - scsiResults.returnCode == kIOReturnTimeout) { /* must be a Bus Reset abort */ - if (!cx->retryInProgress) { /* start a retry if not already doing one */ - cx->retryInProgress = true; - cx->retryCount = kMaxRetries; - } - if (cx->retryCount > 0) { /* OK to continue retrying */ - IOLog("%s[IOBasicSCSI]: AutoRetry cx @ %08lx, cmd @ %08lx; %ld retries to go.\n", - getName(),(unsigned long)cx,(unsigned long)cx->scsireq,cx->retryCount); - cx->retryCount--; - cx->scsireq->execute(); - return(true); - } else { - cx->retryInProgress = false; - return(false); - } - } - - return(customAutomaticRetry(cx)); -} - -bool -IOBasicSCSI::customAutomaticRetry(struct IOBasicSCSI::context *cx) -{ - return(false); /* the default does nothing special */ -} - -void -IOBasicSCSI::genericCompletion(struct IOBasicSCSI::context *cx) -{ - - /* We dispatch the completion depending on our state. */ - - // IOLog("%s[IOBasicSCSI]::genericCompletion: dispatching, state = %s\n", - // getName(),stringFromState(cx->state)); - - switch (cx->state) { - - case kSimpleSynchIO : - if (!automaticRetry(cx)) { - cx->sync->signal(kIOReturnSuccess,false); /* Just wake up the waiting thread: */ - } - break; - - case kAsyncReadWrite : /* normal r/w completion */ - if (!automaticRetry(cx)) { - RWCompletion(cx); - deleteContext(cx); - } - break; - - case kHandlingRecoveryAfterBusReset : /* still handling recovery after reset */ - if (!automaticRetry(cx)) { - busResetRecoveryCommandComplete(cx); - } - break; /* just wait for next completion */ - - case kHandlingUnitAttention : /* still handling UA */ - unitAttentionRecoveryCommandComplete(cx); - break; /* just wait for next completion */ - - case kNone : /* undefined */ - case kMaxStateValue : - case kAwaitingPower : - break; - } - - return; -} - -char * -IOBasicSCSI::getAdditionalDeviceInfoString(void) -{ - return("[SCSI]"); -} - -UInt64 -IOBasicSCSI::getBlockSize(void) -{ - return(_blockSize); -} - -char * -IOBasicSCSI::getProductString(void) -{ - return(_product); -} - -char * -IOBasicSCSI::getRevisionString(void) -{ - return(_rev); -} - -char * -IOBasicSCSI::getVendorString(void) -{ - return(_vendor); -} - -bool -IOBasicSCSI::init(OSDictionary * properties) -{ - _inqBuf = NULL; - _inqBufSize = 0; - _inqLen = 0; - - _vendor[8] = '\0'; - _product[16] = '\0'; - _rev[4] = '\0'; - - _readCapDone = false; - _blockSize = 0; - _maxBlock = 0; - _removable = false; - -#ifdef DISKPM - _powerQueue.head = NULL; - _powerQueue.tail = NULL; - _powerQueue.lock = IOLockAlloc(); - if (_powerQueue.lock == NULL) { - return(false); - } -#endif - - return(super::init(properties)); -} - -IOReturn -IOBasicSCSI::message(UInt32 type,IOService * provider,void * argument) -{ - // IOLog("%s[IOBasicSCSI]: message: type = %lx\n",getName(),type); - switch (type) { - case kSCSIClientMsgBusReset : /* Bus Reset has begun */ - if (!_busResetRecoveryInProgress) { /* try to avoid reset-within-reset recovery */ - setupBusResetRecovery(); /* indicate recovery will be in progress */ - } - break; /* now wait till reset is done */ - - case (kSCSIClientMsgBusReset | kSCSIClientMsgDone) : /* Bus Reset is finished */ - beginBusResetRecovery(); /* now start the actual recovery process */ - break; - - default : - return(super::message(type,provider,argument)); /* not one of ours */ - } - - return(kIOReturnSuccess); -} - -IOService * -IOBasicSCSI::probe(IOService * provider,SInt32 * score) -{ - IOReturn result; - OSString * string; - - if (!super::probe(provider,score)) { - return(NULL); - } - - _provider = (IOSCSIDevice *)provider; - - /* Do an inquiry to get the device type. The inquiry buffer will - * be deleted by free(). - */ - - _inqBufSize = kMaxInqSize; - result = allocateInquiryBuffer(&_inqBuf,_inqBufSize); - if (result != kIOReturnSuccess) { - return(NULL); - } - - result = doInquiry(_inqBuf,_inqBufSize,&_inqLen); - if (result != kIOReturnSuccess) { - return(NULL); - } - -#ifdef notdef - // xxx NEVER match for ID=0, the boot disk. This lets us - // test this driver on other disk drives. - // - if (_provider->getTarget() == 0) { - IOLog("**%s[IOBasicSCSI]:probe; ignoring SCSI ID %d\n", - getName(),(int)_provider->getTarget()); - return(NULL); - } -#endif - - // Fetch SCSI device information from the nub. - - string = OSDynamicCast(OSString, - _provider->getProperty(kSCSIPropertyVendorName)); - if (string) { - strncpy(_vendor, string->getCStringNoCopy(), 8); - _vendor[8] = '\0'; - } - - string = OSDynamicCast(OSString, - _provider->getProperty(kSCSIPropertyProductName)); - if (string) { - strncpy(_product, string->getCStringNoCopy(), 16); - _product[16] = '\0'; - } - - string = OSDynamicCast(OSString, - _provider->getProperty(kSCSIPropertyProductRevision)); - if (string) { - strncpy(_rev, string->getCStringNoCopy(), 4); - _rev[4] = '\0'; - } - - if (deviceTypeMatches(_inqBuf,_inqLen,score)) { - -/*** - IOLog("**%s[IOBasicSCSI]::probe; accepting %s, %s, %s, %s; SCSI ID %d\n", - getName(),getVendorString(),getProductString(),getRevisionString(), - getAdditionalDeviceInfoString(), - (int)_provider->getTarget()); -***/ - return(this); - - } else { - return(NULL); - } -} - -void -IOBasicSCSI::dequeueCommands(void) -{ -#ifdef DISKPM - struct queue *q; - IOReturn result; - - q = &_powerQueue; - - IOLockLock(q->lock); - - /* Dequeue and execute all requests for which we have the proper power level. */ - - while (q->head) { - cx = q->head; - if (pm_vars->myCurrentState != cx->desiredPower) { - break; - } - q->head = cx->next; /* remove command from the queue */ - if (q->head == NULL) { - q->tail = NULL; - } - - cx->state = kNone; - - /* If the queued request was synchronous, all we have to do is wake it up. */ - - if (cx->isSync) { - cx->sync->signal(kIOReturnSuccess, false); /* Just wake up the waiting thread: */ - - } else { /* it's async; fire it off! */ - result = standardAsyncReadWriteExecute(cx); /* execute the async IO */ - if (result != kIOReturnSuccess) { /* provider didn't accept it! */ - RWCompletion(cx); /* force a completion */ - } - } - }; - - IOLockUnlock(q->lock); -#endif -} - -void -IOBasicSCSI::queueCommand(struct context *cx,bool isSync,UInt32 desiredPower) -{ -#ifndef DISKPM //for now, just return immediately without queueing - /* If we're ifdefed out, we have to start async requests. Sync requests - * will just return immediately without any delay for power. - */ - if (isSync == kAsync) { - (void)standardAsyncReadWriteExecute(cx); /* execute the async IO */ - } -#else - struct queue *q; - - /* First, we enqueue the request to ensure sequencing with respect - * to other commands that may already be in the queue. - */ - - q = &_powerQueue; - - cx->next = NULL; - cx->state = kAwaitingPower; - - IOLockLock(q->lock); - - if (q->head == NULL) { /* empty queue */ - q->head = cx; - q->tail = q->head; - - } else { /* not empty; add after tail */ - q->tail->next = cx; - q->tail = cx; - } - - /* If the command is synchronous, start by assuming we'll have to sleep - * awaiting power (and subsequent dequeuing). If, however, power is already - * right, then dequeuCommands will unlock the lock and we will continue, - * returning inline to the call site, exactly as if we were awakened. - * - * An async request will call dequeueCommands and always return immediately. - */ - - IOLockUnlock(q->lock); - - /* Now we try to dequeue pending commands if the power's right. */ - - dequeueCommands(); - - /* If we're synchronous, we'll wait here till dequeued. If we were - * dequeued above (and unlocked), then we'll return to allow the - * caller to continue with the command execution. - */ - - if (isSync) { - cx->sync->wait(false); /* waits here till awakened */ - } -#endif //DISKPM -} - -IOReturn -IOBasicSCSI::reportBlockSize(UInt64 *blockSize) -{ - IOReturn result; - - *blockSize = 0; - result = kIOReturnSuccess; - - if (_readCapDone == false) { - result = doReadCapacity(&_blockSize,&_maxBlock); - _readCapDone = true; - } - - if (result == kIOReturnSuccess) { - *blockSize = _blockSize; - } - - return(result); -} - -IOReturn -IOBasicSCSI::reportEjectability(bool *isEjectable) -{ - *isEjectable = true; /* default: if it's removable, it's ejectable */ - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::reportLockability(bool *isLockable) -{ - *isLockable = true; /* default: if it's removable, it's lockable */ - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::reportMaxReadTransfer (UInt64 blocksize,UInt64 *max) -{ - *max = blocksize * 65536; /* max blocks in a SCSI transfer */ - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::reportMaxValidBlock(UInt64 *maxBlock) -{ - IOReturn result; - - *maxBlock = 0; - result = kIOReturnSuccess; - - if (_readCapDone == false) { - result = doReadCapacity(&_blockSize,&_maxBlock); - _readCapDone = true; - } - - if (result == kIOReturnSuccess) { - *maxBlock = _maxBlock; - } - return(result); -} - -IOReturn -IOBasicSCSI::reportMaxWriteTransfer(UInt64 blocksize,UInt64 *max) -{ - *max = blocksize * 65536; /* max blocks in a SCSI transfer */ - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::reportPollRequirements(bool *pollRequired,bool *pollIsExpensive) -{ - *pollIsExpensive = false; - *pollRequired = _removable; /* for now, all removables need polling */ - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::reportRemovability(bool *isRemovable) -{ - if (_inqLen > 0) { /* inquiry byte exists to check */ - if (_inqBuf[1] & 0x80) { /* it's removable */ - *isRemovable = true; - _removable = true; - } else { /* it's not removable */ - *isRemovable = false; - _removable = false; - } - } else { /* no byte? call it nonremovable */ - *isRemovable = false; - } - - return(kIOReturnSuccess); -} - -/* Issue a Mode Sense to get the Mode Parameter Header but no pages. - * Since we're only interested in the Mode Parameter Header, we just - * issue a standard SCSI-1 6-byte command, nothing fancy. - */ -IOReturn -IOBasicSCSI::reportWriteProtection(bool *writeProtected) -{ - struct context *cx; - struct IOModeSensecdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - SCSIResults scsiResults; - UInt8 *buf; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(SCSICDBInfo) ); - - c = (struct IOModeSensecdb *)&scsiCDB.cdb; - c->opcode = SOP_MODESENSE; - c->lunbits = 0; - c->pagecode = 0 | 0x01; /* get current settings; any page will work */ - c->reserved = 0; - c->len = kModeSenseSize; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 6; - - req->setCDB( &scsiCDB ); - req->setPointers( cx->senseDataDesc, sizeof(SCSISenseData), false, true ); - - req->setTimeout( 30000 ); - - result = allocateTempBuffer(&buf,kModeSenseSize); - - if (result == kIOReturnSuccess) { - - cx->memory = IOMemoryDescriptor::withAddress((void *)buf, - kModeSenseSize, - kIODirectionIn); - - req->setPointers( cx->memory, kModeSenseSize, false ); - - queueCommand(cx,kSync,getReportWriteProtectionPowerState()); /* queue the op, sleep awaiting power */ - - result = simpleSynchIO(cx); - - if (result == kIOReturnUnderrun) { - cx->scsireq->getResults( &scsiResults ); - if (scsiResults.bytesTransferred >= 4) - result = kIOReturnSuccess; - } - - if (result == kIOReturnSuccess) { - if (buf[2] & 0x80) { - *writeProtected = true; - } else { - *writeProtected = false; - } - } - - deleteTempBuffer(buf,kModeSenseSize); - } - - deleteContext(cx); - - return(result); -} - -/* Issue a simple, asynchronous SCSI operation. The caller's supplied context - * contains a SCSI command and Memory Descriptor. The caller is responsible - * for deleting the context. - */ - -IOReturn -IOBasicSCSI::simpleAsynchIO(struct IOBasicSCSI::context *cx) -{ - IOSCSICommand *req; - IOReturn result; - - if (cx == NULL) { /* safety check */ - return(kIOReturnNoMemory); - } - - /* Set completion to return to genericCompletion: */ - - req = cx->scsireq; - req->setCallback( (void *)this, (CallbackFn)IOBasicSCSI_gc_glue, (void *)cx ); - - cx->state = kSimpleSynchIO; - - /* Start the scsi request: */ - - result = req->execute(); - - if (result == true ) { - result = req->getResults((SCSIResults *) 0); - } - - return(result); -} - -/* Issue a simple, synchronous SCSI operation. The caller's supplied context - * contains a SCSI command and Memory Descriptor. The caller is responsible - * for deleting the context. - */ - -IOReturn -IOBasicSCSI::simpleSynchIO(struct context *cx) -{ - IOSCSICommand *req; - IOReturn result; - - if (cx == NULL) { /* safety check */ - return(kIOReturnNoMemory); - } - - /* Set completion to return to genericCompletion: */ - - req = cx->scsireq; - req->setCallback( (void *)this, (CallbackFn)IOBasicSCSI_gc_glue, (void *)cx ); - - cx->state = kSimpleSynchIO; - -/** - IOLog("%s[IOBasicSCSI]::simpleSynchIO; issuing SCSI cmd %02x\n", - getName(),req->cdb.byte[0]); -**/ - /* Start the scsi request: */ - - //IOLog("IOBasicSCSI::simpleSynchIO, lock initted, calling SCSI\n"); - - result = req->execute(); - - if (result == true ) { - -// IOLog("IOBasicSCSI::simpleSynchIO, SCSI req accepted\n"); - - /* Wait for it to complete by attempting to acquire a read-lock, which - * will block until the write-lock is released by the completion routine. - */ - - cx->sync->wait(false); /* waits here till unlocked at completion */ - - /* We're back: */ - - result = req->getResults((SCSIResults *) 0); - -/** - if ((result != kIOReturnSuccess) ) { - IOLog("%s[IOBasicSCSI]::simpleSynchIO; err '%s' from completed req\n", - getName(),stringFromReturn(result)); - } -**/ - } else { -/** - IOLog("%s[IOBasicSCSI]:simpleSynchIO; err '%s' queueing SCSI req\n", - getName(),stringFromReturn(result)); -**/ - } - -// IOLog("IOBasicSCSI: completed; result '%s'\n",stringFromReturn(result)); - - return(result); -} - -IOReturn -IOBasicSCSI::standardAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - struct context *cx; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - UInt32 reqSenseLength; - UInt32 timeoutSeconds; - UInt8 *cdb; - bool isWrite; - - cx = allocateContext(); - - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - buffer->retain(); /* bump the retain count */ - - cx->memory = buffer; - if (buffer->getDirection() == kIODirectionOut) { - isWrite = true; - } else { - isWrite = false; - } - -/** - IOLog("%s[IOBasicSCSI]::standardAsyncReadWrite; (%s) blk %ld nblks %ld\n", - getName(),(isWrite ? "write" : "read"),block,nblks); -**/ - req = cx->scsireq; - - /* Set completion to return to rwCompletion: */ - cx->completion = completion; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - req->setPointers( buffer, nblks * getBlockSize(), isWrite ); - - req->setCallback( this, IOBasicSCSI_gc_glue, cx ); - - cx->state = kAsyncReadWrite; - - cdb = (UInt8 *) &scsiCDB.cdb; - - /* Allow a subclass to override the creation of the cdb and specify - * other parameters for the operation. - */ - - if (isWrite) { - scsiCDB.cdbFlags |= createWriteCdb(cdb,&scsiCDB.cdbLength, - block,nblks, - &reqSenseLength, - &timeoutSeconds); - - } else { - - scsiCDB.cdbFlags |= createReadCdb(cdb,&scsiCDB.cdbLength, - block,nblks, - &reqSenseLength, - &timeoutSeconds); - } - - req->setCDB( &scsiCDB ); - req->setPointers( cx->senseDataDesc, reqSenseLength, false, true ); - req->setTimeout( timeoutSeconds * 1000 ); - - /* Queue the request awaiting power and return. When power comes up, - * the request will be passed to standardAsyncReadWriteExecute. - */ - queueCommand(cx,kAsync,getReadWritePowerState()); /* queue and possibly wait for power */ - - return(kIOReturnSuccess); -} - -IOReturn -IOBasicSCSI::standardAsyncReadWriteExecute(struct context *cx) -{ - return(cx->scsireq->execute()); -} - -IOReturn -IOBasicSCSI::standardSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - struct context *cx; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - UInt32 reqSenseLength; - UInt32 reqTimeoutSeconds; - UInt8 *cdb; - bool isWrite; - IOReturn result; - - cx = allocateContext(); - - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - cx->memory = buffer; - buffer->retain(); /* bump the retain count */ - - if (buffer->getDirection() == kIODirectionOut) { - isWrite = true; - } else { - isWrite = false; - } - -/** - IOLog("%s[IOBasicSCSI]::standardSyncReadWrite; (%s) blk %ld nblks %ld\n", - getName(),(isWrite ? "write" : "read"),block,nblks); -**/ - - bzero(&scsiCDB,sizeof(scsiCDB)); - - req = cx->scsireq; - req->setPointers(buffer,(nblks * getBlockSize()),isWrite); - - cdb = (UInt8 *)&scsiCDB.cdb; - - /* Allow a subclass to override the creation of the cdb and specify - * other parameters for the operation. - */ - - if (isWrite) { - scsiCDB.cdbFlags |= createWriteCdb(cdb,&scsiCDB.cdbLength, - block,nblks, - &reqSenseLength, - &reqTimeoutSeconds); - - } else { - - scsiCDB.cdbFlags |= createReadCdb(cdb,&scsiCDB.cdbLength, - block,nblks, - &reqSenseLength, - &reqTimeoutSeconds); - } - - - req->setCDB(&scsiCDB); - req->setPointers(cx->senseDataDesc,reqSenseLength,false,true); - req->setTimeout(reqTimeoutSeconds * 1000); - - queueCommand(cx,kSync,getReadWritePowerState()); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); /* issue a simple command */ - - deleteContext(cx); - return(result); -} - -bool -IOBasicSCSI::start(IOService *provider) -{ - bool result; - - _busResetContext = allocateContext(); - if (_busResetContext == NULL) { - return(false); - } - _busResetContext->state = kHandlingRecoveryAfterBusReset; - _busResetRecoveryInProgress = false; - - _unitAttentionContext = allocateContext(); - if (_unitAttentionContext == NULL) { - return(false); - } - _unitAttentionContext->state = kHandlingUnitAttention; - _unitAttentionRecoveryInProgress = false; - - result = provider->open(this,0,0); /* set up to receive message() notifications */ - if (result != true) { - IOLog("open result is false\n"); - } - - return(true); -} - -char * -IOBasicSCSI::stringFromState(stateValue state) -{ - static char *stateNames[] = { - "kNone", - "kAsyncReadWrite", - "kSimpleSynchIO", - "kHandlingUnitAttention", - "khandlingRecoveryAfterBusReset" - }; - - if (state < 0 || state > kMaxValidState) { - return("invalid"); - } - - return(stateNames[state]); -} diff --git a/iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp b/iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp deleted file mode 100644 index c74ec25e8..000000000 --- a/iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/IOLib.h> -#include <IOKit/IOReturn.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/scsi/IOSCSIHDDrive.h> -#include <IOKit/storage/scsi/IOSCSIHDDriveNub.h> - -#define super IOBasicSCSI -OSDefineMetaClassAndStructors(IOSCSIHDDrive,IOBasicSCSI) - -IOReturn -IOSCSIHDDrive::allocateFormatBuffer(UInt8 **buf,UInt32 *len) -{ - /* The default implementation uses no buffer. */ - - *buf = 0; - *len = 0; - return(kIOReturnSuccess); -} - -UInt8 -IOSCSIHDDrive::composeFormatBuffer(UInt8 * /* buf */,UInt32 /* buflen */) -{ - return(0); /* default: no fmtdata buffer to transfer */ -} - -OSDictionary * -IOSCSIHDDrive::constructDeviceProperties(void) -{ - OSDictionary *propTable; - OSData *prop; - char *typeString; - - propTable = OSDictionary::withCapacity(6); - - if (propTable) { - - prop = OSData::withBytes((void *)(&_vendor),strlen(_vendor)); - if (prop) { - propTable->setObject("vendor", prop); - } - - prop = OSData::withBytes((void *)(&_product),strlen(_product)); - if (prop) { - propTable->setObject("product", prop); - } - - prop = OSData::withBytes((void *)(&_rev),strlen(_rev)); - if (prop) { - propTable->setObject("revision", prop); - } - - typeString = (char *)getDeviceTypeName(); - prop = OSData::withBytes((void *)(typeString),strlen(typeString)); - if (prop) { - propTable->setObject("device-type", prop); - } - -#ifdef xxx - prop = OSData::withBytes((void *)(&_removable),sizeof(bool)); - if (prop) { - propTable->setObject("removable", prop); - } - - prop = OSData::withBytes((void *)(&_ejectable),sizeof(bool)); - if (prop) { - propTable->setObject("ejectable", prop); - } -#endif //xxx - - } - - return(propTable); -} - -UInt32 -IOSCSIHDDrive::createFormatCdb(UInt64 /* byteCapacity */, - UInt8 *cdb,UInt32 *cdbLength, - UInt8 buf[],UInt32 bufLen, - UInt32 *maxAutoSenseLength,UInt32 *timeoutSeconds) -{ - struct IOFormatcdb *c; - UInt8 formatControls; /* CmpLst & Defect List Format bits */ - - c = (struct IOFormatcdb *)cdb; - - c->opcode = kIOSCSICommandFormatUnit; - c->lunbits = 0; - c->vendor = 0; - c->interleave_msb = 0; - c->interleave_lsb = 0; - c->ctlbyte = 0; - - *cdbLength = 6; - - /* If we are to use a format buffer, set it up: */ - - if (buf != NULL) { - formatControls = composeFormatBuffer(buf,bufLen); - c->lunbits |= (formatControls | 0x10); /* data transfer will occur */ - } - - *maxAutoSenseLength = sizeof(SCSISenseData); /* do the sense */ - *timeoutSeconds = 0; /* infinitely long time */ - - return(0); -} - -IOService * -IOSCSIHDDrive::createNub(void) -{ - IOService *nub; - -// IOLog("%s[IOSCSIHDDrive]::createNub\n",getName()); - - /* Instantiate a nub so a generic driver can match above us. */ - - nub = instantiateNub(); - if (nub == NULL) { - IOLog("%s[IOSCSIHDDrive]::createNub; nub didn't instantiate\n",getName()); - return(NULL); - } - - nub->init(); - - if (!nub->attach(this)) { - IOPanic("IOSCSIHDDrive::createNub; couldn't attach IOSCSIHDDriveNub"); - } - - nub->registerService(); - - return(nub); -} - -void -IOSCSIHDDrive::deleteFormatBuffer(UInt8 * /* buf */, UInt32 /* buflen */) -{ - /* The default implementation has no buffer to free. */ -} - -bool -IOSCSIHDDrive::deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 * /*score*/) -{ - if ((_inqBuf[0] & 0x1f) == kIOSCSIDeviceTypeDirectAccess) { - return(true); - } else { - return(false); /* we don't handle other devices */ - } -} - -IOReturn -IOSCSIHDDrive::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - return(standardAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSIHDDrive::doEjectMedia(void) -{ - /* Spin down, eject, and leave power alone: */ - - return(doStartStop(false,true,IOStartStopcdb::P_NOCHANGE)); -} - -IOReturn -IOSCSIHDDrive::doFormatMedia(UInt64 byteCapacity) -{ - return(standardFormatMedia(byteCapacity)); -} - -UInt32 -IOSCSIHDDrive::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - if ((capacities != NULL) && (capacitiesMaxCount > 0)) { - *capacities = _blockSize * (_maxBlock + 1); - return(1); - } else { - return(0); - } -} - -/* We issue a simple Prevent/Allow command to lock or unlock the media: */ -IOReturn -IOSCSIHDDrive::doLockUnlockMedia(bool doLock) -{ - struct context *cx; - struct IOPrevAllowcdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IOPrevAllowcdb *)&scsiCDB.cdb; - - c->opcode = kIOSCSICommandPreventAllow; - c->lunbits = 0; - c->reserved1 = 0; - c->reserved2 = 0; - - if (doLock) { - c->prevent = 0x01; /* prevent removal from device */ - } else { - c->prevent = 0x00; /* allow removal from device */ - } - - c->ctlbyte = 0; - - scsiCDB.cdbLength = 6; - - req->setCDB( &scsiCDB ); - - cx->memory = 0; - - req->setPointers( cx->memory, 0, false ); - - queueCommand(cx,kSync,getLockUnlockMediaPowerState()); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSIHDDrive::doStart(void) -{ - return(doStartStop(true,false,IOStartStopcdb::P_ACTIVE)); -} - -IOReturn -IOSCSIHDDrive::doStop(void) -{ - return(doStartStop(false,false,IOStartStopcdb::P_NOCHANGE)); -} - -IOReturn -IOSCSIHDDrive::doStartStop(bool start,bool loadEject,UInt8 powerCondition) -{ - struct context *cx; - struct IOStartStopcdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - UInt32 powerLevel; /* what power level we need to be in */ - - /* Issue a Start/Stop Unit command. */ - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - powerLevel = getStopPowerState(); /* assume we're spinning down */ - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(SCSICDBInfo) ); - - c = (struct IOStartStopcdb *)&scsiCDB.cdb; - c->opcode = kIOSCSICommandStartStopUnit; - c->lunImmed = 0; - c->reserved1 = 0; - c->reserved2 = 0; - c->controls = powerCondition; - c->controls = 0; /* xxx powerCondition is a SCSI-3 thing */ - if (loadEject) { - c->controls |= IOStartStopcdb::C_LOEJ; - powerLevel = getEjectPowerState(); /* let subclass decide what we need */ - }; - if (start) { - c->controls |= IOStartStopcdb::C_SPINUP; - powerLevel = getStartPowerState(); - } - c->ctlbyte = 0; - - scsiCDB.cdbLength = 6; - - req->setCDB( &scsiCDB ); - req->setTimeout( 30000 ); - - cx->memory = 0; - - req->setPointers( cx->memory, 0, false ); - - queueCommand(cx,kSync,powerLevel); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); - - deleteContext(cx); - return(result); -} - -IOReturn -IOSCSIHDDrive::doSynchronizeCache(void) -{ - return(standardSynchronizeCache()); -} - -IOReturn -IOSCSIHDDrive::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - return(standardSyncReadWrite(buffer,block,nblks)); -} - -const char * -IOSCSIHDDrive::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeGeneric); -} - -UInt32 -IOSCSIHDDrive::getEjectPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getExecuteCDBPowerState(void) -{ - return(kAllOn); -} - -UInt32 -IOSCSIHDDrive::getFormatMediaPowerState(void) -{ - return(kAllOn); -} - -UInt32 -IOSCSIHDDrive::getInitialPowerState(void) -{ - return(kAllOn); -} - -UInt32 -IOSCSIHDDrive::getInquiryPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getLockUnlockMediaPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getReadCapacityPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getReadWritePowerState(void) -{ - return(kAllOn); -} - -UInt32 -IOSCSIHDDrive::getReportWriteProtectionPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getStartPowerState(void) -{ - return(kElectronicsOn); -} - -UInt32 -IOSCSIHDDrive::getStopPowerState(void) -{ - return(kElectronicsOn); /* we don't have to be spinning to spin down */ -} - -UInt32 -IOSCSIHDDrive::getSynchronizeCachePowerState(void) -{ - return(kAllOn); -} - -UInt32 -IOSCSIHDDrive::getTestUnitReadyPowerState(void) -{ - return(kElectronicsOn); -} - -bool -IOSCSIHDDrive::init(OSDictionary * properties) -{ - _mediaPresent = false; - _startStopDisabled = false; - - return(super::init(properties)); -} - -IOService * -IOSCSIHDDrive::instantiateNub(void) -{ - IOService *nub; - - /* Instantiate a nub so a generic driver can match above us. */ - - nub = new IOSCSIHDDriveNub; - return(nub); -} - -bool -IOSCSIHDDrive::powerTickle(UInt32 desiredState) -{ - return(activityTickle(kIOPMSuperclassPolicy1,desiredState)); -} - -IOReturn -IOSCSIHDDrive::reportMediaState(bool *mediaPresent,bool *changed) -{ - struct context *cx; - struct IOTURcdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - SCSIResults scsiResults; - IOReturn result; - UInt8 status; - UInt8 senseKey; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IOTURcdb *)&scsiCDB.cdb; - c->opcode = kIOSCSICommandTestUnitReady; - c->lunbits = 0; - c->reserved1 = 0; - c->reserved2 = 0; - c->reserved3 = 0; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 6; - - req->setCDB( &scsiCDB ); - req->setPointers( cx->senseDataDesc, 255, false, true ); - - req->setTimeout( 5000 ); - - cx->memory = 0; - - req->setPointers( cx->memory, 0, false ); - -/** - IOLog("IOSCSIHDDrive::reportMediaState: mp=%08x,ch=%08x\n", - (int)mediaPresent,(int)changed); - IOLog("IOSCSIHDDrive::reportMediaState: doing TUR\n"); -**/ - - queueCommand(cx,kSync,getTestUnitReadyPowerState()); - result = simpleSynchIO(cx); - - req->getResults( &scsiResults ); - - status = scsiResults.scsiStatus; - -/** - IOLog("%s[IOSCSIHDDrive]::reportMediaState; result=%s, status=%02x,sense=%02x\n", - getName(),stringFromReturn(result),status,cx->senseData->senseKey - ); -**/ - - if (result == kIOReturnSuccess) { /* TUR succeeded; device is ready */ - - *mediaPresent = true; - *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */ - _mediaPresent = true; /* remember current state */ - result = kIOReturnSuccess; - - } else { /* TUR failed; check sense key */ - - if ( scsiResults.requestSenseDone == true ) { - senseKey = cx->senseData->senseKey; - - if (senseKey == 0x02) { /* device says "not ready" */ - *mediaPresent = false; - *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */ - _mediaPresent = false; /* remember current state */ - result = kIOReturnSuccess; - - } else { /* funky sense key? forget it. */ - - *mediaPresent = false; - *changed = (*mediaPresent != _mediaPresent); /* report if it's changed */ - _mediaPresent = false; /* remember current state */ - result = kIOReturnIOError; -/** - IOLog("%s[IOSCSIHDDrive]:: reportMediaState; funky sense key %d\n", - getName(),senseKey); - **/ - } - } else { /* autosense not done! */ - - /* This condition has been observed with the Matsushita PD-2 DVD-RAM on the - * Curio (external) bus on an 8500. I can't figure out why we get a good status - * but no autosense (after going through Unit-Attention.) We ignore the current - * media check and it'll operate normally on the next pass through. - */ -/** - IOLog("%s[IOSCSIHDDrive]:: reportMediaState; autosense not done: ",getName()); - IOLog("result = '%s', status = %d, senseKey = %d\n", - stringFromReturn(result),status,cx->senseData->senseKey); -**/ - *mediaPresent = _mediaPresent; - *changed = false; - result = kIOReturnSuccess; - } - } - - if (*changed && *mediaPresent) { - _readCapDone = false; - _blockSize = 0; - _maxBlock = 0; - } - - deleteContext(cx); - -#ifndef DISKPM - if (*changed && *mediaPresent) - doStart(); -#endif - -/** - if (result != kIOReturnSuccess) { - IOLog("%s[IOSCSIHDDrive]:: reportMediaState; returning %d %x '%s'\n", - getName(),result,result,stringFromReturn(result)); - } -**/ - return(result); -} - -IOReturn -IOSCSIHDDrive::restoreElectronicsState(void) -{ - return(kIOReturnSuccess); -} - -/* The standard completion for a doAsyncReadWrite operation. We fire it - * up to our target, the generic driver. - */ -void -IOSCSIHDDrive::RWCompletion(struct context *cx) -{ - SCSIResults scsiResults; - - cx->scsireq->getResults( &scsiResults ); - - IOStorage::complete(cx->completion, - scsiResults.returnCode, - scsiResults.bytesTransferred); - - - /* Attempt to dequeue and execute any waiting commands: */ - - dequeueCommands(); -} - -IOReturn -IOSCSIHDDrive::saveElectronicsState(void) -{ - return(kIOReturnSuccess); -} - -static IOPMPowerState ourPowerStates[kNumberOfPowerStates] = { - {1,IOPMNotAttainable,0,0,0,0,0,0,0,0,0,0}, /* state 00 kAllOff */ - {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0}, /* state 01 kElectronicsOn */ - {1,0,0,IOPMPowerOn,0,0,0,0,0,0,0,0} /* state 02 kAllOn */ -}; - -IOReturn -IOSCSIHDDrive::standardFormatMedia(UInt64 byteCapacity) -{ - struct context *cx; - UInt8 *fmtbuf; - IOReturn result; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - UInt32 transferLength; - UInt32 senseLength; - UInt32 timeoutSeconds; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - - /* Allow a subclass to construct the cdb and return an optional - * memory buffer address for defect lists, etc. - */ - - result = allocateFormatBuffer(&fmtbuf,&transferLength); - if (result != kIOReturnSuccess) { - return(result); - } - - bzero( &scsiCDB, sizeof(scsiCDB) ); - - scsiCDB.cdbFlags |= createFormatCdb(byteCapacity,(UInt8 *)&scsiCDB.cdb,&scsiCDB.cdbLength, - fmtbuf,transferLength, - &senseLength, - &timeoutSeconds); - - req->setCDB( &scsiCDB ); - req->setPointers( cx->senseDataDesc, senseLength, false, true ); - req->setTimeout( timeoutSeconds * 1000 ); - - /* If we have a buffer to transfer, create a Memory Descriptor for it: */ - - if ((fmtbuf != NULL) && (transferLength != 0)) { - cx->memory = IOMemoryDescriptor::withAddress((void *)fmtbuf, - transferLength, - kIODirectionOut); - } - - req->setPointers( cx->memory, transferLength, true ); - queueCommand(cx,kSync,getFormatMediaPowerState()); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); /* issue a simple command */ - - /* Free the format buffer, if any: */ - - deleteFormatBuffer(fmtbuf,transferLength); - - deleteContext(cx); - - return(result); -} - -IOReturn -IOSCSIHDDrive::standardSynchronizeCache(void) -{ - struct context *cx; - struct IOSyncCachecdb *c; - IOSCSICommand *req; - SCSICDBInfo scsiCDB; - IOReturn result; - - cx = allocateContext(); - if (cx == NULL) { - return(kIOReturnNoMemory); - } - - req = cx->scsireq; - bzero( &scsiCDB, sizeof(scsiCDB) ); - - c = (struct IOSyncCachecdb *)&scsiCDB.cdb; - - c->opcode = kIOSCSICommandSynchronizeCache; - c->lunbits = 0; - c->lba_3 = 0; /* if zero, start at block zero */ - c->lba_2 = 0; - c->lba_1 = 0; - c->lba_0 = 0; - c->reserved = 0; - c->nblks_msb = 0; /* if zero, do all blocks */ - c->nblks_lsb = 0; - c->ctlbyte = 0; - - scsiCDB.cdbLength = 10; - - req->setCDB( &scsiCDB ); - - cx->memory = 0; - - req->setPointers( cx->memory, 0, false ); - - /* We assume there will be some data in the drive's cache, so we force the - * drive to be running before we issue this command. - */ - - queueCommand(cx,kSync,getSynchronizeCachePowerState()); /* queue the operation, sleep awaiting power */ - - result = simpleSynchIO(cx); - - deleteContext(cx); - - return(result); -} - -bool -IOSCSIHDDrive::start(IOService *provider) -{ - IOService *nub; - - if (!super::start(provider)) { - return(false); - } - -// IOLog("%s[IOSCSIHDDrive]::start\n",getName()); - - /* Initialize and set up to perform Power Management: */ - - PMinit(); - _restoreState = false; -#ifdef notyet // don't register for PM yet till we handle queuing requests! - IOPMRegisterDevice(pm_vars->ourName,this); // join the power management tree -#endif - registerPowerDriver(this,ourPowerStates,kNumberOfPowerStates); // export power states - - nub = createNub(); - if (nub == NULL) { - return(false); - } else { - return(true); - } -} - -// ********************************************************************************** -// maxCapabilityForDomainState -// -// This simple device needs only power. If the power domain is supplying -// power, the disk can go to its highest state. If there is no power -// it can only be in its lowest state, which is off. -// ********************************************************************************** - -unsigned long -IOSCSIHDDrive::maxCapabilityForDomainState(IOPMPowerFlags domainState) -{ - if (domainState & IOPMPowerOn) { - return(kAllOn); - } else { - return(kAllOff); - } -} - -// ********************************************************************************** -// powerStateForDomainState -// -// The power domain may be changing state. If power is ON in its new -// state, we will be on, too. If domain power is OFF, we are off. -// ********************************************************************************** -unsigned long -IOSCSIHDDrive::powerStateForDomainState(IOPMPowerFlags domainState) -{ - if (domainState & IOPMPowerOn) { - return(kAllOn); /* xxx might be kElectronicsOn if drive not spun up */ - } else { - return(kAllOff); - } -} - -// ********************************************************************************** -// initialPowerStateForDomainState -// -// Our parent wants to know what our initial power state is. If power is ON in the -// domain, we are in state kElectronicsOn or kAllOn. If domain power is OFF, we are off. -// ********************************************************************************** -unsigned long -IOSCSIHDDrive::initialPowerStateForDomainState(IOPMPowerFlags domainState) -{ - if (domainState & IOPMPowerOn) { - return(getInitialPowerState()); /* report whether it's spinning on startup */ - } else { - return(kAllOff); - } -} - -// ********************************************************************************** -// setPowerState -// -// Someone has decided to change the disk state. We perform the change here. -// ********************************************************************************** -IOReturn -IOSCSIHDDrive::setPowerState(unsigned long powerStateOrdinal,IOService *) -{ - IOReturn result; - - result = kIOReturnSuccess; - - /* All we do in the default implementation is spin up and down. If the drive reports an - * error to a start/stop command, we don't bother attempting to issue those commands again. - * - * xxx Question: What should we return? Success? or an error meaning "we didn't do it!" - */ - switch (powerStateOrdinal) { - - case kElectronicsOn : /* spin down if necessary */ - if (pm_vars->myCurrentState == kAllOn) { - if (!_startStopDisabled) { - result = doStop(); - if (result != kIOReturnSuccess) { - _startStopDisabled = true; - result = kIOReturnSuccess; - } - } - } - break; - - case kAllOn : /* spin up if necessary */ - if (pm_vars->myCurrentState == kElectronicsOn) { - if (!_startStopDisabled) { - result = doStart(); - if (result != kIOReturnSuccess) { - _startStopDisabled = true; - result = kIOReturnSuccess; - } - } - } - break; - - default: /* we don't do other states */ - result = kIOReturnSuccess; - break; - - } - - return(result); -} - -// ********************************************************************************** -/* We get called here as an advisory that the power state will change. If we are coming up - * from the all-off state, remember to restore the electronics state when we later power up. - * If we are powering-down the electronics, save any required state now. - */ -IOReturn -IOSCSIHDDrive::powerStateWillChangeTo(unsigned long,unsigned long stateOrdinal,IOService *) -{ - if ((pm_vars->myCurrentState == kAllOff) && - (stateOrdinal > kAllOff)) { /* we're powering up from all-off */ - _restoreState = true; - } - - if ((stateOrdinal == kAllOff) && - (pm_vars->myCurrentState > kAllOff)) { /* we're powering down to all-off */ - saveElectronicsState(); - } - - return(IOPMAckImplied); -} - -// ********************************************************************************** -/* We get called here when power has successfully changed state. */ -IOReturn -IOSCSIHDDrive::powerStateDidChangeTo(unsigned long,unsigned long stateOrdinal,IOService*) -{ - IOReturn result; - - /* If we must restore the electronics state, do it now. */ - - if (_restoreState) { - result = restoreElectronicsState(); - _restoreState = false; - } - - /* If we have powered up into a state that can execute commands, release any queued - * requests that were awaiting the power change. - */ - - if (stateOrdinal > kAllOff) { - dequeueCommands(); - } - - return IOPMAckImplied; -} diff --git a/iokit/Families/IOSCSIHDDrive/IOSCSIHDDriveNub.cpp b/iokit/Families/IOSCSIHDDrive/IOSCSIHDDriveNub.cpp deleted file mode 100644 index c43d09970..000000000 --- a/iokit/Families/IOSCSIHDDrive/IOSCSIHDDriveNub.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/IOLib.h> -#include <IOKit/storage/scsi/IOSCSIHDDriveNub.h> -#include <IOKit/storage/scsi/IOSCSIHDDrive.h> - -#define super IOBlockStorageDevice -OSDefineMetaClassAndStructors(IOSCSIHDDriveNub,IOBlockStorageDevice) - -bool -IOSCSIHDDriveNub::attach(IOService * provider) -{ -// IOLog("IOSCSIHDDriveNub: attach\n"); - - if (!super::attach(provider)) { - return(false); - } - -// IOLog("IOSCSIHDDriveNub: attach; casting provider\n"); - _provider = OSDynamicCast(IOSCSIHDDrive,provider); - if (_provider == NULL) { - IOLog("IOSCSIHDDriveNub: attach; wrong provider type!\n"); - return(false); - } else { -// IOLog("IOSCSIHDDriveNub: attach; provider OK\n"); - return(true); - } -} - -void IOSCSIHDDriveNub::detach(IOService * provider) -{ - if( _provider == provider) - _provider = 0; - - super::detach( provider ); -} - -IOReturn -IOSCSIHDDriveNub::doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) -{ - return(_provider->doAsyncReadWrite(buffer,block,nblks,completion)); -} - -IOReturn -IOSCSIHDDriveNub::doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks) -{ - return(_provider->doSyncReadWrite(buffer,block,nblks)); -} - -IOReturn -IOSCSIHDDriveNub::doEjectMedia(void) -{ - return(_provider->doEjectMedia()); -} - -IOReturn -IOSCSIHDDriveNub::doFormatMedia(UInt64 byteCapacity) -{ - return(_provider->doFormatMedia(byteCapacity)); -} - -UInt32 -IOSCSIHDDriveNub::doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return(_provider->doGetFormatCapacities(capacities,capacitiesMaxCount)); -} - -IOReturn -IOSCSIHDDriveNub::doLockUnlockMedia(bool doLock) -{ - return(_provider->doLockUnlockMedia(doLock)); -} - -IOReturn -IOSCSIHDDriveNub::doSynchronizeCache(void) -{ - return(_provider->doSynchronizeCache()); -} - -char * -IOSCSIHDDriveNub::getVendorString(void) -{ - return(_provider->getVendorString()); -} - -char * -IOSCSIHDDriveNub::getProductString(void) -{ - return(_provider->getProductString()); -} - -char * -IOSCSIHDDriveNub::getRevisionString(void) -{ - return(_provider->getRevisionString()); -} - -char * -IOSCSIHDDriveNub::getAdditionalDeviceInfoString(void) -{ - return(_provider-> getAdditionalDeviceInfoString()); -} - -IOReturn -IOSCSIHDDriveNub::reportBlockSize(UInt64 *blockSize) -{ - return(_provider->reportBlockSize(blockSize)); -} - -IOReturn -IOSCSIHDDriveNub::reportEjectability(bool *isEjectable) -{ - return(_provider->reportEjectability(isEjectable)); -} - -IOReturn -IOSCSIHDDriveNub::reportLockability(bool *isLockable) -{ - return(_provider->reportLockability(isLockable)); -} - -IOReturn -IOSCSIHDDriveNub::reportPollRequirements(bool *pollIsRequired,bool *pollIsExpensive) -{ - return(_provider->reportPollRequirements(pollIsRequired,pollIsExpensive)); -} - -IOReturn -IOSCSIHDDriveNub::reportMaxReadTransfer (UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxReadTransfer(blockSize,max)); -} - -IOReturn -IOSCSIHDDriveNub::reportMaxValidBlock(UInt64 *maxBlock) -{ - return(_provider->reportMaxValidBlock(maxBlock)); -} - -IOReturn -IOSCSIHDDriveNub::reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max) -{ - return(_provider->reportMaxWriteTransfer(blockSize,max)); -} - -IOReturn -IOSCSIHDDriveNub::reportMediaState(bool *mediaPresent,bool *changed) -{ - return(_provider->reportMediaState(mediaPresent,changed)); -} - -IOReturn -IOSCSIHDDriveNub::reportRemovability(bool *isRemovable) -{ - return(_provider->reportRemovability(isRemovable)); -} - -IOReturn -IOSCSIHDDriveNub::reportWriteProtection(bool *isWriteProtected) -{ - return(_provider->reportWriteProtection(isWriteProtected)); -} diff --git a/iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp b/iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp index bff8be4bc..1a7d18c8c 100644 --- a/iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp +++ b/iokit/Families/IOSCSIParallel/IOSCSIParallelCommand.cpp @@ -421,8 +421,8 @@ void IOSCSIParallelCommand::zeroCommand() senseData = 0; origCommand = 0; bzero(&completionInfo, sizeof(completionInfo)); - if (dataArea && dataSize) - bzero( dataArea, dataSize ); +// if (dataArea && dataSize) +// bzero( dataArea, dataSize ); // commandPrivateData = <same-as-before>; // clientData = <same-as-before>; sequenceNumber = 0; diff --git a/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.cpp b/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.cpp index bdd9d626f..0f691f745 100644 --- a/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.cpp +++ b/iokit/Families/IOSCSIParallel/IOSCSIParallelDevice.cpp @@ -28,6 +28,7 @@ #include <IOKit/scsi/IOSCSIParallelInterface.h> #include <IOKit/IOKitKeys.h> +#include <IOKit/system.h> #undef super #define super IOSCSIDevice @@ -161,7 +162,7 @@ IOReturn IOSCSIParallelDevice::probeTargetLun() goto probeError; } - size = kDefaultInquirySize; + size = sizeof(SCSIInquiry); if ( !(inqData = (SCSIInquiry *)IOMalloc(size)) ) { @@ -1315,17 +1316,20 @@ bool IOSCSIParallelDevice::checkTag( IOSCSIParallelCommand *scsiCmd ) { break; } + + /* If the command is untagged, then don't allocate a tag nor + * send the untagged command as a simple-tagged command. + */ + if ( scsiCDB.cdbTagMsg == 0 ) + { + break; + } if ( allocTag( &scsiCDB.cdbTag ) == false ) { rc = false; break; } - - if ( scsiCDB.cdbTagMsg == 0 ) - { - scsiCDB.cdbTagMsg = kSCSIMsgSimpleQueueTag; - } } while ( 0 ); @@ -1848,6 +1852,7 @@ OSDictionary *IOSCSIParallelDevice::createProperties() OSObject *regObj; char tmpbuf[81]; char *d; + char unit[10]; propTable = OSDictionary::withCapacity(kSCSIMaxProperties); if ( propTable == NULL ) @@ -1867,6 +1872,9 @@ OSDictionary *IOSCSIParallelDevice::createProperties() goto createprop_error; } + sprintf(unit,"%x",targetLun.target); + setLocation(unit); + regObj = (OSObject *)OSNumber::withNumber(targetLun.lun,32); if ( addToRegistry( propTable, regObj, kSCSIPropertyLun ) != true ) { diff --git a/iokit/Families/IOStorage/IOApplePartitionScheme.cpp b/iokit/Families/IOStorage/IOApplePartitionScheme.cpp deleted file mode 100644 index cf6a91f22..000000000 --- a/iokit/Families/IOStorage/IOApplePartitionScheme.cpp +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOApplePartitionScheme.h> -#include <libkern/OSByteOrder.h> - -#define super IOPartitionScheme -OSDefineMetaClassAndStructors(IOApplePartitionScheme, IOPartitionScheme); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Notes -// -// o the on-disk structure's fields are: 16-bit packed, big-endian formatted -// o the dpme_pblock_start and dpme_pblocks block values are: -// o for media without a driver map: -// o natural block size based -// o for media with a driver map: -// o driver map block size based, unless the driver map block size is 2048 -// and a valid partition entry exists at a 512 byte offset into the disk, -// in which case, assume a 512 byte block size, except for the partition -// entries that lie on a 2048 byte multiple and are one of the following -// types: Apple_Patches, Apple_Driver, Apple_Driver43, Apple_Driver43_CD, -// Apple_Driver_ATA, Apple_Driver_ATAPI; in which case, we assume a 2048 -// byte block size (for the one partition) -// o the dpme_pblock_start block value is relative to the media container -// - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define kIOApplePartitionSchemeContentTable "Content Table" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOApplePartitionScheme::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - // State our assumptions. - - assert(sizeof(dpme) == 512); // (compiler/platform check) - assert(sizeof(DDMap) == 8); // (compiler/platform check) - assert(sizeof(Block0) == 512); // (compiler/platform check) - - // Ask our superclass' opinion. - - if (super::init(properties) == false) return false; - - // Initialize our state. - - _partitions = 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOApplePartitionScheme::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _partitions ) _partitions->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOService * IOApplePartitionScheme::probe(IOService * provider, SInt32 * score) -{ - // - // Determine whether the provider media contains an Apple partition map. - // - - // State our assumptions. - - assert(OSDynamicCast(IOMedia, provider)); - - // Ask superclass' opinion. - - if (super::probe(provider, score) == 0) return 0; - - // Scan the provider media for an Apple partition map. - - _partitions = scan(score); - - return ( _partitions ) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOApplePartitionScheme::start(IOService * provider) -{ - // - // Publish the new media objects which represent our partitions. - // - - IOMedia * partition; - OSIterator * partitionIterator; - - // State our assumptions. - - assert(_partitions); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Attach and register the new media objects representing our partitions. - - partitionIterator = OSCollectionIterator::withCollection(_partitions); - if ( partitionIterator == 0 ) return false; - - while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) - { - if ( partition->attach(this) ) - { - attachMediaObjectToDeviceTree(partition); - - partition->registerService(); - } - } - - partitionIterator->release(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOApplePartitionScheme::stop(IOService * provider) -{ - // - // Clean up after the media objects we published before terminating. - // - - IOMedia * partition; - OSIterator * partitionIterator; - - // State our assumptions. - - assert(_partitions); - - // Detach the media objects we previously attached to the device tree. - - partitionIterator = OSCollectionIterator::withCollection(_partitions); - - if ( partitionIterator ) - { - while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) - { - detachMediaObjectFromDeviceTree(partition); - } - - partitionIterator->release(); - } - - super::stop(provider); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSSet * IOApplePartitionScheme::scan(SInt32 * score) -{ - // - // Scan the provider media for an Apple partition map. Returns the set - // of media objects representing each of the partitions (the retain for - // the set is passed to the caller), or null should no partition map be - // found. The default probe score can be adjusted up or down, based on - // the confidence of the scan. - // - - IOBufferMemoryDescriptor * buffer = 0; - UInt32 bufferReadAt = 0; - UInt32 bufferSize = 0; - UInt32 dpmeBlockSize = 0; - UInt32 dpmeCount = 0; - UInt32 dpmeID = 0; - dpme * dpmeMap = 0; - UInt32 dpmeMaxCount = 0; - bool dpmeOldSchool = false; - Block0 * driverMap = 0; - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - bool mediaIsOpen = false; - OSSet * partitions = 0; - IOReturn status = kIOReturnError; - - // Determine whether this media is formatted. - - if ( media->isFormatted() == false ) goto scanErr; - - // Determine whether this media has an appropriate block size. - - if ( (mediaBlockSize % sizeof(dpme)) ) goto scanErr; - - // Allocate a buffer large enough to hold one map, rounded to a media block. - - bufferSize = IORound(max(sizeof(Block0), sizeof(dpme)), mediaBlockSize); - buffer = IOBufferMemoryDescriptor::withCapacity( - /* capacity */ bufferSize, - /* withDirection */ kIODirectionIn ); - if ( buffer == 0 ) goto scanErr; - - // Allocate a set to hold the set of media objects representing partitions. - - partitions = OSSet::withCapacity(8); - if ( partitions == 0 ) goto scanErr; - - // Open the media with read access. - - mediaIsOpen = media->open(this, 0, kIOStorageAccessReader); - if ( mediaIsOpen == false ) goto scanErr; - - // Read the driver map into our buffer. - - bufferReadAt = 0; - -///m:2333367:workaround:commented:start -// status = media->read(this, bufferReadAt, buffer); -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read(this, bufferReadAt, buffer); -///m:2333367:workaround:added:stop - if ( status != kIOReturnSuccess ) goto scanErr; - - driverMap = (Block0 *) buffer->getBytesNoCopy(); - - // Determine the official block size to use to scan the partition entries. - - dpmeBlockSize = mediaBlockSize; // (natural block size) - - if ( driverMap->sbSig == BLOCK0_SIGNATURE ) - { - dpmeBlockSize = driverMap->sbBlkSize; // (driver map block size) - - // Determine whether we have an old school partition map, where there is - // a partition entry at a 512 byte offset into the disk, even though the - // driver map block size is 2048. - - if ( dpmeBlockSize == 2048 ) - { - if ( bufferSize >= sizeof(Block0) + sizeof(dpme) ) // (in buffer?) - { - dpmeMap = (dpme *) (driverMap + 1); - } - else // (not in buffer) - { - // Read the partition entry at byte offset 512 into our buffer. - - bufferReadAt = sizeof(dpme); - -///m:2333367:workaround:commented:start -// status = media->read(this, bufferReadAt, buffer); -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read(this, bufferReadAt, buffer); -///m:2333367:workaround:added:stop - if ( status != kIOReturnSuccess ) goto scanErr; - - dpmeMap = (dpme *) buffer->getBytesNoCopy(); - } - - // Determine whether the partition entry signature is present. - - if (OSSwapBigToHostInt16(dpmeMap->dpme_signature) == DPME_SIGNATURE) - { - dpmeBlockSize = sizeof(dpme); // (old school block size) - dpmeOldSchool = true; - } - } - - // Increase the probe score when a driver map is detected, since we are - // more confident in the match when it is present. This will eliminate - // conflicts with FDisk when it shares the same block as the driver map. - - *score += 2000; - } - - // Scan the media for Apple partition entries. - - for ( dpmeID = 1, dpmeCount = 1; dpmeID <= dpmeCount; dpmeID++ ) - { - UInt32 partitionBlockSize = dpmeBlockSize; - - // Determine whether we've exhausted the current buffer of entries. - - if ( dpmeID * dpmeBlockSize + sizeof(dpme) > bufferReadAt + bufferSize ) - { - // Read the next partition entry into our buffer. - - bufferReadAt = dpmeID * dpmeBlockSize; - -///m:2333367:workaround:commented:start -// status = media->read(this, bufferReadAt, buffer); -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read(this, bufferReadAt, buffer); -///m:2333367:workaround:added:stop - if ( status != kIOReturnSuccess ) goto scanErr; - } - - dpmeMap = (dpme *) ( ((UInt8 *) buffer->getBytesNoCopy()) + - (dpmeID * dpmeBlockSize) - bufferReadAt ); - - // Determine whether the partition entry signature is present. - - if ( OSSwapBigToHostInt16(dpmeMap->dpme_signature) != DPME_SIGNATURE ) - { - goto scanErr; - } - - // Obtain an accurate number of entries in the partition map. - - if ( !strcmp(dpmeMap->dpme_type, "Apple_partition_map") || - !strcmp(dpmeMap->dpme_type, "Apple_Partition_Map") || - !strcmp(dpmeMap->dpme_type, "Apple_patition_map" ) ) - { - dpmeCount = OSSwapBigToHostInt32(dpmeMap->dpme_map_entries); - dpmeMaxCount = OSSwapBigToHostInt32(dpmeMap->dpme_pblocks); - } - else if ( dpmeCount == 1 ) - { - dpmeCount = OSSwapBigToHostInt32(dpmeMap->dpme_map_entries); - } - - // Obtain an accurate block size for an old school partition map. - - if ( dpmeOldSchool && (dpmeID % 4) == 0 ) - { - if ( !strcmp(dpmeMap->dpme_type, "Apple_Driver" ) || - !strcmp(dpmeMap->dpme_type, "Apple_Driver43" ) || - !strcmp(dpmeMap->dpme_type, "Apple_Driver43_CD" ) || - !strcmp(dpmeMap->dpme_type, "Apple_Driver_ATA" ) || - !strcmp(dpmeMap->dpme_type, "Apple_Driver_ATAPI") || - !strcmp(dpmeMap->dpme_type, "Apple_Patches" ) ) - { - partitionBlockSize = 2048; - } - } - - // Determine whether the partition is corrupt (fatal). - - if ( isPartitionCorrupt( - /* partition */ dpmeMap, - /* partitionID */ dpmeID, - /* partitionBlockSize */ partitionBlockSize ) ) - { - goto scanErr; - } - - // Determine whether the partition is invalid (skipped). - - if ( isPartitionInvalid( - /* partition */ dpmeMap, - /* partitionID */ dpmeID, - /* partitionBlockSize */ partitionBlockSize ) ) - { - continue; - } - - // Create a media object to represent this partition. - - IOMedia * newMedia = instantiateMediaObject( - /* partition */ dpmeMap, - /* partitionID */ dpmeID, - /* partitionBlockSize */ partitionBlockSize ); - - if ( newMedia ) - { - partitions->setObject(newMedia); - newMedia->release(); - } - } - - // Determine whether we ever came accross an Apple_partition_map partition. - - if ( dpmeMaxCount == 0 ) goto scanErr; - - // Release our resources. - - media->close(this); - buffer->release(); - - return partitions; - -scanErr: - - // Release our resources. - - if ( mediaIsOpen ) media->close(this); - if ( partitions ) partitions->release(); - if ( buffer ) buffer->release(); - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOApplePartitionScheme::isPartitionCorrupt( - dpme * /* partition */ , - UInt32 /* partitionID */ , - UInt32 /* partitionBlockSize */ ) -{ - // - // Ask whether the given partition appears to be corrupt. A partition that - // is corrupt will cause the failure of the Apple partition map recognition - // altogether. - // - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOApplePartitionScheme::isPartitionInvalid( dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ) -{ - // - // Ask whether the given partition appears to be invalid. A partition that - // is invalid will cause it to be skipped in the scan, but will not cause a - // failure of the Apple partition map recognition. - // - - IOMedia * media = getProvider(); - UInt64 partitionBase = 0; - UInt64 partitionSize = 0; - - // Compute the relative byte position and size of the new partition. - - partitionBase = OSSwapBigToHostInt32(partition->dpme_pblock_start); - partitionSize = OSSwapBigToHostInt32(partition->dpme_pblocks); - partitionBase *= partitionBlockSize; - partitionSize *= partitionBlockSize; - - // Determine whether the partition is a placeholder. - - if ( partitionSize == 0 ) return true; - - // Determine whether the partition starts at (or past) the end-of-media. - - if ( partitionBase >= media->getSize() ) return true; - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOApplePartitionScheme::instantiateMediaObject( - dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ) -{ - // - // Instantiate a new media object to represent the given partition. - // - - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - UInt64 partitionBase = 0; - char * partitionHint = partition->dpme_type; - bool partitionIsWritable = media->isWritable(); - char * partitionName = partition->dpme_name; - UInt64 partitionSize = 0; - - // Compute the relative byte position and size of the new partition. - - partitionBase = OSSwapBigToHostInt32(partition->dpme_pblock_start); - partitionSize = OSSwapBigToHostInt32(partition->dpme_pblocks); - partitionBase *= partitionBlockSize; - partitionSize *= partitionBlockSize; - - // Clip the size of the new partition if it extends past the end-of-media. - - if ( partitionBase + partitionSize > media->getSize() ) - { - partitionSize = media->getSize() - partitionBase; - } - - // Look up a type for the new partition. - - OSDictionary * hintTable = OSDynamicCast( - /* type */ OSDictionary, - /* instance */ getProperty(kIOApplePartitionSchemeContentTable) ); - - if ( hintTable ) - { - OSString * hintValue = OSDynamicCast( - /* type */ OSString, - /* instance */ hintTable->getObject(partitionHint) ); - - if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy(); - } - - // Look up a name for the new partition. - - while ( *partitionName == ' ' ) { partitionName++; } - - if ( *partitionName == 0 ) partitionName = 0; - - // Determine whether the new partition type is Apple_Free, which we choose - // not to publish because it is an internal concept to the partition map. - - if ( !strcmp(partitionHint, "Apple_Free") ) return 0; - - // Determine whether the new partition is read-only. - // - // Note that we treat the misspelt Apple_patition_map entries as equivalent - // to Apple_partition_map entries due to the messed up CDs noted in 2513960. - - if ( !strcmp(partition->dpme_type, "Apple_partition_map") || - !strcmp(partition->dpme_type, "Apple_Partition_Map") || - !strcmp(partition->dpme_type, "Apple_patition_map" ) || - ( ((partition->dpme_flags & DPME_FLAGS_WRITABLE) == 0) && - ((partition->dpme_flags & DPME_FLAGS_VALID ) != 0) ) ) - { - partitionIsWritable = false; - } - - // Create the new media object. - - IOMedia * newMedia = instantiateDesiredMediaObject( - /* partition */ partition, - /* partitionID */ partitionID, - /* partitionBlockSize */ partitionBlockSize ); - - if ( newMedia ) - { - if ( newMedia->init( - /* base */ partitionBase, - /* size */ partitionSize, - /* preferredBlockSize */ mediaBlockSize, - /* isEjectable */ media->isEjectable(), - /* isWhole */ false, - /* isWritable */ partitionIsWritable, - /* contentHint */ partitionHint ) ) - { - // Set a name for this partition. - - char name[24]; - sprintf(name, "Untitled %ld", partitionID); - newMedia->setName(partitionName ? partitionName : name); - - // Set a location value (the partition number) for this partition. - - char location[12]; - sprintf(location, "%ld", partitionID); - newMedia->setLocation(location); - - // Set the "Partition ID" key for this partition. - - newMedia->setProperty(kIOMediaPartitionIDKey, partitionID, 32); - } - else - { - newMedia->release(); - newMedia = 0; - } - } - - return newMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOApplePartitionScheme::instantiateDesiredMediaObject( - dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ) -{ - // - // Allocate a new media object (called from instantiateMediaObject). - // - - return new IOMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOApplePartitionScheme::attachMediaObjectToDeviceTree( IOMedia * media ) -{ - // - // Attach the given media object to the device tree plane. - // - - IOService * service; - SInt32 unit = -1; - - for ( service = this; service; service = service->getProvider() ) - { - OSNumber * number; - - if ( (number = OSDynamicCast(OSNumber, service->getProperty("IOUnit")))) - { - unit = number->unsigned32BitValue(); - } - - if ( service->inPlane(gIODTPlane) ) - { - IORegistryEntry * child; - IORegistryIterator * children; - - if ( unit == -1 ) break; - - children = IORegistryIterator::iterateOver(service, gIODTPlane); - - if ( children == 0 ) break; - - while ( (child = children->getNextObject()) ) - { - const char * location = child->getLocation(gIODTPlane); - const char * name = child->getName(gIODTPlane); - - if ( name == 0 || strcmp(name, "" ) != 0 || - location == 0 || strchr(location, ':') == 0 ) - { - child->detachAll(gIODTPlane); - } - } - - children->release(); - - if ( media->attachToParent(service, gIODTPlane) ) - { - char location[ sizeof("hhhhhhhh:dddddddddd") ]; - - sprintf(location, "%lx:", unit); - strcat(location, media->getLocation()); - media->setLocation(location, gIODTPlane); - media->setName("", gIODTPlane); - - return true; - } - - break; - } - } - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOApplePartitionScheme::detachMediaObjectFromDeviceTree( IOMedia * media ) -{ - // - // Detach the given media object from the device tree plane. - // - - IORegistryEntry * parent; - - if ( (parent = media->getParentEntry(gIODTPlane)) ) - { - media->detachFromParent(parent, gIODTPlane); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOApplePartitionScheme, 15); diff --git a/iokit/Families/IOStorage/IOBlockStorageDriver.cpp b/iokit/Families/IOStorage/IOBlockStorageDriver.cpp deleted file mode 100644 index 345e55b56..000000000 --- a/iokit/Families/IOStorage/IOBlockStorageDriver.cpp +++ /dev/null @@ -1,2338 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/storage/IOBlockStorageDevice.h> -#include <IOKit/storage/IOBlockStorageDriver.h> -#include <IOKit/storage/IOMedia.h> - -#define super IOStorage -OSDefineMetaClassAndStructors(IOBlockStorageDriver, IOStorage) - -// Hack for Cheetah to prevent sleep if there's disk activity. -static IOService * gIORootPowerDomain = NULL; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const UInt32 kPollerInterval = 1000; // (ms, 1 second) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOBlockStorageDevice * IOBlockStorageDriver::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method to - // return a more specific subclass of IOService -- IOBlockStorageDevice. - // This method serves simply as a convenience to subclass developers. - // - - return (IOBlockStorageDevice *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOBlockStorageDriver::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - if (super::init(properties) == false) return false; - - initMediaState(); - - _ejectable = false; - _lockable = false; - _pollIsExpensive = false; - _pollIsRequired = false; - _removable = false; - - _mediaBlockSize = 0; - _maxBlockNumber = 0; - _maxReadByteTransfer = 0; - _maxWriteByteTransfer = 0; - - _mediaStateLock = IOLockAlloc(); - - if (_mediaStateLock == 0) - return false; - - _deblockRequestWriteLock = IOLockAlloc(); - _openClients = OSSet::withCapacity(2); - _pollerCall = thread_call_allocate(poller, this); - - for (unsigned index = 0; index < kStatisticsCount; index++) - _statistics[index] = OSNumber::withNumber(0ULL, 64); - - if (_deblockRequestWriteLock == 0 || _openClients == 0 || _pollerCall == 0) - return false; - - for (unsigned index = 0; index < kStatisticsCount; index++) - if (_statistics[index] == 0) return false; - - // - // Create the standard block storage driver registry properties. - // - - OSDictionary * statistics = OSDictionary::withCapacity(kStatisticsCount); - - if (statistics == 0) return false; - - statistics->setObject( kIOBlockStorageDriverStatisticsBytesReadKey, - _statistics[kStatisticsBytesRead] ); - statistics->setObject( kIOBlockStorageDriverStatisticsBytesWrittenKey, - _statistics[kStatisticsBytesWritten] ); - statistics->setObject( kIOBlockStorageDriverStatisticsReadErrorsKey, - _statistics[kStatisticsReadErrors] ); - statistics->setObject( kIOBlockStorageDriverStatisticsWriteErrorsKey, - _statistics[kStatisticsWriteErrors] ); - statistics->setObject( kIOBlockStorageDriverStatisticsLatentReadTimeKey, - _statistics[kStatisticsLatentReadTime] ); - statistics->setObject( kIOBlockStorageDriverStatisticsLatentWriteTimeKey, - _statistics[kStatisticsLatentWriteTime] ); - statistics->setObject( kIOBlockStorageDriverStatisticsReadsKey, - _statistics[kStatisticsReads] ); - statistics->setObject( kIOBlockStorageDriverStatisticsWritesKey, - _statistics[kStatisticsWrites] ); - statistics->setObject( kIOBlockStorageDriverStatisticsReadRetriesKey, - _statistics[kStatisticsReadRetries] ); - statistics->setObject( kIOBlockStorageDriverStatisticsWriteRetriesKey, - _statistics[kStatisticsWriteRetries] ); - statistics->setObject( kIOBlockStorageDriverStatisticsTotalReadTimeKey, - _statistics[kStatisticsTotalReadTime] ); - statistics->setObject( kIOBlockStorageDriverStatisticsTotalWriteTimeKey, - _statistics[kStatisticsTotalWriteTime] ); - - setProperty(kIOBlockStorageDriverStatisticsKey, statistics); - - // Hack for Cheetah to prevent sleep if there's disk activity. - if (!gIORootPowerDomain) { - // No danger of race here as we're ultimately just setting - // the gIORootPowerDomain variable. - - do { - IOService * root = NULL; - OSIterator * iterator = NULL; - OSDictionary * pmDict = NULL; - - root = IOService::getServiceRoot(); - if (!root) break; - - pmDict = root->serviceMatching("IOPMrootDomain"); - if (!pmDict) break; - - iterator = root->getMatchingServices(pmDict); - pmDict->release(); - if (!iterator) break; - - if (iterator) { - gIORootPowerDomain = OSDynamicCast(IOService, iterator->getNextObject()); - iterator->release(); - } - } while (false); - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOBlockStorageDriver::start(IOService * provider) -{ - // - // This method is called once we have been attached to the provider object. - // - - // Open the block storage device. - - if (provider->open(this) == false) return false; - - // Prepare the block storage driver for operation. - - if (handleStart(provider) == false) - { - provider->close(this); - return false; - } - - // Initiate the poller mechanism if it is required. - - if (isMediaEjectable() && isMediaPollRequired() && !isMediaPollExpensive()) - { - lockForArbitration(); // (disable opens/closes; a recursive lock) - - if (!isOpen() && !isInactive()) - schedulePoller(); // (schedule the poller, increments retain) - - unlockForArbitration(); // (enable opens/closes; a recursive lock) - } - - // Register this object so it can be found via notification requests. It is - // not being registered to have I/O Kit attempt to have drivers match on it, - // which is the reason most other services are registered -- that's not the - // intention of this registerService call. - - registerService(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOBlockStorageDriver::yield(IOService * provider, - IOOptionBits options, - void * argument) -{ - // - // This method is called as a result of the kIOMessageServiceIsTerminated - // or kIOMessageServiceIsRequestingClose provider messages. The argument - // is passed in as-is from the message. The kIOServiceRequired option is - // set for the kIOMessageServiceIsTerminated message to indicate that the - // yield must succeed. - // - - bool success = false; - - lockForArbitration(); - - // Yield the block storage device. - - success = handleYield(provider, options, argument); - - if (success) - { - // Close the block storage device. - - provider->close(this); - } - - unlockForArbitration(); - - return success; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::free() -{ - // - // Free all of this object's outstanding resources. - // - - if (_mediaStateLock) IOLockFree(_mediaStateLock); - - if (_deblockRequestWriteLock) IOLockFree(_deblockRequestWriteLock); - if (_openClients) _openClients->release(); - if (_pollerCall) thread_call_free(_pollerCall); - - for (unsigned index = 0; index < kStatisticsCount; index++) - if (_statistics[index]) _statistics[index]->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOBlockStorageDriver::handleOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - // - // The handleOpen method grants or denies permission to access this object - // to an interested client. The argument is an IOStorageAccess value that - // specifies the level of access desired -- reader or reader-writer. - // - // This method can be invoked to upgrade or downgrade the access level for - // an existing client as well. The previous access level will prevail for - // upgrades that fail, of course. A downgrade should never fail. If the - // new access level should be the same as the old for a given client, this - // method will do nothing and return success. In all cases, one, singular - // close-per-client is expected for all opens-per-client received. - // - // This method assumes that the arbitration lock is held. - // - - assert(client); - - // Ensure there is media in the block storage device. - - if (getMediaState() == kIOMediaStateOffline) return false; - - // Handle the first open on removable media in a special case. - - if (isMediaEjectable() && _openClients->getCount() == 0) - { - // Halt the poller if it is active and this is the first open. - - if (isMediaPollRequired() && !isMediaPollExpensive()) - unschedulePoller(); // (unschedule the poller) - - // Lock down the media while we have opens on this driver object. - - if (lockMedia(true) != kIOReturnSuccess) - IOLog("%s: Unable to lock down removable media.\n", getName()); - } - - // Process the open. - - _openClients->setObject(client); // (works for up/downgrade case) - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOBlockStorageDriver::handleIsOpen(const IOService * client) const -{ - // - // The handleIsOpen method determines whether the specified client, or any - // client if none is specificed, presently has an open on this object. - // - // This method assumes that the arbitration lock is held. - // - - if (client) - return _openClients->containsObject(client); - else - return (_openClients->getCount() != 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::handleClose(IOService * client, IOOptionBits options) -{ - // - // The handleClose method drops the incoming client's access to this object. - // - // This method assumes that the arbitration lock is held. - // - - assert(client); - - // Process the close. - - _openClients->removeObject(client); - - // Handle the last close in a special case. - - if (!isInactive() && _openClients->getCount() == 0) - { - if (isMediaWritable()) - { - if (getMediaState() == kIOMediaStateOnline) - { - // Synchronize the cache on writeable media. - - if (synchronizeCache(this) != kIOReturnSuccess) - IOLog("%s: Unable to flush cache on media.\n", getName()); - } - } - - if (isMediaEjectable()) - { - // Unlock the removable media. - - if (getMediaState() == kIOMediaStateOnline) - { - if (lockMedia(false) != kIOReturnSuccess) - IOLog("%s: Unable to unlock removable media.\n", getName()); - } - - // Reactivate the poller. - - if (isMediaPollRequired() && !isMediaPollExpensive()) - schedulePoller(); // (schedule the poller, increments retain) - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::read(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // The read method is the receiving end for all read requests from the - // storage framework, ie. via the media object created by this driver. - // - // This method kicks off a sequence of three methods for each read or write - // request. The first is prepareRequest, which allocates and prepares some - // context for the transfer; the second is deblockRequest, which aligns the - // transfer at the media block boundaries; and the third is executeRequest, - // which implements the actual transfer from the block storage device. - // - - // State our assumptions. - - assert(buffer->getDirection() == kIODirectionIn); - - // Prepare the transfer. - - prepareRequest(byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::write(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // The write method is the receiving end for all write requests from the - // storage framework, ie. via the media object created by this driver. - // - // This method kicks off a sequence of three methods for each read or write - // request. The first is prepareRequest, which allocates and prepares some - // context for the transfer; the second is deblockRequest, which aligns the - // transfer at the media block boundaries; and the third is executeRequest, - // which implements the actual transfer from the block storage driver. - // - - // State our assumptions. - - assert(buffer->getDirection() == kIODirectionOut); - - // Prepare the transfer. - - prepareRequest(byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::addToBytesTransferred(UInt64 bytesTransferred, - UInt64 totalTime, // (ns) - UInt64 latentTime, // (ns) - bool isWrite) -{ - // - // Update the total number of bytes transferred, the total transfer time, - // and the total latency time -- used for statistics. - // - - if (isWrite) - { - _statistics[kStatisticsWrites]->addValue(1); - _statistics[kStatisticsBytesWritten]->addValue(bytesTransferred); - _statistics[kStatisticsTotalWriteTime]->addValue(totalTime); - _statistics[kStatisticsLatentWriteTime]->addValue(latentTime); - if (bytesTransferred <= getMediaBlockSize()) - _statistics[kStatisticsSingleBlockWrites]->addValue(1); - } - else - { - _statistics[kStatisticsReads]->addValue(1); - _statistics[kStatisticsBytesRead]->addValue(bytesTransferred); - _statistics[kStatisticsTotalReadTime]->addValue(totalTime); - _statistics[kStatisticsLatentReadTime]->addValue(latentTime); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::incrementRetries(bool isWrite) -{ - // - // Update the total retry count -- used for statistics. - // - - if (isWrite) - _statistics[kStatisticsWriteRetries]->addValue(1); - else - _statistics[kStatisticsReadRetries]->addValue(1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::incrementErrors(bool isWrite) -{ - // - // Update the total error count -- used for statistics. - // - - if (isWrite) - _statistics[kStatisticsWriteErrors]->addValue(1); - else - _statistics[kStatisticsReadErrors]->addValue(1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 IOBlockStorageDriver::getStatistics(UInt64 * statistics, - UInt32 statisticsMaxCount) const -{ - // - // Ask the driver to report its operating statistics. - // - // The statistics are each indexed by IOBlockStorageDriver::Statistics - // indices. This routine fills the caller's buffer, up to the maximum - // count specified if the real number of statistics would overflow the - // buffer. The return value indicates the actual number of statistics - // copied to the buffer. - // - // If the statistics buffer is not supplied or if the maximum count is - // zero, the routine returns the proposed count of statistics instead. - // - - if (statistics == 0) - return kStatisticsCount; - - UInt32 statisticsCount = min(kStatisticsCount, statisticsMaxCount); - - for (unsigned index = 0; index < statisticsCount; index++) - statistics[index] = _statistics[index]->unsigned64BitValue(); - - return statisticsCount; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt64 IOBlockStorageDriver::getStatistic(Statistics statistic) const -{ - // - // Ask the driver to report one of its operating statistics. - // - - if ((UInt32) statistic >= kStatisticsCount) return 0; - - return _statistics[statistic]->unsigned64BitValue(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOBlockStorageDriver::Context * IOBlockStorageDriver::allocateContext() -{ - // - // Allocate a context structure for a read/write operation. - // - - Context * context = IONew(Context, 1); - - if (context) - { - bzero(context, sizeof(Context)); - } - - return context; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::deleteContext( - IOBlockStorageDriver::Context * context) -{ - // - // Delete a context structure from a read/write operation. - // - - IODelete(context, Context, 1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::prepareRequest(UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // The prepareRequest method allocates and prepares state for the transfer. - // - // This method is part of a sequence of methods invoked for each read/write - // request. The first is prepareRequest, which allocates and prepares some - // context for the transfer; the second is deblockRequest, which aligns the - // transfer at the media block boundaries; and the third is executeRequest, - // which implements the actual transfer from the block storage device. - // - - Context * context; - IOReturn status; - - // Allocate a context structure to hold some of our state. - - context = allocateContext(); - - if (context == 0) - { - complete(completion, kIOReturnNoMemory); - return; - } - - // Prepare the transfer buffer. - - status = buffer->prepare(); - - if (status != kIOReturnSuccess) - { - deleteContext(context); - complete(completion, status); - return; - } - - // Fill in the context structure with some of our state. - - context->block.size = getMediaBlockSize(); - context->block.type = kBlockTypeStandard; - - context->original.byteStart = byteStart; - context->original.buffer = buffer; - context->original.buffer->retain(); - context->original.completion = completion; - - completion.target = this; - completion.action = prepareRequestCompletion; - completion.parameter = context; - - // Deblock the transfer. - - deblockRequest(byteStart, buffer, completion, context); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::prepareRequestCompletion(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount) -{ - // - // This is the completion routine for the prepared request. It updates - // the driver's statistics, performs some clean up work, then calls the - // original request's completion routine. - // - - Context * context = (Context *) parameter; - IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; - bool isWrite; - - isWrite = (context->original.buffer->getDirection() == kIODirectionOut); - - // State our assumptions. - - assert(status != kIOReturnSuccess || - context->original.buffer->getLength() == actualByteCount); - - // Update the total number of bytes transferred. - - driver->addToBytesTransferred(actualByteCount, 0, 0, isWrite); - - // Update the total error count. - - if (status != kIOReturnSuccess) - { - driver->incrementErrors(isWrite); - } - - // Complete the transfer buffer. - - context->original.buffer->complete(); - - // Complete the transfer request. - - IOStorage::complete(context->original.completion, status, actualByteCount); - - // Release our resources. - - context->original.buffer->release(); - - driver->deleteContext(context); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::schedulePoller() -{ - // - // Schedule the poller mechanism. - // - // This method assumes that the arbitration lock is held. - // - - AbsoluteTime deadline; - - retain(); - - clock_interval_to_deadline(kPollerInterval, kMillisecondScale, &deadline); - thread_call_enter_delayed(_pollerCall, deadline); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::unschedulePoller() -{ - // - // Unschedule the poller mechanism. - // - // This method assumes that the arbitration lock is held. - // - - if (thread_call_cancel(_pollerCall)) release(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::poller(void * target, void *) -{ - // - // This method is the timeout handler for the poller mechanism. It polls - // for media and reschedules another timeout if there are still no opens. - // - - IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; - - driver->pollMedia(); - - driver->lockForArbitration(); // (disable opens/closes; a recursive lock) - - if (!driver->isOpen() && !driver->isInactive()) - driver->schedulePoller(); // (schedule the poller, increments retain) - - driver->unlockForArbitration(); // (enable opens/closes; a recursive lock) - - driver->release(); // (drop the retain associated with this poll) -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOBlockStorageDriver::message(UInt32 type, - IOService * provider, - void * argument) -{ - // - // Generic entry point for calls from the provider. A return value of - // kIOReturnSuccess indicates that the message was received, and where - // applicable, that it was successful. - // - - switch (type) - { - case kIOMessageMediaStateHasChanged: - { - IOReturn status; - IOLockLock(_mediaStateLock); - status = mediaStateHasChanged((IOMediaState) argument); - IOLockUnlock(_mediaStateLock); - return status; - } - case kIOMessageServiceIsRequestingClose: - { - bool success; - success = yield(provider, 0, argument); - return success ? kIOReturnSuccess : kIOReturnBusy; - } - case kIOMessageServiceIsTerminated: - { - bool success; - success = yield(provider, kIOServiceRequired, argument); - return success ? kIOReturnSuccess : kIOReturnError; - } - default: - { - return super::message(type, provider, argument); - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/* Accept a new piece of media, doing whatever's necessary to make it - * show up properly to the system. The arbitration lock is assumed to - * be held during the call. - */ -IOReturn -IOBlockStorageDriver::acceptNewMedia(void) -{ - IOReturn result; - bool ok; - UInt64 nbytes; - char name[128]; - bool nameSep; - - /* Since the kernel printf doesn't handle 64-bit integers, we - * simply make an assumption that the block count and size - * will be 32-bit values max. - */ - -#ifdef moreDebug - IOLog("%s[IOBlockStorageDriver]::%s media: %ld blocks, %ld bytes each, write-%s.\n", - getName(), - getDeviceTypeName(), - (UInt32)_maxBlockNumber + 1,(UInt32)getMediaBlockSize(), - (_writeProtected ? "protected" : "enabled")); -#endif - - if (_maxBlockNumber) { - nbytes = _mediaBlockSize * (_maxBlockNumber + 1); - } else { - nbytes = 0; - } - - /* Instantiate a media object and attach it to ourselves. */ - - name[0] = 0; - nameSep = false; - if (getProvider()->getVendorString()) { - strcat(name, getProvider()->getVendorString()); - nameSep = true; - } - if (getProvider()->getProductString()) { - if (nameSep == true) strcat(name, " "); - strcat(name, getProvider()->getProductString()); - nameSep = true; - } - if (nameSep == true) strcat(name, " "); - strcat(name, "Media"); - - _mediaObject = instantiateMediaObject(0,nbytes,_mediaBlockSize,name); - result = (_mediaObject) ? kIOReturnSuccess : kIOReturnBadArgument; - - if (result == kIOReturnSuccess) { - ok = _mediaObject->attach(this); /* attach media object above us */ - if (ok) { - _mediaPresent = true; - _mediaObject->registerService(); /* enable matching */ - } else { - _mediaObject->release(); - _mediaObject = 0; - return(kIOReturnNoMemory); /* give up now */ - } - } - - return(result); -} - -IOReturn -IOBlockStorageDriver::checkForMedia(void) -{ - IOReturn result; - bool currentState; - bool changed; - - IOLockLock(_mediaStateLock); - - result = getProvider()->reportMediaState(¤tState,&changed); - if (result != kIOReturnSuccess) { /* the poll operation failed */ - IOLog("%s[IOBlockStorageDriver]::checkForMedia; err '%s' from reportMediaState\n", - getName(),stringFromReturn(result)); - } else if (changed) { /* the poll succeeded, media state has changed */ - result = mediaStateHasChanged(currentState ? kIOMediaStateOnline - : kIOMediaStateOffline); - } - - IOLockUnlock(_mediaStateLock); - return(result); -} - -IOReturn -IOBlockStorageDriver::mediaStateHasChanged(IOMediaState state) -{ - IOReturn result; - - /* The media has changed state. See if it's just inserted or removed. */ - - if (state == kIOMediaStateOnline) { /* media is now present */ - - /* Allow a subclass to decide whether we accept the media. Such a - * decision might be based on things like password-protection, etc. - */ - - if (validateNewMedia() == false) { /* we're told to reject it */ - rejectMedia(); /* so let subclass do whatever it wants */ - return(kIOReturnSuccess); /* pretend nothing happened */ - } - - result = recordMediaParameters(); /* learn about media */ - if (result != kIOReturnSuccess) { /* couldn't record params */ - initMediaState(); /* deny existence of new media */ - IOLog("%s[IOBlockStorageDriver]::checkForMedia: err '%s' from recordMediaParameters\n", - getName(),stringFromReturn(result)); - return(result); - } - - /* Now we do what's necessary to make the new media - * show up properly in the system. - */ - - lockForArbitration(); - result = acceptNewMedia(); - - if (result != kIOReturnSuccess) { - initMediaState(); /* deny existence of new media */ - IOLog("%s[IOBlockStorageDriver]::checkForMedia; err '%s' from acceptNewMedia\n", - getName(),stringFromReturn(result)); - } - - unlockForArbitration(); - return(result); /* all done, new media is ready */ - - } else { /* media is now absent */ - - lockForArbitration(); - result = decommissionMedia(true); /* force a teardown */ - unlockForArbitration(); - - if (result != kIOReturnSuccess && result != kIOReturnNoMedia) { - IOLog("%s[IOBlockStorageDriver]::checkForMedia; err '%s' from decommissionNewMedia\n", - getName(),stringFromReturn(result)); - return(result); - } - - return(kIOReturnSuccess); /* all done; media is gone */ - } -} - -UInt64 -IOBlockStorageDriver::constrainByteCount(UInt64 /* requestedCount */ ,bool isWrite) -{ - if (isWrite) { - return(_maxWriteByteTransfer); - } else { - return(_maxReadByteTransfer); - } -} - -/* Decommission a piece of media that has become unavailable either due to - * ejection or some outside force (e.g. the Giant Hand of the User). - * (I prefer the term "decommission" rather than "abandon." The former implies - * a well-determined procedure, whereas the latter implies leaving the media - * in an orphaned state.) - */ -/* Tear down the stack above the specified object. Usually these objects will - * be of type IOMedia, but they could be any IOService. The arbitration lock is - * assumed to be held during the call. - */ -IOReturn -IOBlockStorageDriver::decommissionMedia(bool forcible) -{ - IOReturn result; - - if (_mediaObject) { - /* If this is a forcible decommission (i.e. media is gone), we don't - * care whether the teardown worked; we forget about the media. - */ - if (_mediaObject->terminate(forcible ? kIOServiceRequired : 0) || forcible) { - _mediaObject->release(); - _mediaObject = 0; - - initMediaState(); /* clear all knowledge of the media */ - result = kIOReturnSuccess; - - } else { - result = kIOReturnBusy; - } - } else { - result = kIOReturnNoMedia; - } - - return(result); -} - -IOReturn -IOBlockStorageDriver::ejectMedia(void) -{ - IOReturn result; - - if (_removable) { - - IOLockLock(_mediaStateLock); - - lockForArbitration(); - result = decommissionMedia(false); /* try to teardown */ - unlockForArbitration(); - - if (result == kIOReturnSuccess) { /* eject */ - if (lockMedia(false) != kIOReturnSuccess) - IOLog("%s: Unable to unlock removable media.\n", getName()); - - (void)getProvider()->doEjectMedia(); /* ignore any error */ - } - - IOLockUnlock(_mediaStateLock); - - return(result); - - } else { - return(kIOReturnUnsupported); - } -} - -void -IOBlockStorageDriver::executeRequest(UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion, - IOBlockStorageDriver::Context * context) -{ - UInt32 block; - UInt32 nblks; - IOReturn result; - - if (!_mediaPresent) { /* no media? you lose */ - complete(completion, kIOReturnNoMedia,0); - return; - } - - /* We know that we are never called with a request too large, - * nor one that is misaligned with a block. - */ - assert((byteStart % _mediaBlockSize) == 0); - assert((buffer->getLength() % _mediaBlockSize) == 0); - - block = byteStart / _mediaBlockSize; - nblks = buffer->getLength() / _mediaBlockSize; - -/* Now the protocol-specific provider implements the actual - * start of the data transfer: */ - - // Tickle the root power domain to reset the sleep countdown. - if (gIORootPowerDomain) { - gIORootPowerDomain->activityTickle(kIOPMSubclassPolicy); - } - - result = getProvider()->doAsyncReadWrite(buffer,block,nblks,completion); - - if (result != kIOReturnSuccess) { /* it failed to start */ - IOLog("%s[IOBlockStorageDriver]; executeRequest: request failed to start!\n",getName()); - complete(completion,result); - return; - } -} - -IOReturn -IOBlockStorageDriver::formatMedia(UInt64 byteCapacity) -{ - if (!_mediaPresent) { - return(kIOReturnNoMedia); - } - - return(getProvider()->doFormatMedia(byteCapacity)); -} - -const char * -IOBlockStorageDriver::getDeviceTypeName(void) -{ - return(kIOBlockStorageDeviceTypeGeneric); -} - -UInt32 -IOBlockStorageDriver::getFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const -{ - return(getProvider()->doGetFormatCapacities(capacities,capacitiesMaxCount)); -} - -UInt64 -IOBlockStorageDriver::getMediaBlockSize() const -{ - return(_mediaBlockSize); -} - -IOMediaState -IOBlockStorageDriver::getMediaState() const -{ - if (_mediaPresent) { - return(kIOMediaStateOnline); - } else { - return(kIOMediaStateOffline); - } -} - -bool -IOBlockStorageDriver::handleStart(IOService * provider) -{ - IOReturn result; - - /* Print device name/type information on the console: */ - - /*The protocol-specific provider determines whether the media is removable. */ - - result = getProvider()->reportRemovability(&_removable); - if (result != kIOReturnSuccess) { - IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportRemovability\n", - getName(),stringFromReturn(result)); - return(false); - } - - if (_removable) { - - /* The protocol-specific provider determines whether we must poll to detect - * media insertion. Nonremovable devices never need polling. - */ - - result = getProvider()->reportPollRequirements(&_pollIsRequired,&_pollIsExpensive); - - if (result != kIOReturnSuccess) { - IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportPollRequirements\n", - getName(),stringFromReturn(result)); - return(false); - } - - /* The protocol-specific provider determines whether the media is ejectable - * under software control. - */ - result = getProvider()->reportEjectability(&_ejectable); - if (result != kIOReturnSuccess) { - IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportEjectability\n", - getName(),stringFromReturn(result)); - return(false); - } - - /* The protocol-specific provider determines whether the media is lockable - * under software control. - */ - result = getProvider()->reportLockability(&_lockable); - if (result != kIOReturnSuccess) { - IOLog("%s[IOBlockStorageDriver]::handleStart; err '%s' from reportLockability\n", - getName(),stringFromReturn(result)); - return(false); - } - - } else { /* fixed disk: not ejectable, not lockable */ - _ejectable = false; - _lockable = false; - _pollIsRequired = true; /* polling detects device disappearance */ - } - - /* Check for the device being ready with media inserted: */ - - result = checkForMedia(); - - /* The poll should never fail for nonremovable media: */ - - if (result != kIOReturnSuccess && !_removable) { - IOLog("%s[IOBlockStorageDriver]::handleStart: err '%s' from checkForMedia\n", - getName(),stringFromReturn(result)); - return(false); - } - - return(true); -} - -/* The driver has been instructed to yield. The arbitration lock is assumed to - * be held during the call. - */ -bool -IOBlockStorageDriver::handleYield(IOService * provider, - IOOptionBits options, - void * argument) -{ - // Determine whether we can yield (for non-required yield requests). - - if ( (options & kIOServiceRequired) == 0 && isOpen() != false ) - { - return false; - } - - // Halt the poller mechanism. - - if ( isMediaEjectable() != false && - isMediaPollRequired() != false && - isMediaPollExpensive() == false ) - { - unschedulePoller(); // (unschedule the poller) - } - - // Force a teardown. - - decommissionMedia(true); - - return true; -} - -void -IOBlockStorageDriver::initMediaState(void) -{ - _mediaPresent = false; - _writeProtected = false; -} - -IOMedia * -IOBlockStorageDriver::instantiateDesiredMediaObject(void) -{ - return(new IOMedia); -} - -IOMedia * -IOBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName) -{ - IOMedia *m; - bool result; - - m = instantiateDesiredMediaObject(); - if (m == NULL) { - return(NULL); - } - - result = m->init( base, /* base byte offset */ - byteSize, /* byte size */ - blockSize, /* preferred block size */ - _ejectable, /* TRUE if ejectable */ - true, /* TRUE if whole physical media */ - !_writeProtected, /* TRUE if writable */ - ""); /* content hint */ - - if (result) { - m->setName(mediaName); - return(m); - - } else { /* some init error */ - m->release(); - return(NULL); /* beats me...call it this error */ - } -} - -bool -IOBlockStorageDriver::isMediaEjectable(void) const -{ - return(_ejectable); -} - -bool -IOBlockStorageDriver::isMediaPollExpensive(void) const -{ - return(_pollIsExpensive); -} - -bool -IOBlockStorageDriver::isMediaPollRequired(void) const -{ - return(_pollIsRequired); -} - -bool -IOBlockStorageDriver::isMediaWritable(void) const -{ - return(!_writeProtected); -} - -IOReturn -IOBlockStorageDriver::lockMedia(bool locked) -{ - if (_lockable) { - return(getProvider()->doLockUnlockMedia(locked)); - } else { - return(kIOReturnUnsupported); - } -} - -IOReturn -IOBlockStorageDriver::pollMedia(void) -{ - if (!_pollIsRequired) { /* shouldn't poll; it's an error */ - - return(kIOReturnUnsupported); - - } else { /* poll is required...do it */ - - return(checkForMedia()); - - } -} - -IOReturn -IOBlockStorageDriver::recordMediaParameters(void) -{ - IOReturn result; - - /* Determine the device's block size and max block number. - * What should an unformatted device report? All zeroes, or an error? - */ - - result = getProvider()->reportBlockSize(&_mediaBlockSize); - if (result != kIOReturnSuccess) { - goto err; - } - - result = getProvider()->reportMaxValidBlock(&_maxBlockNumber); - if (result != kIOReturnSuccess) { - goto err; - } - - /* Calculate the maximum allowed byte transfers for reads and writes. */ - - result = getProvider()->reportMaxReadTransfer(_mediaBlockSize,&_maxReadByteTransfer); - if (result != kIOReturnSuccess) { - goto err; - } - - result = getProvider()->reportMaxWriteTransfer(_mediaBlockSize,&_maxWriteByteTransfer); - if (result != kIOReturnSuccess) { - goto err; - } - - /* Is the media write-protected? */ - - result = getProvider()->reportWriteProtection(&_writeProtected); - if (result != kIOReturnSuccess) { - goto err; - } - - return(kIOReturnSuccess); /* everything was successful */ - - /* If we fall thru to here, we had some kind of error. Set everything to - * a reasonable state since we haven't got any real information. - */ - -err: - _mediaPresent = false; - _writeProtected = true; - - return(result); -} - -void -IOBlockStorageDriver::rejectMedia(void) -{ - (void)getProvider()->doEjectMedia(); /* eject it, ignoring any error */ - initMediaState(); /* deny existence of new media */ -} - -IOReturn -IOBlockStorageDriver::synchronizeCache(IOService *client) -{ - return(getProvider()->doSynchronizeCache()); -} - -bool -IOBlockStorageDriver::validateNewMedia(void) -{ - return(true); -} - -// ----------------------------------------------------------------------------- -// Deblocker Implementation - -#include <IOKit/IOBufferMemoryDescriptor.h> - -class IODeblocker : public IOMemoryDescriptor -{ - OSDeclareDefaultStructors(IODeblocker); - -protected: - - UInt64 _blockSize; - - struct - { - IOMemoryDescriptor * buffer; - UInt32 offset; - UInt32 length; - } _chunks[3]; - UInt32 _chunksCount; - - IOBufferMemoryDescriptor * _excessBuffer; - UInt64 _excessCountFinal; - UInt64 _excessCountStart; - - IOMemoryDescriptor * _requestBuffer; - IOStorageCompletion _requestCompletion; - void * _requestContext; - UInt64 _requestCount; - bool _requestIsOneBlock; - UInt64 _requestStart; - - enum - { - kStageInit, - kStagePrepareExcessStart, - kStagePrepareExcessFinal, - kStageLast, - kStageDone - } _stage; - - virtual void free(); - - virtual bool initWithAddress( void * address, /* not supported */ - IOByteCount withLength, - IODirection withDirection ); - - virtual bool initWithAddress( vm_address_t address, /* not supported */ - IOByteCount withLength, - IODirection withDirection, - task_t withTask ); - - virtual bool initWithPhysicalAddress( - IOPhysicalAddress address, /* not supported */ - IOByteCount withLength, - IODirection withDirection ); - - virtual bool initWithPhysicalRanges( - IOPhysicalRange * ranges, /* not supproted */ - UInt32 withCount, - IODirection withDirection, - bool asReference = false ); - - virtual bool initWithRanges( IOVirtualRange * ranges, /* not supported */ - UInt32 withCount, - IODirection withDirection, - task_t withTask, - bool asReference = false ); - - virtual void * getVirtualSegment( IOByteCount offset, /* not supported */ - IOByteCount * length ); - - IOMemoryDescriptor::withAddress; /* not supported */ - IOMemoryDescriptor::withPhysicalAddress; /* not supported */ - IOMemoryDescriptor::withPhysicalRanges; /* not supported */ - IOMemoryDescriptor::withRanges; /* not supported */ - IOMemoryDescriptor::withSubRange; /* not supported */ - -public: - - static IODeblocker * withBlockSize( - UInt64 blockSize, - UInt64 withRequestStart, - IOMemoryDescriptor * withRequestBuffer, - IOStorageCompletion withRequestCompletion, - void * withRequestContext ); - - virtual bool initWithBlockSize( - UInt64 blockSize, - UInt64 withRequestStart, - IOMemoryDescriptor * withRequestBuffer, - IOStorageCompletion withRequestCompletion, - void * withRequestContext ); - - virtual IOPhysicalAddress getPhysicalSegment( IOByteCount offset, - IOByteCount * length ); - - virtual IOReturn prepare(IODirection forDirection = kIODirectionNone); - - virtual IOReturn complete(IODirection forDirection = kIODirectionNone); - - virtual IOByteCount readBytes( IOByteCount offset, - void * bytes, - IOByteCount withLength ); - - virtual IOByteCount writeBytes( IOByteCount offset, - const void * bytes, - IOByteCount withLength ); - - virtual bool getNextStage(UInt64 * byteStart); - - virtual void getRequestCompletion( IOStorageCompletion * completion, - IOReturn * status, - UInt64 * actualByteCount ); - - virtual IOMemoryDescriptor * getRequestBuffer(); - - virtual void * getRequestContext(); -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#undef super -#define super IOMemoryDescriptor -OSDefineMetaClassAndStructors(IODeblocker, IOMemoryDescriptor) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithAddress( void * /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithAddress( vm_address_t /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ , - task_t /* withTask */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithPhysicalAddress( - IOPhysicalAddress /* address */ , - IOByteCount /* withLength */ , - IODirection /* withDirection */ ) -{ - return false; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithPhysicalRanges( - IOPhysicalRange * /* ranges */ , - UInt32 /* withCount */ , - IODirection /* withDirection */ , - bool /* asReference */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithRanges( IOVirtualRange * /* ranges */ , - UInt32 /* withCount */ , - IODirection /* withDirection */ , - task_t /* withTask */ , - bool /* asReference */ ) -{ - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IODeblocker * IODeblocker::withBlockSize( - UInt64 blockSize, - UInt64 withRequestStart, - IOMemoryDescriptor * withRequestBuffer, - IOStorageCompletion withRequestCompletion, - void * withRequestContext ) -{ - // - // Create a new IODeblocker. - // - - IODeblocker * me = new IODeblocker; - - if ( me && me->initWithBlockSize( - /* blockSize */ blockSize, - /* withRequestStart */ withRequestStart, - /* withRequestBuffer */ withRequestBuffer, - /* withRequestCompletion */ withRequestCompletion, - /* withRequestContext */ withRequestContext ) == false ) - { - me->release(); - me = 0; - } - - return me; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::initWithBlockSize( - UInt64 blockSize, - UInt64 withRequestStart, - IOMemoryDescriptor * withRequestBuffer, - IOStorageCompletion withRequestCompletion, - void * withRequestContext ) -{ - // - // Initialize an IODeblocker. - // - // _excessCountStart = byte count from media boundary to start of request - // _excessCountFinal = byte count from end of request to a media boundary - // - - UInt32 excessBufferSize = 0; - - // Ask our superclass' opinion. - - if ( super::init() == false ) return false; - - // Initialize our minimal state. - - _blockSize = blockSize; - _chunksCount = 0; - _direction = kIODirectionNone; - _length = 0; - - _requestBuffer = withRequestBuffer; - _requestBuffer->retain(); - _requestCompletion = withRequestCompletion; - _requestContext = withRequestContext; - _requestCount = withRequestBuffer->getLength(); - _requestStart = withRequestStart; - - _excessCountStart = (withRequestStart ) % blockSize; - _excessCountFinal = (withRequestStart + _requestCount) % blockSize; - if ( _excessCountFinal ) _excessCountFinal = blockSize - _excessCountFinal; - - _requestIsOneBlock = (_excessCountStart + _requestCount <= blockSize); - - // Determine the necessary size for our scratch buffer. - - switch ( _requestBuffer->getDirection() ) - { - case kIODirectionIn: // (read) - { - excessBufferSize = max(_excessCountStart, _excessCountFinal); - } break; - - case kIODirectionOut: // (write) - { - if ( _excessCountStart ) excessBufferSize += blockSize; - if ( _excessCountFinal ) excessBufferSize += blockSize; - - // If there is excess both ends of the original request, but both - // ends reside within the same media block, then we could shorten - // our buffer size to just one block. - - if ( _excessCountStart && _excessCountFinal && _requestIsOneBlock ) - { - excessBufferSize -= blockSize; - } - } break; - - default: - { - assert(0); - } break; - } - - // Allocate our scratch buffer. - - if ( excessBufferSize ) - { - _excessBuffer = IOBufferMemoryDescriptor::withCapacity( - /* capacity */ excessBufferSize, - /* withDirection */ kIODirectionNone ); - if ( _excessBuffer == 0 ) return false; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IODeblocker::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _requestBuffer ) _requestBuffer->release(); - if ( _excessBuffer ) _excessBuffer->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IODeblocker::prepare(IODirection forDirection) -{ - // - // Prepare the memory for an I/O transfer. - // - // This involves paging in the memory and wiring it down for the duration - // of the transfer. The complete() method finishes the processing of the - // memory after the I/O transfer finishes. - // - - unsigned index; - IOReturn status = kIOReturnInternalError; - IOReturn statusUndo; - - if ( forDirection == kIODirectionNone ) - { - forDirection = _direction; - } - - for ( index = 0; index < _chunksCount; index++ ) - { - status = _chunks[index].buffer->prepare(forDirection); - if ( status != kIOReturnSuccess ) break; - } - - if ( status != kIOReturnSuccess ) - { - for ( unsigned indexUndo = 0; indexUndo <= index; indexUndo++ ) - { - statusUndo = _chunks[index].buffer->complete(forDirection); - assert(statusUndo == kIOReturnSuccess); - } - } - - return status; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IODeblocker::complete(IODirection forDirection) -{ - // - // Complete processing of the memory after an I/O transfer finishes. - // - // This method shouldn't be called unless a prepare() was previously issued; - // the prepare() and complete() must occur in pairs, before and after an I/O - // transfer. - // - - IOReturn status; - IOReturn statusFinal = kIOReturnSuccess; - - if ( forDirection == kIODirectionNone ) - { - forDirection = _direction; - } - - for ( unsigned index = 0; index < _chunksCount; index++ ) - { - status = _chunks[index].buffer->complete(forDirection); - if ( status != kIOReturnSuccess ) statusFinal = status; - assert(status == kIOReturnSuccess); - } - - return statusFinal; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOPhysicalAddress IODeblocker::getPhysicalSegment( IOByteCount offset, - IOByteCount * length ) -{ - // - // This method returns the physical address of the byte at the given offset - // into the memory, and optionally the length of the physically contiguous - // segment from that offset. - // - - assert(offset <= _length); - - for ( unsigned index = 0; index < _chunksCount; index++ ) - { - if ( offset < _chunks[index].length ) - { - IOPhysicalAddress address; - address = _chunks[index].buffer->getPhysicalSegment( - /* offset */ offset + _chunks[index].offset, - /* length */ length ); - if ( length ) *length = min(*length, _chunks[index].length); - return address; - } - offset -= _chunks[index].length; - } - - if ( length ) *length = 0; - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void * IODeblocker::getVirtualSegment( IOByteCount /* offset */ , - IOByteCount * /* length */ ) -{ - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOByteCount IODeblocker::readBytes( IOByteCount offset, - void * bytes, - IOByteCount withLength ) -{ - // - // Copies data from the memory descriptor's buffer at the given offset, to - // the specified buffer. Returns the number of bytes copied. - // - - IOByteCount bytesCopied = 0; - unsigned index; - - for ( index = 0; index < _chunksCount; index++ ) - { - if ( offset < _chunks[index].length ) break; - offset -= _chunks[index].length; - } - - for ( ; index < _chunksCount && withLength; index++) - { - IOByteCount copy = min(_chunks[index].length - offset, withLength); - IOByteCount copied = _chunks[index].buffer->readBytes( - /* offset */ offset + _chunks[index].offset, - /* bytes */ bytes, - /* length */ copy ); - - bytesCopied += copied; - if ( copied != copy ) break; - - bytes = ((UInt8 *) bytes) + copied; - withLength -= copied; - offset = 0; - } - - return bytesCopied; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOByteCount IODeblocker::writeBytes( IOByteCount offset, - const void * bytes, - IOByteCount withLength ) -{ - // - // Copies data to the memory descriptor's buffer at the given offset, from - // the specified buffer. Returns the number of bytes copied. - // - - IOByteCount bytesCopied = 0; - unsigned index; - - for ( index = 0; index < _chunksCount; index++ ) - { - if ( offset < _chunks[index].length ) break; - offset -= _chunks[index].length; - } - - for ( ; index < _chunksCount && withLength; index++) - { - IOByteCount copy = min(_chunks[index].length - offset, withLength); - IOByteCount copied = _chunks[index].buffer->writeBytes( - /* offset */ offset + _chunks[index].offset, - /* bytes */ bytes, - /* length */ copy ); - - bytesCopied += copied; - if ( copied != copy ) break; - - bytes = ((UInt8 *) bytes) + copied; - withLength -= copied; - offset = 0; - } - - return bytesCopied; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IODeblocker::getNextStage(UInt64 * byteStart) -{ - // - // Obtain the next stage of the transfer. The transfer buffer will be the - // deblocker object itself and the byte start will be returned in byteStart. - // - // This method must not be called if the current stage failed with an error - // or a short byte count, but instead getRequestCompletion() must be called - // to adjust the status and actual byte count (with respect to the original - // request) and return the original request's completion routine. The same - // call to getRequestCompletion() should also be done if the getNextStage() - // method returns false. - // - - _chunksCount = 0; - _direction = kIODirectionNone; - _length = 0; - - switch ( _requestBuffer->getDirection() ) - { - case kIODirectionIn: // (read) - { - switch ( _stage ) - { - case kStageInit: - { - _stage = kStageLast; - _excessBuffer->setDirection(kIODirectionIn); - _direction = kIODirectionIn; - *byteStart = _requestStart - _excessCountStart; - - if ( _excessCountStart ) - { - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _excessCountStart; - _chunksCount++; - } - - _chunks[_chunksCount].buffer = _requestBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _requestBuffer->getLength(); - _chunksCount++; - - if ( _excessCountFinal ) - { - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _excessCountFinal; - _chunksCount++; - } - } break; - - case kStageLast: - { - _stage = kStageDone; - } break; - - default: - { - assert(0); - } break; - } // (switch) - } break; - - case kIODirectionOut: // (write) - { - switch ( _stage ) - { - case kStageInit: - { - if ( _excessCountStart ) - { - _stage = kStagePrepareExcessStart; - _excessBuffer->setDirection(kIODirectionIn); - _direction = kIODirectionIn; - *byteStart = _requestStart - _excessCountStart; - - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _blockSize; - _chunksCount++; - break; - } - } // (fall thru) - - case kStagePrepareExcessStart: - { - if ( _excessCountFinal ) - { - // We do not issue this stage if the original transfer - // resides within one media block, and we already read - // that block into our buffer in the previous stage. - - if ( !_excessCountStart || !_requestIsOneBlock ) - { - _stage = kStagePrepareExcessFinal; - _excessBuffer->setDirection(kIODirectionIn); - _direction = kIODirectionIn; - *byteStart = _requestStart + _requestCount + - _excessCountFinal - _blockSize; - - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = (_requestIsOneBlock) - ? 0 - : (_excessCountStart) - ? _blockSize - : 0; - _chunks[_chunksCount].length = _blockSize; - _chunksCount++; - break; - } - } - } // (fall thru) - - case kStagePrepareExcessFinal: - { - _stage = kStageLast; - _excessBuffer->setDirection(kIODirectionOut); - _direction = kIODirectionOut; - *byteStart = _requestStart - _excessCountStart; - - if ( _excessCountStart ) - { - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _excessCountStart; - _chunksCount++; - } - - _chunks[_chunksCount].buffer = _requestBuffer; - _chunks[_chunksCount].offset = 0; - _chunks[_chunksCount].length = _requestBuffer->getLength(); - _chunksCount++; - - if ( _excessCountFinal ) - { - _chunks[_chunksCount].buffer = _excessBuffer; - _chunks[_chunksCount].offset = (_requestIsOneBlock) - ? 0 - : (_excessCountStart) - ? _blockSize - : 0; - _chunks[_chunksCount].offset += ( _blockSize - - _excessCountFinal ); - _chunks[_chunksCount].length = _excessCountFinal; - _chunksCount++; - } - } break; - - case kStageLast: - { - _stage = kStageDone; - } break; - - default: - { - assert(0); - } break; - } // (switch) - } break; - - default: - { - assert(0); - } break; - } // (switch) - - // Determine whether we have an abort or completion condition. - - if ( _chunksCount == 0 ) return false; - - // Compute the total length of the descriptor over all chunks. - - for ( unsigned index = 0; index < _chunksCount; index++ ) - { - _length += _chunks[index].length; - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IODeblocker::getRequestCompletion( IOStorageCompletion * completion, - IOReturn * status, - UInt64 * actualByteCount ) -{ - // - // Obtain the completion information for the original request, taking - // into account the status and actual byte count of the current stage. - // - - *completion = _requestCompletion; - - switch ( _stage ) - { - case kStageInit: // (inital stage) - { - *status = kIOReturnInternalError; - *actualByteCount = 0; - } break; - - case kStagePrepareExcessStart: // (write preparation stage) - case kStagePrepareExcessFinal: - { - *actualByteCount = 0; - } break; - - case kStageLast: // (last stage) - case kStageDone: - { - if ( *actualByteCount > _excessCountStart ) - *actualByteCount -= _excessCountStart; - else - *actualByteCount = 0; - - if ( *actualByteCount > _requestBuffer->getLength() ) - *actualByteCount = _requestBuffer->getLength(); - } break; - - default: - { - assert(0); - } break; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMemoryDescriptor * IODeblocker::getRequestBuffer() -{ - // - // Obtain the buffer for the original request. - // - - return _requestBuffer; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void * IODeblocker::getRequestContext() -{ - // - // Obtain the context for the original request. - // - - return _requestContext; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::deblockRequest( - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion, - IOBlockStorageDriver::Context * context ) -{ - // - // The deblockRequest method checks to see if the incoming request rests - // on the media's block boundaries, and if not, deblocks it. Deblocking - // involves rounding out the request to the nearest block boundaries and - // transferring the excess bytes into a scratch buffer. - // - // This method is part of a sequence of methods invoked for each read/write - // request. The first is prepareRequest, which allocates and prepares some - // context for the transfer; the second is deblockRequest, which aligns the - // transfer at the media block boundaries; and the third is executeRequest, - // which implements the actual transfer from the block storage device. - // - // The current implementation of deblockRequest is asynchronous. - // - - IODeblocker * deblocker; - - // If the request is aligned with the media's block boundaries, we - // do short-circuit the deblocker and call executeRequest directly. - - if ( (byteStart % context->block.size) == 0 && - (buffer->getLength() % context->block.size) == 0 ) - { - executeRequest(byteStart, buffer, completion, context); - return; - } - - // Build a deblocker object. - - deblocker = IODeblocker::withBlockSize( - /* blockSize */ context->block.size, - /* withRequestStart */ byteStart, - /* withRequestBuffer */ buffer, - /* withRequestCompletion */ completion, - /* withRequestContext */ context ); - - if ( deblocker == 0 ) - { - complete(completion, kIOReturnNoMemory); - return; - } - - // This implementation of the deblocker permits only one read-modify-write - // at any given time. Note that other write requests can, and do, proceed - // simultaneously so long as they do not require the deblocker -- refer to - // the read() and the write() routines for the short-cut logic. - // - // Note that the original buffer during a read-modify-write operation must - // be prepared on the client's thread, that is, right now, or else it will - // happen on the controller's thread after the read stage(s) complete, and - // this is bad (causes deadlock if that controller was the swap device). - - if ( buffer->getDirection() == kIODirectionOut ) - { - if ( buffer->prepare() != kIOReturnSuccess ) - { - deblocker->release(); - complete(completion, kIOReturnNoMemory); - return; - } - - IOLockLock(_deblockRequestWriteLock); - } - - // Execute the transfer (for the next stage). - - deblockRequestCompletion(this, deblocker, kIOReturnSuccess, 0); - - return; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOBlockStorageDriver::deblockRequestCompletion( void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount ) -{ - // - // This is the completion routine for the aligned deblocker subrequests. - // It verifies the success of the just-completed stage, transitions to - // the next stage, then builds and issues a transfer for the next stage. - // - - UInt64 byteStart; - IOStorageCompletion completion; - Context * context; - IODeblocker * deblocker = (IODeblocker *) parameter; - IOBlockStorageDriver * driver = (IOBlockStorageDriver *) target; - - // Determine whether an error occurred or whether there are no more stages. - - if ( actualByteCount < deblocker->getLength() || - status != kIOReturnSuccess || - deblocker->getNextStage(&byteStart) == false ) - { - // Unlock the write-lock in order to allow the next write to proceed. - - if ( deblocker->getRequestBuffer()->getDirection() == kIODirectionOut ) - { - IOLockUnlock(driver->_deblockRequestWriteLock); - - deblocker->getRequestBuffer()->complete(); - } - - // Obtain the completion information for the original request, taking - // into account the status and actual byte count of the current stage. - - deblocker->getRequestCompletion(&completion, &status, &actualByteCount); - - // Complete the original request. - - IOStorage::complete(completion, status, actualByteCount); - - // Release our resources. - - deblocker->release(); - - return; - } - - // Execute the transfer (for the next stage). - - completion.target = driver; - completion.action = deblockRequestCompletion; - completion.parameter = deblocker; - - context = (Context *) deblocker->getRequestContext(); - - driver->executeRequest(byteStart, deblocker, completion, context); - - return; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 15); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 16); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 17); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 18); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 19); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 20); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 21); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 22); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 23); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 24); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 25); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 26); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 27); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 28); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 29); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 30); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOBlockStorageDriver, 31); diff --git a/iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp b/iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp deleted file mode 100644 index 3121d021e..000000000 --- a/iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IOFDiskPartitionScheme.h> -#include <libkern/OSByteOrder.h> - -#define super IOPartitionScheme -OSDefineMetaClassAndStructors(IOFDiskPartitionScheme, IOPartitionScheme); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Notes -// -// o the on-disk structure's fields are: 16-bit packed, little-endian formatted -// o the relsect and numsect block values assume the drive's natural block size -// o the relsect block value is: -// o for data partitions: -// o relative to the FDisk map that defines the partition -// o for extended partitions defined in the root-level FDisk map: -// o relative to the FDisk map that defines the partition (start of disk) -// o for extended partitions defined in a second-level or deeper FDisk map: -// o relative to the second-level FDisk map, regardless of depth -// o the valid extended partition types are: 0x05, 0x0F, 0x85 -// o there should be no more than one extended partition defined per FDisk map -// - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define kIOFDiskPartitionSchemeContentTable "Content Table" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - // State our assumptions. - - assert(sizeof(fdisk_part) == 16); // (compiler/platform check) - assert(sizeof(disk_blk0) == 512); // (compiler/platform check) - - // Ask our superclass' opinion. - - if ( super::init(properties) == false ) return false; - - // Initialize our state. - - _partitions = 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOFDiskPartitionScheme::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _partitions ) _partitions->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOService * IOFDiskPartitionScheme::probe(IOService * provider, SInt32 * score) -{ - // - // Determine whether the provider media contains an FDisk partition map. - // - - // State our assumptions. - - assert(OSDynamicCast(IOMedia, provider)); - - // Ask our superclass' opinion. - - if ( super::probe(provider, score) == 0 ) return 0; - - // Scan the provider media for an FDisk partition map. - - _partitions = scan(score); - - // There might be an FDisk partition scheme on disk with boot code, but with - // no partitions defined. We don't consider this a match and return failure - // from probe. - - if ( _partitions && _partitions->getCount() == 0 ) - { - _partitions->release(); - _partitions = 0; - } - - return ( _partitions ) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::start(IOService * provider) -{ - // - // Publish the new media objects which represent our partitions. - // - - IOMedia * partition; - OSIterator * partitionIterator; - - // State our assumptions. - - assert(_partitions); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Attach and register the new media objects representing our partitions. - - partitionIterator = OSCollectionIterator::withCollection(_partitions); - if ( partitionIterator == 0 ) return false; - - while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) - { - if ( partition->attach(this) ) - { - partition->registerService(); - } - } - - partitionIterator->release(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSSet * IOFDiskPartitionScheme::scan(SInt32 * score) -{ - // - // Scan the provider media for an FDisk partition map. Returns the set - // of media objects representing each of the partitions (the retain for - // the set is passed to the caller), or null should no partition map be - // found. The default probe score can be adjusted up or down, based on - // the confidence of the scan. - // - - IOBufferMemoryDescriptor * buffer = 0; - UInt32 bufferSize = 0; - UInt32 fdiskBlock = 0; - UInt32 fdiskBlockExtn = 0; - UInt32 fdiskBlockNext = 0; - UInt32 fdiskID = 0; - disk_blk0 * fdiskMap = 0; - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - bool mediaIsOpen = false; - OSSet * partitions = 0; - IOReturn status = kIOReturnError; - - // Determine whether this media is formatted. - - if ( media->isFormatted() == false ) goto scanErr; - - // Determine whether this media has an appropriate block size. - - if ( (mediaBlockSize % sizeof(disk_blk0)) ) goto scanErr; - - // Allocate a buffer large enough to hold one map, rounded to a media block. - - bufferSize = IORound(sizeof(disk_blk0), mediaBlockSize); - buffer = IOBufferMemoryDescriptor::withCapacity( - /* capacity */ bufferSize, - /* withDirection */ kIODirectionIn ); - if ( buffer == 0 ) goto scanErr; - - // Allocate a set to hold the set of media objects representing partitions. - - partitions = OSSet::withCapacity(4); - if ( partitions == 0 ) goto scanErr; - - // Open the media with read access. - - mediaIsOpen = media->open(this, 0, kIOStorageAccessReader); - if ( mediaIsOpen == false ) goto scanErr; - - // Scan the media for FDisk partition map(s). - - do - { - // Read the next FDisk map into our buffer. - -///m:2333367:workaround:commented:start -// status = media->read(this, fdiskBlock * mediaBlockSize, buffer); -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read(this, fdiskBlock * mediaBlockSize, buffer); -///m:2333367:workaround:added:stop - if ( status != kIOReturnSuccess ) goto scanErr; - - fdiskMap = (disk_blk0 *) buffer->getBytesNoCopy(); - - // Determine whether the partition map signature is present. - - if ( OSSwapLittleToHostInt16(fdiskMap->signature) != DISK_SIGNATURE ) - { - goto scanErr; - } - - // Scan for valid partition entries in the partition map. - - fdiskBlockNext = 0; - - for ( unsigned index = 0; index < DISK_NPART; index++ ) - { - // Determine whether this is an extended (vs. data) partition. - - if ( isPartitionExtended(fdiskMap->parts + index) ) // (extended) - { - // If peer extended partitions exist, we accept only the first. - - if ( fdiskBlockNext == 0 ) // (no peer extended partition) - { - fdiskBlockNext = fdiskBlockExtn + - OSSwapLittleToHostInt32( - /* data */ fdiskMap->parts[index].relsect ); - - if ( fdiskBlockNext * mediaBlockSize >= media->getSize() ) - { - fdiskBlockNext = 0; // (exceeds confines of media) - } - } - } - else if ( isPartitionUsed(fdiskMap->parts + index) ) // (data) - { - // Prepare this partition's ID. - - fdiskID = ( fdiskBlock == 0 ) ? (index + 1) : (fdiskID + 1); - - // Determine whether the partition is corrupt (fatal). - - if ( isPartitionCorrupt( - /* partition */ fdiskMap->parts + index, - /* partitionID */ fdiskID, - /* fdiskBlock */ fdiskBlock ) ) - { - goto scanErr; - } - - // Determine whether the partition is invalid (skipped). - - if ( isPartitionInvalid( - /* partition */ fdiskMap->parts + index, - /* partitionID */ fdiskID, - /* fdiskBlock */ fdiskBlock ) ) - { - continue; - } - - // Create a media object to represent this partition. - - IOMedia * newMedia = instantiateMediaObject( - /* partition */ fdiskMap->parts + index, - /* partitionID */ fdiskID, - /* fdiskBlock */ fdiskBlock ); - - if ( newMedia ) - { - partitions->setObject(newMedia); - newMedia->release(); - } - } - } - - // Prepare for first extended partition, if any. - - if ( fdiskBlock == 0 ) - { - fdiskID = DISK_NPART; - fdiskBlockExtn = fdiskBlockNext; - } - - } while ( (fdiskBlock = fdiskBlockNext) ); - - // Release our resources. - - media->close(this); - buffer->release(); - - return partitions; - -scanErr: - - // Release our resources. - - if ( mediaIsOpen ) media->close(this); - if ( partitions ) partitions->release(); - if ( buffer ) buffer->release(); - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::isPartitionExtended(fdisk_part * partition) -{ - // - // Ask whether the given partition is extended. - // - - return ( partition->systid == 0x05 || - partition->systid == 0x0F || - partition->systid == 0x85 ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::isPartitionUsed(fdisk_part * partition) -{ - // - // Ask whether the given partition is used. - // - - return ( partition->systid != 0 && partition->numsect != 0 ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::isPartitionCorrupt( - fdisk_part * /* partition */ , - UInt32 /* partitionID */ , - UInt32 /* fdiskBlock */ ) -{ - // - // Ask whether the given partition appears to be corrupt. A partition that - // is corrupt will cause the failure of the FDisk partition map recognition - // altogether. - // - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOFDiskPartitionScheme::isPartitionInvalid( fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ) -{ - // - // Ask whether the given partition appears to be invalid. A partition that - // is invalid will cause it to be skipped in the scan, but will not cause a - // failure of the FDisk partition map recognition. - // - - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - UInt64 partitionBase = 0; - UInt64 partitionSize = 0; - - // Compute the relative byte position and size of the new partition. - - partitionBase = OSSwapLittleToHostInt32(partition->relsect) + fdiskBlock; - partitionSize = OSSwapLittleToHostInt32(partition->numsect); - partitionBase *= mediaBlockSize; - partitionSize *= mediaBlockSize; - - // Determine whether the partition starts at (or past) the end-of-media. - - if ( partitionBase >= media->getSize() ) return true; - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOFDiskPartitionScheme::instantiateMediaObject( - fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ) -{ - // - // Instantiate a new media object to represent the given partition. - // - - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - UInt64 partitionBase = 0; - char * partitionHint = 0; - UInt64 partitionSize = 0; - - // Compute the relative byte position and size of the new partition. - - partitionBase = OSSwapLittleToHostInt32(partition->relsect) + fdiskBlock; - partitionSize = OSSwapLittleToHostInt32(partition->numsect); - partitionBase *= mediaBlockSize; - partitionSize *= mediaBlockSize; - - // Clip the size of the new partition if it extends past the end-of-media. - - if ( partitionBase + partitionSize > media->getSize() ) - { - partitionSize = media->getSize() - partitionBase; - } - - // Look up a type for the new partition. - - OSDictionary * hintTable = OSDynamicCast( - /* type */ OSDictionary, - /* instance */ getProperty(kIOFDiskPartitionSchemeContentTable) ); - - if ( hintTable ) - { - char hintIndex[5]; - OSString * hintValue; - - sprintf(hintIndex, "0x%02X", partition->systid & 0xFF); - - hintValue = OSDynamicCast(OSString, hintTable->getObject(hintIndex)); - - if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy(); - } - - // Create the new media object. - - IOMedia * newMedia = instantiateDesiredMediaObject( - /* partition */ partition, - /* partitionID */ partitionID, - /* fdiskBlock */ fdiskBlock ); - - if ( newMedia ) - { - if ( newMedia->init( - /* base */ partitionBase, - /* size */ partitionSize, - /* preferredBlockSize */ mediaBlockSize, - /* isEjectable */ media->isEjectable(), - /* isWhole */ false, - /* isWritable */ media->isWritable(), - /* contentHint */ partitionHint ) ) - { - // Set a name for this partition. - - char name[24]; - sprintf(name, "Untitled %ld", partitionID); - newMedia->setName(name); - - // Set a location value (the partition number) for this partition. - - char location[12]; - sprintf(location, "%ld", partitionID); - newMedia->setLocation(location); - - // Set the "Partition ID" key for this partition. - - newMedia->setProperty(kIOMediaPartitionIDKey, partitionID, 32); - } - else - { - newMedia->release(); - newMedia = 0; - } - } - - return newMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOFDiskPartitionScheme::instantiateDesiredMediaObject( - fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ) -{ - // - // Allocate a new media object (called from instantiateMediaObject). - // - - return new IOMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOFDiskPartitionScheme, 15); diff --git a/iokit/Families/IOStorage/IOMedia.cpp b/iokit/Families/IOStorage/IOMedia.cpp deleted file mode 100644 index 9d97057c7..000000000 --- a/iokit/Families/IOStorage/IOMedia.cpp +++ /dev/null @@ -1,792 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <machine/limits.h> // (ULONG_MAX, ...) -#include <IOKit/IODeviceTreeSupport.h> // (gIODTPlane, ...) -#include <IOKit/storage/IOMedia.h> - -#define super IOStorage -OSDefineMetaClassAndStructors(IOMedia, IOStorage) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOStorage * IOMedia::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method to - // return a more specific subclass of OSObject -- IOStorage. This method - // serves simply as a convenience to subclass developers. - // - - return (IOStorage *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::init(UInt64 base, - UInt64 size, - UInt64 preferredBlockSize, - bool isEjectable, - bool isWhole, - bool isWritable, - const char * contentHint = 0, - OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - if (super::init(properties) == false) return false; - - _mediaBase = base; - _mediaSize = size; - _isEjectable = isEjectable; - _isWhole = isWhole; - _isWritable = isWritable; - _openLevel = kIOStorageAccessNone; - _openReaders = OSSet::withCapacity(1); - _openReaderWriter = 0; - _preferredBlockSize = preferredBlockSize; - - if (_openReaders == 0) return false; - - // - // Create the standard media registry properties. - // - - setProperty(kIOMediaContentKey, contentHint ? contentHint : ""); - setProperty(kIOMediaContentHintKey, contentHint ? contentHint : ""); - setProperty(kIOMediaEjectableKey, isEjectable); - setProperty(kIOMediaLeafKey, true); - setProperty(kIOMediaPreferredBlockSizeKey, preferredBlockSize, 64); - setProperty(kIOMediaSizeKey, size, 64); - setProperty(kIOMediaWholeKey, isWhole); - setProperty(kIOMediaWritableKey, isWritable); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMedia::free(void) -{ - // - // Free all of this object's outstanding resources. - // - - if (_openReaders) _openReaders->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::attachToChild(IORegistryEntry * client, - const IORegistryPlane * plane) -{ - // - // This method is called for each client interested in the services we - // provide. The superclass links us as a parent to this client in the - // I/O Kit registry on success. - // - - OSString * s; - - // Ask our superclass' opinion. - - if (super::attachToChild(client, plane) == false) return false; - - // - // Determine whether the client is a storage object, which we consider - // to be a consumer of this storage object's content and a producer of - // new content. A storage object need not be an IOStorage subclass, so - // long as it identifies itself with a match category of "IOStorage". - // - // If the client is indeed a storage object, we reset the media's Leaf - // property to false and replace the media's Content property with the - // client's Content Mask property, if any. - // - - s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey)); - - if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory)) - { - setProperty(kIOMediaLeafKey, false); - - s = OSDynamicCast(OSString,client->getProperty(kIOMediaContentMaskKey)); - if (s) setProperty(kIOMediaContentKey, s->getCStringNoCopy()); - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMedia::detachFromChild(IORegistryEntry * client, - const IORegistryPlane * plane) -{ - // - // This method is called for each client that loses interest in the - // services we provide. The superclass unlinks us from this client - // in the I/O Kit registry on success. - // - // Note that this method is called at a nondeterministic time after - // our client is terminated, which means another client may already - // have arrived and attached in the meantime. This is not an issue - // should the termination be issued synchrnously, however, which we - // take advantage of when this media needs to eliminate one of its - // clients. If the termination was issued on this media or farther - // below in the hierarchy, we don't really care that the properties - // would not be consistent since this media object is going to die - // anyway. - // - - OSString * s; - - // - // Determine whether the client is a storage object, which we consider - // to be a consumer of this storage object's content and a producer of - // new content. A storage object need not be an IOStorage subclass, so - // long as it identifies itself with a match category of "IOStorage". - // - // If the client is indeed a storage object, we reset the media's Leaf - // property to true and reset the media's Content property to the hint - // we obtained when this media was initialized. - // - - s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey)); - - if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory)) - { - setProperty(kIOMediaContentKey, getContentHint()); - setProperty(kIOMediaLeafKey, true); - } - - // Pass the call onto our superclass. - - super::detachFromChild(client, plane); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::handleOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - // - // The handleOpen method grants or denies permission to access this object - // to an interested client. The argument is an IOStorageAccess value that - // specifies the level of access desired -- reader or reader-writer. - // - // This method can be invoked to upgrade or downgrade the access level for - // an existing client as well. The previous access level will prevail for - // upgrades that fail, of course. A downgrade should never fail. If the - // new access level should be the same as the old for a given client, this - // method will do nothing and return success. In all cases, one, singular - // close-per-client is expected for all opens-per-client received. - // - // This method will work even when the media is in the terminated state. - // - // We are guaranteed that no other opens or closes will be processed until - // we make our decision, change our state, and return from this method. - // - - IOStorageAccess access = (IOStorageAccess) argument; - IOStorageAccess level; - - assert(client); - - // - // Chart our course of action. - // - - switch (access) - { - case kIOStorageAccessReader: - { - if (_openReaders->containsObject(client)) // (access: no change) - return true; - else if (_openReaderWriter == client) // (access: downgrade) - level = kIOStorageAccessReader; - else // (access: new reader) - level = _openReaderWriter ? kIOStorageAccessReaderWriter - : kIOStorageAccessReader; - break; - } - case kIOStorageAccessReaderWriter: - { - if (_openReaders->containsObject(client)) // (access: upgrade) - level = kIOStorageAccessReaderWriter; - else if (_openReaderWriter == client) // (access: no change) - return true; - else // (access: new writer) - level = kIOStorageAccessReaderWriter; - - if (_isWritable == false) // (is this media object writable?) - return false; - - if (_openReaderWriter) // (does a reader-writer already exist?) - return false; - - break; - } - default: - { - assert(0); - return false; - } - } - - // - // If we are in the terminated state, we only accept downgrades. - // - - if (isInactive() && _openReaderWriter != client) // (dead? not a downgrade?) - return false; - - // - // Determine whether the storage objects above us can be torn down, should - // this be a new reader-writer open or an upgrade into a reader-writer (if - // the client issuing the open is not a storage object itself, of course). - // - - if (access == kIOStorageAccessReaderWriter) // (new reader-writer/upgrade?) - { - const OSSymbol * category = OSSymbol::withCString(kIOStorageCategory); - - if (category) - { - IOService * storageObject = getClientWithCategory(category); - category->release(); - - if (storageObject && storageObject != client) - { - if (storageObject->terminate(kIOServiceSynchronous) == false) - return false; - } - } - } - - // - // Determine whether the storage objects below us accept this open at this - // multiplexed level of access -- new opens, upgrades, and downgrades (and - // no changes in access) all enter through the same open api. - // - - if (_openLevel != level) // (has open level changed?) - { - IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); - - if (provider && provider->open(this, options, level) == false) - { - // - // We were unable to open the storage objects below us. We must - // recover from the terminate we issued above before bailing out, - // if applicable, by re-registering the media object for matching. - // - - if (access == kIOStorageAccessReaderWriter) - registerService(kIOServiceSynchronous); // (re-register media) - - return false; - } - } - - // - // Process the open. - // - // We make sure our open state is consistent before calling registerService - // (if applicable) since this method can be called again on the same thread - // (the lock protecting handleOpen is recursive, so access would be given). - // - - _openLevel = level; - - if (access == kIOStorageAccessReader) - { - _openReaders->setObject(client); - - if (_openReaderWriter == client) // (for a downgrade) - { - _openReaderWriter = 0; - registerService(kIOServiceSynchronous); // (re-register media) - } - } - else // (access == kIOStorageAccessReaderWriter) - { - _openReaderWriter = client; - - _openReaders->removeObject(client); // (for an upgrade) - } - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::handleIsOpen(const IOService * client) const -{ - // - // The handleIsOpen method determines whether the specified client, or any - // client if none is specificed, presently has an open on this object. - // - // This method will work even when the media is in the terminated state. - // - // We are guaranteed that no other opens or closes will be processed until - // we return from this method. - // - - if (client == 0) return (_openLevel != kIOStorageAccessNone); - - return ( _openReaderWriter == client || - _openReaders->containsObject(client) ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMedia::handleClose(IOService * client, IOOptionBits options) -{ - // - // A client is informing us that it is giving up access to our contents. - // - // This method will work even when the media is in the terminated state. - // - // We are guaranteed that no other opens or closes will be processed until - // we change our state and return from this method. - // - - assert(client); - - // - // Process the close. - // - - bool reregister = (_openReaderWriter == client) && (isInactive() == false); - - if (_openReaderWriter == client) // (is the client a reader-writer?) - { - _openReaderWriter = 0; - } - else if (_openReaders->containsObject(client)) // (is the client a reader?) - { - _openReaders->removeObject(client); - } - else // (is the client is an imposter?) - { - assert(0); - return; - } - - // - // Reevaluate the open we have on the level below us. If no opens remain, - // we close, or if no reader-writer remains, but readers do, we downgrade. - // - - IOStorageAccess level; - - if (_openReaderWriter) level = kIOStorageAccessReaderWriter; - else if (_openReaders->getCount()) level = kIOStorageAccessReader; - else level = kIOStorageAccessNone; - - if (_openLevel != level) // (has open level changed?) - { - IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); - - assert(level != kIOStorageAccessReaderWriter); - - if (provider) - { - if (level == kIOStorageAccessNone) // (is a close in order?) - { - provider->close(this, options); - } - else // (is a downgrade in order?) - { - bool success; - success = provider->open(this, 0, level); - assert(success); // (should never fail, unless avoided deadlock) - } - } - - _openLevel = level; // (set new open level) - } - - // - // If the reader-writer just closeed, re-register the media so that I/O Kit - // will attempt to match storage objects that may now be interested in this - // media. - // - // We make sure our open state is consistent before calling registerService - // (if applicable) since this method can be called again on the same thread - // (the lock protecting handleClose is recursive, so access would be given). - // - - if (reregister) - registerService(kIOServiceSynchronous); // (re-register media) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMedia::read(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // Read data from the storage object at the specified byte offset into the - // specified buffer, asynchronously. When the read completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the read. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - complete(completion, kIOReturnNoMedia); - return; - } - - if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock) - { - complete(completion, kIOReturnNotOpen); - return; - } - - if (_mediaSize == 0 || _preferredBlockSize == 0) - { - complete(completion, kIOReturnUnformattedMedia); - return; - } - - if (_mediaSize < byteStart + buffer->getLength()) - { - complete(completion, kIOReturnBadArgument); - return; - } - - byteStart += _mediaBase; - getProvider()->read(this, byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMedia::write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // Write data into the storage object at the specified byte offset from the - // specified buffer, asynchronously. When the write completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the write. - // - // This method will work even when the media is in the terminated state. - // - - if (isInactive()) - { - complete(completion, kIOReturnNoMedia); - return; - } - - if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock) - { - complete(completion, kIOReturnNotOpen); - return; - } - - if (_openReaderWriter != client) // (instantaneous value, no lock) - { -///m:2425148:workaround:commented:start -// complete(completion, kIOReturnNotPrivileged); -// return; -///m:2425148:workaround:commented:stop - } - - if (_isWritable == 0) - { - complete(completion, kIOReturnLockedWrite); - return; - } - - if (_mediaSize == 0 || _preferredBlockSize == 0) - { - complete(completion, kIOReturnUnformattedMedia); - return; - } - - if (_mediaSize < byteStart + buffer->getLength()) - { - complete(completion, kIOReturnBadArgument); - return; - } - - byteStart += _mediaBase; - getProvider()->write(this, byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOMedia::synchronizeCache(IOService * client) -{ - if (isInactive()) - { - return kIOReturnNoMedia; - } - - if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock) - { - return kIOReturnNotOpen; - } - - if (_openReaderWriter != client) // (instantaneous value, no lock) - { - return kIOReturnNotPrivileged; - } - - if (_isWritable == 0) - { - return kIOReturnLockedWrite; - } - - if (_mediaSize == 0 || _preferredBlockSize == 0) - { - return kIOReturnUnformattedMedia; - } - - return getProvider()->synchronizeCache(this); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt64 IOMedia::getPreferredBlockSize() const -{ - // - // Ask the media object for its natural block size. This information - // is useful to clients that want to optimize access to the media. - // - - return _preferredBlockSize; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt64 IOMedia::getSize() const -{ - // - // Ask the media object for its total length in bytes. - // - - return _mediaSize; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt64 IOMedia::getBase() const -{ - // - // Ask the media object for its byte offset relative to its provider media - // object below it in the storage hierarchy. - // - - return _mediaBase; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::isEjectable() const -{ - // - // Ask the media object whether it is ejectable. - // - - return _isEjectable; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::isFormatted() const -{ - // - // Ask the media object whether it is formatted. - // - - return (_mediaSize && _preferredBlockSize); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::isWritable() const -{ - // - // Ask the media object whether it is writable. - // - - return _isWritable; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::isWhole() const -{ - // - // Ask the media object whether it represents the whole disk. - // - - return _isWhole; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char * IOMedia::getContent() const -{ - // - // Ask the media object for a description of its contents. The description - // is the same as the hint at the time of the object's creation, but it is - // possible that the description be overrided by a client (which has probed - // the media and identified the content correctly) of the media object. It - // is more accurate than the hint for this reason. The string is formed in - // the likeness of Apple's "Apple_HFS" strings. - // - // The content description can be overrided by any client that matches onto - // this media object with a match category of kIOStorageCategory. The media - // object checks for a kIOMediaContentMaskKey property in the client, and if - // it finds one, it copies it into kIOMediaContentKey property. - // - - OSString * string; - - string = OSDynamicCast(OSString, getProperty(kIOMediaContentKey)); - if (string == 0) return ""; - return string->getCStringNoCopy(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char * IOMedia::getContentHint() const -{ - // - // Ask the media object for a hint of its contents. The hint is set at the - // time of the object's creation, should the creator have a clue as to what - // it may contain. The hint string does not change for the lifetime of the - // object and is also formed in the likeness of Apple's "Apple_HFS" strings. - // - - OSString * string; - - string = OSDynamicCast(OSString, getProperty(kIOMediaContentHintKey)); - if (string == 0) return ""; - return string->getCStringNoCopy(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMedia::matchPropertyTable(OSDictionary * table, SInt32 * score) -{ - // - // Compare the properties in the supplied table to this object's properties. - // - - // Ask our superclass' opinion. - - if (super::matchPropertyTable(table, score) == false) return false; - - // We return success if the following expression is true -- individual - // comparisions evaluate to truth if the named property is not present - // in the supplied table. - - return compareProperty(table, kIOMediaContentKey) && - compareProperty(table, kIOMediaContentHintKey) && - compareProperty(table, kIOMediaEjectableKey) && - compareProperty(table, kIOMediaLeafKey) && - compareProperty(table, kIOMediaSizeKey) && - compareProperty(table, kIOMediaWholeKey) && - compareProperty(table, kIOMediaWritableKey) ; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMedia, 15); diff --git a/iokit/Families/IOStorage/IOMediaBSDClient.cpp b/iokit/Families/IOStorage/IOMediaBSDClient.cpp deleted file mode 100644 index 13b3eb6f1..000000000 --- a/iokit/Families/IOStorage/IOMediaBSDClient.cpp +++ /dev/null @@ -1,2125 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <dev/disk.h> // (DKIOCGETBLOCKSIZE, ...) -#include <mach/vm_types.h> // (mach/vm_region.h, ...) -#include <mach/vm_region.h> // (VM_REGION_BASIC_INFO, ...) -#include <miscfs/devfs/devfs.h> // (devfs_make_node, ...) -#include <sys/buf.h> // (struct buf, ...) -#include <sys/conf.h> // (bdevsw_add, ...) -#include <sys/fcntl.h> // (FWRITE, ...) -#include <sys/ioccom.h> // (IOCGROUP, ...) -#include <sys/stat.h> // (S_ISBLK, ...) -#include <sys/uio.h> // (struct uio, ...) -#include <IOKit/assert.h> -#include <IOKit/IOBSD.h> -#include <IOKit/IODeviceTreeSupport.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/IOMessage.h> -#include <IOKit/storage/IOBlockStorageDriver.h> -#include <IOKit/storage/IOMedia.h> -#include <IOKit/storage/IOMediaBSDClient.h> - -#define super IOService -OSDefineMetaClassAndStructors(IOMediaBSDClient, IOService) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static IOMediaBSDClient * gIOMediaBSDClient = 0; - -const signed kMajor = 14; // (bsd interface [b|c]devsw major) -const unsigned kMinorsGrowCount = 16; // (entries to add on table growth) -const unsigned kMinorsMaxCount = 1 << 24; // (maximum entries; 24-bit minor) -const unsigned kAnchorsGrowCount = 2; // (entries to add on table growth) -const unsigned kAnchorsMaxCount = kMinorsMaxCount; // (maximum entries) - -#define kMsgBadWhole "%s: Peer whole media \"%s\" is not allowed.", getName() -#define kMsgNoWhole "%s: No whole media found for media \"%s\".\n", getName() -#define kMsgNoLocation "%s: No location is found for media \"%s\".\n", getName() - -#define IOMEDIABSDCLIENT_IOSTAT_SUPPORT // (enable iostat support for bsd) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -extern "C" -{ - int dkclose(dev_t dev, int flags, int devtype, struct proc *); - int dkioctl(dev_t dev, u_long cmd, caddr_t data, int, struct proc *); - int dkioctl_bdev(dev_t dev, u_long cmd, caddr_t data, int, struct proc *); - int dkopen(dev_t dev, int flags, int devtype, struct proc *); - int dkread(dev_t dev, struct uio * uio, int flags); - int dksize(dev_t dev); - void dkstrategy(struct buf * bp); - int dkwrite(dev_t dev, struct uio * uio, int flags); -} // extern "C" - -static struct bdevsw bdevswFunctions = -{ - /* d_open */ dkopen, - /* d_close */ dkclose, - /* d_strategy */ dkstrategy, - /* d_ioctl */ dkioctl_bdev, - /* d_dump */ eno_dump, - /* d_psize */ dksize, - /* d_type */ D_DISK -}; - -struct cdevsw cdevswFunctions = -{ - /* d_open */ dkopen, - /* d_close */ dkclose, - /* d_read */ dkread, - /* d_write */ dkwrite, - /* d_ioctl */ dkioctl, - /* d_stop */ eno_stop, - /* d_reset */ eno_reset, - /* d_ttys */ 0, - /* d_select */ eno_select, - /* d_mmap */ eno_mmap, - /* d_strategy */ eno_strat, - /* d_getc */ eno_getc, - /* d_putc */ eno_putc, - /* d_type */ D_TAPE -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -struct dio { dev_t dev; struct uio * uio; }; - -typedef void * dkr_t; /* dkreadwrite request */ -typedef enum { DKRTYPE_BUF, DKRTYPE_DIO } dkrtype_t; - -int dkreadwrite(dkr_t dkr, dkrtype_t dkrtype); -void dkreadwritecompletion(void *, void *, IOReturn, UInt64); - -#define get_kernel_task() kernel_task -#define get_user_task() current_task() - -#ifdef IOMEDIABSDCLIENT_IOSTAT_SUPPORT -#include <sys/dkstat.h> -IOBlockStorageDriver * dk_drive[DK_NDRIVE]; -#endif IOMEDIABSDCLIENT_IOSTAT_SUPPORT - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const UInt32 kInvalidAnchorID = (UInt32) (-1); - -struct AnchorSlot -{ - UInt32 isAssigned:1, // (anchor slot is occupied) - isObsolete:1; // (anchor slot is to be removed once refs gone) - - IOService * anchor; // (anchor object) - IONotifier * notifier; // (anchor termination notification, post-stop) -}; - -class AnchorTable -{ -protected: - AnchorSlot * _table; - UInt32 _tableCount; - UInt32 _tableGrowCount; - UInt32 _tableMaxCount; - - static IOReturn anchorWasNotified( void * target, - void * parameter, - UInt32 messageType, - IOService * provider, - void * messageArgument, - vm_size_t messageArgumentSize ); - -public: - AnchorTable(UInt32 growCount, UInt32 maxCount); - ~AnchorTable(); - - UInt32 insert(IOService * anchor); - UInt32 locate(IOService * anchor); - void obsolete(UInt32 anchorID); - void remove(UInt32 anchorID); - - bool isObsolete(UInt32 anchorID); -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const UInt32 kInvalidMinorID = (UInt32) (-1); - -struct MinorSlot -{ - UInt32 isAssigned:1, // (minor slot is occupied) - isEjecting:1, // (minor slot is in eject flux, needs close) - isObsolete:1; // (minor slot is in eject flux, needs removal) - - UInt32 anchorID; // (minor's associated anchor ID) - IOMedia * media; // (minor's media object) - char * name; // (minor's name, private allocation space) - - UInt64 bdevBlockSize; // (block device's preferred block size) - void * bdevNode; // (block device's devfs node) - UInt32 bdevOpen:1, // (block device's open flag) - bdevWriter:1; // (block device's open writer flag) - - void * cdevNode; // (character device's devfs node) - UInt32 cdevOpen:1, // (character device's open flag) - cdevWriter:1; // (character device's open writer flag) -}; - -class MinorTable -{ -protected: - MinorSlot * _table; - UInt32 _tableCount; - UInt32 _tableGrowCount; - UInt32 _tableMaxCount; - -public: - MinorTable(UInt32 growCount, UInt32 maxCount); - ~MinorTable(); - - UInt32 insert(IOMedia * media, UInt32 anchorID, char * slicePath); - UInt32 locate(IOMedia * media); - void obsolete(UInt32 minorID); - void remove(UInt32 minorID); - - bool isObsolete(UInt32 minorID); - - MinorSlot * getMinor(UInt32 minorID); - - UInt32 getOpenCountForAnchorID(UInt32 anchorID); - IOMedia * getWholeMediaAtAnchorID(UInt32 anchorID); - bool hasReferencesToAnchorID(UInt32 anchorID); -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMediaBSDClient::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - if ( super::init(properties) == false ) return false; - - _anchors = new AnchorTable(kAnchorsGrowCount, kAnchorsMaxCount); - _bdevswInstalled = false; - _cdevswInstalled = false; - _minors = new MinorTable(kMinorsGrowCount, kMinorsMaxCount); - _notifier = 0; - - if ( _anchors == 0 || _minors == 0 ) return false; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMediaBSDClient::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _notifier ) _notifier->remove(); - if ( _cdevswInstalled ) cdevsw_remove(kMajor, &cdevswFunctions); - if ( _bdevswInstalled ) bdevsw_remove(kMajor, &bdevswFunctions); - if ( _minors ) delete _minors; - if ( _anchors ) delete _anchors; - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMediaBSDClient::start(IOService * provider) -{ - // - // This method is called once we have been attached to the provider object. - // - - assert(gIOMediaBSDClient == 0); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Establish a global reference to this instance. - - gIOMediaBSDClient = this; - - // Install bdevsw and cdevsw functions. - - _bdevswInstalled = (bdevsw_add(kMajor, &bdevswFunctions) == kMajor); - _cdevswInstalled = (cdevsw_add(kMajor, &cdevswFunctions) == kMajor); - - if ( _bdevswInstalled == false && _cdevswInstalled == false ) return false; - - // Create a notification handler for media arrival. We ask for a priority - // of ten to ensure that we are notified ahead of other interested clients - // (with a default priority of zero), so that we can place the BSD-related - // properties on the media object that they might need in time. - - _notifier = addNotification( /* type */ gIOFirstPublishNotification, - /* description */ serviceMatching("IOMedia"), - /* action */ mediaHasArrived, - /* target */ this, - /* parameter */ 0, - /* priority */ 10 ); - - if ( _notifier == 0 ) return false; - - // Register this object so it can be found via notification requests. It is - // not being registered to have I/O Kit attempt to have drivers match on it, - // which is the reason most other services are registered -- that's not the - // intention of this registerService call. - - registerService(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOMediaBSDClient::stop(IOService * provider) -{ - // - // This method is called before we are detached from the provider object. - // - - IOMedia * media = (IOMedia *) provider; - UInt32 minorID = 0; - - // Disable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->lockForArbitration(); - - // Find the minor assigned to this media. - - minorID = _minors->locate(media); - assert(minorID != kInvalidMinorID); - - // State our assumptions. - - assert(media->isOpen() == false); - - // Remove the minor from the minor table, unless it's still in flux (which - // means an open on the bdevsw/cdevsw switch is still outstanding: the one - // that sent the eject ioctl), in which case we mark the minor as obsolete - // for later removal. - - if ( _minors->getMinor(minorID)->isEjecting ) // (is minor in flux?) - { - assert(_minors->isObsolete(minorID) == false); - - _minors->obsolete(minorID); - } - else - { - assert(_minors->getMinor(minorID)->bdevOpen == false); - assert(_minors->getMinor(minorID)->cdevOpen == false); - - _minors->remove(minorID); - } - - // Enable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->unlockForArbitration(); - - // Call upon the superclass to finish its work. - - super::stop(media); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMediaBSDClient::mediaHasArrived( void * /* target */, - void * /* parameter */, - IOService * service ) -{ - // - // Notification handler for media arrivals. - // - - IOMedia * media = OSDynamicCast(IOMedia, service); - bool success = false; - - assert(gIOMediaBSDClient); - - // Attach the media-bsd-client object as a client of the new media object. - - if ( media && gIOMediaBSDClient->attach(media) ) - { - // Disable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->lockForArbitration(); - - // Create bdevsw and cdevsw nodes for the new media object. - - success = gIOMediaBSDClient->createNodes(media); - - // Enable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->unlockForArbitration(); - - // Detach the media-bsd-client object from the media object on error. - - if (success == false) gIOMediaBSDClient->detach(media); - } - - return true; // (meaningless return value) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOMediaBSDClient::getWholeMedia( IOMedia * media, - UInt32 * slicePathSize = 0, - char * slicePath = 0 ) -{ - // - // Find the whole media that roots this media tree. A null return value - // indicates no whole media was found or a malformed tree was detected. - // - // If slicePathSize is non-zero, the size required to fit the slice path - // (including the zero terminator) is passed back as a result. - // - // If slicePathSize and slicePath are both non-zero, the slice path will - // be written into the slicePath buffer. The value slicePathSize points - // to must be the size of the slicePath buffer, which is used for sanity - // checking in this method. - // - - UInt32 depth = 1; - UInt32 position = sizeof('\0'); - IOService * service = 0; - - assert(slicePath == 0 || slicePathSize != 0); - - // Search the registry for the parent whole media for this media. - - for ( service = media; service; service = service->getProvider() ) - { - if ( OSDynamicCast(IOMedia, service) ) // (is it a media?) - { - if ( ((IOMedia *)service)->isWhole() ) // (is it a whole media?) - { - if ( slicePath ) // (are we building the slice path?) - { - slicePath[*slicePathSize - 1] = 0; // (zero terminate path) - - if ( position < *slicePathSize ) // (need to move path?) - { - memmove( slicePath, // (move path to start of buffer) - slicePath + (*slicePathSize - position), - position ); - } - } - else if ( slicePathSize ) // (report size req'd for slice path?) - { - *slicePathSize = position; - } - - return (IOMedia *)service; // (return the whole media) - } - - // Determine whether this non-whole media has a location value. It - // must, by definition of a non-whole media, but if it does not, we - // should return an error condition. - - const char * location = service->getLocation(); - - if ( location == 0 ) // (no location on non-whole media?) - { - if ( service == media ) IOLog(kMsgNoLocation, media->getName()); - return 0; - } - - // Otherwise, it's a valid non-whole media: we compute the required - // size for the slice path or build the slice path, if so requested. - // Note that the slice path is built backwards from the ends of the - // supplied buffer to the beginning of the buffer. - - position += sizeof('s') + strlen(location); - - if ( slicePath ) // (build the slice path?) - { - char * path = slicePath + *slicePathSize - position; - - if ( position > *slicePathSize ) { assert(0); return 0; } - - *path = 's'; - strncpy(path + sizeof('s'), location, strlen(location)); - } - - depth += 1; - } - } - - // If we've fallen through, then the whole media was never found. - - if ( depth == 1 ) IOLog(kMsgNoWhole, media->getName()); - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOMediaBSDClient::createNodes(IOMedia * media) -{ - // - // Create bdevsw and cdevsw nodes for the given media object. - // - // This method assumes that the arbitration lock is held. - // - - IOService * anchor; - UInt32 anchorID; - bool anchorNew = false; - UInt32 minorID; - char * slicePath = 0; - UInt32 slicePathSize; - IOMedia * whole; - - // - // Find the anchor that roots this media tree. The anchor is defined as the - // parent of the whole media that roots this media tree. It is an important - // object to us because this object stays in place when media is ejected, so - // we can continue to maintain the "unit number" of the "drive" such that if - // media is re-inserted, it will show up under the same "unit number". You - // can think of the typical anchor as being the drive, if it helps, although - // it could be one of many other kinds of drivers (eg. a RAID scheme). - // - - whole = getWholeMedia(media, &slicePathSize); - if ( whole == 0 ) return false; - - anchor = whole->getProvider(); - if ( anchor == 0 ) return false; - - // - // Determine whether the anchor already exists in the anchor table (obsolete - // occurences are skipped in the search, as appropriate, since those anchor - // IDs are to be removed soon). If the anchor does not exist, insert it into - // anchor table. - // - - anchorID = _anchors->locate(anchor); - - if ( anchorID != kInvalidAnchorID ) - { - // - // The anchor does exist in the table, however we've got more to check. - // - // We need to ensure that the whole media associated with this anchor is - // the same as ours. If it is, all is well. If it isn't, then there is - // still a chance all is well. It is possible to have an old media tree - // still associated with the anchor: the tree would be inactive, but not - // yet terminated (this can happen on forced termination of a media tree - // with oustanding opens, since the close must come before the terminate - // can proceed; it can happen even in normal eject conditions should the - // media be immediately reinserted when the termination on the old tree, - // which is asynchronous, is still chugging along on another thread). In - // case the tree is inactive, we mark the anchorID as obsolete and use a - // new anchorID. In the case the tree is not inactive, then we've got a - // problem and we must bail out. - // - // A few additional notes: - // - // o if the whole media is indeed the same as the one in our tables, we - // need not check that it is active, because by virtue of the fact we - // got a new media notification on the same tree, we know for sure it - // cannot be in the inactive state. - // - // o if the whole media is not in our tables, it is quite possible that - // some child non-whole media from the old media tree is still around - // as terminations work from the bottom (whole media) up (to leaves), - // and the asynchronous termination thread is still not done chugging - // through the medias on the old tree. We use a new anchorID in this - // case. - // - - IOMedia * wholeInTable = _minors->getWholeMediaAtAnchorID(anchorID); - - if ( wholeInTable == 0 ) // (is an existing whole media in our tables?) - { - if ( _minors->hasReferencesToAnchorID(anchorID) ) // (any medias?) - { - _anchors->obsolete(anchorID); // (obsolete old anchor ID) - anchorID = kInvalidAnchorID; // ( request new anchor ID) - } // (else, all is well) - } - else if ( whole != wholeInTable ) // (old whole media not same as new?) - { - if ( wholeInTable->isInactive() ) // (is it inactive/terminating?) - { - _anchors->obsolete(anchorID); // (obsolete old anchor ID) - anchorID = kInvalidAnchorID; // ( request new anchor ID) - } - else // (peer active whole medias detected, log error) - { - if ( whole == media ) IOLog(kMsgBadWhole, whole->getName()); - return false; - } - } // (else, all is well) - } - - if ( anchorID == kInvalidAnchorID ) - { - anchorID = _anchors->insert(anchor); // (get new anchor ID) - if ( anchorID == kInvalidAnchorID ) return false; - anchorNew = true; - } - - // - // Allocate space for and build the slice path for the device node names. - // - - slicePath = (char *) IOMalloc(slicePathSize); - if ( slicePath == 0 ) goto createNodesErr; - - whole = getWholeMedia(media, &slicePathSize, slicePath); - assert(whole); - - // - // Insert the new media into our minor table (we're almost done :-). - // - - minorID = _minors->insert(media, anchorID, slicePath); - if ( minorID == kInvalidMinorID ) goto createNodesErr; - - // - // Create the required properties on the media. - // - - media->setProperty(kIOBSDNameKey, _minors->getMinor(minorID)->name); - media->setProperty(kIOBSDUnitKey, anchorID, 32); // ("BSD Unit" ) - media->setProperty(kIOBSDMajorKey, kMajor, 32); // ("BSD Major") - media->setProperty(kIOBSDMinorKey, minorID, 32); // ("BSD Minor") - - // - // Clean up outstanding resources. - // - - IOFree(slicePath, slicePathSize); - - return true; // (success) - -createNodesErr: - - if (anchorNew) _anchors->remove(anchorID); - if (slicePath) IOFree(slicePath, slicePathSize); - - return false; // (failure) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AnchorTable * IOMediaBSDClient::getAnchors() -{ - // - // Obtain the table of anchors. - // - - return _anchors; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MinorTable * IOMediaBSDClient::getMinors() -{ - // - // Obtain the table of anchors. - // - - return _minors; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MinorSlot * IOMediaBSDClient::getMinor(UInt32 minorID) -{ - // - // Obtain information for the specified minor ID. - // - - return _minors->getMinor(minorID); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOMediaBSDClient, 15); - -// ============================================================================= -// BSD Functions - -int dkopen(dev_t dev, int flags, int devtype, struct proc *) -{ - // - // dkopen opens the device (called on each open). - // - - int error; - IOStorageAccess level; - MinorSlot * minor; - - assert(gIOMediaBSDClient); - assert(S_ISBLK(devtype) || S_ISCHR(devtype)); - - gIOMediaBSDClient->lockForArbitration(); // (disable access) - - assert(gIOMediaBSDClient->getMinors()); - - error = 0; - level = (flags & FWRITE) ? kIOStorageAccessReaderWriter - : kIOStorageAccessReader; - minor = gIOMediaBSDClient->getMinor(minor(dev)); - - // - // Process the open. - // - - if ( minor == 0 ) // (is minor valid?) - { - error = ENXIO; - } - else if ( minor->isEjecting ) // (is minor in flux?) - { - error = EBUSY; - } - else if ( (flags & FWRITE) ) // (is client a writer?) - { - if ( minor->bdevWriter || minor->cdevWriter ) - level = kIOStorageAccessNone; - } - else // (is client a reader?) - { - if ( minor->bdevOpen || minor->cdevOpen ) - level = kIOStorageAccessNone; - } - - if ( error == 0 && level != kIOStorageAccessNone ) // (issue open/upgrade?) - { - if ( minor->media->open(gIOMediaBSDClient, 0, level) == false ) // (go) - { - error = EBUSY; - } - } - - if ( error == 0 ) // (update state) - { - if ( S_ISBLK(devtype) ) - { - minor->bdevOpen = true; - if ( (flags & FWRITE) ) minor->bdevWriter = true; - } - else - { - minor->cdevOpen = true; - if ( (flags & FWRITE) ) minor->cdevWriter = true; - } - } - - gIOMediaBSDClient->unlockForArbitration(); // (enable access) - - return error; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkclose(dev_t dev, int /* flags */, int devtype, struct proc *) -{ - // - // dkclose closes the device (called on last close). - // - - MinorSlot * minor; - bool wasWriter; - - assert(S_ISBLK(devtype) || S_ISCHR(devtype)); - - gIOMediaBSDClient->lockForArbitration(); // (disable access) - - minor = gIOMediaBSDClient->getMinor(minor(dev)); - wasWriter = (minor->bdevWriter || minor->cdevWriter); - - if ( S_ISBLK(devtype) ) // (update state) - { - minor->bdevBlockSize = minor->media->getPreferredBlockSize(); - minor->bdevOpen = false; - minor->bdevWriter = false; - } - else - { - minor->cdevOpen = false; - minor->cdevWriter = false; - } - - if ( minor->isEjecting ) // (is minor in flux?) - { - // - // We've determined that the specified minor is in ejection flux. This - // means we are in a state where the media object has been closed, only - // the device node is still open. This happens to the minor subsequent - // to a DKIOCEJECT ioctl -- this close resets the flux state to normal. - // - - minor->isEjecting = false; - - // If this minor is marked as obsolete, then we've already received the - // media's termination notification (stop method), but the minor is yet - // to be removed from the table -- remove it now. - - assert(minor->bdevOpen == false); - assert(minor->cdevOpen == false); - - if ( minor->isObsolete ) - gIOMediaBSDClient->getMinors()->remove(minor(dev)); - } - else if ( !minor->bdevOpen && !minor->cdevOpen ) - { - // - // We communicate the close down to the media object once all opens are - // gone, on both the block and character device nodes. - // - - minor->media->close(gIOMediaBSDClient); // (go) - } - else if ( !minor->bdevWriter && !minor->cdevWriter && wasWriter ) - { - // - // We communicate a downgrade down to the media object once all writers - // are gone and while readers still exist. - // - - bool s; - s = minor->media->open(gIOMediaBSDClient, 0, kIOStorageAccessReader); - assert(s); // (should never fail, unless deadlock avoided) - } - - gIOMediaBSDClient->unlockForArbitration(); // (enable access) - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkread(dev_t dev, struct uio * uio, int /* flags */) -{ - // - // dkread reads data from a device. - // - - struct dio dio = { dev, uio }; - - return dkreadwrite(&dio, DKRTYPE_DIO); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkwrite(dev_t dev, struct uio * uio, int /* flags */) -{ - // - // dkwrite writes data to a device. - // - - struct dio dio = { dev, uio }; - - return dkreadwrite(&dio, DKRTYPE_DIO); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void dkstrategy(struct buf * bp) -{ - // - // dkstrategy starts an asynchronous read or write operation. It returns - // to the caller as soon as the operation is queued, and completes it via - // the biodone function. - // - - dkreadwrite(bp, DKRTYPE_BUF); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkioctl(dev_t dev, u_long cmd, caddr_t data, int, struct proc *) -{ - // - // dkioctl performs operations other than a read or write. - // - - int error = 0; - MinorSlot * minor = gIOMediaBSDClient->getMinor(minor(dev)); - - if ( minor->isEjecting ) return EBADF; // (is minor in flux?) - - // - // Process the ioctl. - // - - switch ( cmd ) - { - case DKIOCGETBLOCKSIZE: // getBlockSize(int * out); - { - // - // This ioctl returns the preferred block size of the media object. - // - - *(int *)data = (int) minor->media->getPreferredBlockSize(); - - } break; - - case DKIOCGETBLOCKCOUNT: // getBlockCount(int * out); - { - // - // This ioctl returns the size of the media object in blocks. The - // implied block size is returned by DKIOCGETBLOCKSIZE. - // - - if ( minor->media->getPreferredBlockSize() ) - *(int *)data = (int) ( minor->media->getSize() / - minor->media->getPreferredBlockSize() ); - else - *(int *)data = 0; - - } break; - - case DKIOCISFORMATTED: // isFormatted(int * out); - { - // - // This ioctl returns truth if the media object is formatted. - // - - *(int *)data = (int) minor->media->isFormatted(); - - } break; - - case DKIOCISWRITABLE: // isWritable(int * out); - { - // - // This ioctl returns truth if the media object is writable. - // - - *(int *)data = (int) minor->media->isWritable(); - - } break; - - case DKIOCGETLOCATION: // getLocation(char[128] out); - { - // - // This ioctl returns the open firmware path for this media object. - // - - int l = sizeof(((struct drive_location *)data)->location); - char * p = ((struct drive_location *)data)->location; - - if ( minor->media->getPath(p, &l, gIODTPlane) && strchr(p, ':') ) - strcpy(p, strchr(p, ':') + 1); // (strip the plane name) - else - error = EINVAL; - - } break; - - case DKIOCEJECT: // eject(void); - { - // - // This ioctl asks that the media object be ejected from the device. - // - - IOBlockStorageDriver * driver; - MinorTable * minors; - - driver = OSDynamicCast( IOBlockStorageDriver, - minor->media->getProvider() ); - minors = gIOMediaBSDClient->getMinors(); - - // Determine whether this media has an IOBlockStorageDriver parent. - - if ( driver == 0 ) { error = ENOTTY; break; } - - // Disable access to tables, matching, opens, closes, terminations. - - gIOMediaBSDClient->lockForArbitration(); - - // Determine whether there are other opens on the device nodes that - // are associated with this anchor -- the one valid open is the one - // that issued this eject. - - if ( minors->getOpenCountForAnchorID(minor->anchorID) > 1 ) - { - error = EBUSY; - - // Enable access to tables, matching, opens, closes, and so on. - - gIOMediaBSDClient->unlockForArbitration(); - } - else - { - IOReturn status; - - // Mark this minor as being in ejection flux (which means are in - // a state where the media object has been closed but the device - // node is still open; we must reject all future accesses to the - // device node until it is closed; note that we do this both on - // success and failure of the ejection call). - - minor->isEjecting = true; - - // Enable access to tables, matching, opens, closes, and so on. - - gIOMediaBSDClient->unlockForArbitration(); - - // Close the media object before the ejection request is made. - - minor->media->close(gIOMediaBSDClient); - - // Open the block storage driver to make the ejection request. - - if (driver->open(gIOMediaBSDClient, 0, kIOStorageAccessReader)) - { - // Eject the media from the drive. - - status = driver->ejectMedia(); - - // Close the block storage driver. - - driver->close(gIOMediaBSDClient); - } - else - { - status = kIOReturnBusy; - } - - error = gIOMediaBSDClient->errnoFromReturn(status); - } - - } break; - - default: - { - // - // A foreign ioctl was received. Log an error to the console. - // - - IOLog( "%s: ioctl(%s\'%c\',%d,%d) is unsupported.\n", - minor->name, - ((cmd & IOC_INOUT) == IOC_INOUT) ? ("_IOWR,") : - ( ((cmd & IOC_OUT) == IOC_OUT) ? ("_IOR,") : - ( ((cmd & IOC_IN) == IOC_IN) ? ("_IOW,") : - ( ((cmd & IOC_VOID) == IOC_VOID) ? ("_IO,") : "" ) ) ), - (char) IOCGROUP(cmd), - (int) (cmd & 0xff), - (int) IOCPARM_LEN(cmd) ); - - error = ENOTTY; - - } break; - } - - return error; // (return error status) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkioctl_bdev(dev_t dev, u_long cmd, caddr_t data, int f, struct proc * proc) -{ - // - // dkioctl_bdev performs operations other than a read or write, specific to - // the block device. - // - - int error = 0; - MinorSlot * minor = gIOMediaBSDClient->getMinor(minor(dev)); - - if ( minor->isEjecting ) return EBADF; // (is minor in flux?) - - // - // Process the ioctl. - // - - switch ( cmd ) - { - case DKIOCGETBLOCKSIZE: // getBlockSize(int * out); - { - // - // This ioctl returns the preferred (or overrided) block size of the - // media object. - // - - *(int *)data = (int) minor->bdevBlockSize; - - } break; - - case DKIOCSETBLOCKSIZE: // setBlockSize(int * in); - { - // - // This ioctl overrides the block size for the media object, for the - // duration of all block device opens at this minor. - // - - if ( *(int *)data > 0 ) - minor->bdevBlockSize = (UInt64) (*(int *)data); - else - error = EINVAL; - - } break; - - case DKIOCGETBLOCKCOUNT: // getBlockCount(int * out); - { - // - // This ioctl returns the size of the media object in blocks. The - // implied block size is returned by DKIOCGETBLOCKSIZE. - // - - if ( minor->bdevBlockSize ) - *(int *)data = (int) ( minor->media->getSize() / - minor->bdevBlockSize ); - else - *(int *)data = 0; - - } break; - - default: - { - // - // Call the common ioctl handler for all other ioctls. - // - - error = dkioctl(dev, cmd, data, f, proc); - - } break; - } - - return error; // (return error status) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dksize(dev_t dev) -{ - // - // dksize returns the block size of the media. - // - // This is a departure from BSD 4.4's definition of this function, that is, - // it will not return the size of the disk partition, as would be expected - // in a BSD 4.4 implementation. - // - - MinorSlot * minor = gIOMediaBSDClient->getMinor(minor(dev)); - - if ( minor->isEjecting ) return 0; // (is minor in flux?) - - return (int) minor->bdevBlockSize; // (return block size) -} - -// ============================================================================= -// Support For BSD Functions - -inline dev_t DKR_GET_DEV(dkr_t dkr, dkrtype_t dkrtype) -{ - return (dkrtype == DKRTYPE_BUF) - ? ((struct buf *)dkr)->b_dev - : ((struct dio *)dkr)->dev; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline UInt64 DKR_GET_BYTE_COUNT(dkr_t dkr, dkrtype_t dkrtype) -{ - return (dkrtype == DKRTYPE_BUF) - ? ((struct buf *)dkr)->b_bcount - : ((struct dio *)dkr)->uio->uio_resid; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline UInt64 DKR_GET_BYTE_START(dkr_t dkr, dkrtype_t dkrtype) -{ - if (dkrtype == DKRTYPE_BUF) - { - struct buf * bp = (struct buf *)dkr; - MinorSlot * minor = gIOMediaBSDClient->getMinor(minor(bp->b_dev)); - - return bp->b_blkno * minor->bdevBlockSize; - } - return ((struct dio *)dkr)->uio->uio_offset; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline bool DKR_IS_READ(dkr_t dkr, dkrtype_t dkrtype) -{ - return (dkrtype == DKRTYPE_BUF) - ? ((((struct buf *)dkr)->b_flags & B_READ) == B_READ) - : ((((struct dio *)dkr)->uio->uio_rw) == UIO_READ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline bool DKR_IS_ASYNCHRONOUS(dkr_t dkr, dkrtype_t dkrtype) -{ - return (dkrtype == DKRTYPE_BUF) - ? true - : false; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline bool DKR_IS_RAW(dkr_t dkr, dkrtype_t dkrtype) -{ - return (dkrtype == DKRTYPE_BUF) - ? false - : true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline void DKR_SET_BYTE_COUNT(dkr_t dkr, dkrtype_t dkrtype, UInt64 bcount) -{ - if (dkrtype == DKRTYPE_BUF) - ((struct buf *)dkr)->b_resid = ((struct buf *)dkr)->b_bcount - bcount; - else - ((struct dio *)dkr)->uio->uio_resid -= bcount; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline void DKR_RUN_COMPLETION(dkr_t dkr, dkrtype_t dkrtype, IOReturn status) -{ - if (dkrtype == DKRTYPE_BUF) - { - struct buf * bp = (struct buf *)dkr; - - bp->b_error = gIOMediaBSDClient->errnoFromReturn(status); // (error?) - bp->b_flags |= (status != kIOReturnSuccess) ? B_ERROR : 0; // (error?) - biodone(bp); // (complete request) - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline IOMemoryDescriptor * DKR_GET_BUFFER(dkr_t dkr, dkrtype_t dkrtype) -{ - if (dkrtype == DKRTYPE_BUF) - { - struct buf * bp = (struct buf *)dkr; - - if ( (bp->b_flags & B_VECTORLIST) ) - { - assert(sizeof(IOPhysicalRange ) == sizeof(iovec )); - assert(sizeof(IOPhysicalRange::address) == sizeof(iovec::iov_base)); - assert(sizeof(IOPhysicalRange::length ) == sizeof(iovec::iov_len )); - - return IOMemoryDescriptor::withPhysicalRanges( // (multiple-range) - (IOPhysicalRange *) bp->b_vectorlist, - (UInt32) bp->b_vectorcount, - (bp->b_flags & B_READ) ? kIODirectionIn : kIODirectionOut, - true ); - } - - return IOMemoryDescriptor::withAddress( // (single-range) - (vm_address_t) bp->b_data, - (vm_size_t) bp->b_bcount, - (bp->b_flags & B_READ) ? kIODirectionIn : kIODirectionOut, - (bp->b_flags & B_PHYS) ? get_user_task() : get_kernel_task() ); - } - else - { - struct uio * uio = ((struct dio *)dkr)->uio; - - assert(sizeof(IOVirtualRange ) == sizeof(iovec )); - assert(sizeof(IOVirtualRange::address) == sizeof(iovec::iov_base)); - assert(sizeof(IOVirtualRange::length ) == sizeof(iovec::iov_len )); - - return IOMemoryDescriptor::withRanges( // (multiple-range) - (IOVirtualRange *) uio->uio_iov, - (UInt32) uio->uio_iovcnt, - (uio->uio_rw == UIO_READ ) ? kIODirectionIn : kIODirectionOut, - (uio->uio_segflg != UIO_SYSSPACE) ? get_user_task() : get_kernel_task(), - true ); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int dkreadwrite(dkr_t dkr, dkrtype_t dkrtype) -{ - // - // dkreadwrite performs a read or write operation. - // - - IOMemoryDescriptor * buffer; - register UInt64 byteCount; - register UInt64 byteStart; - UInt64 mediaSize; - MinorSlot * minor; - IOReturn status; - - minor = gIOMediaBSDClient->getMinor(minor(DKR_GET_DEV(dkr, dkrtype))); - - if ( minor->isEjecting ) // (is minor in flux?) - { - status = kIOReturnNoMedia; - goto dkreadwriteErr; - } - - if ( minor->media->isFormatted() == false ) // (is media unformatted?) - { - status = kIOReturnUnformattedMedia; - goto dkreadwriteErr; - } - - byteCount = DKR_GET_BYTE_COUNT(dkr, dkrtype); // (get byte count) - byteStart = DKR_GET_BYTE_START(dkr, dkrtype); // (get byte start) - mediaSize = minor->media->getSize(); // (get media size) - - // - // Reads that start at (or perhaps past) the end-of-media are not considered - // errors, even though no data is transferred, while writes at (or past) the - // end-of-media do indeed return errors under BSD semantics. - // - - if ( byteStart >= mediaSize ) // (is start at or past the end-of-media?) - { - status = DKR_IS_READ(dkr,dkrtype) ? kIOReturnSuccess : kIOReturnIOError; - goto dkreadwriteErr; - } - - // - // Reads and writes, via the character device, that do not start or end on a - // media block boundary are considered errors under BSD semantics. - // - - if ( DKR_IS_RAW(dkr, dkrtype) ) - { - UInt64 mediaBlockSize = minor->media->getPreferredBlockSize(); - - if ( (byteStart % mediaBlockSize) || (byteCount % mediaBlockSize) ) - { - status = kIOReturnNotAligned; - goto dkreadwriteErr; - } - } - - // - // Build a descriptor which describes the buffer involved in the transfer. - // - - buffer = DKR_GET_BUFFER(dkr, dkrtype); - - if ( buffer == 0 ) // (no buffer?) - { - status = kIOReturnNoMemory; - goto dkreadwriteErr; - } - - // - // Reads and writes that extend beyond the end-of-media are not considered - // errors under BSD semantics. We are to transfer as many bytes as can be - // read or written from the medium and return no error. This differs from - // IOMedia semantics which is to fail the entire request without copying a - // single byte should it include something past the end-of-media. We must - // adapt the IOMedia semantics to look like BSD semantics here. - // - // Clip the transfer buffer should this be a short read or write request. - // - - if ( byteCount > mediaSize - byteStart ) // (clip at end-of-media) - { - IOMemoryDescriptor * originalBuffer = buffer; - - buffer = IOMemoryDescriptor::withSubRange( - /* descriptor */ originalBuffer, - /* withOffset */ 0, - /* withLength */ mediaSize - byteStart, - /* withDirection */ originalBuffer->getDirection() ); - - originalBuffer->release(); // (either retained above or about to fail) - - if ( buffer == 0 ) // (no buffer?) - { - status = kIOReturnNoMemory; - goto dkreadwriteErr; - } - } - - // - // Execute the transfer. - // - - if ( DKR_IS_ASYNCHRONOUS(dkr, dkrtype) ) // (an asynchronous request?) - { - IOStorageCompletion completion; - - completion.target = dkr; - completion.action = dkreadwritecompletion; - completion.parameter = (void *) dkrtype; - - if ( DKR_IS_READ(dkr, dkrtype) ) // (a read?) - { - minor->media->read( /* client */ gIOMediaBSDClient, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* completion */ completion ); // (go) - } - else // (a write?) - { - minor->media->write( /* client */ gIOMediaBSDClient, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* completion */ completion ); // (go) - } - - status = kIOReturnSuccess; - } - else // (is this a synchronous request?) - { - if ( DKR_IS_READ(dkr, dkrtype) ) // (a read?) - { -///m:2333367:workaround:commented:start -// status = minor->media->read( -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = minor->media->IOStorage::read( -///m:2333367:workaround:added:stop - /* client */ gIOMediaBSDClient, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* actualByteCount */ &byteCount ); // (go) - } - else // (a write?) - { -///m:2333367:workaround:commented:start -// status = minor->media->write( -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = minor->media->IOStorage::write( -///m:2333367:workaround:added:stop - /* client */ gIOMediaBSDClient, - /* byteStart */ byteStart, - /* buffer */ buffer, - /* actualByteCount */ &byteCount ); // (go) - } - - dkreadwritecompletion(dkr, (void *)dkrtype, status, byteCount); - } - - // - // We release our retain on the buffer now, even though in the asynchronous - // case, the object needs to exist for the duration of the transfer. While - // this might appear to be a mistake, it is not. The layers below us will - // have retained the buffer themselves. - // - - buffer->release(); // (release our retain on the buffer) - - return gIOMediaBSDClient->errnoFromReturn(status); // (return error status) - -dkreadwriteErr: - - dkreadwritecompletion(dkr, (void *)dkrtype, status, 0); - - return gIOMediaBSDClient->errnoFromReturn(status); // (return error status) -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void dkreadwritecompletion( void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount ) -{ - // - // dkreadwritecompletion cleans up after a read or write operation. - // - - dkr_t dkr = (dkr_t) target; - dkrtype_t dkrtype = (dkrtype_t) (int) parameter; - dev_t dev = DKR_GET_DEV(dkr, dkrtype); - -#ifdef IOMEDIABSDCLIENT_IOSTAT_SUPPORT - UInt32 anchorID = gIOMediaBSDClient->getMinor(minor(dev))->anchorID; - - if ( anchorID < DK_NDRIVE ) - { - IOBlockStorageDriver * d = dk_drive[anchorID]; - - if ( d ) - { - dk_xfer[anchorID] = (long) - ( d->getStatistic(IOBlockStorageDriver::kStatisticsReads ) + - d->getStatistic(IOBlockStorageDriver::kStatisticsWrites) ); - dk_wds[anchorID] = (long) (8 * - ( d->getStatistic(IOBlockStorageDriver::kStatisticsBytesRead ) + - d->getStatistic(IOBlockStorageDriver::kStatisticsBytesWritten)) ); - } - } -#endif IOMEDIABSDCLIENT_IOSTAT_SUPPORT - - if ( status != kIOReturnSuccess ) // (log errors to the console) - { - IOLog( "%s: %s.\n", - gIOMediaBSDClient->getMinor(minor(dev))->name, - gIOMediaBSDClient->stringFromReturn(status) ); - } - - DKR_SET_BYTE_COUNT(dkr, dkrtype, actualByteCount); // (set byte count) - DKR_RUN_COMPLETION(dkr, dkrtype, status); // (run completion) -} - -// ============================================================================= -// AnchorTable Class - -AnchorTable::AnchorTable(UInt32 growCount, UInt32 maxCount) -{ - // - // Initialize this object's minimal state. - // - - _table = 0; - _tableCount = 0; - _tableGrowCount = growCount; - _tableMaxCount = maxCount; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -AnchorTable::~AnchorTable() -{ - // - // Free all of this object's outstanding resources. - // - - for ( UInt32 anchorID = 0; anchorID < _tableCount; anchorID++ ) - if ( _table[anchorID].isAssigned ) remove(anchorID); - - if ( _table ) IODelete(_table, AnchorSlot, _tableCount); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 AnchorTable::insert(IOService * anchor) -{ - // - // This method inserts the specified anchor into an unassigned slot in the - // anchor table and returns its ID (or kInvalidAnchorID on a failure). - // - // Note that the anchor is transparently removed from the table should the - // anchor terminate (or it is at least marked obsolete, should references - // to the anchor still exist in the minor table). - // - - UInt32 anchorID; - IONotifier * notifier; - - // Search for an unassigned slot in the anchor table. - - for ( anchorID = 0; anchorID < _tableCount; anchorID++ ) - if ( _table[anchorID].isAssigned == false ) break; - - // Was an unassigned slot found? If not, grow the table. - - if ( anchorID == _tableCount ) - { - AnchorSlot * newTable; - UInt32 newTableCount; - - // We must expand the anchor table since no more slots are available. - - if ( _tableCount >= _tableMaxCount ) return kInvalidAnchorID; - - newTableCount = min(_tableGrowCount + _tableCount, _tableMaxCount); - newTable = IONew(AnchorSlot, newTableCount); - - if ( newTable == 0 ) return kInvalidAnchorID; - - bzero(newTable, newTableCount * sizeof(AnchorSlot)); - - // Copy over the old table's entries, then free the old table. - - if ( _table ) - { - bcopy(_table, newTable, _tableCount * sizeof(AnchorSlot)); - IODelete(_table, AnchorSlot, _tableCount); - } - - // Obtain the next unassigned index (simple since we know the size of - // the old table), then update our instance variables to reflect the - // new tables. - - anchorID = _tableCount; - _table = newTable; - _tableCount = newTableCount; - } - - // Create a notification handler for the anchor's termination (post-stop); - // the handler will remove the anchor transparently from the table if the - // anchor terminates (or at least marks it obsolete, if references to the - // anchor still exist in the minor table). - - notifier = anchor->registerInterest( - /* type */ gIOGeneralInterest, - /* action */ anchorWasNotified, - /* target */ this, - /* parameter */ 0 ); - - if ( notifier == 0 ) return kInvalidAnchorID; - - // Zero the new slot, fill it in, and retain the anchor object. - - bzero(&_table[anchorID], sizeof(AnchorSlot)); // (zero slot) - - _table[anchorID].isAssigned = true; // (fill in slot) - _table[anchorID].isObsolete = false; - _table[anchorID].anchor = anchor; - _table[anchorID].notifier = notifier; - - _table[anchorID].anchor->retain(); // (retain anchor) - -#ifdef IOMEDIABSDCLIENT_IOSTAT_SUPPORT - if ( anchorID < DK_NDRIVE ) - { - dk_drive[anchorID] = OSDynamicCast(IOBlockStorageDriver, anchor); - if ( anchorID + 1 > (UInt32) dk_ndrive ) dk_ndrive = anchorID + 1; - } -#endif IOMEDIABSDCLIENT_IOSTAT_SUPPORT - - return anchorID; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AnchorTable::remove(UInt32 anchorID) -{ - // - // This method removes the specified anchor from the anchor table. - // - - assert(anchorID < _tableCount); - assert(_table[anchorID].isAssigned); - - // Release the resources retained in the anchor slot and zero it. - - _table[anchorID].notifier->remove(); - _table[anchorID].anchor->release(); // (release anchor) - - bzero(&_table[anchorID], sizeof(AnchorSlot)); // (zero slot) - -#ifdef IOMEDIABSDCLIENT_IOSTAT_SUPPORT - if ( anchorID < DK_NDRIVE ) - { - dk_drive[anchorID] = 0; - for (dk_ndrive = DK_NDRIVE; dk_ndrive; dk_ndrive--) - { - if ( dk_drive[dk_ndrive - 1] ) break; - } - } -#endif IOMEDIABSDCLIENT_IOSTAT_SUPPORT -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AnchorTable::obsolete(UInt32 anchorID) -{ - // - // This method obsoletes the specified anchor, that is, the slot is marked - // as obsolete and will be removed later via the minor table remove method - // once it detects references to the anchor ID drop to 0. Once obsoleted, - // the anchor can be considered to be removed, since it will not appear in - // locate searches, even though behind the scenes it still occupies a slot. - // - - assert(anchorID < _tableCount); - assert(_table[anchorID].isAssigned); - - // Mark the anchor as obsolete so that it can be removed from the table as - // soon as all its references go away (minor table's responsibility). - - _table[anchorID].isObsolete = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 AnchorTable::locate(IOService * anchor) -{ - // - // This method searches for the specified anchor in the anchor table and - // returns its ID (or kInvalidAnchorID on a failure). It ignores slots - // marked as obsolete. - // - - for (UInt32 anchorID = 0; anchorID < _tableCount; anchorID++) - { - if ( _table[anchorID].isAssigned != false && - _table[anchorID].isObsolete == false && - _table[anchorID].anchor == anchor ) return anchorID; - } - - return kInvalidAnchorID; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool AnchorTable::isObsolete(UInt32 anchorID) -{ - // - // Determine whether the specified anchor ID is marked as obsolete. - // - - assert(anchorID < _tableCount); - assert(_table[anchorID].isAssigned); - - return _table[anchorID].isObsolete ? true : false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn AnchorTable::anchorWasNotified( void * /* target */, - void * /* parameter */, - UInt32 messageType, - IOService * anchor, - void * /* messageArgument */, - vm_size_t /* messageArgumentSize */ ) -{ - // - // Notification handler for anchors. - // - - UInt32 anchorID; - - assert(gIOMediaBSDClient); - - // Determine whether this is a termination notification (post-stop). - - if ( messageType != kIOMessageServiceIsTerminated ) - return kIOReturnSuccess; - - // Disable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->lockForArbitration(); - - // Determine whether this anchor is in the anchor table (obsolete occurences - // are skipped in the search, as appropriate, since those anchor IDs will be - // removed as it is). - - anchorID = gIOMediaBSDClient->getAnchors()->locate(anchor); - - if ( anchorID != kInvalidAnchorID ) - { - // Determine whether this anchor is still has references in the minor - // table. If it does, we mark the the anchor as obsolete so that it - // will be removed later, once references to it go to zero (which is - // handled by MinorTable::remove). - - if ( gIOMediaBSDClient->getMinors()->hasReferencesToAnchorID(anchorID) ) - gIOMediaBSDClient->getAnchors()->obsolete(anchorID); - else - gIOMediaBSDClient->getAnchors()->remove(anchorID); - } - - // Enable access to tables, matching, opens, closes, and terminations. - - gIOMediaBSDClient->unlockForArbitration(); - - return kIOReturnSuccess; -} - -// ============================================================================= -// MinorTable Class - -MinorTable::MinorTable(UInt32 growCount, UInt32 maxCount) -{ - // - // Initialize this object's minimal state. - // - - _table = 0; - _tableCount = 0; - _tableGrowCount = growCount; - _tableMaxCount = maxCount; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MinorTable::~MinorTable() -{ - // - // Free all of this object's outstanding resources. - // - - for ( UInt32 minorID = 0; minorID < _tableCount; minorID++ ) - if ( _table[minorID].isAssigned ) remove(minorID); - - if ( _table ) IODelete(_table, MinorSlot, _tableCount); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 MinorTable::insert(IOMedia * media, UInt32 anchorID, char * slicePath) -{ - // - // This method inserts the specified media/anchorID pair into an unassigned - // slot in the minor table and returns its ID (or kInvalidMinorID on error). - // - // Note that the bdev and cdev nodes are published as a result of this call, - // with the name "[r]disk<anchorID><slicePath>". For instance, "disk2s3s1" - // for an anchorID of 2 and slicePath of "s3s1". - // - - void * bdevNode; - void * cdevNode; - UInt32 minorID; - char * minorName; - UInt32 minorNameSize; - - // Search for an unassigned slot in the minor table. - - for ( minorID = 0; minorID < _tableCount; minorID++ ) - if ( _table[minorID].isAssigned == false ) break; - - // Was an unassigned slot found? If not, grow the table. - - if ( minorID == _tableCount ) - { - MinorSlot * newTable; - UInt32 newTableCount; - - // We must expand the minor table since no more slots are available. - - if ( _tableCount >= _tableMaxCount) return kInvalidMinorID; - - newTableCount = min(_tableGrowCount + _tableCount, _tableMaxCount); - newTable = IONew(MinorSlot, newTableCount); - - if ( newTable == 0 ) return kInvalidMinorID; - - bzero(newTable, newTableCount * sizeof(MinorSlot)); - - // Copy over the old table's entries, then free the old table. - - if ( _table ) - { - bcopy(_table, newTable, _tableCount * sizeof(MinorSlot)); - IODelete(_table, MinorSlot, _tableCount); - } - - // Obtain the next unassigned index (simple since we know the size of - // the old table), then update our instance variables to reflect the - // new tables. - - minorID = _tableCount; - _table = newTable; - _tableCount = newTableCount; - } - - // Create a buffer large enough to hold the full name of the minor. - - minorNameSize = strlen("disk#"); - for (unsigned temp = anchorID; temp >= 10; temp /= 10) minorNameSize++; - minorNameSize += strlen(slicePath); - minorNameSize += 1; - minorName = IONew(char, minorNameSize); - - // Create a block and character device node in BSD for this media. - - bdevNode = devfs_make_node( /* dev */ makedev(kMajor, minorID), - /* type */ DEVFS_BLOCK, - /* owner */ UID_ROOT, - /* group */ GID_OPERATOR, - /* permission */ media->isWritable()?0640:0440, - /* name (fmt) */ "disk%d%s", - /* name (arg) */ anchorID, - /* name (arg) */ slicePath ); - - cdevNode = devfs_make_node( /* dev */ makedev(kMajor, minorID), - /* type */ DEVFS_CHAR, - /* owner */ UID_ROOT, - /* group */ GID_OPERATOR, - /* permission */ media->isWritable()?0640:0440, - /* name (fmt) */ "rdisk%d%s", - /* name (arg) */ anchorID, - /* name (arg) */ slicePath ); - - if ( minorName == 0 || bdevNode == 0 || cdevNode == 0 ) - { - if ( cdevNode ) devfs_remove(cdevNode); - if ( bdevNode ) devfs_remove(bdevNode); - if ( minorName ) IODelete(minorName, char, minorNameSize); - - return kInvalidMinorID; - } - - // Construct a name for the node. - - sprintf(minorName, "disk%ld%s", anchorID, slicePath); - assert(strlen(minorName) + 1 == minorNameSize); - - // Zero the new slot, fill it in, and retain the media object. - - bzero(&_table[minorID], sizeof(MinorSlot)); // (zero slot) - - _table[minorID].isAssigned = true; // (fill in slot) - _table[minorID].isEjecting = false; - _table[minorID].isObsolete = false; - _table[minorID].anchorID = anchorID; - _table[minorID].media = media; - _table[minorID].name = minorName; - _table[minorID].bdevBlockSize = media->getPreferredBlockSize(); - _table[minorID].bdevNode = bdevNode; - _table[minorID].bdevOpen = false; - _table[minorID].cdevNode = cdevNode; - _table[minorID].cdevOpen = false; - - _table[minorID].media->retain(); // (retain media) - - return minorID; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MinorTable::remove(UInt32 minorID) -{ - // - // This method removes the specified minor from the minor table. - // - - UInt32 anchorID; - - assert(minorID < _tableCount); - assert(_table[minorID].isAssigned); - - assert(_table[minorID].isEjecting == false); - assert(_table[minorID].bdevOpen == false); - assert(_table[minorID].cdevOpen == false); - - anchorID = _table[minorID].anchorID; - - // Release the resources retained in the minor slot and zero it. - - devfs_remove(_table[minorID].cdevNode); - devfs_remove(_table[minorID].bdevNode); - IODelete(_table[minorID].name, char, strlen(_table[minorID].name) + 1); - _table[minorID].media->release(); // (release media) - - bzero(&_table[minorID], sizeof(MinorSlot)); // (zero slot) - - // Determine whether the associated anchor ID is marked as obsolete. If it - // is and there are no other references to the anchor ID in the minor table, - // we remove the anchor ID from the anchor table. - - assert(gIOMediaBSDClient); - - if ( gIOMediaBSDClient->getAnchors()->isObsolete(anchorID) ) - { - if ( hasReferencesToAnchorID(anchorID) == false ) - gIOMediaBSDClient->getAnchors()->remove(anchorID); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 MinorTable::locate(IOMedia * media) -{ - // - // This method searches for the specified media in the minor table and - // returns its ID (or kInvalidMinorID on an error). It ignores slots - // marked as obsolete. - // - - for (UInt32 minorID = 0; minorID < _tableCount; minorID++) - { - if ( _table[minorID].isAssigned != false && - _table[minorID].isObsolete == false && - _table[minorID].media == media ) return minorID; - } - - return kInvalidMinorID; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt32 MinorTable::getOpenCountForAnchorID(UInt32 anchorID) -{ - // - // This method obtains a count of opens on the minors associated with the - // specified anchor ID. A block device open is counted separately from a - // character device open. - // - - UInt32 opens = 0; - - for ( UInt32 minorID = 0; minorID < _tableCount; minorID++ ) - { - if ( _table[minorID].isAssigned != false && - _table[minorID].anchorID == anchorID ) - { - opens += (_table[minorID].bdevOpen) ? 1 : 0; - opens += (_table[minorID].cdevOpen) ? 1 : 0; - } - } - - return opens; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * MinorTable::getWholeMediaAtAnchorID(UInt32 anchorID) -{ - // - // This method obtains the whole media associated with the specified anchor - // ID. - // - - for ( UInt32 minorID = 0; minorID < _tableCount; minorID++ ) - { - if ( _table[minorID].isAssigned != false && - _table[minorID].anchorID == anchorID && - _table[minorID].media->isWhole() ) return _table[minorID].media; - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool MinorTable::hasReferencesToAnchorID(UInt32 anchorID) -{ - // - // This method determines whether there are assigned minors in the minor - // table that refer to the specified anchor ID. - // - - for ( UInt32 minorID = 0; minorID < _tableCount; minorID++ ) - { - if ( _table[minorID].isAssigned != false && - _table[minorID].anchorID == anchorID ) return true; - } - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MinorSlot * MinorTable::getMinor(UInt32 minorID) -{ - // - // Obtain the structure describing the specified minor. - // - - if ( minorID < _tableCount && _table[minorID].isAssigned ) - return &_table[minorID]; - else - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MinorTable::obsolete(UInt32 minorID) -{ - // - // This method obsoletes the specified minor, that is, the slot is marked - // as obsolete and will be removed later via the dkclose function once it - // detects the last close arrive. Once obsoleted, the minor can be cons- - // idered to be removed, since it will not appear in locate searches. - // - - assert(minorID < _tableCount); - assert(_table[minorID].isAssigned); - - // Mark the minor as obsolete so that it can be removed from the table as - // soon as the last close arrives (dkclose function's responsibility). - - _table[minorID].isObsolete = true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool MinorTable::isObsolete(UInt32 minorID) -{ - // - // Determine whether the specified minor ID is marked as obsolete. - // - - assert(minorID < _tableCount); - assert(_table[minorID].isAssigned); - - return _table[minorID].isObsolete ? true : false; -} diff --git a/iokit/Families/IOStorage/IONeXTPartitionScheme.cpp b/iokit/Families/IOStorage/IONeXTPartitionScheme.cpp deleted file mode 100644 index e7ccb3052..000000000 --- a/iokit/Families/IOStorage/IONeXTPartitionScheme.cpp +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <sys/param.h> -#include <IOKit/assert.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/IOLib.h> -#include <IOKit/storage/IONeXTPartitionScheme.h> -#include <libkern/OSByteOrder.h> - -#define super IOPartitionScheme -OSDefineMetaClassAndStructors(IONeXTPartitionScheme, IOPartitionScheme); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Notes -// -// o the on-disk structure's fields are: 16-bit packed, big-endian formatted -// o the on-disk structure is stored four times in succession, each takes up -// sizeof(disk_label_t) bytes rounded up to the drive's natural block size -// o the dl_label_blkno block value assumes the drive's natural block size -// o the dl_part[].p_base, dl_part[].p_size and dl_front block values assume -// a dl_secsize byte block size -// o the dl_part[].p_base and dl_label_blkno block values are absolute, with -// respect to the whole disk -// o the dl_part[].p_base block value doesn't take into account the dl_front -// offset, which is required in order to compute the actual start position -// of the partition on the disk -// o note that CDs often suffer from the mastering-with-a-different-natural- -// block-size problem, but we can assume that the first map will always be -// valid in those cases, and that we'll never need to compute the position -// of the next map correctly -// o note that bootable i386 disks will never have a valid first map, due to -// the boot code that lives in block zero, however the second map is valid -// o this implementation checks for the existence of the first map only; it -// does not bother with the last three maps, since backwards compatibility -// with unreleased NeXT-style i386 disks is a non-goal, and for reasons of -// minimizing access to the media during probe -// - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#define kIONeXTPartitionSchemeContentTable "Content Table" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IONeXTPartitionScheme::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - // State our assumptions. - - assert(sizeof(disktab_t) == 514); // (compiler/platform check) - assert(sizeof(partition_t) == 46); // (compiler/platform check) - assert(sizeof(disk_label_t) == 7240); // (compiler/platform check) - - // Ask our superclass' opinion. - - if ( super::init(properties) == false ) return false; - - // Initialize our state. - - _partitions = 0; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IONeXTPartitionScheme::free() -{ - // - // Free all of this object's outstanding resources. - // - - if ( _partitions ) _partitions->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOService * IONeXTPartitionScheme::probe(IOService * provider, SInt32 * score) -{ - // - // Determine whether the provider media contains a NeXT partition map. If - // it does, we return "this" to indicate success, otherwise we return zero. - // - - // State our assumptions. - - assert(OSDynamicCast(IOMedia, provider)); - - // Ask our superclass' opinion. - - if ( super::probe(provider, score) == 0 ) return 0; - - // Scan the provider media for a NeXT partition map. - - _partitions = scan(score); - - return ( _partitions ) ? this : 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IONeXTPartitionScheme::start(IOService * provider) -{ - // - // Publish the new media objects which represent our partitions. - // - - IOMedia * partition; - OSIterator * partitionIterator; - - // State our assumptions. - - assert(_partitions); - - // Ask our superclass' opinion. - - if ( super::start(provider) == false ) return false; - - // Attach and register the new media objects representing our partitions. - - partitionIterator = OSCollectionIterator::withCollection(_partitions); - if ( partitionIterator == 0 ) return false; - - while ( (partition = (IOMedia *) partitionIterator->getNextObject()) ) - { - if ( partition->attach(this) ) - { - partition->registerService(); - } - } - - partitionIterator->release(); - - return true; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSSet * IONeXTPartitionScheme::scan(SInt32 * score) -{ - // - // Scan the provider media for a NeXT partition map. Returns the set - // of media objects representing each of the partitions (the retain for - // the set is passed to the caller), or null should no partition map be - // found. The default probe score can be adjusted up or down, based on - // the confidence of the scan. - // - - IOBufferMemoryDescriptor * buffer = 0; - UInt32 bufferSize = 0; - UInt64 labelBase = 0; - UInt32 labelBlock = 0; - UInt16 * labelCheckPtr = 0; - UInt32 labelCheckSize = 0; - bool labelFound = false; - UInt32 labelIndex = 0; - disk_label_t * labelMap = 0; - IOMedia * media = getProvider(); - UInt64 mediaBlockSize = media->getPreferredBlockSize(); - bool mediaIsOpen = false; - OSSet * partitions = 0; - IOReturn status = kIOReturnError; - - // Determine whether this media is formatted. - - if ( media->isFormatted() == false ) goto scanErr; - - // Determine whether this media has an appropriate block size. - - if ( (mediaBlockSize % DEV_BSIZE) ) goto scanErr; - - // Allocate a buffer large enough to hold one map, rounded to a media block. - - bufferSize = IORound(sizeof(disk_label_t), mediaBlockSize); - buffer = IOBufferMemoryDescriptor::withCapacity( - /* capacity */ bufferSize, - /* withDirection */ kIODirectionIn ); - if ( buffer == 0 ) goto scanErr; - - // Allocate a set to hold the set of media objects representing partitions. - - partitions = OSSet::withCapacity(1); - if ( partitions == 0 ) goto scanErr; - - // Open the media with read access. - - mediaIsOpen = media->open(this, 0, kIOStorageAccessReader); - if ( mediaIsOpen == false ) goto scanErr; - - // Compute this partition's absolute offset with respect to the whole media, - // since the disk_label structure requires this information; we go down the - // service hierarchy summing bases until we reach the whole media object. - - for (IOService * service = media; service; service = service->getProvider()) - { - if ( OSDynamicCast(IOMedia, service) ) // (is this a media object?) - { - labelBase += ((IOMedia *)service)->getBase(); - if ( ((IOMedia *)service)->isWhole() ) break; - } - } - - // Scan the media for a NeXT partition map. - // - // In the spirit of minimizing reads, we only check the first of the four - // possible label positions. Backwards compatibility with old NeXT-style - // i386 disks, including redundancy for NeXT-style disks in general, is a - // non-goal. - - for ( labelIndex = 0; labelIndex < 1; labelIndex++ ) // (first map only) - { - // Read the next NeXT map into our buffer. - -///m:2333367:workaround:commented:start -// status = media->read(this, labelIndex * bufferSize, buffer); -///m:2333367:workaround:commented:stop -///m:2333367:workaround:added:start - status = media->IOStorage::read(this, labelIndex * bufferSize, buffer); -///m:2333367:workaround:added:stop - if ( status != kIOReturnSuccess ) goto scanErr; - - labelBlock = ((labelIndex * bufferSize) + labelBase) / mediaBlockSize; - labelMap = (disk_label_t *) buffer->getBytesNoCopy(); - - // Determine whether the partition map signature is present. - - if ( OSSwapBigToHostInt32(labelMap->dl_version) == DL_V3 ) - { - labelCheckPtr = &(labelMap->dl_v3_checksum); - } - else if ( OSSwapBigToHostInt32(labelMap->dl_version) == DL_V2 || - OSSwapBigToHostInt32(labelMap->dl_version) == DL_V1 ) - { - labelCheckPtr = &(labelMap->dl_checksum); - } - else - { - continue; - } - - labelCheckSize = (UInt8 *) labelCheckPtr - - (UInt8 *) labelMap - sizeof(UInt16); - - // Determine whether the partition map block position is correct. - - if ( OSSwapBigToHostInt32(labelMap->dl_label_blkno) != labelBlock ) - { - continue; - } - - // Determine whether the partition map checksum is correct. - - labelMap->dl_label_blkno = OSSwapHostToBigInt32(0); - - if ( checksum16(labelMap, labelCheckSize) != *labelCheckPtr ) - { - continue; - } - - labelMap->dl_label_blkno = labelBlock; - - labelFound = true; - break; - } - - if ( labelFound == false ) - { - goto scanErr; - } - - // Scan for valid partition entries in the partition map. - - for ( unsigned index = 0; index < NPART; index++ ) - { - if ( isPartitionUsed(labelMap->dl_part + index) ) - { - // Determine whether the partition is corrupt (fatal). - - if ( isPartitionCorrupt( - /* partition */ labelMap->dl_part + index, - /* partitionID */ index + 1, - /* labelBase */ labelBase, - /* labelMap */ labelMap ) ) - { - goto scanErr; - } - - // Determine whether the partition is invalid (skipped). - - if ( isPartitionInvalid( - /* partition */ labelMap->dl_part + index, - /* partitionID */ index + 1, - /* labelBase */ labelBase, - /* labelMap */ labelMap ) ) - { - continue; - } - - // Create a media object to represent this partition. - - IOMedia * newMedia = instantiateMediaObject( - /* partition */ labelMap->dl_part + index, - /* partitionID */ index + 1, - /* labelBase */ labelBase, - /* labelMap */ labelMap ); - - if ( newMedia ) - { - partitions->setObject(newMedia); - newMedia->release(); - } - } - } - - // Release our resources. - - media->close(this); - buffer->release(); - - return partitions; - -scanErr: - - // Release our resources. - - if ( mediaIsOpen ) media->close(this); - if ( partitions ) partitions->release(); - if ( buffer ) buffer->release(); - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IONeXTPartitionScheme::isPartitionUsed(partition_t * partition) -{ - // - // Ask whether the given partition is used. - // - - return ( (SInt32) OSSwapBigToHostInt32(partition->p_base) >= 0 && - (SInt32) OSSwapBigToHostInt32(partition->p_size) > 0 ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IONeXTPartitionScheme::isPartitionCorrupt( - partition_t * /* partition */ , - UInt32 /* partitionID */ , - UInt64 /* labelBase */ , - disk_label_t * /* labelMap */ ) -{ - // - // Ask whether the given partition appears to be corrupt. A partition that - // is corrupt will cause the failure of the NeXT partition map recognition - // altogether. - // - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IONeXTPartitionScheme::isPartitionInvalid( partition_t * partition, - UInt32 partitionID, - UInt64 labelBase, - disk_label_t * labelMap ) -{ - // - // Ask whether the given partition appears to be invalid. A partition that - // is invalid will cause it to be skipped in the scan, but will not cause a - // failure of the NeXT partition map recognition. - // - - IOMedia * media = getProvider(); - UInt64 partitionBase = 0; - UInt64 partitionSize = 0; - - // Compute the absolute byte position and size of the new partition. - - partitionBase = OSSwapBigToHostInt32(partition->p_base) + - OSSwapBigToHostInt16(labelMap->dl_front); - partitionSize = OSSwapBigToHostInt32(partition->p_size); - partitionBase *= OSSwapBigToHostInt32(labelMap->dl_secsize); - partitionSize *= OSSwapBigToHostInt32(labelMap->dl_secsize); - - // Determine whether the new partition leaves the confines of the container. - - if ( partitionBase < labelBase ) return true; // (absolute partitionBase) - - // Compute the relative byte position of the new partition. - - partitionBase -= labelBase; // (relative partitionBase) - - // Determine whether the new partition leaves the confines of the container. - - if ( partitionBase + partitionSize > media->getSize() ) return true; - - return false; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IONeXTPartitionScheme::instantiateMediaObject( - partition_t * partition, - UInt32 partitionID, - UInt64 labelBase, - disk_label_t * labelMap ) -{ - // - // Instantiate a new media object to represent the given partition. - // - - IOMedia * media = getProvider(); - UInt64 partitionBase = 0; - UInt64 partitionBlockSize = OSSwapBigToHostInt32(labelMap->dl_secsize); - char * partitionHint = 0; - char * partitionName = 0; - UInt64 partitionSize = 0; - - // Compute the relative byte position and size of the new partition. - - partitionBase = OSSwapBigToHostInt32(partition->p_base) + - OSSwapBigToHostInt16(labelMap->dl_front); - partitionSize = OSSwapBigToHostInt32(partition->p_size); - partitionBase *= OSSwapBigToHostInt32(labelMap->dl_secsize); - partitionSize *= OSSwapBigToHostInt32(labelMap->dl_secsize); - partitionBase -= labelBase; - - // Look up a type for the new partition. - - OSDictionary * hintTable = OSDynamicCast( - /* type */ OSDictionary, - /* instance */ getProperty(kIONeXTPartitionSchemeContentTable) ); - - if ( hintTable ) - { - OSString * hintValue = OSDynamicCast( - /* type */ OSString, - /* instance */ hintTable->getObject(partition->p_type) ); - - if ( hintValue ) partitionHint = (char *) hintValue->getCStringNoCopy(); - } - - // Look up a name for the new partition. - - if ( partition->p_mountpt[0] ) - partitionName = partition->p_mountpt; - else if ( labelMap->dl_label[0] ) - partitionName = labelMap->dl_label; - - // Create the new media object. - - IOMedia * newMedia = instantiateDesiredMediaObject( - /* partition */ partition, - /* partitionID */ partitionID, - /* labelBase */ labelBase, - /* labelMap */ labelMap ); - - if ( newMedia ) - { - if ( newMedia->init( - /* base */ partitionBase, - /* size */ partitionSize, - /* preferredBlockSize */ partitionBlockSize, - /* isEjectable */ media->isEjectable(), - /* isWhole */ false, - /* isWritable */ media->isWritable(), - /* contentHint */ partitionHint ) ) - { - // Set a name for this partition. - - char name[24]; - sprintf(name, "Untitled %ld", partitionID); - newMedia->setName(partitionName ? partitionName : name); - - // Set a location value (the partition number) for this partition. - - char location[12]; - sprintf(location, "%ld", partitionID); - newMedia->setLocation(location); - - // Set the "Partition ID" key for this partition. - - newMedia->setProperty(kIOMediaPartitionIDKey, partitionID, 32); - } - else - { - newMedia->release(); - newMedia = 0; - } - } - - return newMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IONeXTPartitionScheme::instantiateDesiredMediaObject( - partition_t * partition, - UInt32 partitionID, - UInt64 labelBase, - disk_label_t * labelMap ) -{ - // - // Allocate a new media object (called from instantiateMediaObject). - // - - return new IOMedia; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UInt16 IONeXTPartitionScheme::checksum16(void * data, UInt32 bytes) const -{ - // - // Compute a big-endian, 16-bit checksum over the specified data range. - // - - UInt32 sum1 = 0; - UInt32 sum2; - UInt16 * wp = (UInt16 *) data; - - while ( bytes >= 2 ) - { - sum1 += OSSwapBigToHostInt16(*wp); - bytes -= sizeof(UInt16); - wp++; - } - - sum2 = ((sum1 & 0xFFFF0000) >> 16) + (sum1 & 0xFFFF); - - if ( sum2 > 65535 ) - sum2 -= 65535; - - return sum2; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IONeXTPartitionScheme, 15); diff --git a/iokit/Families/IOStorage/IOPartitionScheme.cpp b/iokit/Families/IOStorage/IOPartitionScheme.cpp deleted file mode 100644 index 022d384e5..000000000 --- a/iokit/Families/IOStorage/IOPartitionScheme.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/storage/IOPartitionScheme.h> - -#define super IOStorage -OSDefineMetaClassAndStructors(IOPartitionScheme, IOStorage) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOMedia * IOPartitionScheme::getProvider() const -{ - // - // Obtain this object's provider. We override the superclass's method - // to return a more specific subclass of OSObject -- an IOMedia. This - // method serves simply as a convenience to subclass developers. - // - - return (IOMedia *) IOService::getProvider(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOPartitionScheme::init(OSDictionary * properties = 0) -{ - // - // Initialize this object's minimal state. - // - - if (super::init(properties) == false) return false; - - _openLevel = kIOStorageAccessNone; - _openReaders = OSSet::withCapacity(16); - _openReaderWriters = OSSet::withCapacity(16); - - if (_openReaders == 0 || _openReaderWriters == 0) return false; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOPartitionScheme::free() -{ - // - // Free all of this object's outstanding resources. - // - - if (_openReaders) _openReaders->release(); - if (_openReaderWriters) _openReaderWriters->release(); - - super::free(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOPartitionScheme::handleOpen(IOService * client, - IOOptionBits options, - void * argument) -{ - // - // The handleOpen method grants or denies permission to access this object - // to an interested client. The argument is an IOStorageAccess value that - // specifies the level of access desired -- reader or reader-writer. - // - // This method can be invoked to upgrade or downgrade the access level for - // an existing client as well. The previous access level will prevail for - // upgrades that fail, of course. A downgrade should never fail. If the - // new access level should be the same as the old for a given client, this - // method will do nothing and return success. In all cases, one, singular - // close-per-client is expected for all opens-per-client received. - // - // This implementation replaces the IOService definition of handleOpen(). - // - // We are guaranteed that no other opens or closes will be processed until - // we make our decision, change our state, and return from this method. - // - - IOStorageAccess access = (IOStorageAccess) argument; - IOStorageAccess level; - - assert(client); - assert( access == kIOStorageAccessReader || - access == kIOStorageAccessReaderWriter ); - - // - // A partition scheme multiplexes the opens it receives from several clients - // and sends one open to the level below that satisfies the highest level of - // access. - // - - unsigned writers = _openReaderWriters->getCount(); - - if (_openReaderWriters->containsObject(client)) writers--; - if (access == kIOStorageAccessReaderWriter) writers++; - - level = (writers) ? kIOStorageAccessReaderWriter : kIOStorageAccessReader; - - // - // Determine whether the levels below us accept this open or not (we avoid - // the open if the required access is the access we already hold). - // - - if (_openLevel != level) // (has open level changed?) - { - IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); - - if (provider && provider->open(this, options, level) == false) - return false; - } - - // - // Process the open. - // - - if (access == kIOStorageAccessReader) - { - _openReaders->setObject(client); - - _openReaderWriters->removeObject(client); // (for a downgrade) - } - else // (access == kIOStorageAccessReaderWriter) - { - _openReaderWriters->setObject(client); - - _openReaders->removeObject(client); // (for an upgrade) - } - - _openLevel = level; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOPartitionScheme::handleIsOpen(const IOService * client) const -{ - // - // The handleIsOpen method determines whether the specified client, or any - // client if none is specificed, presently has an open on this object. - // - // This implementation replaces the IOService definition of handleIsOpen(). - // - // We are guaranteed that no other opens or closes will be processed until - // we return from this method. - // - - if (client == 0) return (_openLevel != kIOStorageAccessNone); - - return ( _openReaderWriters->containsObject(client) || - _openReaders->containsObject(client) ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOPartitionScheme::handleClose(IOService * client, IOOptionBits options) -{ - // - // The handleClose method closes the client's access to this object. - // - // This implementation replaces the IOService definition of handleClose(). - // - // We are guaranteed that no other opens or closes will be processed until - // we change our state and return from this method. - // - - assert(client); - - // - // Process the close. - // - - if (_openReaderWriters->containsObject(client)) // (is it a reader-writer?) - { - _openReaderWriters->removeObject(client); - } - else if (_openReaders->containsObject(client)) // (is the client a reader?) - { - _openReaders->removeObject(client); - } - else // (is the client is an imposter?) - { - assert(0); - return; - } - - // - // Reevaluate the open we have on the level below us. If no opens remain, - // we close, or if no reader-writer remains, but readers do, we downgrade. - // - - IOStorageAccess level; - - if (_openReaderWriters->getCount()) level = kIOStorageAccessReaderWriter; - else if (_openReaders->getCount()) level = kIOStorageAccessReader; - else level = kIOStorageAccessNone; - - if (_openLevel != level) // (has open level changed?) - { - IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); - - assert(level != kIOStorageAccessReaderWriter); - - if (provider) - { - if (level == kIOStorageAccessNone) // (is a close in order?) - { - provider->close(this, options); - } - else // (is a downgrade in order?) - { - bool success; - success = provider->open(this, 0, level); - assert(success); // (should never fail, unless avoided deadlock) - } - } - - _openLevel = level; // (set new open level) - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOPartitionScheme::read(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // Read data from the storage object at the specified byte offset into the - // specified buffer, asynchronously. When the read completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the read. - // - // For simple partition schemes, the default behavior is to simply pass the - // read through to the provider media. More complex partition schemes such - // as RAID will need to do extra processing here. - // - - getProvider()->read(this, byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void IOPartitionScheme::write(IOService * /* client */, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) -{ - // - // Write data into the storage object at the specified byte offset from the - // specified buffer, asynchronously. When the write completes, the caller - // will be notified via the specified completion action. - // - // The buffer will be retained for the duration of the write. - // - // For simple partition schemes, the default behavior is to simply pass the - // write through to the provider media. More complex partition schemes such - // as RAID will need to do extra processing here. - // - - getProvider()->write(this, byteStart, buffer, completion); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOPartitionScheme::synchronizeCache(IOService * client) -{ - return getProvider()->synchronizeCache(this); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 15); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 16); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 17); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 18); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 19); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 20); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 21); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 22); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 23); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 24); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 25); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 26); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 27); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 28); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 29); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 30); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOPartitionScheme, 31); diff --git a/iokit/Families/IOStorage/IOStorage.cpp b/iokit/Families/IOStorage/IOStorage.cpp deleted file mode 100644 index 535c8878c..000000000 --- a/iokit/Families/IOStorage/IOStorage.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#include <IOKit/assert.h> -#include <IOKit/IOLib.h> -#include <IOKit/IOSyncer.h> -#include <IOKit/storage/IOStorage.h> - -#define super IOService -OSDefineMetaClass(IOStorage, IOService) -OSDefineAbstractStructors(IOStorage, IOService) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Local Functions - -static void storageCompletion(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount) -{ - // - // Internal completion routine for synchronous versions of read and write. - // - - if (parameter) *((UInt64 *)parameter) = actualByteCount; - ((IOSyncer *)target)->signal(status); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool IOStorage::open(IOService * client, - IOOptionBits options, - IOStorageAccess access) -{ - // - // Ask the storage object for permission to access its contents; the method - // is equivalent to IOService::open(), but with the correct parameter types. - // - - return super::open(client, options, (void *) access); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOStorage::read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - UInt64 * actualByteCount = 0) -{ - // - // Read data from the storage object at the specified byte offset into the - // specified buffer, synchronously. When the read completes, this method - // will return to the caller. The actual byte count field is optional. - // - - IOStorageCompletion completion; - IOSyncer * completionSyncer; - - // Initialize the lock we will synchronize against. - - completionSyncer = IOSyncer::create(); - - // Fill in the completion information for this request. - - completion.target = completionSyncer; - completion.action = storageCompletion; - completion.parameter = actualByteCount; - - // Issue the asynchronous read. - - read(client, byteStart, buffer, completion); - - // Wait for the read to complete. - - return completionSyncer->wait(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -IOReturn IOStorage::write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - UInt64 * actualByteCount = 0) -{ - // - // Write data into the storage object at the specified byte offset from the - // specified buffer, synchronously. When the write completes, this method - // will return to the caller. The actual byte count field is optional. - // - - IOStorageCompletion completion; - IOSyncer * completionSyncer; - - // Initialize the lock we will synchronize against. - - completionSyncer = IOSyncer::create(); - - // Fill in the completion information for this request. - - completion.target = completionSyncer; - completion.action = storageCompletion; - completion.parameter = actualByteCount; - - // Issue the asynchronous write. - - write(client, byteStart, buffer, completion); - - // Wait for the write to complete. - - return completionSyncer->wait(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 0); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 1); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 2); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 3); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 4); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 5); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 6); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 7); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 8); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 9); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 10); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 11); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 12); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 13); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 14); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -OSMetaClassDefineReservedUnused(IOStorage, 15); diff --git a/iokit/IOKit/IOCatalogue.h b/iokit/IOKit/IOCatalogue.h index 1b72688f4..e81e0f486 100644 --- a/iokit/IOKit/IOCatalogue.h +++ b/iokit/IOKit/IOCatalogue.h @@ -56,6 +56,8 @@ private: IOLock * lock; SInt32 generation; + IOLock * kld_lock; + public: /*! @function initialize diff --git a/iokit/IOKit/IOCommandGate.h b/iokit/IOKit/IOCommandGate.h index 9542199b1..1bb549d8c 100644 --- a/iokit/IOKit/IOCommandGate.h +++ b/iokit/IOKit/IOCommandGate.h @@ -133,7 +133,7 @@ event source is currently disabled, kIOReturnNoResources if no action available. @discussion Client function that causes the given action to be called in a single threaded manner. Beware the work-loop's gate is recursive and command gates can cause direct or indirect re-entrancy. When the executing on a -client's thread runCommand will sleep until the work-loop's gate opens for +client's thread runAction will sleep until the work-loop's gate opens for execution of client actions, the action is single threaded against all other work-loop event sources. @param action Pointer to function to be executed in work-loop context. diff --git a/iokit/IOKit/IOKitKeys.h b/iokit/IOKit/IOKitKeys.h index 9fa67fe50..b0ecbf899 100644 --- a/iokit/IOKit/IOKitKeys.h +++ b/iokit/IOKit/IOKitKeys.h @@ -86,12 +86,19 @@ #define kIOGeneralInterest "IOGeneralInterest" #define kIOBusyInterest "IOBusyInterest" #define kIOAppPowerStateInterest "IOAppPowerStateInterest" +#define kIOPriorityPowerStateInterest "IOPriorityPowerStateInterest" // IOService interest notification types #define kIOCFPlugInTypesKey "IOCFPlugInTypes" // properties found in services that implement command pooling -#define kIOCommandPoolSizeKey "IOCommandPoolSize" +#define kIOCommandPoolSizeKey "IOCommandPoolSize" // (OSNumber) + +// properties found in services that have transfer constraints +#define kIOMaximumBlockCountReadKey "IOMaximumBlockCountRead" // (OSNumber) +#define kIOMaximumBlockCountWriteKey "IOMaximumBlockCountWrite" // (OSNumber) +#define kIOMaximumSegmentCountReadKey "IOMaximumSegmentCountRead" // (OSNumber) +#define kIOMaximumSegmentCountWriteKey "IOMaximumSegmentCountWrite" // (OSNumber) #endif /* ! _IOKIT_IOKITKEYS_H */ diff --git a/iokit/IOKit/IOLib.h b/iokit/IOKit/IOLib.h index 7e46f2a13..1f02f63cd 100644 --- a/iokit/IOKit/IOLib.h +++ b/iokit/IOKit/IOLib.h @@ -51,6 +51,7 @@ extern "C" { #include <kern/thread_call.h> #include <kern/clock.h> + /* * min/max macros. */ @@ -281,7 +282,7 @@ static inline IOFixed IOFixedDivide(IOFixed a, IOFixed b) void IOPanic(const char *reason); -/* The AbsoluteTime clock API exported by kern/clock.h +/* The API exported by kern/clock.h should be used for high resolution timing. */ void IOGetTime( mach_timespec_t * clock_time); diff --git a/iokit/IOKit/IOLocks.h b/iokit/IOKit/IOLocks.h index 7771cff8c..4e2e9c22c 100644 --- a/iokit/IOKit/IOLocks.h +++ b/iokit/IOKit/IOLocks.h @@ -75,7 +75,7 @@ void IOLockFree( IOLock * lock); static __inline__ void IOLockLock( IOLock * lock) { - _mutex_lock(lock); + mutex_lock(lock); } /*! @function IOLockTryLock @@ -87,7 +87,7 @@ void IOLockLock( IOLock * lock) static __inline__ boolean_t IOLockTryLock( IOLock * lock) { - return(_mutex_try(lock)); + return(mutex_try(lock)); } /*! @function IOLockUnlock @@ -273,7 +273,7 @@ void IOSimpleLockInit( IOSimpleLock * lock ); static __inline__ void IOSimpleLockLock( IOSimpleLock * lock ) { - simple_lock( lock ); + usimple_lock( lock ); } /*! @function IOSimpleLockTryLock @@ -285,7 +285,7 @@ void IOSimpleLockLock( IOSimpleLock * lock ) static __inline__ boolean_t IOSimpleLockTryLock( IOSimpleLock * lock ) { - return( simple_lock_try( lock ) ); + return( usimple_lock_try( lock ) ); } /*! @function IOSimpleLockUnlock @@ -296,7 +296,7 @@ boolean_t IOSimpleLockTryLock( IOSimpleLock * lock ) static __inline__ void IOSimpleLockUnlock( IOSimpleLock * lock ) { - simple_unlock( lock ); + usimple_unlock( lock ); } typedef long int IOInterruptState; @@ -310,7 +310,7 @@ static __inline__ IOInterruptState IOSimpleLockLockDisableInterrupt( IOSimpleLock * lock ) { IOInterruptState state = ml_set_interrupts_enabled( false ); - simple_lock( lock ); + usimple_lock( lock ); return( state ); } @@ -324,7 +324,7 @@ static __inline__ void IOSimpleLockUnlockEnableInterrupt( IOSimpleLock * lock, IOInterruptState state ) { - simple_unlock( lock ); + usimple_unlock( lock ); ml_set_interrupts_enabled( state ); } diff --git a/iokit/IOKit/IOMemoryDescriptor.h b/iokit/IOKit/IOMemoryDescriptor.h index 2c33b3001..a23734872 100644 --- a/iokit/IOKit/IOMemoryDescriptor.h +++ b/iokit/IOKit/IOMemoryDescriptor.h @@ -59,7 +59,11 @@ protected: /*! @struct ExpansionData @discussion This structure will be used to expand the capablilties of this class in the future. */ - struct ExpansionData { }; + struct ExpansionData { + void * devicePager; + unsigned int pagerContig:1; + unsigned int unused:31; + }; /*! @var reserved Reserved for future use. (Internal use only) */ @@ -74,8 +78,13 @@ protected: IOByteCount _length; /* length of all ranges */ IOOptionBits _tag; +public: + + virtual IOPhysicalAddress getSourceSegment( IOByteCount offset, + IOByteCount * length ); + private: - OSMetaClassDeclareReservedUnused(IOMemoryDescriptor, 0); + OSMetaClassDeclareReservedUsed(IOMemoryDescriptor, 0); OSMetaClassDeclareReservedUnused(IOMemoryDescriptor, 1); OSMetaClassDeclareReservedUnused(IOMemoryDescriptor, 2); OSMetaClassDeclareReservedUnused(IOMemoryDescriptor, 3); @@ -288,7 +297,7 @@ public: @result The number of bytes copied, zero will be returned if the specified offset is beyond the length of the descriptor. */ virtual IOByteCount readBytes(IOByteCount offset, - void * bytes, IOByteCount withLength) = 0; + void * bytes, IOByteCount withLength); /*! @function writeBytes @abstract Copy data to the memory descriptor's buffer from the specified buffer. @@ -299,7 +308,7 @@ public: @result The number of bytes copied, zero will be returned if the specified offset is beyond the length of the descriptor. */ virtual IOByteCount writeBytes(IOByteCount offset, - const void * bytes, IOByteCount withLength) = 0; + const void * bytes, IOByteCount withLength); /*! @function getPhysicalSegment @abstract Break a memory descriptor into its physically contiguous segments. @@ -319,16 +328,10 @@ public: inline IOPhysicalAddress getPhysicalAddress() { return( getPhysicalSegment( 0, 0 )); } - /* - * getVirtualSegment: - * - * Get the virtual address of the buffer, relative to the given offset. - * If the memory wasn't mapped into the caller's address space, it will be - * mapped in now. If the current position is at the end of the buffer, a - * null is returned. - */ - virtual void * getVirtualSegment(IOByteCount offset, - IOByteCount * length) = 0; + /* DEPRECATED */ /* USE INSTEAD: map(), readBytes(), writeBytes() */ + /* DEPRECATED */ virtual void * getVirtualSegment(IOByteCount offset, + /* DEPRECATED */ IOByteCount * length) = 0; + /* DEPRECATED */ /* USE INSTEAD: map(), readBytes(), writeBytes() */ /*! @function prepare @abstract Prepare the memory for an I/O transfer. @@ -399,6 +402,14 @@ public: // make virtual IOReturn redirect( task_t safeTask, bool redirect ); + IOReturn handleFault( + void * pager, + vm_map_t addressMap, + IOVirtualAddress address, + IOByteCount sourceOffset, + IOByteCount length, + IOOptionBits options ); + protected: virtual IOMemoryMap * makeMapping( IOMemoryDescriptor * owner, @@ -504,8 +515,10 @@ public: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // The following classes are private implementation of IOMemoryDescriptor - they -// should not be reference directly, just through the public API's in the -// IOMemoryDescriptor class. +// should not be referenced directly, just through the public API's in the +// IOMemoryDescriptor class. For example, an IOGeneralMemoryDescriptor instance +// might be created by IOMemoryDescriptor::withAddress(), but there should be +// no need to reference as anything but a generic IOMemoryDescriptor *. enum { kIOMemoryRequiresWire = 0x00000001 @@ -539,20 +552,20 @@ protected: virtual void free(); -protected: /* (to be deprecated) */ - IOByteCount _position; /* absolute position over all ranges */ - virtual void setPosition(IOByteCount position); +protected: + /* DEPRECATED */ IOByteCount _position; /* absolute position over all ranges */ + /* DEPRECATED */ virtual void setPosition(IOByteCount position); private: - unsigned _positionAtIndex; /* range #n in which position is now */ - IOByteCount _positionAtOffset; /* relative position within range #n */ + /* DEPRECATED */ unsigned _positionAtIndex; /* range #n in which position is now */ + /* DEPRECATED */ IOByteCount _positionAtOffset; /* relative position within range #n */ OSData *_memoryEntries; - vm_offset_t _kernPtrAligned; - unsigned _kernPtrAtIndex; - IOByteCount _kernSize; - virtual void mapIntoKernel(unsigned rangeIndex); - virtual void unmapFromKernel(); + /* DEPRECATED */ vm_offset_t _kernPtrAligned; + /* DEPRECATED */ unsigned _kernPtrAtIndex; + /* DEPRECATED */ IOByteCount _kernSize; + /* DEPRECATED */ virtual void mapIntoKernel(unsigned rangeIndex); + /* DEPRECATED */ virtual void unmapFromKernel(); inline vm_map_t getMapForTask( task_t task, vm_address_t address ); public: @@ -585,17 +598,14 @@ public: IODirection withDirection, bool asReference = false); - virtual IOByteCount readBytes(IOByteCount offset, - void * bytes, IOByteCount withLength); - - virtual IOByteCount writeBytes(IOByteCount offset, - const void * bytes, IOByteCount withLength); - virtual IOPhysicalAddress getPhysicalSegment(IOByteCount offset, IOByteCount * length); - virtual void * getVirtualSegment(IOByteCount offset, - IOByteCount * length); + virtual IOPhysicalAddress getSourceSegment(IOByteCount offset, + IOByteCount * length); + + /* DEPRECATED */ virtual void * getVirtualSegment(IOByteCount offset, + /* DEPRECATED */ IOByteCount * length); virtual IOReturn prepare(IODirection forDirection = kIODirectionNone); @@ -671,6 +681,9 @@ public: virtual IOPhysicalAddress getPhysicalSegment(IOByteCount offset, IOByteCount * length); + virtual IOPhysicalAddress getSourceSegment(IOByteCount offset, + IOByteCount * length); + virtual IOByteCount readBytes(IOByteCount offset, void * bytes, IOByteCount withLength); diff --git a/iokit/IOKit/IOMessage.h b/iokit/IOKit/IOMessage.h index 5e1addf59..d5bd33e9e 100644 --- a/iokit/IOKit/IOMessage.h +++ b/iokit/IOKit/IOMessage.h @@ -36,6 +36,7 @@ typedef UInt32 IOMessage; #define kIOMessageServiceIsResumed iokit_common_msg(0x030) #define kIOMessageServiceIsRequestingClose iokit_common_msg(0x100) +#define kIOMessageServiceIsAttemptingOpen iokit_common_msg(0x101) #define kIOMessageServiceWasClosed iokit_common_msg(0x110) #define kIOMessageServiceBusyStateChange iokit_common_msg(0x120) @@ -51,5 +52,6 @@ typedef UInt32 IOMessage; #define kIOMessageSystemWillSleep iokit_common_msg(0x280) #define kIOMessageSystemWillNotSleep iokit_common_msg(0x290) #define kIOMessageSystemHasPoweredOn iokit_common_msg(0x300) +#define kIOMessageSystemWillRestart iokit_common_msg(0x310) #endif /* ! __IOKIT_IOMESSAGE_H */ diff --git a/iokit/IOKit/IOMultiMemoryDescriptor.h b/iokit/IOKit/IOMultiMemoryDescriptor.h index 68c8c41f8..1032842a6 100644 --- a/iokit/IOKit/IOMultiMemoryDescriptor.h +++ b/iokit/IOKit/IOMultiMemoryDescriptor.h @@ -159,6 +159,9 @@ public: virtual IOByteCount writeBytes( IOByteCount offset, const void * bytes, IOByteCount withLength ); + + virtual IOPhysicalAddress getSourceSegment(IOByteCount offset, + IOByteCount * length); }; #endif /* !_IOMULTIMEMORYDESCRIPTOR_H */ diff --git a/iokit/IOKit/IORegistryEntry.h b/iokit/IOKit/IORegistryEntry.h index c1a067fc2..6fa65bf36 100644 --- a/iokit/IOKit/IORegistryEntry.h +++ b/iokit/IOKit/IORegistryEntry.h @@ -75,12 +75,74 @@ private: OSDictionary * fRegistryTable; OSDictionary * fPropertyTable; +public: + /* methods available in Mac OS X 10.1 or later */ + +/*! @function copyProperty + @abstract Synchronized method to obtain a property from a registry entry or one of its parents (or children) in the hierarchy. Available in Mac OS X 10.1 or later. + @discussion This method will search for a property, starting first with this registry entry's property table, then iterating recusively through either the parent registry entries or the child registry entries of this entry. Once the first occurrence is found, it will lookup and return the value of the property, using the OSDictionary::getObject semantics. The iteration keeps track of entries that have been recursed into previously to avoid loops. This method is synchronized with other IORegistryEntry accesses to the property table(s). + @param aKey The property's name as a C-string. + @param plane The plane to iterate over, eg. gIOServicePlane. + @param options kIORegistryIterateRecursively may be set to recurse automatically into the registry hierarchy. Without this option, this method degenerates into the standard getProperty() call. kIORegistryIterateParents may be set to iterate the parents of the entry, in place of the children. + @result The property value found, or zero. A reference on any found property is returned to caller, which should be released. */ + + virtual OSObject * copyProperty( const char * aKey, + const IORegistryPlane * plane, + IOOptionBits options = + kIORegistryIterateRecursively | + kIORegistryIterateParents) const; +/*! @function copyProperty + @abstract Synchronized method to obtain a property from a registry entry or one of its parents (or children) in the hierarchy. Available in Mac OS X 10.1 or later. + @discussion This method will search for a property, starting first with this registry entry's property table, then iterating recusively through either the parent registry entries or the child registry entries of this entry. Once the first occurrence is found, it will lookup and return the value of the property, using the OSDictionary::getObject semantics. The iteration keeps track of entries that have been recursed into previously to avoid loops. This method is synchronized with other IORegistryEntry accesses to the property table(s). + @param aKey The property's name as an OSString. + @param plane The plane to iterate over, eg. gIOServicePlane. + @param options kIORegistryIterateRecursively may be set to recurse automatically into the registry hierarchy. Without this option, this method degenerates into the standard getProperty() call. kIORegistryIterateParents may be set to iterate the parents of the entry, in place of the children. + @result The property value found, or zero. A reference on any found property is returned to caller, which should be released. */ + + virtual OSObject * copyProperty( const OSString * aKey, + const IORegistryPlane * plane, + IOOptionBits options = + kIORegistryIterateRecursively | + kIORegistryIterateParents) const; + +/*! @function copyProperty + @abstract Synchronized method to obtain a property from a registry entry or one of its parents (or children) in the hierarchy. Available in Mac OS X 10.1 or later. + @discussion This method will search for a property, starting first with this registry entry's property table, then iterating recusively through either the parent registry entries or the child registry entries of this entry. Once the first occurrence is found, it will lookup and return the value of the property, using the OSDictionary::getObject semantics. The iteration keeps track of entries that have been recursed into previously to avoid loops. This method is synchronized with other IORegistryEntry accesses to the property table(s). + @param aKey The property's name as an OSSymbol. + @param plane The plane to iterate over, eg. gIOServicePlane. + @param options kIORegistryIterateRecursively may be set to recurse automatically into the registry hierarchy. Without this option, this method degenerates into the standard getProperty() call. kIORegistryIterateParents may be set to iterate the parents of the entry, in place of the children. + @result The property value found, or zero. A reference on any found property is returned to caller, which should be released. */ + + virtual OSObject * copyProperty( const OSSymbol * aKey, + const IORegistryPlane * plane, + IOOptionBits options = + kIORegistryIterateRecursively | + kIORegistryIterateParents) const; + +/*! @function copyParentEntry + @abstract Returns an registry entry's first parent entry in a plane. Available in Mac OS X 10.1 or later. + @discussion This function will return the parent to which a registry entry was first attached. Since the majority of registry entrys have only one provider, this is a useful simplification. + @param plane The plane object. + @result Returns the first parent of the registry entry, or zero if the entry is not attached into the registry in that plane. A reference on the entry is returned to caller, which should be released. */ + + virtual IORegistryEntry * copyParentEntry( const IORegistryPlane * plane ) const; + +/*! @function copyChildEntry + @abstract Returns an registry entry's first child entry in a plane. Available in Mac OS X 10.1 or later. + @discussion This function will return the child which first attached to a registry entry. + @param plane The plane object. + @result Returns the first child of the registry entry, or zero if the entry is not attached into the registry in that plane. A reference on the entry is returned to caller, which should be released. */ + + virtual IORegistryEntry * copyChildEntry( const IORegistryPlane * plane ) const; + private: - OSMetaClassDeclareReservedUnused(IORegistryEntry, 0); - OSMetaClassDeclareReservedUnused(IORegistryEntry, 1); - OSMetaClassDeclareReservedUnused(IORegistryEntry, 2); - OSMetaClassDeclareReservedUnused(IORegistryEntry, 3); - OSMetaClassDeclareReservedUnused(IORegistryEntry, 4); + + OSMetaClassDeclareReservedUsed(IORegistryEntry, 0); + OSMetaClassDeclareReservedUsed(IORegistryEntry, 1); + OSMetaClassDeclareReservedUsed(IORegistryEntry, 2); + OSMetaClassDeclareReservedUsed(IORegistryEntry, 3); + OSMetaClassDeclareReservedUsed(IORegistryEntry, 4); + OSMetaClassDeclareReservedUnused(IORegistryEntry, 5); OSMetaClassDeclareReservedUnused(IORegistryEntry, 6); OSMetaClassDeclareReservedUnused(IORegistryEntry, 7); @@ -394,8 +456,7 @@ public: @param plane The plane object. @result Returns the first parent of the registry entry, or zero if the entry is not attached into the registry in that plane. The parent is retained while the entry is attached, and should not be released by the caller. */ - virtual IORegistryEntry * getParentEntry( const IORegistryPlane * plane ) - const; + virtual IORegistryEntry * getParentEntry( const IORegistryPlane * plane ) const; /*! @function getChildIterator @abstract Returns an iterator over an registry entry's child entries in a plane. @@ -416,8 +477,7 @@ public: @param plane The plane object. @result Returns the first child of the registry entry, or zero if the entry is not attached into the registry in that plane. The child is retained while the entry is attached, and should not be released by the caller. */ - virtual IORegistryEntry * getChildEntry( const IORegistryPlane * plane ) - const; + virtual IORegistryEntry * getChildEntry( const IORegistryPlane * plane ) const; /*! @function isChild @abstract Determines whether a registry entry is the child of another in a plane. diff --git a/iokit/IOKit/IOService.h b/iokit/IOKit/IOService.h index dfcee1855..9dd414e63 100644 --- a/iokit/IOKit/IOService.h +++ b/iokit/IOKit/IOService.h @@ -62,15 +62,18 @@ enum { kIOServiceFirstMatchState = 0x00000010 }; -// options for registerService() enum { + // options for registerService() kIOServiceExclusive = 0x00000001, - kIOServiceSynchronous = 0x00000002, -}; -// options for terminate() -enum { - kIOServiceRequired = 0x00000001 + // options for terminate() + kIOServiceRequired = 0x00000001, + kIOServiceTerminate = 0x00000004, + + // options for registerService() & terminate() + kIOServiceSynchronous = 0x00000002, + // options for registerService() + kIOServiceAsynchronous = 0x00000008 }; // options for open() @@ -115,7 +118,9 @@ extern const OSSymbol * gIOTerminatedNotification; extern const OSSymbol * gIOGeneralInterest; extern const OSSymbol * gIOBusyInterest; +extern const OSSymbol * gIOOpenInterest; extern const OSSymbol * gIOAppPowerStateInterest; +extern const OSSymbol * gIOPriorityPowerStateInterest; extern const OSSymbol * gIODeviceMemoryKey; extern const OSSymbol * gIOInterruptControllersKey; @@ -273,13 +278,46 @@ private: protected: // TRUE once PMinit has been called bool initialized; + +public: // pointer to protected instance variables for power management IOPMprot * pm_vars; +public: + /* methods available in Mac OS X 10.1 or later */ +/*! @function requestTerminate + @abstract Passes a termination up the stack. + @discussion When an IOService is made inactive the default behaviour is to also make any of its clients that have it as their only provider also inactive, in this way recursing the termination up the driver stack. This method allows an IOService object to override this behaviour. Returning true from this method when passed a just terminated provider will cause the client to also be terminated. + @param provider The terminated provider of this object. + @param options Options originally passed to terminate, plus kIOServiceRecursing. + @result true if this object should be terminated now that its provider as been. */ + + virtual bool requestTerminate( IOService * provider, IOOptionBits options ); + +/*! @function willTerminate + @abstract Passes a termination up the stack. + @discussion Notification that a provider has been terminated, sent before recursing up the stack, in root-to-leaf order. + @param provider The terminated provider of this object. + @param options Options originally passed to terminate. + @result true return true. */ + + virtual bool willTerminate( IOService * provider, IOOptionBits options ); + +/*! @function didTerminate + @abstract Passes a termination up the stack. + @discussion Notification that a provider has been terminated, sent after recursing up the stack, in leaf-to-root order. + @param provider The terminated provider of this object. + @param options Options originally passed to terminate. + @param defer If there is pending I/O that requires this object to persist, and the provider is not opened by this object set defer to true and call the IOService::didTerminate() implementation when the I/O completes. Otherwise, leave defer set to its default value of false. + @result true return true. */ + + virtual bool didTerminate( IOService * provider, IOOptionBits options, bool * defer ); + private: - OSMetaClassDeclareReservedUnused(IOService, 0); - OSMetaClassDeclareReservedUnused(IOService, 1); - OSMetaClassDeclareReservedUnused(IOService, 2); + OSMetaClassDeclareReservedUsed(IOService, 0); + OSMetaClassDeclareReservedUsed(IOService, 1); + OSMetaClassDeclareReservedUsed(IOService, 2); + OSMetaClassDeclareReservedUnused(IOService, 3); OSMetaClassDeclareReservedUnused(IOService, 4); OSMetaClassDeclareReservedUnused(IOService, 5); @@ -465,6 +503,11 @@ public: virtual bool finalize( IOOptionBits options ); +/*! @function free + @discussion Free data structures that were allocated when power management was initialized on this service. */ + + virtual void free( void ); + /*! @function lockForArbitration @abstract Locks an IOService against changes in state or ownership. @discussion The registration, termination and open / close functions of IOService use lockForArbtration to single thread access to an IOService. lockForArbitration will grant recursive access to the same thread. @@ -498,7 +541,7 @@ public: /*! @function adjustBusy @abstract Adjusts the busyState of an IOService. - @discussion Applies a delta to an IOService's busyState. A change in the busyState to or from zero will changes the IOService's provider's busyState by one (in the same direction). + @discussion Applies a delta to an IOService's busyState. A change in the busyState to or from zero will change the IOService's provider's busyState by one (in the same direction). @param delta The delta to be applied to the IOService busy state. */ virtual void adjustBusy( SInt32 delta ); @@ -807,6 +850,13 @@ public: static IOPlatformExpert * getPlatform( void ); +/*! @function getPMRootDomain + @abstract Returns a pointer to the power management root domain instance for the machine. + @discussion This method provides an accessor to the power management root domain instance for the machine. + @result A pointer to the power management root domain instance. It should not be released by the caller. */ + + static class IOPMrootDomain * getPMRootDomain( void ); + /*! @function getServiceRoot @abstract Returns a pointer to the root of the service plane. @discussion This method provides an accessor to the root of the service plane for the machine. @@ -814,6 +864,13 @@ public: static IOService * getServiceRoot( void ); +/*! @function getResourceService + @abstract Returns a pointer to the IOResources service. + @discussion IOService maintains a resource service IOResources that allows objects to be published and found globally in IOKit based on a name, using the standard IOService matching and notification calls. + @result A pointer to the IOResources instance. It should not be released by the caller. */ + + static IOService * getResourceService( void ); + /* Allocate resources for a matched service */ /*! @function getResources @@ -1028,8 +1085,10 @@ public: virtual bool serializeProperties( OSSerialize * s ) const; static void setPlatform( IOPlatformExpert * platform); + static void setPMRootDomain( class IOPMrootDomain * rootDomain ); static IOReturn catalogNewDrivers( OSOrderedSet * newTables ); + static IOReturn waitMatchIdle( UInt32 ms ); static IOService * resources( void ); virtual bool checkResources( void ); @@ -1073,6 +1132,22 @@ public: virtual IOReturn waitForState( UInt32 mask, UInt32 value, mach_timespec_t * timeout = 0 ); + UInt32 _adjustBusy( SInt32 delta ); + + bool terminatePhase1( IOOptionBits options = 0 ); + void scheduleTerminatePhase2( IOOptionBits options = 0 ); + void scheduleStop( IOService * provider ); + void scheduleFinalize( void ); + static void terminateThread( void * arg ); + static void terminateWorker( IOOptionBits options ); + static void actionWillTerminate( IOService * victim, IOOptionBits options, + OSArray * doPhase2List ); + static void actionDidTerminate( IOService * victim, IOOptionBits options ); + static void actionFinalize( IOService * victim, IOOptionBits options ); + static void actionStop( IOService * client, IOService * provider ); + + void PMfree( void ); + virtual IOReturn resolveInterrupt(IOService *nub, int source); virtual IOReturn lookupInterrupt(int source, bool resolve, IOInterruptController **interruptController); @@ -1647,6 +1722,8 @@ virtual IOReturn newTemperature ( long currentTemp, IOService * whichZone ); virtual bool askChangeDown ( unsigned long ); virtual bool tellChangeDown ( unsigned long ); + bool tellChangeDown1 ( unsigned long ); + bool tellChangeDown2 ( unsigned long ); virtual void tellNoChangeDown ( unsigned long ); virtual void tellChangeUp ( unsigned long ); virtual IOReturn allowPowerChange ( unsigned long refcon ); @@ -1702,7 +1779,7 @@ virtual IOReturn newTemperature ( long currentTemp, IOService * whichZone ); subclassed policy-makers, and that is how one finds out that a power change it initiated is complete @param stateNumber - This is the number of the state in the state array that the device has switched to. */ + This is the number of the state in the state array that the device has switched from. */ virtual void powerChangeDone ( unsigned long ); bool tellClientsWithResponse ( int messageType ); @@ -1710,17 +1787,21 @@ virtual IOReturn newTemperature ( long currentTemp, IOService * whichZone ); private: - IOReturn enqueuePowerChange ( unsigned long, unsigned long, unsigned long, IOPowerConnection * ); + IOReturn enqueuePowerChange ( unsigned long, unsigned long, unsigned long, IOPowerConnection *, unsigned long ); + void setParentInfo ( IOPMPowerFlags, IOPowerConnection * ); IOReturn notifyAll ( bool is_prechange ); bool notifyChild ( IOPowerConnection * nextObject, bool is_prechange ); bool inform ( IOPMinformee * nextObject, bool is_prechange ); void our_prechange_03 ( void ); + void our_prechange_04 ( void ); void our_prechange_05 ( void ); void our_prechange_1 ( void ); void our_prechange_2 ( void ); void our_prechange_3 ( void ); void our_prechange_4 ( void ); IOReturn parent_down_0 ( void ); + IOReturn parent_down_02 ( void ); + void parent_down_04 ( void ); void parent_down_05 ( void ); IOReturn parent_down_1 ( void ); IOReturn parent_down_2 ( void ); @@ -1753,6 +1834,7 @@ private: bool checkForDone ( void ); bool responseValid ( unsigned long x ); IOReturn allowCancelCommon ( void ); + void computeDesiredState ( void ); }; #endif /* ! _IOKIT_IOSERVICE_H */ diff --git a/iokit/IOKit/IOServicePM.h b/iokit/IOKit/IOServicePM.h index 2b48bb337..965201f2a 100644 --- a/iokit/IOKit/IOServicePM.h +++ b/iokit/IOKit/IOServicePM.h @@ -118,6 +118,9 @@ class IOPMpriv : public OSObject /*! @field flags_lock used to control access to response flags array */ IOLock * flags_lock; + /*! @field queue_lock used to control access to change note queue */ + IOLock * queue_lock; + /*! @field initial_change true forces first state to be broadcast even if it isn't a change */ bool initial_change; @@ -203,8 +206,7 @@ except while a power change is in progress. /*! @field askingFor -Used by activityTickle so it doesn't try to raise the device to a lower state than -what it may have previously requested. +Not used. */ unsigned long askingFor; @@ -293,6 +295,17 @@ class IOPMprot : public OSObject //management /*! @field doNotPowerDown keeps track of any negative responses from notified apps and clients */ bool doNotPowerDown; + /*! @field childLock used to serialize scanning the children */ + IOLock * childLock; + + /*! @field parentLock used to serialize scanning the parents */ + IOLock * parentLock; + + /*! @field outofbandparameter used to communicate desired function to tellClientsWithResponse(). + This is used because it avoids changing the signatures of the affected + virtual methods. */ + int outofbandparameter; + /*! @function serialize Serialize protected instance variables for debug output (IORegistryDumper). */ diff --git a/iokit/IOKit/IOWorkLoop.h b/iokit/IOKit/IOWorkLoop.h index 6e8f7ecfc..f3c6e1a1e 100644 --- a/iokit/IOKit/IOWorkLoop.h +++ b/iokit/IOKit/IOWorkLoop.h @@ -51,6 +51,26 @@ class IOWorkLoop : public OSObject { OSDeclareDefaultStructors(IOWorkLoop) +public: +/*! + @typedef Action + @discussion Type and arguments of callout C function that is used when +a runCommand is executed by a client. Cast to this type when you want a C++ +member function to be used. Note the arg1 - arg3 parameters are straight pass +through from the runCommand to the action callout. + @param target + Target of the function, can be used as a refcon. Note if a C++ function +was specified this parameter is implicitly the first paramter in the target +member function's parameter list. + @param arg0 Argument to action from run operation. + @param arg1 Argument to action from run operation. + @param arg2 Argument to action from run operation. + @param arg3 Argument to action from run operation. +*/ + typedef IOReturn (*Action)(OSObject *target, + void *arg0, void *arg1, + void *arg2, void *arg3); + private: /*! @function launchThreadMain @abstract Static function that setup thread state and calls the continuation function, $link threadMainContinuation */ @@ -178,6 +198,7 @@ public: @discussion For all event sources, ES, for which IODynamicCast(IOInterruptEventSource, ES) is valid, in $link eventChain call disable() function. See $link IOEventSource::disable() */ virtual void disableAllInterrupts() const; + protected: // Internal APIs used by event sources to control the thread friend class IOEventSource; @@ -188,7 +209,31 @@ protected: virtual int sleepGate(void *event, UInt32 interuptibleType); virtual void wakeupGate(void *event, bool oneThread); - OSMetaClassDeclareReservedUnused(IOWorkLoop, 0); +public: + /* methods available in Mac OS X 10.1 or later */ + +/*! @function runAction + @abstract Single thread a call to an action with the work-loop. + @discussion Client function that causes the given action to be called in +a single threaded manner. Beware the work-loop's gate is recursive and runAction + can cause direct or indirect re-entrancy. When the executing on a +client's thread runAction will sleep until the work-loop's gate opens for +execution of client actions, the action is single threaded against all other +work-loop event sources. + @param action Pointer to function to be executed in work-loop context. + @param arg0 Parameter for action parameter, defaults to 0. + @param arg1 Parameter for action parameter, defaults to 0. + @param arg2 Parameter for action parameter, defaults to 0. + @param arg3 Parameter for action parameter, defaults to 0. + @result return value of the Action callout. +*/ + virtual IOReturn runAction(Action action, OSObject *target, + void *arg0 = 0, void *arg1 = 0, + void *arg2 = 0, void *arg3 = 0); + +protected: + OSMetaClassDeclareReservedUsed(IOWorkLoop, 0); + OSMetaClassDeclareReservedUnused(IOWorkLoop, 1); OSMetaClassDeclareReservedUnused(IOWorkLoop, 2); OSMetaClassDeclareReservedUnused(IOWorkLoop, 3); diff --git a/iokit/IOKit/Makefile b/iokit/IOKit/Makefile index f7f7c729b..ecfdc457f 100644 --- a/iokit/IOKit/Makefile +++ b/iokit/IOKit/Makefile @@ -13,9 +13,6 @@ include $(MakeInc_def) INSTINC_SUBDIRS = \ adb \ cdb \ - graphics \ - hidsystem \ - network \ nvram \ pci \ platform \ @@ -23,16 +20,14 @@ INSTINC_SUBDIRS = \ pwr_mgt \ rtc \ scsi \ - storage \ system_management INSTINC_SUBDIRS_PPC = \ - ppc \ - ndrvsupport + ppc INSTINC_SUBDIRS_I386 = \ - i386 \ - ps2 + ata \ + i386 EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} diff --git a/iokit/IOKit/adb/IOADBController.h b/iokit/IOKit/adb/IOADBController.h index 44eca38ab..886f9529f 100644 --- a/iokit/IOKit/adb/IOADBController.h +++ b/iokit/IOKit/adb/IOADBController.h @@ -71,6 +71,7 @@ public: virtual IOReturn getAutoPollList(UInt16 * activeAddressMask) = 0; virtual IOReturn setAutoPollEnable(bool enable) = 0; virtual IOReturn resetBus(void) = 0; + virtual IOReturn cancelAllIO(void) = 0; virtual IOReturn flushDevice(IOADBAddress address) = 0; virtual IOReturn readFromDevice(IOADBAddress address, IOADBRegister adbRegister, UInt8 * data, IOByteCount * length) = 0; diff --git a/iokit/IOKit/adb/Makefile b/iokit/IOKit/adb/Makefile index 30071de72..d6b386d64 100644 --- a/iokit/IOKit/adb/Makefile +++ b/iokit/IOKit/adb/Makefile @@ -11,7 +11,7 @@ include $(MakeInc_cmd) include $(MakeInc_def) MI_DIR = adb -NOT_EXPORT_HEADERS = adb.h +# NOT_EXPORT_HEADERS = adb.h INSTINC_SUBDIRS = INSTINC_SUBDIRS_PPC = diff --git a/iokit/IOKit/ata/Makefile b/iokit/IOKit/ata/Makefile index 1eb916703..b8ee2c137 100644 --- a/iokit/IOKit/ata/Makefile +++ b/iokit/IOKit/ata/Makefile @@ -10,13 +10,14 @@ export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders include $(MakeInc_cmd) include $(MakeInc_def) -MI_DIR = ata +MD_DIR = ata NOT_EXPORT_HEADERS = IOATADevice_Reference.h IOATACommand_Reference.h \ - IOATAController_Reference.h IOATADriver_Reference.h + IOATAController_Reference.h IOATADriver_Reference.h \ + IOATAStandardInterface.h -INSTINC_SUBDIRS = ata-device ata-standard +INSTINC_SUBDIRS = INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = +INSTINC_SUBDIRS_I386 = ata-device EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} @@ -24,14 +25,12 @@ EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) -INSTALL_MI_LIST = -INSTALL_MI_LCL_LIST = "" +INSTALL_MD_LIST = +INSTALL_MD_LCL_LIST = "" +INSTALL_MD_DIR = $(MD_DIR) -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) - -EXPORT_MI_DIR = IOKit/$(MI_DIR) +EXPORT_MD_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) +EXPORT_MD_DIR = IOKit/$(MD_DIR) include $(MakeInc_rule) include $(MakeInc_dir) diff --git a/iokit/IOKit/ata/ata-device/Makefile b/iokit/IOKit/ata/ata-device/Makefile index 9b8dbeafa..c8b895fcf 100644 --- a/iokit/IOKit/ata/ata-device/Makefile +++ b/iokit/IOKit/ata/ata-device/Makefile @@ -10,7 +10,7 @@ export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders include $(MakeInc_cmd) include $(MakeInc_def) -MI_DIR = ata/ata-device +MD_DIR = ata/ata-device NOT_EXPORT_HEADERS = INSTINC_SUBDIRS = @@ -23,14 +23,12 @@ EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) -INSTALL_MI_LIST = -INSTALL_MI_LCL_LIST = "" +INSTALL_MD_LIST = +INSTALL_MD_LCL_LIST = "" +INSTALL_MD_DIR = $(MD_DIR) -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) - -EXPORT_MI_DIR = IOKit/$(MI_DIR) +EXPORT_MD_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) +EXPORT_MD_DIR = IOKit/$(MD_DIR) include $(MakeInc_rule) include $(MakeInc_dir) diff --git a/iokit/IOKit/graphics/IOAccelSurfaceConnect.h b/iokit/IOKit/graphics/IOAccelSurfaceConnect.h deleted file mode 100644 index fe83f5395..000000000 --- a/iokit/IOKit/graphics/IOAccelSurfaceConnect.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOACCEL_SURFACE_CONNECT_H -#define _IOACCEL_SURFACE_CONNECT_H - -#include <IOKit/graphics/IOAccelTypes.h> -#include <IOKit/graphics/IOAccelClientConnect.h> - - -/* -** Surface visible region in device coordinates. -** -** num_rects: The number of rectangles in the rect array. If num_rects -** is zero the bounds rectangle is used for the visible rectangle. -** If num_rects is zero the surface must be completely contained -** by the device. -** -** bounds: The unclipped surface rectangle in device coords. Extends -** beyond the device bounds if the surface is not totally on -** the device. -** -** rect[]: An array of visible rectangles in device coords. If num_rects -** is non-zero only the region described by these rectangles is -** copied to the frame buffer during a flush operation. -*/ -typedef struct -{ - UInt32 num_rects; - IOAccelBounds bounds; - IOAccelBounds rect[0]; -} IOAccelDeviceRegion; - - -/* -** Determine the size of a region. -*/ -#define IOACCEL_SIZEOF_DEVICE_REGION(_rgn_) (sizeof(IOAccelDeviceRegion) + (_rgn_)->num_rects * sizeof(IOAccelBounds)) - - -/* -** Surface client public memory types. Private memory types start with -** kIOAccelNumSurfaceMemoryTypes. -*/ -enum eIOAccelSurfaceMemoryTypes { - kIOAccelNumSurfaceMemoryTypes, -}; - - -/* -** Surface client public methods. Private methods start with -** kIOAccelNumSurfaceMethods. -*/ -enum eIOAccelSurfaceMethods { - kIOAccelSurfaceSetIDMode, - kIOAccelSurfaceSetShape, - kIOAccelSurfaceGetState, - kIOAccelSurfaceLock, - kIOAccelSurfaceUnlock, - kIOAccelSurfaceRead, - kIOAccelSurfaceFlush, - kIOAccelNumSurfaceMethods, -}; - - -/* -** Option bits for IOAccelCreateSurface and the kIOAccelSurfaceSetIDMode method. -** The color depth field can take any value of the _CGSDepth enumeration. -*/ -typedef enum { - kIOAccelSurfaceModeColorDepthBits = 0x0000000F, -} eIOAccelSurfaceModeBits; - - -/* -** Options bits for IOAccelSetSurfaceShape and the kIOAccelSurfaceSetShape method. -*/ -typedef enum { - kIOAccelSurfaceShapeNone = 0x00000000, - kIOAccelSurfaceShapeBlockingBit = 0x00000001, - kIOAccelSurfaceShapeNonSimpleBit = 0x00000002, -} eIOAccelSurfaceShapeBits; - - -/* -** Return bits for the kIOAccelSurfaceGetState method. -*/ -typedef enum { - kIOAccelSurfaceStateNone = 0x00000000, - kIOAccelSurfaceStateIdleBit = 0x00000001, -} eIOAccelSurfaceStateBits; - - -#endif /* _IOACCEL_SURFACE_CONNECT_H */ - diff --git a/iokit/IOKit/graphics/IOAccelerator.h b/iokit/IOKit/graphics/IOAccelerator.h deleted file mode 100644 index a188a2a3d..000000000 --- a/iokit/IOKit/graphics/IOAccelerator.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IO_ACCELERATOR_H -#define _IO_ACCELERATOR_H - -#include <IOKit/IOService.h> - -class IOAccelerator : public IOService -{ - OSDeclareDefaultStructors(IOAccelerator) -}; - - -#endif /* _IO_ACCELERATOR_H */ - diff --git a/iokit/IOKit/graphics/IODisplay.h b/iokit/IOKit/graphics/IODisplay.h deleted file mode 100644 index ae78f8d24..000000000 --- a/iokit/IOKit/graphics/IODisplay.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 23 Jul 98 - start IOKit - */ - -#ifndef _IOKIT_IODISPLAY_H -#define _IOKIT_IODISPLAY_H - -#include <IOKit/IOService.h> -#include <IOKit/graphics/IOFramebuffer.h> - -extern const OSSymbol * gIODisplayParametersKey; -extern const OSSymbol * gIODisplayGUIDKey; - -extern const OSSymbol * gIODisplayValueKey; -extern const OSSymbol * gIODisplayMinValueKey; -extern const OSSymbol * gIODisplayMaxValueKey; - -extern const OSSymbol * gIODisplayContrastKey; -extern const OSSymbol * gIODisplayBrightnessKey; -extern const OSSymbol * gIODisplayHorizontalPositionKey; -extern const OSSymbol * gIODisplayHorizontalSizeKey; -extern const OSSymbol * gIODisplayVerticalPositionKey; -extern const OSSymbol * gIODisplayVerticalSizeKey; -extern const OSSymbol * gIODisplayTrapezoidKey; -extern const OSSymbol * gIODisplayPincushionKey; -extern const OSSymbol * gIODisplayParallelogramKey; -extern const OSSymbol * gIODisplayRotationKey; - -extern const OSSymbol * gIODisplayParametersCommitKey; -extern const OSSymbol * gIODisplayParametersDefaultKey; - -enum { - kIODisplayMaxPowerStates = 4 -}; - -struct DisplayPMVars // these are the private instance variables for power management -{ - IOIndex connectIndex; - // control bytes we send to the framebuffer to control syncs - UInt32 syncControls[kIODisplayMaxPowerStates]; - // mask bits that go with the control byte - UInt32 syncMask; - // current state of sync signals - UInt32 currentSyncs; - // highest state number normally, lowest usable state in emergency - unsigned long max_display_state; - bool displayIdle; // true if the display has had power lowered due to user inactivity - bool powerControllable; // false if no sync control available on video display -}; - -class IODisplayConnect : public IOService -{ - OSDeclareDefaultStructors(IODisplayConnect) - -private: - IOIndex connection; - -public: - virtual bool initWithConnection( IOIndex connection ); - virtual IOFramebuffer * getFramebuffer( void ); - virtual IOIndex getConnection( void ); - virtual IOReturn getAttributeForConnection( IOIndex, IOSelect, UInt32 * ); - virtual IOReturn setAttributeForConnection( IOIndex, IOSelect, UInt32 ); - virtual void joinPMtree ( IOService * driver ); -}; - -class IODisplay : public IOService -{ - OSDeclareAbstractStructors(IODisplay) - -public: - static void initialize( void ); - -private: - - // used to query the framebuffer controller - IODisplayConnect * connection; -protected: - // pointer to protected instance variables for power management - struct DisplayPMVars * displayPMVars; - - /* Reserved for future expansion. */ - int _IODisplay_reserved[2]; - - virtual void initForPM ( IOService * ); - - virtual IOReturn setProperties( OSObject * properties ); - - virtual IOReturn setAggressiveness ( unsigned long, unsigned long newLevel ); - virtual IOReturn setPowerState ( unsigned long, IOService* ); - virtual unsigned long maxCapabilityForDomainState ( IOPMPowerFlags ); - virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags ); - virtual unsigned long powerStateForDomainState ( IOPMPowerFlags ); - -public: - virtual IOService * probe( IOService * provider, - SInt32 * score ); - - virtual bool start( IOService * provider ); - - virtual IODisplayConnect * getConnection( void ); - - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ) = 0; - - virtual IOReturn getGammaTableByIndex( - UInt32 * channelCount, UInt32 * dataCount, - UInt32 * dataWidth, void ** data ); - - virtual void dropOneLevel ( void ); - virtual void makeDisplayUsable ( void ); - IOReturn registerPowerDriver ( IOService*, IOPMPowerState*, unsigned long ); -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class AppleSenseDisplay : public IODisplay -{ - OSDeclareDefaultStructors(AppleSenseDisplay) - -public: - virtual IOService * probe( IOService * provider, - SInt32 * score ); - - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ); -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -class AppleNoSenseDisplay : public IODisplay -{ - OSDeclareDefaultStructors(AppleNoSenseDisplay) - -public: - virtual IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, UInt32 * flags ); -}; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#endif /* ! _IOKIT_IODISPLAY_H */ - diff --git a/iokit/IOKit/graphics/IOFramebuffer.h b/iokit/IOKit/graphics/IOFramebuffer.h deleted file mode 100644 index 533a45041..000000000 --- a/iokit/IOKit/graphics/IOFramebuffer.h +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * 30 Nov 98 sdouglas start cpp, from previous versions. - */ - -#ifndef _IOKIT_IOFRAMEBUFFER_H -#define _IOKIT_IOFRAMEBUFFER_H - -#include <IOKit/IOService.h> -#include <IOKit/graphics/IOGraphicsDevice.h> -#include <IOKit/graphics/IOFramebufferShared.h> -#include <IOKit/IOLib.h> - -class IOFramebuffer; -class IOBufferMemoryDescriptor; - -typedef void (*CursorBlitProc)( - IOFramebuffer * inst, - void * shmem, - volatile unsigned char *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - -typedef void (*CursorRemoveProc)( - IOFramebuffer * inst, - void * shmem, - volatile unsigned char *vramPtr, - unsigned int vramRow, - int width, - int height ); - -enum { - kTransparentEncoding = 0, - kInvertingEncoding -}; - -enum { - kTransparentEncodingShift = (kTransparentEncoding << 1), - kTransparentEncodedPixel = (0x01 << kTransparentEncodingShift), - - kInvertingEncodingShift = (kInvertingEncoding << 1), - kInvertingEncodedPixel = (0x01 << kInvertingEncodingShift), -}; - -enum { - kHardwareCursorDescriptorMajorVersion = 0x0001, - kHardwareCursorDescriptorMinorVersion = 0x0000 -}; - -struct IOHardwareCursorDescriptor { - UInt16 majorVersion; - UInt16 minorVersion; - UInt32 height; - UInt32 width; - UInt32 bitDepth; - UInt32 maskBitDepth; - UInt32 numColors; - UInt32 * colorEncodings; - UInt32 flags; - UInt32 supportedSpecialEncodings; - UInt32 specialEncodings[16]; -}; -typedef struct IOHardwareCursorDescriptor IOHardwareCursorDescriptor; - -enum { - kHardwareCursorInfoMajorVersion = 0x0001, - kHardwareCursorInfoMinorVersion = 0x0000 -}; - -struct IOHardwareCursorInfo { - UInt16 majorVersion; - UInt16 minorVersion; - UInt32 cursorHeight; - UInt32 cursorWidth; - // nil or big enough for hardware's max colors - IOColorEntry * colorMap; - UInt8 * hardwareCursorData; - UInt32 reserved[6]; -}; -typedef struct IOHardwareCursorInfo IOHardwareCursorInfo; - -// clock & data values -enum { - kIODDCLow = 0, - kIODDCHigh = 1, - kIODDCTristate = 2 -}; -// ddcBlockType constants -enum { - // EDID block type. - kIODDCBlockTypeEDID = 0 -}; - -// ddcFlags constants -enum { - // Force a new read of the EDID. - kIODDCForceRead = 0x00000001, -}; - -enum { - kDisabledInterruptState = 0, - kEnabledInterruptState = 1 -}; - -typedef void (*IOFBInterruptProc)( OSObject * target, void * ref ); - - -typedef IOReturn (*IOFramebufferNotificationHandler) - (OSObject * self, void * ref, - IOFramebuffer * framebuffer, IOIndex event, - void * info); - -// IOFramebufferNotificationHandler events -enum { - kIOFBNotifyDisplayModeWillChange = 1, - kIOFBNotifyDisplayModeDidChange, - kIOFBNotifyWillSleep, - kIOFBNotifyDidWake, -}; - - -struct StdFBShmem_t; -class IOFramebufferUserClient; - -class IOFramebuffer : public IOGraphicsDevice -{ - friend class IOFramebufferUserClient; - friend class IOFramebufferSharedUserClient; - friend class IOGraphicsEngineClient; - - OSDeclareDefaultStructors(IOFramebuffer) - -protected: -/*! @struct ExpansionData - @discussion This structure will be used to expand the capablilties of this class in the future. - */ - struct ExpansionData { }; - -/*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * reserved; - -private: - -protected: - StdFBShmem_t * priv; - int shmemClientVersion; - IOBufferMemoryDescriptor * sharedCursor; - - union { - struct { - /* Mapping tables used in cursor drawing to 5-5-5 displays. */ - unsigned char * _bm34To35SampleTable; - unsigned char * _bm35To34SampleTable; - /* Mapping tables used in cursor drawing to 8-bit RGB displays. */ - unsigned int * _bm256To38SampleTable; - unsigned char * _bm38To256SampleTable; - } t; - UInt8 * tables[ 4 ]; - } colorConvert; - - /* cursor blitting vars */ - CursorBlitProc cursorBlitProc; - CursorRemoveProc cursorRemoveProc; - - IOGSize maxCursorSize; - volatile unsigned char * cursorImages[ kIOFBNumCursorFrames ]; - volatile unsigned char * cursorMasks[ kIOFBNumCursorFrames ]; - volatile unsigned char * cursorSave; - unsigned int white; - - Point nextCursorLoc; - int nextCursorFrame; - void * vblInterrupt; - semaphore_t vblSemaphore; - - /* memory ranges */ - volatile unsigned char * frameBuffer; - unsigned int totalWidth; - unsigned int rowBytes; - unsigned int bytesPerPixel; - - IOMemoryMap * vramMap; - IOByteCount vramMapOffset; - OSArray * userAccessRanges; - OSArray * engineAccessRanges; - IOBufferMemoryDescriptor * engineContext; - OSSet * fbNotifications; - - class IOFramebufferUserClient * serverConnect; - class IOFramebufferSharedUserClient * sharedConnect; - - bool opened; - bool closed; - bool clutValid; - bool currentMono; - bool needCursorService; - bool haveVBLService; - bool haveHWCursor; - bool hwCursorLoaded; - - void * pmRef; - - /* Reserved for future expansion. */ - int _IOFramebuffer_reserved[7]; - -private: - OSMetaClassDeclareReservedUnused(IOFramebuffer, 0); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 1); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 2); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 3); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 4); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 5); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 6); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 7); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 8); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 9); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 10); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 11); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 12); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 13); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 14); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 15); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 16); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 17); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 18); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 19); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 20); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 21); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 22); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 23); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 24); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 25); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 26); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 27); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 28); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 29); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 30); - OSMetaClassDeclareReservedUnused(IOFramebuffer, 31); - - -public: - static void initialize(); - - virtual IOReturn powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService* ); - virtual IOReturn powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService* ); - virtual IOReturn setPowerState( unsigned long powerStateOrdinal, IOService * device); - virtual IOReturn newUserClient( task_t owningTask, - void * security_id, - UInt32 type, - IOUserClient ** handler ); - - - virtual void hideCursor( void ); - virtual void showCursor( Point * cursorLoc, int frame ); - virtual void moveCursor( Point * cursorLoc, int frame ); - // virtual - void resetCursor( void ); - - virtual void getVBLTime( AbsoluteTime * time, AbsoluteTime * delta ); - - virtual void getBoundingRect ( Bounds ** bounds ); - - virtual bool start( IOService * provider ); - - virtual IOReturn open( void ); - - virtual void close( void ); - - virtual bool isConsoleDevice( void ); - - virtual IOReturn setupForCurrentConfig( void ); - - virtual bool serializeInfo( OSSerialize * s ); - virtual bool setNumber( OSDictionary * dict, const char * key, - UInt32 number ); - - IONotifier * addFramebufferNotification( - IOFramebufferNotificationHandler handler, - OSObject * self, void * ref); - - virtual IODeviceMemory * getApertureRange( IOPixelAperture aperture ) = 0; - virtual IODeviceMemory * getVRAMRange( void ); - -protected: - - IOReturn deliverFramebufferNotification( - IOIndex event, void * info = 0 ); - -#ifdef IOFRAMEBUFFER_PRIVATE -#include <IOKit/graphics/IOFramebufferPrivate.h> -#endif - -public: - - virtual IOReturn enableController( void ); - - // List of pixel formats supported, null separated, - // doubly null terminated. - virtual const char * getPixelFormats( void ) = 0; - - // Array of supported display modes - virtual IOItemCount getDisplayModeCount( void ) = 0; - virtual IOReturn getDisplayModes( IODisplayModeID * allDisplayModes ) = 0; - - // Info about a display mode - virtual IOReturn getInformationForDisplayMode( IODisplayModeID displayMode, - IODisplayModeInformation * info ) = 0; - - // Mask of pixel formats available in mode and depth - virtual UInt64 getPixelFormatsForDisplayMode( IODisplayModeID displayMode, - IOIndex depth ) = 0; - - virtual IOReturn getPixelInformation( - IODisplayModeID displayMode, IOIndex depth, - IOPixelAperture aperture, IOPixelInformation * pixelInfo ) = 0; - - // Framebuffer info - - // Current display mode and depth - virtual IOReturn getCurrentDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ) = 0; - - // Set display mode and depth - virtual IOReturn setDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - - // For pages - virtual IOReturn setApertureEnable( IOPixelAperture aperture, - IOOptionBits enable ); - - // Display mode and depth for startup - virtual IOReturn setStartupDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - virtual IOReturn getStartupDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ); - - //// CLUTs - - virtual IOReturn setCLUTWithEntries( IOColorEntry * colors, UInt32 index, - UInt32 numEntries, IOOptionBits options ); - - //// Gamma - - virtual IOReturn setGammaTable( UInt32 channelCount, UInt32 dataCount, - UInt32 dataWidth, void * data ); - - //// Controller attributes - - virtual IOReturn setAttribute( IOSelect attribute, UInt32 value ); - virtual IOReturn getAttribute( IOSelect attribute, UInt32 * value ); - - //// Display mode timing information - - virtual IOReturn getTimingInfoForDisplayMode( - IODisplayModeID displayMode, IOTimingInformation * info ); - - //// Detailed timing information - - virtual IOReturn validateDetailedTiming( - void * description, IOByteCount descripSize ); - - virtual IOReturn setDetailedTimings( OSArray * array ); - - //// Connections - - virtual IOItemCount getConnectionCount( void ); - - virtual IOReturn setAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 value ); - virtual IOReturn getAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 * value ); - - //// HW Cursors - - virtual bool convertCursorImage( void * cursorImage, - IOHardwareCursorDescriptor * description, - IOHardwareCursorInfo * cursor ); - - virtual IOReturn setCursorImage( void * cursorImage ); - virtual IOReturn setCursorState( SInt32 x, SInt32 y, bool visible ); - - //// SW Cursors - - virtual void flushCursor( void ); - - // Apple sensing - - virtual IOReturn getAppleSense( IOIndex connectIndex, - UInt32 * senseType, - UInt32 * primary, - UInt32 * extended, - UInt32 * displayType ); - - virtual IOReturn connectFlags( IOIndex connectIndex, - IODisplayModeID displayMode, IOOptionBits * flags ); - - //// IOLowLevelDDCSense - - virtual void setDDCClock( IOIndex connectIndex, UInt32 value ); - virtual void setDDCData( IOIndex connectIndex, UInt32 value ); - virtual bool readDDCClock( IOIndex connectIndex ); - virtual bool readDDCData( IOIndex connectIndex ); - virtual IOReturn enableDDCRaster( bool enable ); - - //// IOHighLevelDDCSense - - virtual bool hasDDCConnect( IOIndex connectIndex ); - virtual IOReturn getDDCBlock( IOIndex connectIndex, UInt32 blockNumber, - IOSelect blockType, IOOptionBits options, - UInt8 * data, IOByteCount * length ); - - //// Interrupts - - // This is driven in the opposite direction to ndrv's ie. the base class - // registers a proc with the driver, and controls int generation with - // setInterruptState. Clients ask for serviceType. - - virtual IOReturn registerForInterruptType( IOSelect interruptType, - IOFBInterruptProc proc, OSObject * target, void * ref, - void ** interruptRef ); - virtual IOReturn unregisterInterrupt( void * interruptRef ); - virtual IOReturn setInterruptState( void * interruptRef, UInt32 state ); - - virtual IOReturn getNotificationSemaphore( IOSelect interruptType, - semaphore_t * semaphore ); -}; - -#endif /* ! _IOKIT_IOFRAMEBUFFER_H */ diff --git a/iokit/IOKit/graphics/IOFramebufferPrivate.h b/iokit/IOKit/graphics/IOFramebufferPrivate.h deleted file mode 100644 index 098191ec1..000000000 --- a/iokit/IOKit/graphics/IOFramebufferPrivate.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - void setupCursor( IOPixelInformation * info ); - void stopCursor( void ); - IOReturn doSetup( bool full ); - IOReturn createSharedCursor( int shmemVersion, - int maxWidth, int maxHeight ); - IOReturn setBoundingRect( Bounds * bounds ); - IOReturn setUserRanges( void ); - IOReturn getConnectFlagsForDisplayMode( - IODisplayModeID mode, IOIndex connection, UInt32 * flags ); - IOReturn extGetDisplayModeCount( IOItemCount * count ); - IOReturn extGetDisplayModes( IODisplayModeID * allModes, - IOByteCount * size ); - IOReturn extSetDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - IOReturn extGetInformationForDisplayMode( - IODisplayModeID mode, IODisplayModeInformation * info ); - - IOReturn extGetVRAMMapOffset( IOPixelAperture aperture, - IOByteCount * offset ); - IOReturn extSetBounds( Bounds * bounds ); - - IOReturn extSetNewCursor( void * cursor, IOIndex frame, - IOOptionBits options ); - IOReturn extSetCursorVisible( bool visible ); - IOReturn extSetCursorPosition( SInt32 x, SInt32 y ); - IOReturn extSetColorConvertTable( UInt32 select, - UInt8 * data, IOByteCount length ); - IOReturn extSetCLUTWithEntries( UInt32 index, IOOptionBits options, - IOColorEntry * colors, IOByteCount inputCount ); - IOReturn makeModeList( void ); - IOReturn getDefaultMode( IOIndex connection, IODisplayModeID * mode, - IOIndex * depth); - IOReturn extValidateDetailedTiming( - void * description, void * outDescription, - IOByteCount inSize, IOByteCount * outSize ); - IOReturn beginSystemSleep( void * ackRef ); - - static inline void StdFBDisplayCursor( IOFramebuffer * inst ); - static inline void StdFBRemoveCursor( IOFramebuffer * inst ); - static inline void RemoveCursor( IOFramebuffer * inst ); - static inline void DisplayCursor( IOFramebuffer * inst ); - static inline void SysHideCursor( IOFramebuffer * inst ); - static inline void SysShowCursor( IOFramebuffer * inst ); - static inline void CheckShield( IOFramebuffer * inst ); - - static void StdFBDisplayCursor8P( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBDisplayCursor8G( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBDisplayCursor555( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBDisplayCursor444( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBDisplayCursor32Axxx( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBDisplayCursor32xxxA( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int cursStart, - unsigned int vramRow, - unsigned int cursRow, - int width, - int height ); - - static void StdFBRemoveCursor8( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned char *vramPtr, - unsigned int vramRow, - int width, - int height ); - static void StdFBRemoveCursor16( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned short *vramPtr, - unsigned int vramRow, - int width, - int height ); - - static void StdFBRemoveCursor32( - IOFramebuffer * inst, - StdFBShmem_t *shmem, - volatile unsigned int *vramPtr, - unsigned int vramRow, - int width, - int height ); - - static void deferredMoveCursor(IOFramebuffer * inst); - static void handleVBL(IOFramebuffer * inst, void * ref); diff --git a/iokit/IOKit/graphics/IOFramebufferShared.h b/iokit/IOKit/graphics/IOFramebufferShared.h deleted file mode 100644 index 4426a3945..000000000 --- a/iokit/IOKit/graphics/IOFramebufferShared.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992, 1993 NeXT Computer, Inc. All rights reserved. - * - * IOFrameBufferShared.h - Definitions of objects and types shared between - * kernel level IOFrameBufferDisplay driver and PostScript level driver. - * - * HISTORY - * 03 Sep 92 Joe Pasqua - * Created. - * 24 Jun 93 Derek B Clegg - * Moved to driverkit. - */ - -#ifndef _IOKIT_IOFRAMEBUFFERSHARED_H -#define _IOKIT_IOFRAMEBUFFERSHARED_H - -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/graphics/IOGraphicsTypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef KERNEL -// CGS use optional -#define IOFB_ARBITRARY_SIZE_CURSOR -#endif - -#define IOFB_SUPPORTS_XOR_CURSOR - -// -// Cursor and Window Server state data, occupying a slice of shared memory -// between the kernel and WindowServer. -// - -enum { - kIOFBNumCursorFrames = 4, - kIOFBNumCursorFramesShift = 2, - kIOFBMaxCursorDepth = 32 -}; - -#ifndef IOFB_ARBITRARY_SIZE_CURSOR - -#define CURSORWIDTH 16 /* width in pixels */ -#define CURSORHEIGHT 16 /* height in pixels */ - -struct bm12Cursor { - unsigned int image[4][16]; - unsigned int mask[4][16]; - unsigned int save[16]; -}; - -struct bm18Cursor { - unsigned char image[4][256]; - unsigned char mask[4][256]; - unsigned char save[256]; -}; - -struct bm34Cursor { - unsigned short image[4][256]; - unsigned short save[256]; -}; - -struct bm38Cursor { - unsigned int image[4][256]; - unsigned int save[256]; -}; - -#endif /* IOFB_ARBITRARY_SIZE_CURSOR */ - -struct StdFBShmem_t { - ev_lock_data_t cursorSema; - int frame; - char cursorShow; - char cursorObscured; - char shieldFlag; - char shielded; - IOGBounds saveRect; - IOGBounds shieldRect; - IOGPoint cursorLoc; - IOGBounds cursorRect; - IOGBounds oldCursorRect; - IOGBounds screenBounds; - int version; - int structSize; - AbsoluteTime vblTime; - AbsoluteTime vblDelta; - unsigned int reservedC[30]; - unsigned char hardwareCursorCapable; - unsigned char hardwareCursorActive; - unsigned char reservedB[2]; - IOGSize cursorSize[kIOFBNumCursorFrames]; - IOGPoint hotSpot[kIOFBNumCursorFrames]; -#ifndef IOFB_ARBITRARY_SIZE_CURSOR - union { - struct bm12Cursor bw; - struct bm18Cursor bw8; - struct bm34Cursor rgb; - struct bm38Cursor rgb24; - } cursor; -#else /* IOFB_ARBITRARY_SIZE_CURSOR */ - unsigned char cursor[0]; -#endif /* IOFB_ARBITRARY_SIZE_CURSOR */ -}; -#ifndef __cplusplus -typedef volatile struct StdFBShmem_t StdFBShmem_t; -#endif - - -enum { - // version for IOFBCreateSharedCursor - kIOFBCurrentShmemVersion = 2, - // memory types for IOConnectMapMemory. - // 0..n are apertures - kIOFBCursorMemory = 100, - kIOFBVRAMMemory = 110 -}; - -#define IOFRAMEBUFFER_CONFORMSTO "IOFramebuffer" - -#ifdef __cplusplus -} -#endif - -#endif /* ! _IOKIT_IOFRAMEBUFFERSHARED_H */ diff --git a/iokit/IOKit/graphics/IOGraphicsTypes.h b/iokit/IOKit/graphics/IOGraphicsTypes.h deleted file mode 100644 index e580fea71..000000000 --- a/iokit/IOKit/graphics/IOGraphicsTypes.h +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - - -#ifndef _IOKIT_IOGRAPHICSTYPES_H -#define _IOKIT_IOGRAPHICSTYPES_H - - -#include <IOKit/IOTypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef SInt32 IOIndex; -typedef UInt32 IOSelect; -typedef UInt32 IOFixed1616; -typedef SInt32 IODisplayModeID; -typedef UInt32 IODisplayVendorID; -typedef UInt32 IODisplayProductID; - -enum { - kIOMaxPixelBits = 64 -}; -typedef char IOPixelEncoding[ kIOMaxPixelBits ]; - -// Common Apple pixel formats - -#define IO1BitIndexedPixels "P" -#define IO2BitIndexedPixels "PP" -#define IO4BitIndexedPixels "PPPP" -#define IO8BitIndexedPixels "PPPPPPPP" -#define IO16BitDirectPixels "-RRRRRGGGGGBBBBB" -#define IO32BitDirectPixels "--------RRRRRRRRGGGGGGGGBBBBBBBB" - -// other possible pixel formats - -#define IOYUV422Pixels "Y4U2V2" -#define IO8BitOverlayPixels "O8" -// page flipping -#define IOPagedPixels "Page1" - -#define IO_SampleTypeAlpha 'A' -#define IO_SampleTypeSkip '-' - -// Info about a pixel format -enum { - kIOCLUTPixels = 0, - kIOFixedCLUTPixels = 1, - kIORGBDirectPixels = 2, - kIOMonoDirectPixels = 3, - kIOMonoInverseDirectPixels = 4, -}; - -struct IOPixelInformation { - IOByteCount bytesPerRow; - IOByteCount bytesPerPlane; - UInt32 bitsPerPixel; - UInt32 pixelType; - UInt32 componentCount; - UInt32 bitsPerComponent; - UInt32 componentMasks[ 8 * 2 ]; - IOPixelEncoding pixelFormat; - UInt32 flags; - UInt32 activeWidth; - UInt32 activeHeight; - UInt32 reserved[ 2 ]; -}; -typedef struct IOPixelInformation IOPixelInformation; - -// Info about a display mode -typedef UInt32 IOAppleTimingID; - -struct IODisplayModeInformation { - UInt32 nominalWidth; - UInt32 nominalHeight; - IOFixed1616 refreshRate; - IOIndex maxDepthIndex; - UInt32 flags; - UInt32 reserved[ 4 ]; -}; -typedef struct IODisplayModeInformation IODisplayModeInformation; - -// flags -enum { - kDisplayModeSafetyFlags = 0x00000007, - - kDisplayModeAlwaysShowFlag = 0x00000008, - kDisplayModeNeverShowFlag = 0x00000080, - kDisplayModeNotResizeFlag = 0x00000010, - kDisplayModeRequiresPanFlag = 0x00000020, - - kDisplayModeInterlacedFlag = 0x00000040, - - kDisplayModeSimulscanFlag = 0x00000100, - kDisplayModeBuiltInFlag = 0x00000400, - kDisplayModeNotPresetFlag = 0x00000200, - kDisplayModeStretchedFlag = 0x00000800 -}; -enum { - kDisplayModeValidFlag = 0x00000001, - kDisplayModeSafeFlag = 0x00000002, - kDisplayModeDefaultFlag = 0x00000004, -}; - -// Framebuffer info - -struct IOFramebufferInformation { - IOPhysicalAddress baseAddress; - UInt32 activeWidth; - UInt32 activeHeight; - IOByteCount bytesPerRow; - IOByteCount bytesPerPlane; - UInt32 bitsPerPixel; - UInt32 pixelType; - UInt32 flags; - UInt32 reserved[ 4 ]; -}; -typedef struct IOFramebufferInformation IOFramebufferInformation; - -// flags -enum { - kFramebufferSupportsCopybackCache = 0x00010000, - kFramebufferSupportsWritethruCache = 0x00020000, - kFramebufferSupportsGammaCorrection = 0x00040000, - kFramebufferDisableAltivecAccess = 0x00080000, -}; - -// Aperture is an index into supported pixel formats for a mode & depth -typedef IOIndex IOPixelAperture; -enum { - kIOFBSystemAperture = 0 -}; - -//// CLUTs - -typedef UInt16 IOColorComponent; - -struct IOColorEntry { - UInt16 index; - IOColorComponent red; - IOColorComponent green; - IOColorComponent blue; -}; -typedef struct IOColorEntry IOColorEntry; - -// options (masks) -enum { - kSetCLUTByValue = 0x00000001, // else at index - kSetCLUTImmediately = 0x00000002, // else at VBL - kSetCLUTWithLuminance = 0x00000004 // else RGB -}; - -//// Controller attributes - -enum { - kIOPowerAttribute = 'powr', - kIOHardwareCursorAttribute = 'crsr' -}; - -//// Display mode timing information - -struct IODetailedTimingInformation { - // from EDID defn - UInt32 pixelClock; // Hertz - UInt32 horizontalActive; // pixels - UInt32 horizontalBlanking; // pixels - UInt32 horizontalBorder; // pixels - UInt32 horizontalSyncOffset; // pixels - UInt32 horizontalSyncWidth; // pixels - UInt32 verticalActive; // lines - UInt32 verticalBlanking; // lines - UInt32 verticalBorder; // lines - UInt32 verticalSyncOffset; // lines - UInt32 verticalSyncWidth; // lines -}; -typedef struct IODetailedTimingInformation IODetailedTimingInformation; - -struct IOTimingInformation { - IOAppleTimingID appleTimingID; // appleTimingXXX const - UInt32 flags; - IODetailedTimingInformation detailedInfo; -}; -typedef struct IOTimingInformation IOTimingInformation; - -enum { - // b0-7 from EDID flags - kIODetailedTimingValid = 0x80000000 -}; - -//// Connections - -enum { - kOrConnections = 0xffffffe, - kAndConnections = 0xffffffd -}; - -enum { - kConnectionEnable = 'enab', - kConnectionSyncEnable = 'sync', - kConnectionSyncFlags = 'sycf', - kConnectionSupportsAppleSense = 'asns', - kConnectionSupportsLLDDCSense = 'lddc', - kConnectionSupportsHLDDCSense = 'hddc' -}; - -// kConnectionSyncControl values -enum { - kIOHSyncDisable = 0x00000001, - kIOVSyncDisable = 0x00000002, - kIOCSyncDisable = 0x00000004, - kIONoSeparateSyncControl = 0x00000040, - kIOTriStateSyncs = 0x00000080, - kIOSyncOnBlue = 0x00000008, - kIOSyncOnGreen = 0x00000010, - kIOSyncOnRed = 0x00000020 -}; - - -#define IO_DISPLAY_CAN_FILL 0x00000040 -#define IO_DISPLAY_CAN_BLIT 0x00000020 - -#define IO_24BPP_TRANSFER_TABLE_SIZE 256 -#define IO_15BPP_TRANSFER_TABLE_SIZE 256 -#define IO_8BPP_TRANSFER_TABLE_SIZE 256 -#define IO_12BPP_TRANSFER_TABLE_SIZE 256 -#define IO_2BPP_TRANSFER_TABLE_SIZE 256 - -#define STDFB_BM256_TO_BM38_MAP_SIZE 256 -#define STDFB_BM38_TO_BM256_MAP_SIZE 256 -#define STDFB_BM38_TO_256_WITH_LOGICAL_SIZE \ - (STDFB_BM38_TO_BM256_MAP_SIZE + (256/sizeof(int))) - -#define STDFB_4BPS_TO_5BPS_MAP_SIZE 16 -#define STDFB_5BPS_TO_4BPS_MAP_SIZE 32 - -enum { - // connection types for IOServiceOpen - kIOFBServerConnectType = 0, - kIOFBSharedConnectType = 1, - kIOFBEngineControllerConnectType = 20, - kIOFBEngineConnectType = 21 -}; - -struct IOGPoint { - SInt16 x; - SInt16 y; -}; -typedef struct IOGPoint IOGPoint; - -struct IOGSize { - SInt16 width; - SInt16 height; -}; -typedef struct IOGSize IOGSize; - -struct IOGBounds { - SInt16 minx; - SInt16 maxx; - SInt16 miny; - SInt16 maxy; -}; -typedef struct IOGBounds IOGBounds; - -#if !defined(__Point__) && !defined(BINTREE_H) && !defined(__MACTYPES__) -#define __Point__ -typedef IOGPoint Point; -#endif - -#if !defined(__Bounds__) && !defined(BINTREE_H) && !defined(__MACTYPES__) -#define __Bounds__ -typedef IOGBounds Bounds; -#endif - -// interrupt types - -enum { - kIOFBVBLInterruptType = 'vbl ', - kIOFBHBLInterruptType = 'hbl ', - kIOFBFrameInterruptType = 'fram', - kIOFBConnectInterruptType = 'dci ' -}; - -// property keys - -#define kIOFramebufferInfoKey "IOFramebufferInformation" - -#define kIOFBWidthKey "IOFBWidth" -#define kIOFBHeightKey "IOFBHeight" -#define kIOFBRefreshRateKey "IOFBRefreshRate" -#define kIOFBFlagsKey "IOFBFlags" -#define kIOFBBytesPerRowKey "IOFBBytesPerRow" -#define kIOFBBytesPerPlaneKey "IOFBBytesPerPlane" -#define kIOFBBitsPerPixelKey "IOFBBitsPerPixel" -#define kIOFBComponentCountKey "IOFBComponentCount" -#define kIOFBBitsPerComponentKey "IOFBBitsPerComponent" - -#define kIOFBDetailedTimingsKey "IOFBDetailedTimings" -#define kIOFBTimingRangeKey "IOFBTimingRange" - -#define kIOFBHostAccessFlagsKey "IOFBHostAccessFlags" - -#define kIODisplayEDIDKey "IODisplayEDID" -#define kIODisplayLocationKey "IODisplayLocation" - -enum { - kDisplayVendorIDUnknown = 'unkn', - kDisplayProductIDGeneric = 0x717 -}; - -#define kDisplayVendorID "DisplayVendorID" // CFNumber -#define kDisplayProductID "DisplayProductID" // CFNumber -#define kDisplaySerialNumber "DisplaySerialNumber" // CFNumber -#define kDisplaySerialString "DisplaySerialString" // CFString -#define kDisplayWeekOfManufacture "DisplayWeekManufacture" // CFNumber -#define kDisplayYearOfManufacture "DisplayYearManufacture" // CFNumber - -// CFDictionary of language-locale keys, name values -// eg. "en"="Color LCD", "en-GB"="Colour LCD" -#define kDisplayProductName "DisplayProductName" - -// all CFNumber or CFArray of CFNumber (floats) -#define kDisplayWhitePointX "DisplayWhitePointX" -#define kDisplayWhitePointY "DisplayWhitePointY" -#define kDisplayRedPointX "DisplayRedPointX" -#define kDisplayRedPointY "DisplayRedPointY" -#define kDisplayGreenPointX "DisplayGreenPointX" -#define kDisplayGreenPointY "DisplayGreenPointY" -#define kDisplayBluePointX "DisplayBluePointX" -#define kDisplayBluePointY "DisplayBluePointY" -#define kDisplayWhiteGamma "DisplayWhiteGamma" -#define kDisplayRedGamma "DisplayRedGamma" -#define kDisplayGreenGamma "DisplayGreenGamma" -#define kDisplayBlueGamma "DisplayBlueGamma" - -// CFData -#define kDisplayCSProfile "DisplayCSProfile" - -// CFNumber -#define kDisplayHorizontalImageSize "DisplayHorizontalImageSize" -#define kDisplayVerticalImageSize "DisplayVerticalImageSize" - -// Display parameters - -#define kIODisplayParametersKey "IODisplayParameters" -#define kIODisplayGUIDKey "IODisplayGUID" - -#define kIODisplayValueKey "value" -#define kIODisplayMinValueKey "min" -#define kIODisplayMaxValueKey "max" - -#define kIODisplayBrightnessKey "brightness" -#define kIODisplayContrastKey "contrast" -#define kIODisplayHorizontalPositionKey "horizontal-position" -#define kIODisplayHorizontalSizeKey "horizontal-size" -#define kIODisplayVerticalPositionKey "vertical-position" -#define kIODisplayVerticalSizeKey "vertical-size" -#define kIODisplayTrapezoidKey "trapezoid" -#define kIODisplayPincushionKey "pincushion" -#define kIODisplayParallelogramKey "parallelogram" -#define kIODisplayRotationKey "rotation" -#define kIODisplayTheatreModeKey "theatre-mode" - -#define kIODisplayParametersCommitKey "commit" -#define kIODisplayParametersDefaultKey "defaults" - -#ifdef __cplusplus -} -#endif - -#endif /* ! _IOKIT_IOGRAPHICSTYPES_H */ diff --git a/iokit/IOKit/graphics/Makefile b/iokit/IOKit/graphics/Makefile deleted file mode 100644 index c533af748..000000000 --- a/iokit/IOKit/graphics/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = graphics -NOT_EXPORT_HEADERS = IOFramebufferPrivate.h - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = IOGraphicsEngine.h IOFramebufferShared.h \ - IOGraphicsTypes.h IOAccelTypes.h IOAccelClientConnect.h \ - IOAccelSurfaceConnect.h - -INSTALL_MI_LCL_LIST = "" - -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) - -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/hidsystem/IOHIDDescriptorParser.h b/iokit/IOKit/hidsystem/IOHIDDescriptorParser.h deleted file mode 100644 index 8777daea8..000000000 --- a/iokit/IOKit/hidsystem/IOHIDDescriptorParser.h +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef __IOHIDDescriptorParser__ -#define __IOHIDDescriptorParser__ - -#include <IOKit/IOTypes.h> -#include <IOKit/hidsystem/IOHIDUsageTables.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/* Types and enums required by these functions but not in IOTypes.h */ - -typedef UInt8 Byte; -typedef SInt8 SignedByte; -typedef unsigned long FourCharCode; -typedef FourCharCode OSType; -typedef UInt32 ByteCount; - -enum { - noErr = 0 -}; - -/* End missing types and enums */ - -enum -{ - kHIDSuccess = 0, - -/* HID assigned error numbers are -13949 .. -13900 */ - kHIDBaseError = -13950, - - kHIDNullStateErr, - kHIDBufferTooSmallErr, - kHIDValueOutOfRangeErr, - kHIDUsageNotFoundErr, - kHIDNotValueArrayErr, - kHIDInvalidPreparsedDataErr, - kHIDIncompatibleReportErr, - kHIDBadLogPhysValuesErr, - kHIDInvalidReportTypeErr, - kHIDInvalidReportLengthErr, - kHIDNullPointerErr, - kHIDBadParameterErr, - kHIDNotEnoughMemoryErr, - kHIDEndOfDescriptorErr, - kHIDUsagePageZeroErr, - kHIDBadLogicalMinimumErr, - kHIDBadLogicalMaximumErr, - kHIDInvertedLogicalRangeErr, - kHIDInvertedPhysicalRangeErr, - kHIDUnmatchedUsageRangeErr, - kHIDInvertedUsageRangeErr, - kHIDUnmatchedStringRangeErr, - kHIDUnmatchedDesignatorRangeErr, - kHIDReportSizeZeroErr, - kHIDReportCountZeroErr, - kHIDReportIDZeroErr, - kHIDInvalidRangePageErr, - - // - // HID device driver errors - // - - kHIDDeviceNotReady = -13910, // The device is still initializing, try again later - kHIDVersionIncompatibleErr, -}; - -// types of HID reports (input, output, feature) -enum -{ - kHIDInputReport = 1, - kHIDOutputReport, - kHIDFeatureReport, - kHIDUnknownReport = 255 -}; - -// flags passed to HIDOpenReportDescriptor -enum -{ - kHIDFlag_StrictErrorChecking = 0x00000001 -}; - -typedef UInt32 HIDReportType; -typedef UInt32 HIDUsage; - -typedef void *HIDPreparsedDataRef; - -/*! - @typedef HIDUsageAndPage - @abstract The HIDUsageAndPage data structure is used by HID clients when obtaining status of buttons to hold the usage page and usage of a button that is down. - @discussion Clients use the HIDUSageAndPage structure with the HIDGetButtonsEx function to obtain both the usage page and usage identifiers of each button that is down. - @field usage Specifies the usage identifier within the usage page specified by usagePage of a button that is down. - @field usagePage Specifies the usage page identifier of a button that is down. - */ -struct HIDUsageAndPage -{ - HIDUsage usage; - HIDUsage usagePage; -}; -typedef struct HIDUsageAndPage HIDUsageAndPage, *HIDUsageAndPagePtr; - -/*! - @typedef HIDCaps - @abstract The HIDCaps data structure is used by HID clients to hold the capabilities of a HID device. - @discussion This structure holds the parsed capabilities and data maximums returned for a device by the HIDGetCaps function. - @field usage Specifies the specific class of functionality that this device provides. This value is dependent and specific to the value provided in the usagePage field. For example, a keyboard could have a usagePage of kHIDUsagePage_Generic and a usage of kHIDUsage_Generic_Keyboard. - @field usagePage Specifies the usage page identifier for this top level collection. - @field inputReportByteLength Specifies the maximum length, in bytes, of an input report for this device, including the report ID which is unilaterally prepended to the device data. - @field outputReportByteLength Specifies the maximum length, in bytes, of an output report for this device, including the report ID which is unilaterally prepended to the device data. - @field featureReportByteLength Specifies the maximum length, in bytes, of a feature report for this device, including the report ID which is unilaterally prepended to the device data. - @field numberCollectionNodes Specifies the number of HIDCollectionNode structures that are returned for this top level collection by the HIDGetConnectionNodes function. - @field numberInputButtonCaps Specifies the number of input buttons. - @field numberInputValueCaps Specifies the number of input values. - @field numberOutputButtonCaps Specifies the number of output buttons. - @field numberOutputValueCaps Specifies the number of output values - @field numberFeatureButtonCaps Specifies the number of feature buttons. - @field numberFeatureValueCaps Specifies the number of feature values. - */ -struct HIDCaps -{ - HIDUsage usage; - HIDUsage usagePage; - ByteCount inputReportByteLength; - ByteCount outputReportByteLength; - ByteCount featureReportByteLength; - UInt32 numberCollectionNodes; - UInt32 numberInputButtonCaps; - UInt32 numberInputValueCaps; - UInt32 numberOutputButtonCaps; - UInt32 numberOutputValueCaps; - UInt32 numberFeatureButtonCaps; - UInt32 numberFeatureValueCaps; -}; -typedef struct HIDCaps HIDCaps, * HIDCapsPtr; - -struct HIDCapabilities { - HIDUsage usage; - HIDUsage usagePage; - ByteCount inputReportByteLength; - ByteCount outputReportByteLength; - ByteCount featureReportByteLength; - UInt32 numberCollectionNodes; - UInt32 numberInputButtonCaps; - UInt32 numberInputValueCaps; - UInt32 numberOutputButtonCaps; - UInt32 numberOutputValueCaps; - UInt32 numberFeatureButtonCaps; - UInt32 numberFeatureValueCaps; -}; -typedef struct HIDCapabilities HIDCapabilities, * HIDCapabilitiesPtr; - - -struct HIDCollectionNode -{ - HIDUsage collectionUsage; - HIDUsage collectionUsagePage; - UInt32 parent; - UInt32 numberOfChildren; - UInt32 nextSibling; - UInt32 firstChild; -}; -typedef struct HIDCollectionNode HIDCollectionNode, * HIDCollectionNodePtr; - -struct HIDButtonCaps -{ - HIDUsage usagePage; - UInt32 reportID; - UInt32 bitField; - UInt32 collection; - HIDUsage collectionUsage; - HIDUsage collectionUsagePage; - Boolean isRange; - Boolean isStringRange; - Boolean isDesignatorRange; - Boolean isAbsolute; - SInt32 startBit; // Added esb 9-29-99 - - union - { - struct - { - HIDUsage usageMin; - HIDUsage usageMax; - UInt32 stringMin; - UInt32 stringMax; - UInt32 designatorMin; - UInt32 designatorMax; - } range; - struct - { - HIDUsage usage; - HIDUsage reserved1; - UInt32 stringIndex; - UInt32 reserved2; - UInt32 designatorIndex; - UInt32 reserved3; - } notRange; - } u; -}; -typedef struct HIDButtonCaps HIDButtonCaps, * HIDButtonCapsPtr; - -struct HIDButtonCapabilities -{ - HIDUsage usagePage; - UInt32 reportID; - UInt32 bitField; - UInt32 collection; - HIDUsage collectionUsage; - HIDUsage collectionUsagePage; - Boolean isRange; - Boolean isStringRange; - Boolean isDesignatorRange; - Boolean isAbsolute; - - SInt32 unitExponent; // Added KH 1/25/01 - SInt32 units; // Added KH 1/25/01 -// UInt32 reserved; // Not added KH 1/25/01 - SInt32 startBit; // Added esb 9-29-99 - UInt32 pbVersion; // Added KH 1/25/01 - - union - { - struct - { - HIDUsage usageMin; - HIDUsage usageMax; - UInt32 stringMin; - UInt32 stringMax; - UInt32 designatorMin; - UInt32 designatorMax; - } range; - struct - { - HIDUsage usage; - HIDUsage reserved1; - UInt32 stringIndex; - UInt32 reserved2; - UInt32 designatorIndex; - UInt32 reserved3; - } notRange; - } u; -}; -typedef struct HIDButtonCapabilities HIDButtonCapabilities, * HIDButtonCapabilitiesPtr; - -struct HIDValueCaps -{ - HIDUsage usagePage; - UInt32 reportID; - UInt32 bitField; - UInt32 collection; - HIDUsage collectionUsage; - HIDUsage collectionUsagePage; - - Boolean isRange; - Boolean isStringRange; - Boolean isDesignatorRange; - Boolean isAbsolute; - - UInt32 startBit; // Added by esb 9-28-99 - UInt32 bitSize; - UInt32 reportCount; - - SInt32 logicalMin; - SInt32 logicalMax; - SInt32 physicalMin; - SInt32 physicalMax; - - union - { - struct - { - HIDUsage usageMin; - HIDUsage usageMax; - UInt32 stringMin; - UInt32 stringMax; - UInt32 designatorMin; - UInt32 designatorMax; - } range; - struct - { - HIDUsage usage; - HIDUsage reserved1; - UInt32 stringIndex; - UInt32 reserved2; - UInt32 designatorIndex; - UInt32 reserved3; - } notRange; - } u; -}; -typedef struct HIDValueCaps HIDValueCaps, * HIDValueCapsPtr; - -struct HIDValueCapabilities -{ - HIDUsage usagePage; - UInt32 reportID; - UInt32 bitField; - UInt32 collection; - HIDUsage collectionUsage; - HIDUsage collectionUsagePage; - - Boolean isRange; - Boolean isStringRange; - Boolean isDesignatorRange; - Boolean isAbsolute; - - UInt32 bitSize; - UInt32 reportCount; - - SInt32 logicalMin; - SInt32 logicalMax; - SInt32 physicalMin; - SInt32 physicalMax; - - SInt32 unitExponent; // Added KH 1/25/01 - SInt32 units; // Added KH 1/25/01 -// UInt32 reserved; // Not added KH 1/25/01 - SInt32 startBit; // Added esb 9-29-99 // Moved here KH 1/25/01 - UInt32 pbVersion; // Added KH 1/25/01 - - union - { - struct - { - HIDUsage usageMin; - HIDUsage usageMax; - UInt32 stringMin; - UInt32 stringMax; - UInt32 designatorMin; - UInt32 designatorMax; - } range; - struct - { - HIDUsage usage; - HIDUsage reserved1; - UInt32 stringIndex; - UInt32 reserved2; - UInt32 designatorIndex; - UInt32 reserved3; - } notRange; - } u; -}; -typedef struct HIDValueCapabilities HIDValueCapabilities, * HIDValueCapabilitiesPtr; - -/*! - @function HIDOpenReportDescriptor - @abstract The HIDOpenReportDescriptor function allocates the memory the parser needs to handle the given report descriptor, and then parses the report descriptor. - @discussion When the parsed information is no longer needed, clients should call the HIDCloseReportDescriptor function. - @param hidReportDescriptor Contains a pointer to the actual HID report descriptor from the USB device's firmware - @param descriptorLength The length of the HID report descriptor - @param preparsedDataRef Preparsed data reference to be used for subsequent function calls - @param flags Flags for this runction are kHIDFlag_StrictErrorChecking = 0x00000001 - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDOpenReportDescriptor (void * hidReportDescriptor, - ByteCount descriptorLength, - HIDPreparsedDataRef * preparsedDataRef, - UInt32 flags); - -/*! - @function HIDCloseReportDescriptor - @abstract Disposes of the memory the parser allocated for the HIDOpenReportDescriptor function. - @param hidReportDescriptor Contains a pointer to the actual HID report descriptor from the USB device's firmware - @param preparsedDataRef Preparsed data reference for the report that is returned by the HIDOpenReportDescriptor function. After making a call to the HIDCloseReportDescriptor function, the preparsedDataRef is invalid and should not be used. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDCloseReportDescriptor (HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetButtonCaps - @abstract Returns the button capabilities structures for a HID device based on the given preparsed data. - @param reportType Specifies the type of report for which to retrieve the scaled value. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport - @param buttonCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDButtonCaps structures. The structures contain information for all buttons that meet the search criteria - @param buttonCapsSize Contains the size of the buttonCaps array passed in to the function and is set to the number of elements actually placed in the array after the call completes. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetButtonCaps (HIDReportType reportType, - HIDButtonCapsPtr buttonCaps, - UInt32 * buttonCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetButtonCapabilities - @abstract Returns the button capabilities structures for a HID device based on the given preparsed data. - @param reportType Specifies the type of report for which to retrieve the scaled value. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport - @param buttonCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDButtonCapabilities structures. The structures contain information for all buttons that meet the search criteria - @param buttonCapsSize Contains the size of the buttonCaps array passed in to the function and is set to the number of elements actually placed in the array after the call completes. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetButtonCapabilities (HIDReportType reportType, - HIDButtonCapabilitiesPtr buttonCaps, - UInt32 * buttonCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetCaps - @abstract Returns the capabilities of a HID device based on the given preparsed data. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param capabilities Points to a caller allocated buffer, that upon return contains the parsed capability information for this HID device. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetCaps (HIDPreparsedDataRef preparsedDataRef, - HIDCapsPtr capabilities); - -/*! - @function HIDGetCapabilities - @abstract Returns the capabilities of a HID device based on the given preparsed data. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param capabilities Points to a caller allocated buffer, that upon return contains the parsed capability information for this HID device. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetCapabilities (HIDPreparsedDataRef preparsedDataRef, - HIDCapabilitiesPtr capabilities); - -/*! - @function HIDGetCollectionNodes - @abstract Returns an array of HIDCollectionNode structures that describe the relationships and layout of the link collections within this top level collection. - @discussion The length of the buffer required, in array elements, for an entire collection node array is found in the HIDCaps structure member numberCollectionNodes. You obtain the HIDCaps information by calling the HIDGetCaps function. For information on the relationships of link collections described by the data returned from this routine, see the descripton of the HIDCollectionNode structure. - @param collectionNodes Points to a caller-allocated array of HIDCollectionNode structures in which this routine returns an entry for each collection within the top level collection. A collection is a group of corresponding HID descriptors containing input, output, and feature items that have some common relationship to one another. For example, a pointer collection contains items for x and y position data, and button data. - @param collectionNodesSize On input, specifies the length in array elements of the buffer provided at collectionNodes. On output, this parameter is set to the number of entries in the collectionNodes array that were initialized. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetCollectionNodes (HIDCollectionNodePtr collectionNodes, - UInt32 * collectionNodesSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetScaledUsageValue - @abstract The HIDGetScaledUsageValue function returns the capabilities for all buttons for a given top level collection. - @discussion Clients who which to obtain all capabilities for a usage that contains multiple data items for a single usage that corresponds to a HID byte array, must call the HIDGetUsageValueArray function. - @param reportType Specifies the type of report for which to retrieve the scaled value. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page of the value to be retrieved. - @param collection Optionally specifies the link collection identifier of the value to be retrieved. - @param usage Specifies the usage of the scaled value to be retrieved. - @param usageValue Points to a variable, that on return from this routine holds the scaled value retrieved from the device report. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data - @param reportLength Specifies the length, in bytes, of the report data provided at report - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetScaledUsageValue (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - SInt32 * usageValue, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDGetSpecificButtonCaps - @abstract Retrieves the capabilities for all buttons in a specific type of report that meet the search criteria. - @discussion The HIDGetSpecificButtonCaps function retrieves capability data for buttons that meet a given search criteria, as opposed to the HIDGetButtonCaps function which returns the capability data for all buttons on the device. Calling this routine specifying zero for usagePage, usage and collection is equivalent to calling the HIDGetButtonCaps function. - @param reportType Specifies the type of report for which to retrieve the button capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies a usage page identifier to use as a search criteria. If this parameter is non-zero, then only buttons that specify this usage page will be retrieved. - @param collection Specifies a link collection identifier to use as a search criteria. If this parameter is non-zero, then only buttons that are part of the specified link collection are retrieved. - @param usage Specifies a usage identifier to use as a search criteria. If this parameter is non-zero, then only buttons that match the value specified are retrieved. - @param buttonCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDButtonCaps structures. The structures contain information for all buttons that meet the search criteria. - @param buttonCapsLength On input, specifies the length, in array elements, of the buffer provided in the buttonCaps parameter. On output, this parameter is set to the actual number of elements that were returned by the function call, in the buffer provided in the buttonCaps parameter, if the routine completed without error. The correct length necessary to retrieve the button capabilities can be found in the capability data returned for the device by the HIDGetCaps function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetSpecificButtonCaps (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDButtonCapsPtr buttonCaps, - UInt32 * buttonCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetSpecificButtonCapabilities - @abstract Retrieves the capabilities for all buttons in a specific type of report that meet the search criteria. - @discussion The HIDGetSpecificButtonCapabilities function retrieves capability data for buttons that meet a given search criteria, as opposed to the HIDGetButtonCapabilities function which returns the capability data for all buttons on the device. Calling this routine specifying zero for usagePage, usage and collection is equivalent to calling the HIDGetButtonCapabilities function. - @param reportType Specifies the type of report for which to retrieve the button capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies a usage page identifier to use as a search criteria. If this parameter is non-zero, then only buttons that specify this usage page will be retrieved. - @param collection Specifies a link collection identifier to use as a search criteria. If this parameter is non-zero, then only buttons that are part of the specified link collection are retrieved. - @param usage Specifies a usage identifier to use as a search criteria. If this parameter is non-zero, then only buttons that match the value specified are retrieved. - @param buttonCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDButtonCapabilities structures. The structures contain information for all buttons that meet the search criteria. - @param buttonCapsLength On input, specifies the length, in array elements, of the buffer provided in the buttonCaps parameter. On output, this parameter is set to the actual number of elements that were returned by the function call, in the buffer provided in the buttonCaps parameter, if the routine completed without error. The correct length necessary to retrieve the button capabilities can be found in the capability data returned for the device by the HIDGetCaps function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetSpecificButtonCapabilities (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDButtonCapabilitiesPtr buttonCaps, - UInt32 * buttonCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetSpecificValueCaps - @abstract Retrieves the capabilities for all values in a specific type of report that meet the search criteria. - @discussion The HIDGetSpecificValueCaps function retrieves capability data for values that meet given search criteria, as opposed to the HIDGetValueCaps function, which returns the capability data for all values on the device. Calling this routine with a value of zero for usagePage, usage and collection parameters is equivalent to calling the HIDGetValueCaps function. - @param reportType Specifies the type of report for which to retrieve the value capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport or kHIDFeatureReport. - @param usagePage Specifies a usage page identifier to use as a search criteria. If this parameter is non-zero, then only values that specify this usage page will be retrieved. - @param collection Specifies a link collection identifier to use as a search criteria. If this parameter is non-zero, then only values that are part of this link collection will be retrieved. - @param usage Specifies a usage identifier to use as a search criteria. If this parameter is non-zero, then only values that specify this usage will be retrieved. - @param valueCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDValueCaps structures that contain information for all values that meet the search criteria. - @param valueCapsSize Specifies the length on input, in array elements, of the buffer provided in the valueCaps parameter. On output, this parameter is set to the actual number of elements that were returned by this function call, in the buffer provided in the valueCaps parameter, if the routine completed without error. The correct length necessary to retrieve the value capabilities can be found in the capability data returned for the device from the HIDGetCaps function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetSpecificValueCaps (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDValueCapsPtr valueCaps, - UInt32 * valueCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetSpecificValueCapabilities - @abstract Retrieves the capabilities for all values in a specific type of report that meet the search criteria. - @discussion The HIDGetSpecificValueCapabilities function retrieves capability data for values that meet given search criteria, as opposed to the HIDGetValueCapabilities function, which returns the capability data for all values on the device. Calling this routine with a value of zero for usagePage, usage and collection parameters is equivalent to calling the HIDGetValueCapabilities function. - @param reportType Specifies the type of report for which to retrieve the value capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport or kHIDFeatureReport. - @param usagePage Specifies a usage page identifier to use as a search criteria. If this parameter is non-zero, then only values that specify this usage page will be retrieved. - @param collection Specifies a link collection identifier to use as a search criteria. If this parameter is non-zero, then only values that are part of this link collection will be retrieved. - @param usage Specifies a usage identifier to use as a search criteria. If this parameter is non-zero, then only values that specify this usage will be retrieved. - @param valueCaps Points to a caller-allocated buffer that will contain, on return, an array of HIDValueCapabilities structures that contain information for all values that meet the search criteria. - @param valueCapsSize Specifies the length on input, in array elements, of the buffer provided in the valueCaps parameter. On output, this parameter is set to the actual number of elements that were returned by this function call, in the buffer provided in the valueCaps parameter, if the routine completed without error. The correct length necessary to retrieve the value capabilities can be found in the capability data returned for the device from the HIDGetCaps function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetSpecificValueCapabilities (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDValueCapabilitiesPtr valueCaps, - UInt32 * valueCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetButtonsOnPage - @abstract Retrieves the button stat information for buttons on a specified usage page. - @param reportType Specifies the type of report, provided in the report parameter, from which to retrieve the buttons. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport or kHIDFeatureReport. - @param usagePage Specifies the usage page of the buttons for which to retrieve the current state. - @param collection Optionally specifies the link collection identifier used to retrieve only specific button states. If this value is non-zero, only the buttons that are part of the given collection are returned. - @param usageList On return, points to a caller-allocated buffer that contains the usages of all the buttons that are perssed and belong to the usage page specified in the usagePage parameter. - @param usageListSize Is the size, in array elements, of the buffer provided in the usageList parameter. On return, this parameter contains the number of button states that were set by this routine. If the error kHIDBufferTooSmallErr was returned, this parameter contains the number of array elements required to hold all button data requested. The maximum number of buttons that can ever be returned for a given type of report can be obtained by calling the HIDMaxUsageListLength function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetButtonsOnPage (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage * usageList, - UInt32 * usageListSize, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDGetButtons - @abstract The HIDGetButtons function takes a report from a HID device and gets the current state of the buttons in that report. - @param reportType Specifies the type of report, provided in the report parameter, from which to retrieve the buttons. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport or kHIDFeatureReport - @param collection Optionally specifies the link collection identifier used to retrieve only specific button states. If this value is non-zero, only the buttons that are part of the given collection are returned. - @param usageList On return, points to a caller-allocated buffer that contains the usages of all the buttons that are pressed. - @param usageListSize Is the size, in array elements, of the buffer provided in the usageList parameter. On return, this parameter contains the number of button states that were set by this routine. If the error kHIDBufferToSmallErr was returned, this parameter contains the number of array elements required to hold all button data requested. The maximum number of buttons that can ever be returned for a given type of report can be obtained by calling the HIDMaxUsageListLength function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the length, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetButtons (HIDReportType reportType, - UInt32 collection, - HIDUsageAndPagePtr usageList, - UInt32 * usageListSize, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -extern -OSStatus -HIDGetNextButtonInfo (HIDReportType reportType, - HIDUsage usagePage, - HIDUsage usage, - UInt32 * collection, - UInt8 * reportID, - HIDPreparsedDataRef preparsedDataRef); - -extern -OSStatus -HIDGetNextUsageValueInfo (HIDReportType reportType, - HIDUsage usagePage, - HIDUsage usage, - UInt32 * collection, - UInt8 * reportID, - HIDPreparsedDataRef preparsedDataRef); - -extern -OSStatus -HIDGetReportLength (HIDReportType reportType, - UInt8 reportID, - ByteCount * reportLength, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetUsageValue - @abstract The HIDGetUsageValue function returns a value from a device data report given a selected search criteria. - @discussion The HIDGetUsageValue function does not sign the value. To have the sign bit automatically applied, use the HIDGetScaledUsageValue function instead. For manually assigning the sign bit, the position of the sign bit can be found in the HIDValueCaps structure for this value. Clients who wish to obtain all data for a usage that contains multiple data items for a single usage, corresponding to a HID byte array, must call the HIDGetUsageValueArray function instead. - @param reportType Specifies the type of report, provided in report, from which to retrieve the value. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page of the value to retrieve. - @param collection Optionally specifies the link collection identifier of the value to be retrieved. - @param usage Specifies the usage of the value to be retrieved. - @param usageValue Points to a variable, that on return from this routine holds the value retrieved from the device report. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetUsageValue (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - SInt32 * usageValue, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDGetUsageValueArray - @abstract The HIDGetUsageValueArray function returns a value from a device data report given a selected search criteria. - @discussion When the HIDGetUsageValueArray function retrieves the data, it fills in the buffer in little-endian order beginning with the least significant bit of the data for this usage. The data is filled in without regard to byte alignment and is shifted such that the least significant bit is placed as the 1st bit of the given buffer. - @param reportType Specifies the type of report, provided in report, from which to retrieve the value. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page of the data to be retrieved. - @param collection Optionally specifies the link collection identifier of the data to be retrieved. - @param usage Specifies the usage identifier of the value to be retrieved. - @param usageValueBuffer Points to a caller-allocated buffer that contains, on output, the data from the device. The correct length for this buffer can be found by multiplying the reportCount and bitSize fields of the HIDValueCaps structure for the value and rounding the resulting value up to the nearest byte. - @param usageValueBufferSize Specifies the size, in bytes, of the buffer in the usageValueBuffer parameter. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in report. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetUsageValueArray (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - Byte * usageValueBuffer, - ByteCount usageValueBufferSize, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDGetValueCaps - @abstract The HIDGetValueCaps function retrieves the capabilities for all values for a specified top level collection. - @discussion The HIDGetValueCaps function retrieves the capability data for all values in a top level collection without regard for the usage, usage page or collection of the value. To retrieve value capabilities for a specific usage, usage page or collection, use the HIDGetSpecificValueCaps function. - @param reportType Specifies the type of report for which to retrieve the value capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param valueCaps On return, points to a caller-allocated buffer that contains an array of HIDValueCaps structures containing information for all values in the top level collection. - @param valueCapsSize On input, specifies the size in array elements of the buffer provided in the valueCaps parameter. On output, this parameter is set to the actual number of elements that were returned in the buffer provided in the valueCaps parameter, if the function completed without error. The correct length necessary to retrieve the value capabilities can be found in the capability data returned for the device by the HIDGetCaps function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetValueCaps (HIDReportType reportType, - HIDValueCapsPtr valueCaps, - UInt32 * valueCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDGetValueCapabilities - @abstract The HIDGetValueCapabilities function retrieves the capabilities for all values for a specified top level collection. - @discussion The HIDGetValueCapabilities function retrieves the capability data for all values in a top level collection without regard for the usage, usage page or collection of the value. To retrieve value capabilities for a specific usage, usage page or collection, use the HIDGetSpecificValueCapabilities function. - @param reportType Specifies the type of report for which to retrieve the value capabilities. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param valueCaps On return, points to a caller-allocated buffer that contains an array of HIDValueCapabilities structures containing information for all values in the top level collection. - @param valueCapsSize On input, specifies the size in array elements of the buffer provided in the valueCaps parameter. On output, this parameter is set to the actual number of elements that were returned in the buffer provided in the valueCaps parameter, if the function completed without error. The correct length necessary to retrieve the value capabilities can be found in the capability data returned for the device by the HIDGetCapabilities function. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDGetValueCapabilities (HIDReportType reportType, - HIDValueCapabilitiesPtr valueCaps, - UInt32 * valueCapsSize, - HIDPreparsedDataRef preparsedDataRef); - -extern -OSStatus -HIDInitReport (HIDReportType reportType, - UInt8 reportID, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDMaxUsageListLength - @abstract The HIDMaxUsageListLength function returns the maximum number of buttons that can be returned from a given report type for the top level collection. - @param reportType Specifies the type of report for which to get a maximum usage count. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Optionally specifies the usage page identifier to use as a search criteria. If this parameter is zero, the function returns the number of buttons for the entire top-level collection regardless of the actual value of the usage page. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -UInt32 -HIDMaxUsageListLength (HIDReportType reportType, - HIDUsage usagePage, - HIDPreparsedDataRef preparsedDataRef); - -/*! - @function HIDSetScaledUsageValue - @abstract The HIDSetScaledUsageValue function takes a signed physical (scaled) number and converts it to the logical, or device representation and inserts it in a given report. - @discussion The HIDSetScaledUsageValue function automatically handles the setting of the signed bit in the data to be sent to the device. - @param reportType Specifies the type of report. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page identifier of the value to be set in the report. - @param collection Optionally specifies the link collection identifier to distinguish between values that have the same usage page and usage identifiers. If this parameter is zero, it will be ignored. - @param usage Specifies the usage identifier of the value to be set in the report. - @param usageValue Specifies the physical, or scaled, value to be set in the value for the given report. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param Specifies the length, in bytes of the report data specified in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDSetScaledUsageValue (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - SInt32 usageValue, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDSetButtons - @abstract The HIDSetButtons function takes a report from a HID device and returns the current state of the buttons in that report. - @param reportType Specifies the type of repor. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page identifier of the value to be set in the report. - @param collection Optionally specifies the link collection identifier to distinguish between buttons. If this parameter is zero, it is ignored. - @param usageList Points to a caller-allocated buffer that contains an array of button data to be set in the report in the report parameter. - @param usageListSize Specifies the size, in array elements, of the buffer provided in the usageList parameter. If an error is returned by a call to this function, the usageListLength parameter contains the location in the array provided in the usageList parameter where the error was encountered. All array entries encountered prior to the error location were successfully set in the report provided in the report parameter. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDSetButtons (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage * usageList, - UInt32 * usageListSize, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDSetUsageValue - @abstract The HIDSetUsageValue function sets a value in a give report. - @discussion The HIDSetUsageVlaue function does not automatically handle the sign bit. Clients must either manually set the sign bit, at the position provided in the HIDValueCaps structure for this value, or call the HIDSetScaledUsageValue function. - @param reportType Specifies the type of report. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page identifier of the value to be set in the report. - @param collection Optionally specifies the link collection identifier to distinguish between values that have the same usage page and usage identifiers. If this parameter is zero, it is ignored. - @param usage Specifies the usage identifier of the value to be set in the report. - @param usageValue Specifies the data that is to be set in the value for the given report. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDSetUsageValue (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - SInt32 usageValue, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDSetUsageValueArray - @abstract The HIDSetUsageValueArray function sets an array of values in a given report. - @discussion The HIDSetUsageValue function does not automatically handle the sign bit. Clients must either manually set the sign bit, at the position provided in the HIDValueCaps structure for this value, or call the HIDSetScaledUsageValue function. - @param reportType Specifies the type of report. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page identifier of the value to be set in the report. - @param collection Optionally specifies the link collection identifier to distinguish between values that have the same usage page and usage identifiers. If this parameter is zero, it is ignored. - @param usage Specifies the usage identifier of the value to be set in the report. - @param usageValueBuffer Points to a caller-allocated buffer that contains, on output, the data from the device. The correct length for this buffer can be found by multiplying the reportCount and bitSize fields of the HIDValueCaps structure for this value and rounding the resulting value up to the nearest byte. - @param usageValueBufferLength Specifies the size, in bytes, of the buffer in the usageValueBuffer parameter. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDSetUsageValueArray (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - Byte * usageValueBuffer, - ByteCount usageValueBufferLength, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - -/*! - @function HIDUsageListDifference - @abstract The HIDUsageListDifference function compares and provides the differences between two lists of buttons. - @param previousUsageList Points to the older button list to be used for comparison. - @param currentUsageList Points to the newer button list to be used for comparison. - @param breakUsageList On return, points to a caller-allocated buffer that contains the buttons set in the older list, specified in the previousUsageList parameter, but not set in the new list, specified in the currentUsageList parameter. - @param makeUsageList On return, points to a caller-allocated buffer that contains the buttons set in the new list, specified in the currentUsageList parameter, but not set in the old list, specified in the previousUsageList parameter. - @param usageListsLength Specifies the length, in array elements, of the buffers provided in the currentUsageList and previousUssageList parameters. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDUsageListDifference (HIDUsage * previousUsageList, - HIDUsage * currentUsageList, - HIDUsage * breakUsageList, - HIDUsage * makeUsageList, - UInt32 usageListsSize); - -/*! - @function HIDSetButton - @abstract The HIDSetButton function takes a report from a HID device and sets the current state of the specified button in that report. - @param reportType Specifies the type of report. This parameter must be one of the following: kHIDInputReport, kHIDOutputReport, or kHIDFeatureReport. - @param usagePage Specifies the usage page identifier of the value to be set in the report. - @param collection Optionally specifies the link collection identifier to distinguish between buttons. If this parameter is zero, it is ignored. - @param usage Points to a caller-allocated buffer that contains the button data to be set in the report in the report parameter. - @param preparsedDataRef Preparsed data reference for the report that is retuned by the HIDOpenReportDescriptor function - @param report Points to the caller-allocated buffer that contains the device report data. - @param reportLength Specifies the size, in bytes, of the report data provided in the report parameter. - @result OSStatus Returns an error code if an error was encountered or noErr on success. - */ - -extern -OSStatus -HIDSetButton (HIDReportType reportType, - HIDUsage usagePage, - UInt32 collection, - HIDUsage usage, - HIDPreparsedDataRef preparsedDataRef, - void * report, - ByteCount reportLength); - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/iokit/IOKit/hidsystem/IOHIDParameter.h b/iokit/IOKit/hidsystem/IOHIDParameter.h deleted file mode 100644 index bb806e679..000000000 --- a/iokit/IOKit/hidsystem/IOHIDParameter.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * evsio.h - Get/Set parameter calls for Event Status Driver. - * - * CAUTION: Developers should stick to the API exported in - * <drivers/event_status_driver.h> to guarantee - * binary compatability of their applications in future - * releases. - * - * HISTORY - * 22 May 1992 Mike Paquette at NeXT - * Created. - */ -#ifndef _DEV_EVSIO_H -#define _DEV_EVSIO_H - -/* Public type definitions. */ -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOLLEvent.h> - -/* - * Identify this driver as one that uses the new driverkit and messaging API - */ -#ifndef _NeXT_MACH_EVENT_DRIVER_ -#define _NeXT_MACH_EVENT_DRIVER_ (1) -#endif /* !_NeXT_MACH_EVENT_DRIVER_ */ - -/* * */ - -#define kIOHIDKindKey "HIDKind" -#define kIOHIDInterfaceIDKey "HIDInterfaceID" -#define kIOHIDSubinterfaceIDKey "HIDSubinterfaceID" - -#define kIOHIDKeyRepeatKey "HIDKeyRepeat" -#define kIOHIDInitialKeyRepeatKey "HIDInitialKeyRepeat" -#define kIOHIDKeyMappingKey "HIDKeyMapping" -#define kIOHIDResetKeyboardKey "HIDResetKeyboard" - -#define kIOHIDPointerResolutionKey "HIDPointerResolution" -#define kIOHIDPointerAccelerationKey "HIDPointerAcceleration" -#define kIOHIDResetPointerKey "HIDResetPointer" -#define kIOHIDPointerConvertAbsoluteKey "HIDPointerConvertAbsolute" -#define kIOHIDPointerContactToMoveKey "HIDPointerContactToMove" -#define kIOHIDPointerPressureToClickKey "HIDPointerPressureToClick" - -#define kIOHIDClickTimeKey "HIDClickTime" -#define kIOHIDClickSpaceKey "HIDClickSpace" - -#define kIOHIDAutoDimThresholdKey "HIDAutoDimThreshold" -#define kIOHIDAutoDimStateKey "HIDAutoDimState" -#define kIOHIDAutoDimTimeKey "HIDAutoDimTime" -#define kIOHIDIdleTimeKey "HIDIdleTime" - -#define kIOHIDBrightnessKey "HIDBrightness" -#define kIOHIDAutoDimBrightnessKey "HIDAutoDimBrightness" - -#ifdef _undef -#define EVS_PREFIX "Evs_" /* All EVS calls start with this string */ - -/* WaitCursor-related ioctls */ - -#define EVSIOSWT "Evs_SetWaitThreshold" -#define EVSIOSWT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOSWS "Evs_SetWaitSustain" -#define EVSIOSWS_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOSWFI "Evs_SetWaitFrameInterval" -#define EVSIOSWFI_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOCWINFO "Evs_CurrentWaitCursorInfo" -#define EVSIOCWINFO_THRESH 0 -#define EVSIOCWINFO_SUSTAIN (EVSIOCWINFO_THRESH + EVS_PACKED_TIME_SIZE) -#define EVSIOCWINFO_FINTERVAL (EVSIOCWINFO_SUSTAIN + EVS_PACKED_TIME_SIZE) -#define EVSIOCWINFO_SIZE (EVSIOCWINFO_FINTERVAL + EVS_PACKED_TIME_SIZE) -#endif - -#define EVS_PACKED_TIME_SIZE (sizeof(UInt64) / sizeof( unsigned int)) - -/* Device control ioctls. Levels specified may be in the range 0 - 64. */ - -#define EVSIOSB kIOHIDBrightnessKey -#define EVSIOSB_SIZE 1 - -#define EVSIOSADB kIOHIDAutoDimBrightnessKey -#define EVSIOSADB_SIZE 1 - -#ifdef _undef -#define EVSIOSA "Evs_SetAttenuation" -#define EVIOSA_SIZE 1 - -#define EVSIO_DCTLINFO "Evs_DeviceControlInfo" -typedef enum { - EVSIO_DCTLINFO_BRIGHT, - EVSIO_DCTLINFO_ATTEN, - EVSIO_DCTLINFO_AUTODIMBRIGHT -} evsio_DCTLINFOIndices; -#define EVSIO_DCTLINFO_SIZE (EVSIO_DCTLINFO_AUTODIMBRIGHT + 1) -#endif - -/* - * Device status request - */ -#define EVSIOINFO NX_EVS_DEVICE_INFO - - -/* Keyboard-related ioctls - implemented within Event Sources */ - -#define EVSIOSKR kIOHIDKeyRepeatKey -#define EVSIOSKR_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOSIKR kIOHIDInitialKeyRepeatKey -#define EVSIOSIKR_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIORKBD kIOHIDResetKeyboardKey -#define EVSIORKBD_SIZE 1 - -#define EVSIOCKR_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOCKML kIOHIDKeyMappingKey -#define EVSIOCKML_SIZE 1 - -/* The following two tokens are for use with the get/set character routines. */ -#define EVSIOSKM kIOHIDKeyMappingKey -#define EVSIOSKM_SIZE 4096 - -#define EVSIOCKM kIOHIDKeyMappingKey -#define EVSIOCKM_SIZE 4096 - -/* Mouse-related ioctls - implemented within Event Sources */ - -#define EVSIOSMS kIOHIDPointerAccelerationKey -#define EVSIOSMS_SIZE (1) - -#define EVSIOCMS kIOHIDPointerAccelerationKey -#define EVSIOCMS_SIZE (1) - -#ifdef _undef -#define EVSIOSMH "Evs_SetMouseHandedness" -#define EVSIOSMH_SIZE 1 // value from NXMouseButton enum - -#define EVSIOCMH "Evs_CurrentMouseHandedness" -#define EVSIOCMH_SIZE 1 -#endif - -/* Generic pointer device controls, implemented by the Event Driver. */ -#define EVSIOSCT kIOHIDClickTimeKey -#define EVSIOSCT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOSCS kIOHIDClickSpaceKey -typedef enum { - EVSIOSCS_X, - EVSIOSCS_Y -} evsioEVSIOSCSIndices; -#define EVSIOSCS_SIZE (EVSIOSCS_Y + 1) - -#define EVSIOSADT kIOHIDAutoDimThresholdKey -#define EVSIOSADT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOSADS kIOHIDAutoDimStateKey -#define EVSIOSADS_SIZE 1 - -#define EVSIORMS kIOHIDResetPointerKey -#define EVSIORMS_SIZE 1 - -#define EVSIOCCT kIOHIDClickTimeKey -#define EVSIOCCT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOCADT kIOHIDAutoDimThresholdKey -#define EVSIOCADT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOGDADT kIOHIDAutoDimTimeKey -#define EVSIOGDADT_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOIDLE kIOHIDIdleTimeKey -#define EVSIOIDLE_SIZE EVS_PACKED_TIME_SIZE - -#define EVSIOCCS kIOHIDClickSpaceKey -typedef enum { - EVSIOCCS_X, - EVSIOCCS_Y -} evsioEVSIOCCSIndices; -#define EVSIOCCS_SIZE (EVSIOCCS_Y + 1) - -#define EVSIOCADS kIOHIDAutoDimStateKey -#define EVSIOCADS_SIZE 1 - -#endif /* !_DEV_EVSIO_H */ diff --git a/iokit/IOKit/hidsystem/IOHIDShared.h b/iokit/IOKit/hidsystem/IOHIDShared.h deleted file mode 100644 index e1f5325ae..000000000 --- a/iokit/IOKit/hidsystem/IOHIDShared.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/****************************************************************************** - - evio.h - Ioctl calls for the events driver - Leovitch 02Jan88 - - Copyright 1988 NeXT, Inc. - - CAUTION: Developers should stick to the API exported in - <drivers/event_status_driver.h> to guarantee - binary compatability of their applications in future - releases. - - Modified: - - 09Dec88 Leo Broken out from evsio.h - 24Aug89 Ted ANSI function prototyping. - 19Feb90 Ted Major revision for multiple driver support. - 26Feb90 Ted New evioScreen structure and EVIOST ioctl. - 12Mar90 Ted New ev_unregister_screen function, SCREENTOKEN constant. - 06May90 Ted Added AALastEventSent and AALastEventConsumed to EvVars. - 22May90 Trey More wait cursor vars in EvVars. - 13Jun90 Ted NXCursorData structure. - 18Jun90 Ted Default wait cursor constants. - 26Sep90 Ted Enhanced cursor system to support intelligent drivers. - 26Nov90 Ted Removed NXSaveCursor and NXCursorData structures - 28Nov90 Ted Remove EvVars, rolled into EventGlobals - 28Nov90 Ted Renamed EventGlobals -> EvGlobals, eventGlobals -> evg - 05May92 Mike Reworked for NRW driver architecture. - -******************************************************************************/ - -#ifndef _DEV_EVIO_H -#define _DEV_EVIO_H - -#include <sys/cdefs.h> - -__BEGIN_DECLS - -#if KERNEL -#include <IOKit/system.h> -#else /* !KERNEL */ -#include <mach/message.h> -#include <IOKit/IOKitLib.h> -#endif /* KERNEL */ - -#include <IOKit/IOReturn.h> -#include <IOKit/graphics/IOGraphicsTypes.h> -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOLLEvent.h> - -/* - * Identify this driver as one that uses the new driverkit and messaging API - */ -#ifndef _NeXT_MACH_EVENT_DRIVER_ -#define _NeXT_MACH_EVENT_DRIVER_ (1) -#endif /* _NeXT_MACH_EVENT_DRIVER_ */ - - -/* Pressure Constants */ -#define MINPRESSURE EV_MINPRESSURE -#define MAXPRESSURE EV_MAXPRESSURE - -#define LLEQSIZE 80 /* Entries in low-level event queue */ - -typedef struct _NXEQElStruct { - int next; /* Slot of lleq for next event */ - ev_lock_data_t sema; /* Is high-level code reading this event now? */ - NXEvent event; /* The event itself */ -} NXEQElement; - - -/****************************************************************************** - SHARED MEMORY OVERVIEW - - PERSPECTIVE - The ev driver and PostScript share at least one page of wired memory. - This memory contains the low-level event queue which ev deposits events - into and PostScript reads events from. Also, this memory contains other - important data such as wait cursor state and some general cursor state. - This memory is critical for speed. That is, we avoid having to make - system calls for common operations. - - SHARED MEMORY REGIONS - There are currently three "regions" or "zones" delineated within this - shared memory. The first zone is the EvOffsets structure. This structure - contains two offsets from the beginning of shared memory. The first offset - is to the second zone, EvGlobals. The second offset is to the third - zone, private shmem for drivers. - - INITIALIZATION OF SHARED MEMORY - When the WindowServer starts up, it finds all screens that will be active. - It then opens the ev driver and calls the EVIOSSCR ioctl repeatedly for - each screen in use. This lets the ev driver set up the evScreen array - and fill in each element. This ioctl also returns to PostScript a running - total shared memory size with which to allocate. PostScript then allocates - a region of memory this size and calls evmmap to "map in" this shared - region. Evmmap initializes and fills in the EvOffsets and EvGlobals. - Next the WindowServer calls each screen in turn to register itself with - the ev driver in the same sequence as presented to EVIOSSCR. Each screen - driver calls ev_register_screen() which among other things allocates a - part of the private shmem (of the third shared memory zone) for the driver. - - DEBUGGING NOTES - You can easily display and set this shared memory from kgdb, but usually - cannot do so from within PostScript. Gdb (or some weird interaction - between gdb and the os) chokes on this shmem. So if you read or write - this area of memory, copy-on-write will occur and you'll get a completely - new page for PostScript. This will render the shared memory scheme - useless and you will have to restart PostScript. It was my understanding - that before, we were able to "read" this area from PS, but not write to - it (the idea behind copy-on-WRITE). However, this seems to be broken - in 2.0. We think this is a kernel bug. -******************************************************************************/ - -typedef volatile struct _evOffsets { - int evGlobalsOffset; /* Offset to EvGlobals structure */ - int evShmemOffset; /* Offset to private shmem regions */ -} EvOffsets; - -/****************************************************************************** - EvGlobals - This structures defines the portion of the events driver data structure - that is exported to the PostScript server. It contains the event queue - which is in memory shared between the driver and the PostScript server. - All the variables necessary to read and process events from the queue are - contained here. -******************************************************************************/ - -typedef volatile struct _evGlobals { - ev_lock_data_t cursorSema; /* set to disable periodic code */ - int LLEHead; /* The next event to be read */ - int LLETail; /* Where the next event will go */ - int LLELast; /* The last event entered */ - int eNum; /* Unique id for mouse events */ - int buttons; /* State of the mouse buttons 1==down, 0==up */ - int eventFlags; /* The current value of event.flags */ - int VertRetraceClock; /* The current value of event.time */ - IOGPoint cursorLoc; /* The current location of the cursor */ - int frame; /* current cursor frame */ - IOGBounds workBounds; /* bounding box of all screens */ - IOGBounds mouseRect; /* Rect for mouse-exited events */ - int version; /* for run time checks */ - int structSize; /* for run time checks */ - unsigned int reservedA[32]; - - unsigned reserved:27; - unsigned wantPressure:1; /* pressure in current mouseRect? */ - unsigned wantPrecision:1; /* precise coordinates in current mouseRect? */ - unsigned dontWantCoalesce:1;/* coalesce within the current mouseRect? */ - unsigned dontCoalesce:1; /* actual flag which determines coalescing */ - unsigned mouseRectValid:1; /* If nonzero, post a mouse-exited - whenever mouse outside mouseRect. */ - int movedMask; /* This contains an event mask for the - three events MOUSEMOVED, - LMOUSEDRAGGED, and RMOUSEDRAGGED. - It says whether driver should - generate those events. */ - int AALastEventSent; /* timestamp for wait cursor */ - int AALastEventConsumed; /* timestamp for wait cursor */ - ev_lock_data_t waitCursorSema; /* protects wait cursor fields */ - int waitCursorUp; /* Is wait cursor up? */ - char ctxtTimedOut; /* Has wait cursor timer expired? */ - char waitCursorEnabled; /* Play wait cursor game (per ctxt)? */ - char globalWaitCursorEnabled; /* Play wait cursor game (global)? */ - int waitThreshold; /* time before wait cursor appears */ - NXEQElement lleq[LLEQSIZE]; /* The event queue itself */ -} EvGlobals; - - -/* These evio structs are used in various calls supported by the ev driver. */ - -struct evioLLEvent { - int setCursor; - int type; - IOGPoint location; - NXEventData data; - int setFlags; - int flags; -}; - -typedef struct evioLLEvent _NXLLEvent; - -#ifdef mach3xxx - -/* - * On a keypress of a VOL UP or VOL DOWN key, we send a message to the - * sound server to notify it of the volume change. The message includes - * a flag to indicate which key was pressed, and the machine independant - * flag bits to indicate which modifier keys were pressed. - */ - -struct evioSpecialKeyMsg -{ - msg_header_t Head; - msg_type_t keyType; - int key; // special key number, from bsd/dev/ev_keymap.h - msg_type_t directionType; - int direction; // NX_KEYDOWN, NX_KEYUP from event.h - msg_type_t flagsType; - int flags; // device independant flags from event.h - msg_type_t levelType; - int level; // EV_AUDIO_MIN_VOLUME to EV_AUDIO_MAX_VOLUME -}; -#else -struct evioSpecialKeyMsg -{ - mach_msg_header_t Head; - int key; // special key number, from bsd/dev/ev_keymap.h - int direction; // NX_KEYDOWN, NX_KEYUP from event.h - int flags; // device independant flags from event.h - int level; // EV_AUDIO_MIN_VOLUME to EV_AUDIO_MAX_VOLUME -}; -#endif - -#define EV_SPECIAL_KEY_MSG_ID (('S'<<24) | ('k'<<16) | ('e'<<8) | ('y')) -typedef struct evioSpecialKeyMsg *evioSpecialKeyMsg_t; - -/* - * Volume ranges - */ -#define EV_AUDIO_MIN_VOLUME 0 -#define EV_AUDIO_MAX_VOLUME 64 - -#define kIOHIDSystemClass "IOHIDSystem" -#define kIOHIKeyboardClass "IOHIKeyboard" -#define kIOHIPointingClass "IOHIPointing" - -#define IOHIDSYSTEM_CONFORMSTO kIOHIDSystemClass - -enum { - kIOHIDCurrentShmemVersion = 2, - kIOHIDServerConnectType = 0, - kIOHIDParamConnectType = 1, - kIOHIDGlobalMemory = 0, - kIOHIDEventNotification = 0 -}; - -#ifdef KERNEL -typedef UInt16 (*MasterVolumeUpdate)(void); -typedef bool (*MasterMuteUpdate)(void); - -typedef struct { - MasterVolumeUpdate incrementMasterVolume; - MasterVolumeUpdate decrementMasterVolume; - MasterMuteUpdate toggleMasterMute; -} MasterAudioFunctions; - -extern MasterAudioFunctions *masterAudioFunctions; -#endif - -#ifndef KERNEL -#ifndef _IOKIT_IOHIDLIB_H -#include <IOKit/hidsystem/IOHIDLib.h> -#endif -#endif /* !KERNEL */ - -__END_DECLS - - -#endif /* !_DEV_EVIO_H */ diff --git a/iokit/IOKit/hidsystem/IOHIDSystem.h b/iokit/IOKit/hidsystem/IOHIDSystem.h deleted file mode 100644 index c39558c89..000000000 --- a/iokit/IOKit/hidsystem/IOHIDSystem.h +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * EventDriver.h - Exported Interface Event Driver object. - * - * The EventDriver is a pseudo-device driver. - * - * HISTORY - * 19 Mar 1992 Mike Paquette at NeXT - * Created. - * 4 Aug 1993 Erik Kay at NeXT - * API cleanup - */ - -#ifndef _IOHIDSYSTEM_H -#define _IOHIDSYSTEM_H - -#include <IOKit/IOTimerEventSource.h> -#include <IOKit/IOService.h> -#include <IOKit/IOUserClient.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/IOCommandQueue.h> -#include <IOKit/IOBufferMemoryDescriptor.h> -#include <IOKit/pwr_mgt/IOPM.h> -#include <IOKit/graphics/IOGraphicsDevice.h> -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHIDShared.h> -#include <IOKit/hidsystem/IOHIDTypes.h> -#include <IOKit/hidsystem/IOLLEvent.h> -#include "ev_keymap.h" /* For NX_NUM_SCANNED_SPECIALKEYS */ - -typedef void (*IOHIDAction)(OSObject *, void *); - -class IOHIDSystem : public IOService -{ - OSDeclareDefaultStructors(IOHIDSystem); - - friend class IOHIDUserClient; - friend class IOHIDParamUserClient; - -private: - IOLock * driverLock; - - IOWorkLoop * workLoop; - IOTimerEventSource * timerES; - IOCommandQueue * cmdQ; - IOUserClient * serverConnect; - IOUserClient * paramConnect; - IONotifier * publishNotify; - - // Ports on which we hold send rights - mach_port_t eventPort; // Send msg here when event queue - // goes non-empty - mach_port_t _specialKeyPort[NX_NUM_SCANNED_SPECIALKEYS]; // Special key msgs - void *eventMsg; // Msg to be sent to Window Server. - - // Shared memory area information - IOBufferMemoryDescriptor * globalMemory; - vm_offset_t shmem_addr; // kernel address of shared memory - vm_size_t shmem_size; // size of shared memory - - // Pointers to structures which occupy the shared memory area. - volatile void *evs; // Pointer to private driver shmem - volatile EvGlobals *evg; // Pointer to EvGlobals (shmem) - // Internal variables related to the shared memory area - int lleqSize; // # of entries in low-level queue - // FIXME: why is this ivar lleqSize an ivar? {Dan] - - // Screens list - vm_size_t evScreenSize; // Byte size of evScreen array - void *evScreen; // array of screens known to driver - volatile void *lastShmemPtr; // Pointer used to index thru shmem - // while assigning shared areas to - // drivers. - int screens; // running total of allocated screens - UInt32 cursorScreens; // bit mask of screens with cursor present - UInt32 cursorPinScreen;// a screen to pin against - Bounds cursorPin; // Range to which cursor is pinned - // while on this screen. - Bounds workSpace; // Bounds of full workspace. - // Event Status state - This includes things like event timestamps, - // time til screen dim, and related things manipulated through the - // Event Status API. - // - Point pointerLoc; // Current pointing device location - // The value leads evg->cursorLoc. - Point pointerDelta; // The cumulative pointer delta values since - // previous mouse move event was posted - Point clickLoc; // location of last mouse click - Point clickSpaceThresh; // max mouse delta to be a doubleclick - int clickState; // Current click state - unsigned char lastPressure; // last pressure seen - bool lastProximity; // last proximity state seen - - SInt32 curVolume; // Value of volume setting. - SInt32 dimmedBrightness;// Value of screen brightness when autoDim - // has turned on. - SInt32 curBright; // The current brightness is cached here while - // the driver is open. This number is always - // the user-specified brightness level; if the - // screen is autodimmed, the actual brightness - // level in the monitor will be less. - SInt32 autoDimmed; // Is screen currently autodimmed? - bool evOpenCalled; // Has the driver been opened? - bool evInitialized; // Has the first-open-only initialization run? - bool eventsOpen; // Boolean: has evmmap been called yet? - bool cursorStarted; // periodic events running? - bool cursorEnabled; // cursor positioning ok? - bool cursorCoupled; // cursor positioning on pointer moves ok? - - short leftENum; // Unique ID for last left down event - short rightENum; // Unique ID for last right down event - - // The periodic event mechanism timestamps and state - // are recorded here. - AbsoluteTime thisPeriodicRun; - AbsoluteTime periodicEventDelta;// Time between periodic events - // todo: make infinite - AbsoluteTime clickTime; // Timestamps used to determine doubleclicks - AbsoluteTime clickTimeThresh; - AbsoluteTime autoDimPeriod; // How long since last user action before - // we autodim screen? User preference item, - // set by InitMouse and evsioctl - AbsoluteTime autoDimTime; // Time value when we will autodim screen, - // if autoDimmed is 0. - // Set in LLEventPost. - - AbsoluteTime waitSustain; // Sustain time before removing cursor - AbsoluteTime waitSusTime; // Sustain counter - AbsoluteTime waitFrameRate; // Ticks per wait cursor frame - AbsoluteTime waitFrameTime; // Wait cursor frame timer - - AbsoluteTime postedVBLTime; // Used to post mouse events once per frame - AbsoluteTime lastEventTime; - AbsoluteTime lastMoveTime; - SInt32 accumDX; - SInt32 accumDY; - - // Flags used in scheduling periodic event callbacks - bool needSetCursorPosition; - bool needToKickEventConsumer; - IOLock * kickConsumerLock; - -public: - IOService * displayManager; // points to display manager - IOPMPowerFlags displayState; - -private: - inline short getUniqueEventNum(); - - virtual IOReturn powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService*); - /* Resets */ - void _resetMouseParameters(); - void _resetKeyboardParameters(); - - /* Initialize the shared memory area */ - void initShmem(); - /* Dispatch low level events through shared memory to the WindowServer */ - void postEvent(int what, - /* at */ Point * location, - /* atTime */ AbsoluteTime ts, - /* withData */ NXEventData * myData); - /* Dispatch mechanisms for screen state changes */ - void evDispatch( - /* command */ EvCmd evcmd); - /* Dispatch mechanism for special key press */ - void evSpecialKeyMsg(unsigned key, - /* direction */ unsigned dir, - /* flags */ unsigned f, - /* level */ unsigned l); - /* Message the event consumer to process posted events */ - void kickEventConsumer(); - IOReturn sendWorkLoopCommand(OSObject * target, - IOHIDAction action, - void * data); - static void _doPerformInIOThread( void* self, - void* target, - void* action, - void* data, - void* unused); - static void _periodicEvents(IOHIDSystem * self, - IOTimerEventSource *timer); - - static void _performSpecialKeyMsg(IOHIDSystem * self, - struct evioSpecialKeyMsg *msg); - static void _performKickEventConsumer(IOHIDSystem * self,void *); - - static bool publishNotificationHandler( IOHIDSystem * self, - void * ref, IOService * newService ); - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOHIDSystem(Input) category; - * the declarations have now been merged directly into this class. - * - * Exported Interface Event Driver object input services. - */ - -private: - // Schedule next periodic run based on current event system state. - void scheduleNextPeriodicEvent(); - // Message invoked to run periodic events. This method runs in the workloop. - void periodicEvents(IOTimerEventSource *timer); - // Start the cursor running. - bool startCursor(); - // Repin cursor location. - bool resetCursor(); - // Wait Cursor machinery. - void showWaitCursor(); - void hideWaitCursor(); - void animateWaitCursor(); - void changeCursor(int frame); - // Return screen number a point lies on. - int pointToScreen(Point * p); - // Set the undimmed brightness. - void setBrightness(int b); - // Return undimmed brightness. - int brightness(); - // Set the dimmed brightness. - void setAutoDimBrightness(int b); - // Return dimmed brightness. - int autoDimBrightness(); - // Return the current brightness. - int currentBrightness(); - // Dim all displays. - void doAutoDim(); - // Return display brightness to normal. - void undoAutoDim(); - // Force dim/undim. - void forceAutoDimState(bool dim); - // Audio volume control. - void setAudioVolume(int v); - // Audio volume control, from ext user. - void setUserAudioVolume(int v); - // Return audio volume. - int audioVolume(); - // Propagate state out to screens. - inline void setBrightness(); - - inline void showCursor(); - inline void hideCursor(); - inline void moveCursor(); - // Claim ownership of event sources. - void attachDefaultEventSources(); - // Give up ownership of event sources. - void detachEventSources(); - bool registerEventSource(IOHIDevice * source); - - // Set abs cursor position. - void setCursorPosition(Point * newLoc, bool external); - void _setButtonState(int buttons, - /* atTime */ AbsoluteTime ts); - void _setCursorPosition(Point * newLoc, bool external); - - void _postMouseMoveEvent(int what, - Point * location, - AbsoluteTime theClock); - -/* END HISTORICAL NOTE */ - -public: - static IOHIDSystem * instance(); /* Return the current instance of the */ - /* EventDriver, or 0 if none. */ - - virtual bool init(OSDictionary * properties = 0); - virtual IOHIDSystem * probe(IOService * provider, - SInt32 * score); - virtual bool start(IOService * provider); - virtual IOReturn message(UInt32 type, IOService * provider, - void * argument); - virtual void free(); - - virtual IOWorkLoop *getWorkLoop() const; - - virtual IOReturn evOpen(void); - virtual IOReturn evClose(void); - - virtual bool updateProperties(void); - virtual IOReturn setParamProperties(OSDictionary * dict); - virtual bool serializeProperties( OSSerialize * s ) const; - - /* Create the shared memory area */ - virtual IOReturn createShmem(void*,void*,void*,void*,void*,void*); - /* Set the port for event available notify msg */ - virtual void setEventPort(mach_port_t port); - /* Set the port for the special key keypress msg */ - virtual IOReturn setSpecialKeyPort( - /* keyFlavor */ int special_key, - /* keyPort */ mach_port_t key_port); - virtual mach_port_t specialKeyPort(int special_key); - - - virtual IOReturn newUserClient(task_t owningTask, - /* withToken */ void * security_id, - /* ofType */ UInt32 type, - /* client */ IOUserClient ** handler); - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOHIPointingEvents protocol; - * the declarations have now been merged directly into this class. - */ - -public: - /* Mouse event reporting */ - virtual void relativePointerEvent(int buttons, - /* deltaX */ int dx, - /* deltaY */ int dy, - /* atTime */ AbsoluteTime ts); - - /* Tablet event reporting */ - virtual void absolutePointerEvent(int buttons, - /* at */ Point * newLoc, - /* withBounds */ Bounds * bounds, - /* inProximity */ bool proximity, - /* withPressure */ int pressure, - /* withAngle */ int stylusAngle, - /* atTime */ AbsoluteTime ts); - - /* Mouse scroll wheel event reporting */ - virtual void scrollWheelEvent(short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - AbsoluteTime ts); - - - virtual void tabletEvent(NXEventData *tabletData, - AbsoluteTime ts); - - virtual void proximityEvent(NXEventData *proximityData, - AbsoluteTime ts); - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOHIKeyboardEvents protocol; - * the declarations have now been merged directly into this class. - */ - -public: - virtual void keyboardEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - - virtual void keyboardSpecialEvent( unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* specialty */ unsigned flavor, - /* guid */ UInt64 guid, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - - virtual void updateEventFlags(unsigned flags); /* Does not generate events */ - - - - -private: - - /* - * statics for upstream callouts - */ - - void _scaleLocationToCurrentScreen(Point *location, Bounds *bounds); // Should this one be public??? - - static void _relativePointerEvent( IOHIDSystem * self, - int buttons, - /* deltaX */ int dx, - /* deltaY */ int dy, - /* atTime */ AbsoluteTime ts); - - /* Tablet event reporting */ - static void _absolutePointerEvent(IOHIDSystem * self, - int buttons, - /* at */ Point * newLoc, - /* withBounds */ Bounds * bounds, - /* inProximity */ bool proximity, - /* withPressure */ int pressure, - /* withAngle */ int stylusAngle, - /* atTime */ AbsoluteTime ts); - - /* Mouse scroll wheel event reporting */ - static void _scrollWheelEvent(IOHIDSystem *self, - short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - AbsoluteTime ts); - - static void _tabletEvent(IOHIDSystem *self, - NXEventData *tabletData, - AbsoluteTime ts); - - static void _proximityEvent(IOHIDSystem *self, - NXEventData *proximityData, - AbsoluteTime ts); - - static void _keyboardEvent( IOHIDSystem * self, - unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - static void _keyboardSpecialEvent( IOHIDSystem * self, - unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* specialty */ unsigned flavor, - /* guid */ UInt64 guid, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - static void _updateEventFlags( IOHIDSystem * self, - unsigned flags); /* Does not generate events */ - - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOUserClient protocol; - * the declarations have now been merged directly into this class. - */ - -public: - - virtual IOReturn setEventsEnable(void*,void*,void*,void*,void*,void*); - virtual IOReturn setCursorEnable(void*,void*,void*,void*,void*,void*); - virtual IOReturn extPostEvent(void*,void*,void*,void*,void*,void*); - virtual IOReturn extSetMouseLocation(void*,void*,void*,void*,void*,void*); - virtual IOReturn extGetButtonEventNum(void*,void*,void*,void*,void*,void*); - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOScreenRegistration protocol; - * the declarations have now been merged directly into this class. - * - * Methods exported by the EventDriver for display systems. - * - * The screenRegister protocol is used by frame buffer drivers to register - * themselves with the Event Driver. These methods are called in response - * to an _IOGetParameterInIntArray() call with "IO_Framebuffer_Register" or - * "IO_Framebuffer_Unregister". - */ - -public: - virtual int registerScreen(IOGraphicsDevice * instance, - /* bounds */ Bounds * bp); -// /* shmem */ void ** addr, -// /* size */ int * size) - virtual void unregisterScreen(int index); - -/* - * HISTORICAL NOTE: - * The following methods were part of the IOWorkspaceBounds protocol; - * the declarations have now been merged directly into this class. - * - * Absolute position input devices and some specialized output devices - * may need to know the bounding rectangle for all attached displays. - * The following method returns a Bounds* for the workspace. Please note - * that the bounds are kept as signed values, and that on a multi-display - * system the minx and miny values may very well be negative. - */ - -public: - virtual Bounds * workspaceBounds(); - -/* END HISTORICAL NOTES */ -}; - -#endif /* !_IOHIDSYSTEM_H */ diff --git a/iokit/IOKit/hidsystem/IOHIDTypes.h b/iokit/IOKit/hidsystem/IOHIDTypes.h deleted file mode 100644 index 63e3912d5..000000000 --- a/iokit/IOKit/hidsystem/IOHIDTypes.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/****************************************************************************** - ev_types.h - Data types for the events status driver. - This file contains public API. - mpaque 11Oct91 - - Copyright 1991 NeXT Computer, Inc. - - Modified: - -******************************************************************************/ - -#ifndef _DEV_EV_TYPES_H -#define _DEV_EV_TYPES_H - -#include <mach/boolean.h> -#include <IOKit/IOSharedLock.h> -#include <IOKit/graphics/IOGraphicsTypes.h> - -/* Shared memory versions */ -#define EVENT_SYSTEM_VERSION 2 - -/* Maximum length of SetMouseScaling arrays */ -#define NX_MAXMOUSESCALINGS 20 - -typedef struct evsioKeymapping /* Match old struct names in kernel */ -{ - int size; - char *mapping; -} NXKeyMapping; - -typedef struct evsioMouseScaling /* Match old struct names in kernel */ -{ - int numScaleLevels; - short scaleThresholds[NX_MAXMOUSESCALINGS]; - short scaleFactors[NX_MAXMOUSESCALINGS]; -} NXMouseScaling; - -typedef enum { - NX_OneButton, - NX_LeftButton, - NX_RightButton -} NXMouseButton; - -/* - * NXEventSystemInfo() information structures. These are designed to - * allow for expansion. - * - * The current implementation of NXEventSystemInfo() uses an ioctl call. - * THIS WILL CHANGE. - */ - -/* - * Generic query max size and typedefs. - * - * The maximum size is selected to support anticipated future extensions - * of request flavors. Certain flavors planned for future releases may - * require roughtly 800 ints to represent. We allow a little extra, in - * case further growth is needed. - */ -typedef int *NXEventSystemInfoType; -#define NX_EVS_INFO_MAX (1024) /* Max array size */ -typedef int NXEventSystemInfoData[NX_EVS_INFO_MAX]; - -/* Event System Devices query */ -#define NX_EVS_DEVICE_MAX 16 - - /* Interface types */ -#define NX_EVS_DEVICE_INTERFACE_OTHER 0 -#define NX_EVS_DEVICE_INTERFACE_NeXT 1 // NeXT custom, in older sys -#define NX_EVS_DEVICE_INTERFACE_ADB 2 // NeXT/fruit keybds/mice -#define NX_EVS_DEVICE_INTERFACE_ACE 3 // For x86 PC keyboards -#define NX_EVS_DEVICE_INTERFACE_SERIAL_ACE 4 // For PC serial mice -#define NX_EVS_DEVICE_INTERFACE_BUS_ACE 5 // For PC bus mice -#define NX_EVS_DEVICE_INTERFACE_HIL 6 // For HIL hp keyboard -#define NX_EVS_DEVICE_INTERFACE_TYPE5 7 // For Sun Type5 keyboard - -/* - * Note! if any new interface types are added above, the following - * definition of the number of interfaces supported must reflect this. - * This is used in the libkeymap project (storemap.c module) which needs - * to be cognizant of the number of new devices coming online - * via support for heterogeneous architecture platforms. - * e.g., PCs, HP's HIL, Sun's Type5 keyboard,... - */ -#define NUM_SUPPORTED_INTERFACES (NX_EVS_DEVICE_INTERFACE_TYPE5 + 1) - // Other, NeXT, ADB, ACE,... - - /* Device types */ -#define NX_EVS_DEVICE_TYPE_OTHER 0 -#define NX_EVS_DEVICE_TYPE_KEYBOARD 1 -#define NX_EVS_DEVICE_TYPE_MOUSE 2 // Relative position devices -#define NX_EVS_DEVICE_TYPE_TABLET 3 // Absolute position devices - -typedef struct { - int interface; /* NeXT, ADB, other */ - int interface_addr; /* Device address on the interface */ - int dev_type; /* Keyboard, mouse, tablet, other */ - int id; /* manufacturer's device handler ID */ -} NXEventSystemDevice; - -typedef struct { - NXEventSystemDevice dev[NX_EVS_DEVICE_MAX]; -} NXEventSystemDeviceList; - -#define __OLD_NX_EVS_DEVICE_INFO 1 -#define NX_EVS_DEVICE_INFO "Evs_EventDeviceInfo" -#define NX_EVS_DEVICE_INFO_COUNT \ - (sizeof (NXEventSystemDeviceList) / sizeof (int)) - -/* - * Types used in evScreen protocol compliant operations. - */ - -typedef enum {EVNOP, EVHIDE, EVSHOW, EVMOVE, EVLEVEL} EvCmd; /* Cursor state */ - -#define EV_SCREEN_MIN_BRIGHTNESS 0 -#define EV_SCREEN_MAX_BRIGHTNESS 64 -/* Scale should lie between MIN_BRIGHTNESS and MAX_BRIGHTNESS */ -#define EV_SCALE_BRIGHTNESS( scale, datum ) \ - ((((unsigned long)(datum))*((unsigned long)scale)) >> 6) - -/* - * Definition of a tick, as a time in milliseconds. This controls how - * often the event system periodic jobs are run. All actual tick times - * are derived from the nanosecond timer. These values are typically used - * as part of computing mouse velocity for acceleration purposes. - */ -#define EV_TICK_TIME 16 /* 16 milliseconds */ -#define EV_TICKS_PER_SEC (1000/EV_TICK_TIME) /* ~ 62 Hz */ - -/* Mouse Button bits, as passed from an EventSrc to the Event Driver */ -#define EV_RB (0x01) -#define EV_LB (0x04) -#define EV_MOUSEBUTTONMASK (EV_LB | EV_RB) - -/* Tablet Pressure Constants, as passed from an EventSrc to the Event Driver */ -#define EV_MINPRESSURE 0 -#define EV_MAXPRESSURE 255 - -/* Cursor size in pixels */ -#define EV_CURSOR_WIDTH 16 -#define EV_CURSOR_HEIGHT 16 - - -#define kAppleOnboardGUID 0x0610000000000000ULL - -#endif /* !_DEV_EV_TYPES_H */ - diff --git a/iokit/IOKit/hidsystem/IOHIDUsageTables.h b/iokit/IOKit/hidsystem/IOHIDUsageTables.h deleted file mode 100644 index b7b63401d..000000000 --- a/iokit/IOKit/hidsystem/IOHIDUsageTables.h +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOHIDUSAGETABLES_H -#define _IOHIDUSAGETABLES_H - -/* ****************************************************************************************** - * HID Usage Tables - * - * The following constants are from the USB 'HID Usage Tables' specification, revision 1.1rc3 - * ****************************************************************************************** */ - - -/* Usage Pages */ -enum -{ - kHIDPage_Undefined = 0x00, - kHIDPage_GenericDesktop = 0x01, - kHIDPage_Simulation = 0x02, - kHIDPage_VR = 0x03, - kHIDPage_Sport = 0x04, - kHIDPage_Game = 0x05, - /* Reserved 0x06 */ - kHIDPage_KeyboardOrKeypad = 0x07, /* USB Device Class Definition for Human Interface Devices (HID). Note: the usage type for all key codes is Selector (Sel). */ - kHIDPage_LEDs = 0x08, - kHIDPage_Button = 0x09, - kHIDPage_Ordinal = 0x0A, - kHIDPage_Telephony = 0x0B, - kHIDPage_Consumer = 0x0C, - kHIDPage_Digitizer = 0x0D, - /* Reserved 0x0E */ - kHIDPage_PID = 0x0F, /* USB Physical Interface Device definitions for force feedback and related devices. */ - kHIDPage_Unicode = 0x10, - /* Reserved 0x11 - 0x13 */ - kHIDPage_AlphanumericDisplay = 0x14, - /* Reserved 0x15 - 0x7F */ - /* Monitor 0x80 - 0x83 USB Device Class Definition for Monitor Devices */ - /* Power 0x84 - 0x87 USB Device Class Definition for Power Devices */ - /* Reserved 0x88 - 0x8B */ - kHIDPage_BarCodeScanner = 0x8C, /* (Point of Sale) USB Device Class Definition for Bar Code Scanner Devices */ - kHIDPage_Scale = 0x8D, /* (Point of Sale) USB Device Class Definition for Scale Devices */ - /* ReservedPointofSalepages 0x8E - 0x8F */ - kHIDPage_CameraControl = 0x90, /* USB Device Class Definition for Image Class Devices */ - kHIDPage_Arcade = 0x91, /* OAAF Definitions for arcade and coinop related Devices */ - /* Reserved 0x92 - 0xFEFF */ - /* VendorDefined 0xFF00 - 0xFFFF */ - kHIDPage_VendorDefinedStart = 0xFF00, -}; - -/* Undefined Usage for all usage pages */ -enum -{ - kHIDUsage_Undefined = 0x00 -}; - -/* GenericDesktop Page (0x01) */ -enum -{ - kHIDUsage_GD_Pointer = 0x01, /* Physical Collection */ - kHIDUsage_GD_Mouse = 0x02, /* Application Collection */ - /* 0x03 Reserved */ - kHIDUsage_GD_Joystick = 0x04, /* Application Collection */ - kHIDUsage_GD_GamePad = 0x05, /* Application Collection */ - kHIDUsage_GD_Keyboard = 0x06, /* Application Collection */ - kHIDUsage_GD_Keypad = 0x07, /* Application Collection */ - kHIDUsage_GD_MultiAxisController = 0x08, /* Application Collection */ - /* 0x09 - 0x2F Reserved */ - kHIDUsage_GD_X = 0x30, /* Dynamic Value */ - kHIDUsage_GD_Y = 0x31, /* Dynamic Value */ - kHIDUsage_GD_Z = 0x32, /* Dynamic Value */ - kHIDUsage_GD_Rx = 0x33, /* Dynamic Value */ - kHIDUsage_GD_Ry = 0x34, /* Dynamic Value */ - kHIDUsage_GD_Rz = 0x35, /* Dynamic Value */ - kHIDUsage_GD_Slider = 0x36, /* Dynamic Value */ - kHIDUsage_GD_Dial = 0x37, /* Dynamic Value */ - kHIDUsage_GD_Wheel = 0x38, /* Dynamic Value */ - kHIDUsage_GD_Hatswitch = 0x39, /* Dynamic Value */ - kHIDUsage_GD_CountedBuffer = 0x3A, /* Logical Collection */ - kHIDUsage_GD_ByteCount = 0x3B, /* Dynamic Value */ - kHIDUsage_GD_MotionWakeup = 0x3C, /* One-Shot Control */ - kHIDUsage_GD_Start = 0x3D, /* On/Off Control */ - kHIDUsage_GD_Select = 0x3E, /* On/Off Control */ - /* 0x3F Reserved */ - kHIDUsage_GD_Vx = 0x40, /* Dynamic Value */ - kHIDUsage_GD_Vy = 0x41, /* Dynamic Value */ - kHIDUsage_GD_Vz = 0x42, /* Dynamic Value */ - kHIDUsage_GD_Vbrx = 0x43, /* Dynamic Value */ - kHIDUsage_GD_Vbry = 0x44, /* Dynamic Value */ - kHIDUsage_GD_Vbrz = 0x45, /* Dynamic Value */ - kHIDUsage_GD_Vno = 0x46, /* Dynamic Value */ - /* 0x47 - 0x7F Reserved */ - kHIDUsage_GD_SystemControl = 0x80, /* Application Collection */ - kHIDUsage_GD_SystemPowerDown = 0x81, /* One-Shot Control */ - kHIDUsage_GD_SystemSleep = 0x82, /* One-Shot Control */ - kHIDUsage_GD_SystemWakeUp = 0x83, /* One-Shot Control */ - kHIDUsage_GD_SystemContextMenu = 0x84, /* One-Shot Control */ - kHIDUsage_GD_SystemMainMenu = 0x85, /* One-Shot Control */ - kHIDUsage_GD_SystemAppMenu = 0x86, /* One-Shot Control */ - kHIDUsage_GD_SystemMenuHelp = 0x87, /* One-Shot Control */ - kHIDUsage_GD_SystemMenuExit = 0x88, /* One-Shot Control */ - kHIDUsage_GD_SystemMenu = 0x89, /* Selector */ - kHIDUsage_GD_SystemMenuRight = 0x8A, /* Re-Trigger Control */ - kHIDUsage_GD_SystemMenuLeft = 0x8B, /* Re-Trigger Control */ - kHIDUsage_GD_SystemMenuUp = 0x8C, /* Re-Trigger Control */ - kHIDUsage_GD_SystemMenuDown = 0x8D, /* Re-Trigger Control */ - /* 0x8E - 0x8F Reserved */ - kHIDUsage_GD_DPadUp = 0x90, /* On/Off Control */ - kHIDUsage_GD_DPadDown = 0x91, /* On/Off Control */ - kHIDUsage_GD_DPadRight = 0x92, /* On/Off Control */ - kHIDUsage_GD_DPadLeft = 0x93, /* On/Off Control */ - /* 0x94 - 0xFFFF Reserved */ - kHIDUsage_GD_Reserved = 0xFFFF, -}; - -/* Simulation Page (0x02) */ -/* This section provides detailed descriptions of the usages employed by simulation devices. */ -enum -{ - kHIDUsage_Sim_FlightSimulationDevice = 0x01, /* Application Collection */ - kHIDUsage_Sim_AutomobileSimulationDevice = 0x02, /* Application Collection */ - kHIDUsage_Sim_TankSimulationDevice = 0x03, /* Application Collection */ - kHIDUsage_Sim_SpaceshipSimulationDevice = 0x04, /* Application Collection */ - kHIDUsage_Sim_SubmarineSimulationDevice = 0x05, /* Application Collection */ - kHIDUsage_Sim_SailingSimulationDevice = 0x06, /* Application Collection */ - kHIDUsage_Sim_MotorcycleSimulationDevice = 0x07, /* Application Collection */ - kHIDUsage_Sim_SportsSimulationDevice = 0x08, /* Application Collection */ - kHIDUsage_Sim_AirplaneSimulationDevice = 0x09, /* Application Collection */ - kHIDUsage_Sim_HelicopterSimulationDevice = 0x0A, /* Application Collection */ - kHIDUsage_Sim_MagicCarpetSimulationDevice = 0x0B, /* Application Collection */ - kHIDUsage_Sim_BicycleSimulationDevice = 0x0C, /* Application Collection */ - /* 0x0D - 0x1F Reserved */ - kHIDUsage_Sim_FlightControlStick = 0x20, /* Application Collection */ - kHIDUsage_Sim_FlightStick = 0x21, /* Application Collection */ - kHIDUsage_Sim_CyclicControl = 0x22, /* Physical Collection */ - kHIDUsage_Sim_CyclicTrim = 0x23, /* Physical Collection */ - kHIDUsage_Sim_FlightYoke = 0x24, /* Application Collection */ - kHIDUsage_Sim_TrackControl = 0x25, /* Physical Collection */ - /* 0x26 - 0xAF Reserved */ - kHIDUsage_Sim_Aileron = 0xB0, /* Dynamic Value */ - kHIDUsage_Sim_AileronTrim = 0xB1, /* Dynamic Value */ - kHIDUsage_Sim_AntiTorqueControl = 0xB2, /* Dynamic Value */ - kHIDUsage_Sim_AutopilotEnable = 0xB3, /* On/Off Control */ - kHIDUsage_Sim_ChaffRelease = 0xB4, /* One-Shot Control */ - kHIDUsage_Sim_CollectiveControl = 0xB5, /* Dynamic Value */ - kHIDUsage_Sim_DiveBrake = 0xB6, /* Dynamic Value */ - kHIDUsage_Sim_ElectronicCountermeasures = 0xB7, /* On/Off Control */ - kHIDUsage_Sim_Elevator = 0xB8, /* Dynamic Value */ - kHIDUsage_Sim_ElevatorTrim = 0xB9, /* Dynamic Value */ - kHIDUsage_Sim_Rudder = 0xBA, /* Dynamic Value */ - kHIDUsage_Sim_Throttle = 0xBB, /* Dynamic Value */ - kHIDUsage_Sim_FlightCommunications = 0xBC, /* On/Off Control */ - kHIDUsage_Sim_FlareRelease = 0xBD, /* One-Shot Control */ - kHIDUsage_Sim_LandingGear = 0xBE, /* On/Off Control */ - kHIDUsage_Sim_ToeBrake = 0xBF, /* Dynamic Value */ - kHIDUsage_Sim_Trigger = 0xC0, /* Momentary Control */ - kHIDUsage_Sim_WeaponsArm = 0xC1, /* On/Off Control */ - kHIDUsage_Sim_Weapons = 0xC2, /* Selector */ - kHIDUsage_Sim_WingFlaps = 0xC3, /* Dynamic Value */ - kHIDUsage_Sim_Accelerator = 0xC4, /* Dynamic Value */ - kHIDUsage_Sim_Brake = 0xC5, /* Dynamic Value */ - kHIDUsage_Sim_Clutch = 0xC6, /* Dynamic Value */ - kHIDUsage_Sim_Shifter = 0xC7, /* Dynamic Value */ - kHIDUsage_Sim_Steering = 0xC8, /* Dynamic Value */ - kHIDUsage_Sim_TurretDirection = 0xC9, /* Dynamic Value */ - kHIDUsage_Sim_BarrelElevation = 0xCA, /* Dynamic Value */ - kHIDUsage_Sim_DivePlane = 0xCB, /* Dynamic Value */ - kHIDUsage_Sim_Ballast = 0xCC, /* Dynamic Value */ - kHIDUsage_Sim_BicycleCrank = 0xCD, /* Dynamic Value */ - kHIDUsage_Sim_HandleBars = 0xCE, /* Dynamic Value */ - kHIDUsage_Sim_FrontBrake = 0xCF, /* Dynamic Value */ - kHIDUsage_Sim_RearBrake = 0xD0, /* Dynamic Value */ - /* 0xD1 - 0xFFFF Reserved */ - kHIDUsage_Sim_Reserved = 0xFFFF, -}; - -/* VR Page (0x03) */ -/* Virtual Reality controls depend on designators to identify the individual controls. Most of the following are */ -/* usages are applied to the collections of entities that comprise the actual device. */ -enum -{ - kHIDUsage_VR_Belt = 0x01, /* Application Collection */ - kHIDUsage_VR_BodySuit = 0x02, /* Application Collection */ - kHIDUsage_VR_Flexor = 0x03, /* Physical Collection */ - kHIDUsage_VR_Glove = 0x04, /* Application Collection */ - kHIDUsage_VR_HeadTracker = 0x05, /* Physical Collection */ - kHIDUsage_VR_HeadMountedDisplay = 0x06, /* Application Collection */ - kHIDUsage_VR_HandTracker = 0x07, /* Application Collection */ - kHIDUsage_VR_Oculometer = 0x08, /* Application Collection */ - kHIDUsage_VR_Vest = 0x09, /* Application Collection */ - kHIDUsage_VR_AnimatronicDevice = 0x0A, /* Application Collection */ - /* 0x0B - 0x1F Reserved */ - kHIDUsage_VR_StereoEnable = 0x20, /* On/Off Control */ - kHIDUsage_VR_DisplayEnable = 0x21, /* On/Off Control */ - /* 0x22 - 0xFFFF Reserved */ - kHIDUsage_VR_Reserved = 0xFFFF, -}; - -/* Sport Page (0x04) */ -enum -{ - kHIDUsage_Sprt_BaseballBat = 0x01, /* Application Collection */ - kHIDUsage_Sprt_GolfClub = 0x02, /* Application Collection */ - kHIDUsage_Sprt_RowingMachine = 0x03, /* Application Collection */ - kHIDUsage_Sprt_Treadmill = 0x04, /* Application Collection */ - /* 0x05 - 0x2F Reserved */ - kHIDUsage_Sprt_Oar = 0x30, /* Dynamic Value */ - kHIDUsage_Sprt_Slope = 0x31, /* Dynamic Value */ - kHIDUsage_Sprt_Rate = 0x32, /* Dynamic Value */ - kHIDUsage_Sprt_StickSpeed = 0x33, /* Dynamic Value */ - kHIDUsage_Sprt_StickFaceAngle = 0x34, /* Dynamic Value */ - kHIDUsage_Sprt_StickHeelOrToe = 0x35, /* Dynamic Value */ - kHIDUsage_Sprt_StickFollowThrough = 0x36, /* Dynamic Value */ - kHIDUsage_Sprt_StickTempo = 0x37, /* Dynamic Value */ - kHIDUsage_Sprt_StickType = 0x38, /* Named Array */ - kHIDUsage_Sprt_StickHeight = 0x39, /* Dynamic Value */ - /* 0x3A - 0x4F Reserved */ - kHIDUsage_Sprt_Putter = 0x50, /* Selector */ - kHIDUsage_Sprt_1Iron = 0x51, /* Selector */ - kHIDUsage_Sprt_2Iron = 0x52, /* Selector */ - kHIDUsage_Sprt_3Iron = 0x53, /* Selector */ - kHIDUsage_Sprt_4Iron = 0x54, /* Selector */ - kHIDUsage_Sprt_5Iron = 0x55, /* Selector */ - kHIDUsage_Sprt_6Iron = 0x56, /* Selector */ - kHIDUsage_Sprt_7Iron = 0x57, /* Selector */ - kHIDUsage_Sprt_8Iron = 0x58, /* Selector */ - kHIDUsage_Sprt_9Iron = 0x59, /* Selector */ - kHIDUsage_Sprt_10Iron = 0x5A, /* Selector */ - kHIDUsage_Sprt_11Iron = 0x5B, /* Selector */ - kHIDUsage_Sprt_SandWedge = 0x5C, /* Selector */ - kHIDUsage_Sprt_LoftWedge = 0x5D, /* Selector */ - kHIDUsage_Sprt_PowerWedge = 0x5E, /* Selector */ - kHIDUsage_Sprt_1Wood = 0x5F, /* Selector */ - kHIDUsage_Sprt_3Wood = 0x60, /* Selector */ - kHIDUsage_Sprt_5Wood = 0x61, /* Selector */ - kHIDUsage_Sprt_7Wood = 0x62, /* Selector */ - kHIDUsage_Sprt_9Wood = 0x63, /* Selector */ - /* 0x64 - 0xFFFF Reserved */ - kHIDUsage_Sprt_Reserved = 0xFFFF, -}; - -/* Game Page (0x05) */ -enum -{ - kHIDUsage_Game_3DGameController = 0x01, /* Application Collection */ - kHIDUsage_Game_PinballDevice = 0x02, /* Application Collection */ - kHIDUsage_Game_GunDevice = 0x03, /* Application Collection */ - /* 0x04 - 0x1F Reserved */ - kHIDUsage_Game_PointofView = 0x20, /* Physical Collection */ - kHIDUsage_Game_TurnRightOrLeft = 0x21, /* Dynamic Value */ - kHIDUsage_Game_PitchUpOrDown = 0x22, /* Dynamic Value */ - kHIDUsage_Game_RollRightOrLeft = 0x23, /* Dynamic Value */ - kHIDUsage_Game_MoveRightOrLeft = 0x24, /* Dynamic Value */ - kHIDUsage_Game_MoveForwardOrBackward = 0x25, /* Dynamic Value */ - kHIDUsage_Game_MoveUpOrDown = 0x26, /* Dynamic Value */ - kHIDUsage_Game_LeanRightOrLeft = 0x27, /* Dynamic Value */ - kHIDUsage_Game_LeanForwardOrBackward = 0x28, /* Dynamic Value */ - kHIDUsage_Game_HeightOfPOV = 0x29, /* Dynamic Value */ - kHIDUsage_Game_Flipper = 0x2A, /* Momentary Control */ - kHIDUsage_Game_SecondaryFlipper = 0x2B, /* Momentary Control */ - kHIDUsage_Game_Bump = 0x2C, /* Momentary Control */ - kHIDUsage_Game_NewGame = 0x2D, /* One-Shot Control */ - kHIDUsage_Game_ShootBall = 0x2E, /* One-Shot Control */ - kHIDUsage_Game_Player = 0x2F, /* One-Shot Control */ - kHIDUsage_Game_GunBolt = 0x30, /* On/Off Control */ - kHIDUsage_Game_GunClip = 0x31, /* On/Off Control */ - kHIDUsage_Game_Gun = 0x32, /* Selector */ - kHIDUsage_Game_GunSingleShot = 0x33, /* Selector */ - kHIDUsage_Game_GunBurst = 0x34, /* Selector */ - kHIDUsage_Game_GunAutomatic = 0x35, /* Selector */ - kHIDUsage_Game_GunSafety = 0x36, /* On/Off Control */ - kHIDUsage_Game_GamepadFireOrJump = 0x37, /* Logical Collection */ - kHIDUsage_Game_GamepadTrigger = 0x39, /* Logical Collection */ - /* 0x3A - 0xFFFF Reserved */ - kHIDUsage_Game_Reserved = 0xFFFF, -}; - -/* KeyboardOrKeypad Page (0x07) */ -/* This section is the Usage Page for key codes to be used in implementing a USB keyboard. A Boot Keyboard (84-, 101- or 104-key) should at a minimum support all associated usage codes as indicated in the Ã’BootÓ */ -/* column below. */ -/* The usage type of all key codes is Selectors (Sel), except for the modifier keys Keyboard Left Control (0x224) to Keyboard Right GUI (0x231) which are Dynamic Flags (DV). */ -/* Note: A general note on Usages and languages: Due to the variation of keyboards from language to language, it is not feasible to specify exact key mappings for every language. Where this list is not specific for a key function in a language, the closest equivalent key position should be used, so that a keyboard may be modified for a different language by simply printing different keycaps. One example is the Y key on a North American keyboard. In Germany this is typically Z. Rather than changing the keyboard firmware to put the Z Usage into that place in the descriptor list, the vendor should use the Y Usage on both the North American and German keyboards. This continues to be the existing practice in the industry, in order to minimize the number of changes to the electronics to accommodate otherlanguages. */ -enum -{ - kHIDUsage_KeyboardErrorRollOver = 0x01, /* ErrorRollOver */ - kHIDUsage_KeyboardPOSTFail = 0x02, /* POSTFail */ - kHIDUsage_KeyboardErrorUndefined = 0x03, /* ErrorUndefined */ - kHIDUsage_KeyboardA = 0x04, /* a or A */ - kHIDUsage_KeyboardB = 0x05, /* b or B */ - kHIDUsage_KeyboardC = 0x06, /* c or C */ - kHIDUsage_KeyboardD = 0x07, /* d or D */ - kHIDUsage_KeyboardE = 0x08, /* e or E */ - kHIDUsage_KeyboardF = 0x09, /* f or F */ - kHIDUsage_KeyboardG = 0x0A, /* g or G */ - kHIDUsage_KeyboardH = 0x0B, /* h or H */ - kHIDUsage_KeyboardI = 0x0C, /* i or I */ - kHIDUsage_KeyboardJ = 0x0D, /* j or J */ - kHIDUsage_KeyboardK = 0x0E, /* k or K */ - kHIDUsage_KeyboardL = 0x0F, /* l or L */ - kHIDUsage_KeyboardM = 0x10, /* m or M */ - kHIDUsage_KeyboardN = 0x11, /* n or N */ - kHIDUsage_KeyboardO = 0x12, /* o or O */ - kHIDUsage_KeyboardP = 0x13, /* p or P */ - kHIDUsage_KeyboardQ = 0x14, /* q or Q */ - kHIDUsage_KeyboardR = 0x15, /* r or R */ - kHIDUsage_KeyboardS = 0x16, /* s or S */ - kHIDUsage_KeyboardT = 0x17, /* t or T */ - kHIDUsage_KeyboardU = 0x18, /* u or U */ - kHIDUsage_KeyboardV = 0x19, /* v or V */ - kHIDUsage_KeyboardW = 0x1A, /* w or W */ - kHIDUsage_KeyboardX = 0x1B, /* x or X */ - kHIDUsage_KeyboardY = 0x1C, /* y or Y */ - kHIDUsage_KeyboardZ = 0x1D, /* z or Z */ - kHIDUsage_Keyboard1 = 0x1E, /* 1 or ! */ - kHIDUsage_Keyboard2 = 0x1F, /* 2 or @ */ - kHIDUsage_Keyboard3 = 0x20, /* 3 or # */ - kHIDUsage_Keyboard4 = 0x21, /* 4 or $ */ - kHIDUsage_Keyboard5 = 0x22, /* 5 or % */ - kHIDUsage_Keyboard6 = 0x23, /* 6 or ^ */ - kHIDUsage_Keyboard7 = 0x24, /* 7 or & */ - kHIDUsage_Keyboard8 = 0x25, /* 8 or * */ - kHIDUsage_Keyboard9 = 0x26, /* 9 or ( */ - kHIDUsage_Keyboard0 = 0x27, /* 0 or ) */ - kHIDUsage_KeyboardReturnOrEnter = 0x28, /* Return (Enter) */ - kHIDUsage_KeyboardEscape = 0x29, /* Escape */ - kHIDUsage_KeyboardDeleteOrBackspace = 0x2A, /* Delete (Backspace) */ - kHIDUsage_KeyboardTab = 0x2B, /* Tab */ - kHIDUsage_KeyboardSpacebar = 0x2C, /* Spacebar */ - kHIDUsage_KeyboardHyphen = 0x2D, /* - or _ */ - kHIDUsage_KeyboardEqualSign = 0x2E, /* = or + */ - kHIDUsage_KeyboardOpenBracket = 0x2F, /* [ or { */ - kHIDUsage_KeyboardCloseBracket = 0x30, /* ] or } */ - kHIDUsage_KeyboardBackslash = 0x31, /* \ or | */ - kHIDUsage_KeyboardNonUSPound = 0x32, /* Non-US # or _ */ - kHIDUsage_KeyboardSemicolon = 0x33, /* ; or : */ - kHIDUsage_KeyboardQuote = 0x34, /* ' or " */ - kHIDUsage_KeyboardGraveAccentAndTilde = 0x35, /* Grave Accent and Tilde */ - kHIDUsage_KeyboardComma = 0x36, /* , or < */ - kHIDUsage_KeyboardPeriod = 0x37, /* . or > */ - kHIDUsage_KeyboardSlash = 0x38, /* / or ? */ - kHIDUsage_KeyboardCapsLock = 0x39, /* Caps Lock */ - kHIDUsage_KeyboardF1 = 0x3A, /* F1 */ - kHIDUsage_KeyboardF2 = 0x3B, /* F2 */ - kHIDUsage_KeyboardF3 = 0x3C, /* F3 */ - kHIDUsage_KeyboardF4 = 0x3D, /* F4 */ - kHIDUsage_KeyboardF5 = 0x3E, /* F5 */ - kHIDUsage_KeyboardF6 = 0x3F, /* F6 */ - kHIDUsage_KeyboardF7 = 0x40, /* F7 */ - kHIDUsage_KeyboardF8 = 0x41, /* F8 */ - kHIDUsage_KeyboardF9 = 0x42, /* F9 */ - kHIDUsage_KeyboardF10 = 0x43, /* F10 */ - kHIDUsage_KeyboardF11 = 0x44, /* F11 */ - kHIDUsage_KeyboardF12 = 0x45, /* F12 */ - kHIDUsage_KeyboardPrintScreen = 0x46, /* Print Screen */ - kHIDUsage_KeyboardScrollLock = 0x47, /* Scroll Lock */ - kHIDUsage_KeyboardPause = 0x48, /* Pause */ - kHIDUsage_KeyboardInsert = 0x49, /* Insert */ - kHIDUsage_KeyboardHome = 0x4A, /* Home */ - kHIDUsage_KeyboardPageUp = 0x4B, /* Page Up */ - kHIDUsage_KeyboardDeleteForward = 0x4C, /* Delete Forward */ - kHIDUsage_KeyboardEnd = 0x4D, /* End */ - kHIDUsage_KeyboardPageDown = 0x4E, /* Page Down */ - kHIDUsage_KeyboardRightArrow = 0x4F, /* Right Arrow */ - kHIDUsage_KeyboardLeftArrow = 0x50, /* Left Arrow */ - kHIDUsage_KeyboardDownArrow = 0x51, /* Down Arrow */ - kHIDUsage_KeyboardUpArrow = 0x52, /* Up Arrow */ - kHIDUsage_KeypadNumLock = 0x53, /* Keypad NumLock or Clear */ - kHIDUsage_KeypadSlash = 0x54, /* Keypad / */ - kHIDUsage_KeypadAsterisk = 0x55, /* Keypad * */ - kHIDUsage_KeypadHyphen = 0x56, /* Keypad - */ - kHIDUsage_KeypadPlus = 0x57, /* Keypad + */ - kHIDUsage_KeypadEnter = 0x58, /* Keypad Enter */ - kHIDUsage_Keypad1 = 0x59, /* Keypad 1 or End */ - kHIDUsage_Keypad2 = 0x5A, /* Keypad 2 or Down Arrow */ - kHIDUsage_Keypad3 = 0x5B, /* Keypad 3 or Page Down */ - kHIDUsage_Keypad4 = 0x5C, /* Keypad 4 or Left Arrow */ - kHIDUsage_Keypad5 = 0x5D, /* Keypad 5 */ - kHIDUsage_Keypad6 = 0x5E, /* Keypad 6 or Right Arrow */ - kHIDUsage_Keypad7 = 0x5F, /* Keypad 7 or Home */ - kHIDUsage_Keypad8 = 0x60, /* Keypad 8 or Up Arrow */ - kHIDUsage_Keypad9 = 0x61, /* Keypad 9 or Page Up */ - kHIDUsage_Keypad0 = 0x62, /* Keypad 0 or Insert */ - kHIDUsage_KeypadPeriod = 0x63, /* Keypad . or Delete */ - kHIDUsage_KeyboardNonUSBackslash = 0x64, /* Non-US \ or | */ - kHIDUsage_KeyboardApplication = 0x65, /* Application */ - kHIDUsage_KeyboardPower = 0x66, /* Power */ - kHIDUsage_KeypadEqualSign = 0x67, /* Keypad = */ - kHIDUsage_KeyboardF13 = 0x68, /* F13 */ - kHIDUsage_KeyboardF14 = 0x69, /* F14 */ - kHIDUsage_KeyboardF15 = 0x6A, /* F15 */ - kHIDUsage_KeyboardF16 = 0x6B, /* F16 */ - kHIDUsage_KeyboardF17 = 0x6C, /* F17 */ - kHIDUsage_KeyboardF18 = 0x6D, /* F18 */ - kHIDUsage_KeyboardF19 = 0x6E, /* F19 */ - kHIDUsage_KeyboardF20 = 0x6F, /* F20 */ - kHIDUsage_KeyboardF21 = 0x70, /* F21 */ - kHIDUsage_KeyboardF22 = 0x71, /* F22 */ - kHIDUsage_KeyboardF23 = 0x72, /* F23 */ - kHIDUsage_KeyboardF24 = 0x73, /* F24 */ - kHIDUsage_KeyboardExecute = 0x74, /* Execute */ - kHIDUsage_KeyboardHelp = 0x75, /* Help */ - kHIDUsage_KeyboardMenu = 0x76, /* Menu */ - kHIDUsage_KeyboardSelect = 0x77, /* Select */ - kHIDUsage_KeyboardStop = 0x78, /* Stop */ - kHIDUsage_KeyboardAgain = 0x79, /* Again */ - kHIDUsage_KeyboardUndo = 0x7A, /* Undo */ - kHIDUsage_KeyboardCut = 0x7B, /* Cut */ - kHIDUsage_KeyboardCopy = 0x7C, /* Copy */ - kHIDUsage_KeyboardPaste = 0x7D, /* Paste */ - kHIDUsage_KeyboardFind = 0x7E, /* Find */ - kHIDUsage_KeyboardMute = 0x7F, /* Mute */ - kHIDUsage_KeyboardVolumeUp = 0x80, /* Volume Up */ - kHIDUsage_KeyboardVolumeDown = 0x81, /* Volume Down */ - kHIDUsage_KeyboardLockingCapsLock = 0x82, /* Locking Caps Lock */ - kHIDUsage_KeyboardLockingNumLock = 0x83, /* Locking Num Lock */ - kHIDUsage_KeyboardLockingScrollLock = 0x84, /* Locking Scroll Lock */ - kHIDUsage_KeypadComma = 0x85, /* Keypad Comma */ - kHIDUsage_KeypadEqualSignAS400 = 0x86, /* Keypad Equal Sign for AS/400 */ - kHIDUsage_KeyboardInternational1 = 0x87, /* International1 */ - kHIDUsage_KeyboardInternational2 = 0x88, /* International2 */ - kHIDUsage_KeyboardInternational3 = 0x89, /* International3 */ - kHIDUsage_KeyboardInternational4 = 0x8A, /* International4 */ - kHIDUsage_KeyboardInternational5 = 0x8B, /* International5 */ - kHIDUsage_KeyboardInternational6 = 0x8C, /* International6 */ - kHIDUsage_KeyboardInternational7 = 0x8D, /* International7 */ - kHIDUsage_KeyboardInternational8 = 0x8E, /* International8 */ - kHIDUsage_KeyboardInternational9 = 0x8F, /* International9 */ - kHIDUsage_KeyboardLANG1 = 0x90, /* LANG1 */ - kHIDUsage_KeyboardLANG2 = 0x91, /* LANG2 */ - kHIDUsage_KeyboardLANG3 = 0x92, /* LANG3 */ - kHIDUsage_KeyboardLANG4 = 0x93, /* LANG4 */ - kHIDUsage_KeyboardLANG5 = 0x94, /* LANG5 */ - kHIDUsage_KeyboardLANG6 = 0x95, /* LANG6 */ - kHIDUsage_KeyboardLANG7 = 0x96, /* LANG7 */ - kHIDUsage_KeyboardLANG8 = 0x97, /* LANG8 */ - kHIDUsage_KeyboardLANG9 = 0x98, /* LANG9 */ - kHIDUsage_KeyboardAlternateErase = 0x99, /* AlternateErase */ - kHIDUsage_KeyboardSysReqOrAttention = 0x9A, /* SysReq/Attention */ - kHIDUsage_KeyboardCancel = 0x9B, /* Cancel */ - kHIDUsage_KeyboardClear = 0x9C, /* Clear */ - kHIDUsage_KeyboardPrior = 0x9D, /* Prior */ - kHIDUsage_KeyboardReturn = 0x9E, /* Return */ - kHIDUsage_KeyboardSeparator = 0x9F, /* Separator */ - kHIDUsage_KeyboardOut = 0xA0, /* Out */ - kHIDUsage_KeyboardOper = 0xA1, /* Oper */ - kHIDUsage_KeyboardClearOrAgain = 0xA2, /* Clear/Again */ - kHIDUsage_KeyboardCrSelOrProps = 0xA3, /* CrSel/Props */ - kHIDUsage_KeyboardExSel = 0xA4, /* ExSel */ - /* 0xA5-0xDF Reserved */ - kHIDUsage_KeyboardLeftControl = 0xE0, /* Left Control */ - kHIDUsage_KeyboardLeftShift = 0xE1, /* Left Shift */ - kHIDUsage_KeyboardLeftAlt = 0xE2, /* Left Alt */ - kHIDUsage_KeyboardLeftGUI = 0xE3, /* Left GUI */ - kHIDUsage_KeyboardRightControl = 0xE4, /* Right Control */ - kHIDUsage_KeyboardRightShift = 0xE5, /* Right Shift */ - kHIDUsage_KeyboardRightAlt = 0xE6, /* Right Alt */ - kHIDUsage_KeyboardRightGUI = 0xE7, /* Right GUI */ - /* 0xE8-0xFFFF Reserved */ - kHIDUsage_Keyboard_Reserved = 0xFFFF, -}; - -/* LEDs Page (0x08) */ -/* An LED or indicator is implemented as an On/Off Control (OOF) using the Ã’Single button toggleÓ mode, where a value of 1 will turn on the indicator, and a value of 0 will turn it off. The exceptions are described below. */ -enum -{ - kHIDUsage_LED_NumLock = 0x01, /* On/Off Control */ - kHIDUsage_LED_CapsLock = 0x02, /* On/Off Control */ - kHIDUsage_LED_ScrollLock = 0x03, /* On/Off Control */ - kHIDUsage_LED_Compose = 0x04, /* On/Off Control */ - kHIDUsage_LED_Kana = 0x05, /* On/Off Control */ - kHIDUsage_LED_Power = 0x06, /* On/Off Control */ - kHIDUsage_LED_Shift = 0x07, /* On/Off Control */ - kHIDUsage_LED_DoNotDisturb = 0x08, /* On/Off Control */ - kHIDUsage_LED_Mute = 0x09, /* On/Off Control */ - kHIDUsage_LED_ToneEnable = 0x0A, /* On/Off Control */ - kHIDUsage_LED_HighCutFilter = 0x0B, /* On/Off Control */ - kHIDUsage_LED_LowCutFilter = 0x0C, /* On/Off Control */ - kHIDUsage_LED_EqualizerEnable = 0x0D, /* On/Off Control */ - kHIDUsage_LED_SoundFieldOn = 0x0E, /* On/Off Control */ - kHIDUsage_LED_SurroundOn = 0x0F, /* On/Off Control */ - kHIDUsage_LED_Repeat = 0x10, /* On/Off Control */ - kHIDUsage_LED_Stereo = 0x11, /* On/Off Control */ - kHIDUsage_LED_SamplingRateDetect = 0x12, /* On/Off Control */ - kHIDUsage_LED_Spinning = 0x13, /* On/Off Control */ - kHIDUsage_LED_CAV = 0x14, /* On/Off Control */ - kHIDUsage_LED_CLV = 0x15, /* On/Off Control */ - kHIDUsage_LED_RecordingFormatDetect = 0x16, /* On/Off Control */ - kHIDUsage_LED_OffHook = 0x17, /* On/Off Control */ - kHIDUsage_LED_Ring = 0x18, /* On/Off Control */ - kHIDUsage_LED_MessageWaiting = 0x19, /* On/Off Control */ - kHIDUsage_LED_DataMode = 0x1A, /* On/Off Control */ - kHIDUsage_LED_BatteryOperation = 0x1B, /* On/Off Control */ - kHIDUsage_LED_BatteryOK = 0x1C, /* On/Off Control */ - kHIDUsage_LED_BatteryLow = 0x1D, /* On/Off Control */ - kHIDUsage_LED_Speaker = 0x1E, /* On/Off Control */ - kHIDUsage_LED_HeadSet = 0x1F, /* On/Off Control */ - kHIDUsage_LED_Hold = 0x20, /* On/Off Control */ - kHIDUsage_LED_Microphone = 0x21, /* On/Off Control */ - kHIDUsage_LED_Coverage = 0x22, /* On/Off Control */ - kHIDUsage_LED_NightMode = 0x23, /* On/Off Control */ - kHIDUsage_LED_SendCalls = 0x24, /* On/Off Control */ - kHIDUsage_LED_CallPickup = 0x25, /* On/Off Control */ - kHIDUsage_LED_Conference = 0x26, /* On/Off Control */ - kHIDUsage_LED_StandBy = 0x27, /* On/Off Control */ - kHIDUsage_LED_CameraOn = 0x28, /* On/Off Control */ - kHIDUsage_LED_CameraOff = 0x29, /* On/Off Control */ - kHIDUsage_LED_OnLine = 0x2A, /* On/Off Control */ - kHIDUsage_LED_OffLine = 0x2B, /* On/Off Control */ - kHIDUsage_LED_Busy = 0x2C, /* On/Off Control */ - kHIDUsage_LED_Ready = 0x2D, /* On/Off Control */ - kHIDUsage_LED_PaperOut = 0x2E, /* On/Off Control */ - kHIDUsage_LED_PaperJam = 0x2F, /* On/Off Control */ - kHIDUsage_LED_Remote = 0x30, /* On/Off Control */ - kHIDUsage_LED_Forward = 0x31, /* On/Off Control */ - kHIDUsage_LED_Reverse = 0x32, /* On/Off Control */ - kHIDUsage_LED_Stop = 0x33, /* On/Off Control */ - kHIDUsage_LED_Rewind = 0x34, /* On/Off Control */ - kHIDUsage_LED_FastForward = 0x35, /* On/Off Control */ - kHIDUsage_LED_Play = 0x36, /* On/Off Control */ - kHIDUsage_LED_Pause = 0x37, /* On/Off Control */ - kHIDUsage_LED_Record = 0x38, /* On/Off Control */ - kHIDUsage_LED_Error = 0x39, /* On/Off Control */ - kHIDUsage_LED_Usage = 0x3A, /* Selector */ - kHIDUsage_LED_UsageInUseIndicator = 0x3B, /* Usage Switch */ - kHIDUsage_LED_UsageMultiModeIndicator = 0x3C, /* Usage Modifier */ - kHIDUsage_LED_IndicatorOn = 0x3D, /* Selector */ - kHIDUsage_LED_IndicatorFlash = 0x3E, /* Selector */ - kHIDUsage_LED_IndicatorSlowBlink = 0x3F, /* Selector */ - kHIDUsage_LED_IndicatorFastBlink = 0x40, /* Selector */ - kHIDUsage_LED_IndicatorOff = 0x41, /* Selector */ - kHIDUsage_LED_FlashOnTime = 0x42, /* Dynamic Value */ - kHIDUsage_LED_SlowBlinkOnTime = 0x43, /* Dynamic Value */ - kHIDUsage_LED_SlowBlinkOffTime = 0x44, /* Dynamic Value */ - kHIDUsage_LED_FastBlinkOnTime = 0x45, /* Dynamic Value */ - kHIDUsage_LED_FastBlinkOffTime = 0x46, /* Dynamic Value */ - kHIDUsage_LED_UsageIndicatorColor = 0x47, /* Usage Modifier */ - kHIDUsage_LED_IndicatorRed = 0x48, /* Selector */ - kHIDUsage_LED_IndicatorGreen = 0x49, /* Selector */ - kHIDUsage_LED_IndicatorAmber = 0x4A, /* Selector */ - kHIDUsage_LED_GenericIndicator = 0x4B, /* On/Off Control */ - kHIDUsage_LED_SystemSuspend = 0x4C, /* On/Off Control */ - kHIDUsage_LED_ExternalPowerConnected = 0x4D, /* On/Off Control */ - /* 0x4E - 0xFFFF Reserved */ - kHIDUsage_LED_Reserved = 0xFFFF, -}; - -/* Button Page (0x09) */ -/* The Button page is the first place an application should look for user selection controls. System graphical user interfaces typically employ a pointer and a set of hierarchical selectors to select, move and otherwise manipulate their environment. For these purposes the following assignment of significance can be applied to the Button usages: */ -/* Â¥ Button 1, Primary Button. Used for object selecting, dragging, and double click activation. On MacOS, this is the only button. Microsoft operating systems call this a logical left button, because it */ -/* is not necessarily physically located on the left of the pointing device. */ -/* Â¥ Button 2, Secondary Button. Used by newer graphical user interfaces to browse object properties. Exposed by systems to applications that typically assign application-specific functionality. */ -/* Â¥ Button 3, Tertiary Button. Optional control. Exposed to applications, but seldom assigned functionality due to prevalence of two- and one-button devices. */ -/* Â¥ Buttons 4 -55. As the button number increases, its significance as a selector decreases. */ -/* In many ways the assignment of button numbers is similar to the assignment of Effort in Physical descriptors. Button 1 would be used to define the button a finger rests on when the hand is in the Ã’at restÓ position, that is, virtually no effort is required by the user to activate the button. Button values increment as the finger has to stretch to reach a control. See Section 6.2.3, Ã’Physical Descriptors,Ó in the HID Specification for methods of further qualifying buttons. */ -enum -{ - kHIDUsage_Button_1 = 0x01, /* (primary/trigger) */ - kHIDUsage_Button_2 = 0x02, /* (secondary) */ - kHIDUsage_Button_3 = 0x03, /* (tertiary) */ - kHIDUsage_Button_4 = 0x04, /* 4th button */ - /* ... */ - kHIDUsage_Button_65535 = 0xFFFF, -}; - -/* Ordinal Page (0x0A) */ -/* The Ordinal page allows multiple instances of a control or sets of controls to be declared without requiring individual enumeration in the native usage page. For example, it is not necessary to declare usages of Pointer 1, Pointer 2, and so forth on the Generic Desktop page. When parsed, the ordinal instance number is, in essence, concatenated to the usages attached to the encompassing collection to create Pointer 1, Pointer 2, and so forth. */ -/* For an example, see Section A.5, Ã’Multiple Instances of a Control,Ó in Appendix A, Ã’Usage Examples.Ó By convention, an Ordinal collection is placed inside the collection for which it is declaring multiple instances. */ -/* Instances do not have to be identical. */ -enum -{ - /* 0x00 Reserved */ - kHIDUsage_Ord_Instance1 = 0x01, /* Usage Modifier */ - kHIDUsage_Ord_Instance2 = 0x02, /* Usage Modifier */ - kHIDUsage_Ord_Instance3 = 0x03, /* Usage Modifier */ - kHIDUsage_Ord_Instance4 = 0x04, /* Usage Modifier */ - kHIDUsage_Ord_Instance65535 = 0xFFFF, /* Usage Modifier */ -}; - -/* Telephony Page (0x0B) */ -/* This usage page defines the keytop and control usages for telephony devices. */ -/* Indicators on a phone are handled by wrapping them in LED: Usage In Use Indicator and LED: Usage Selected Indicator usages. For example, a message-indicator LED would be identified by a Telephony: Message usage declared as a Feature or Output in a LED: Usage In Use Indicator collection. */ -/* See Section 14, Ã’Consumer Page (0x0C),Ó for audio volume and tone controls. */ -enum -{ - kHIDUsage_Tfon_Phone = 0x01, /* Application Collection */ - kHIDUsage_Tfon_AnsweringMachine = 0x02, /* Application Collection */ - kHIDUsage_Tfon_MessageControls = 0x03, /* Logical Collection */ - kHIDUsage_Tfon_Handset = 0x04, /* Logical Collection */ - kHIDUsage_Tfon_Headset = 0x05, /* Logical Collection */ - kHIDUsage_Tfon_TelephonyKeyPad = 0x06, /* Named Array */ - kHIDUsage_Tfon_ProgrammableButton = 0x07, /* Named Array */ - /* 0x08 - 0x1F Reserved */ - kHIDUsage_Tfon_HookSwitch = 0x20, /* On/Off Control */ - kHIDUsage_Tfon_Flash = 0x21, /* Momentary Control */ - kHIDUsage_Tfon_Feature = 0x22, /* One-Shot Control */ - kHIDUsage_Tfon_Hold = 0x23, /* On/Off Control */ - kHIDUsage_Tfon_Redial = 0x24, /* One-Shot Control */ - kHIDUsage_Tfon_Transfer = 0x25, /* One-Shot Control */ - kHIDUsage_Tfon_Drop = 0x26, /* One-Shot Control */ - kHIDUsage_Tfon_Park = 0x27, /* On/Off Control */ - kHIDUsage_Tfon_ForwardCalls = 0x28, /* On/Off Control */ - kHIDUsage_Tfon_AlternateFunction = 0x29, /* Momentary Control */ - kHIDUsage_Tfon_Line = 0x2A, /* One-Shot Control */ - kHIDUsage_Tfon_SpeakerPhone = 0x2B, /* On/Off Control */ - kHIDUsage_Tfon_Conference = 0x2C, /* On/Off Control */ - kHIDUsage_Tfon_RingEnable = 0x2D, /* On/Off Control */ - kHIDUsage_Tfon_Ring = 0x2E, /* Selector */ - kHIDUsage_Tfon_PhoneMute = 0x2F, /* On/Off Control */ - kHIDUsage_Tfon_CallerID = 0x30, /* Momentary Control */ - /* 0x31 - 0x4F Reserved */ - kHIDUsage_Tfon_SpeedDial = 0x50, /* One-Shot Control */ - kHIDUsage_Tfon_StoreNumber = 0x51, /* One-Shot Control */ - kHIDUsage_Tfon_RecallNumber = 0x52, /* One-Shot Control */ - kHIDUsage_Tfon_PhoneDirectory = 0x53, /* On/Off Control */ - /* 0x54 - 0x6F Reserved */ - kHIDUsage_Tfon_VoiceMail = 0x70, /* On/Off Control */ - kHIDUsage_Tfon_ScreenCalls = 0x71, /* On/Off Control */ - kHIDUsage_Tfon_DoNotDisturb = 0x72, /* On/Off Control */ - kHIDUsage_Tfon_Message = 0x73, /* One-Shot Control */ - kHIDUsage_Tfon_AnswerOnOrOff = 0x74, /* On/Off Control */ - /* 0x75 - 0x8F Reserved */ - kHIDUsage_Tfon_InsideDialTone = 0x90, /* Momentary Control */ - kHIDUsage_Tfon_OutsideDialTone = 0x91, /* Momentary Control */ - kHIDUsage_Tfon_InsideRingTone = 0x92, /* Momentary Control */ - kHIDUsage_Tfon_OutsideRingTone = 0x93, /* Momentary Control */ - kHIDUsage_Tfon_PriorityRingTone = 0x94, /* Momentary Control */ - kHIDUsage_Tfon_InsideRingback = 0x95, /* Momentary Control */ - kHIDUsage_Tfon_PriorityRingback = 0x96, /* Momentary Control */ - kHIDUsage_Tfon_LineBusyTone = 0x97, /* Momentary Control */ - kHIDUsage_Tfon_ReorderTone = 0x98, /* Momentary Control */ - kHIDUsage_Tfon_CallWaitingTone = 0x99, /* Momentary Control */ - kHIDUsage_Tfon_ConfirmationTone1 = 0x9A, /* Momentary Control */ - kHIDUsage_Tfon_ConfirmationTone2 = 0x9B, /* Momentary Control */ - kHIDUsage_Tfon_TonesOff = 0x9C, /* On/Off Control */ - kHIDUsage_Tfon_OutsideRingback = 0x9D, /* Momentary Control */ - /* 0x9E - 0xAF Reserved */ - kHIDUsage_Tfon_PhoneKey0 = 0xB0, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey1 = 0xB1, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey2 = 0xB2, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey3 = 0xB3, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey4 = 0xB4, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey5 = 0xB5, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey6 = 0xB6, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey7 = 0xB7, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey8 = 0xB8, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKey9 = 0xB9, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyStar = 0xBA, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyPound = 0xBB, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyA = 0xBC, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyB = 0xBD, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyC = 0xBE, /* Selector/One-Shot Control */ - kHIDUsage_Tfon_PhoneKeyD = 0xBF, /* Selector/One-Shot Control */ - /* 0xC0 - 0xFFFF Reserved */ - kHIDUsage_TFon_Reserved = 0xFFFF, -}; - -/* Consumer Page (0x0C) */ -/* All controls on the Consumer page are application-specific. That is, they affect a specific device, not the system as a whole. */ -enum -{ - kHIDUsage_Csmr_ConsumerControl = 0x01, /* Application Collection */ - kHIDUsage_Csmr_NumericKeyPad = 0x02, /* Named Array */ - kHIDUsage_Csmr_ProgrammableButtons = 0x03, /* Named Array */ - /* 0x03 - 0x1F Reserved */ - kHIDUsage_Csmr_Plus10 = 0x20, /* One-Shot Control */ - kHIDUsage_Csmr_Plus100 = 0x21, /* One-Shot Control */ - kHIDUsage_Csmr_AMOrPM = 0x22, /* One-Shot Control */ - /* 0x23 - 0x3F Reserved */ - kHIDUsage_Csmr_Power = 0x30, /* On/Off Control */ - kHIDUsage_Csmr_Reset = 0x31, /* One-Shot Control */ - kHIDUsage_Csmr_Sleep = 0x32, /* One-Shot Control */ - kHIDUsage_Csmr_SleepAfter = 0x33, /* One-Shot Control */ - kHIDUsage_Csmr_SleepMode = 0x34, /* Re-Trigger Control */ - kHIDUsage_Csmr_Illumination = 0x35, /* On/Off Control */ - kHIDUsage_Csmr_FunctionButtons = 0x36, /* Named Array */ - /* 0x37 - 0x3F Reserved */ - kHIDUsage_Csmr_Menu = 0x40, /* On/Off Control */ - kHIDUsage_Csmr_MenuPick = 0x41, /* One-Shot Control */ - kHIDUsage_Csmr_MenuUp = 0x42, /* One-Shot Control */ - kHIDUsage_Csmr_MenuDown = 0x43, /* One-Shot Control */ - kHIDUsage_Csmr_MenuLeft = 0x44, /* One-Shot Control */ - kHIDUsage_Csmr_MenuRight = 0x45, /* One-Shot Control */ - kHIDUsage_Csmr_MenuEscape = 0x46, /* One-Shot Control */ - kHIDUsage_Csmr_MenuValueIncrease = 0x47, /* One-Shot Control */ - kHIDUsage_Csmr_MenuValueDecrease = 0x48, /* One-Shot Control */ - /* 0x49 - 0x5F Reserved */ - kHIDUsage_Csmr_DataOnScreen = 0x60, /* On/Off Control */ - kHIDUsage_Csmr_ClosedCaption = 0x61, /* On/Off Control */ - kHIDUsage_Csmr_ClosedCaptionSelect = 0x62, /* Selector */ - kHIDUsage_Csmr_VCROrTV = 0x63, /* On/Off Control */ - kHIDUsage_Csmr_BroadcastMode = 0x64, /* One-Shot Control */ - kHIDUsage_Csmr_Snapshot = 0x65, /* One-Shot Control */ - kHIDUsage_Csmr_Still = 0x66, /* One-Shot Control */ - /* 0x67 - 0x7F Reserved */ - kHIDUsage_Csmr_Selection = 0x80, /* Named Array */ - kHIDUsage_Csmr_Assign = 0x81, /* Selector */ - kHIDUsage_Csmr_ModeStep = 0x82, /* One-Shot Control */ - kHIDUsage_Csmr_RecallLast = 0x83, /* One-Shot Control */ - kHIDUsage_Csmr_EnterChannel = 0x84, /* One-Shot Control */ - kHIDUsage_Csmr_OrderMovie = 0x85, /* One-Shot Control */ - kHIDUsage_Csmr_Channel = 0x86, /* Linear Control */ - kHIDUsage_Csmr_MediaSelection = 0x87, /* Selector */ - kHIDUsage_Csmr_MediaSelectComputer = 0x88, /* Selector */ - kHIDUsage_Csmr_MediaSelectTV = 0x89, /* Selector */ - kHIDUsage_Csmr_MediaSelectWWW = 0x8A, /* Selector */ - kHIDUsage_Csmr_MediaSelectDVD = 0x8B, /* Selector */ - kHIDUsage_Csmr_MediaSelectTelephone = 0x8C, /* Selector */ - kHIDUsage_Csmr_MediaSelectProgramGuide = 0x8D, /* Selector */ - kHIDUsage_Csmr_MediaSelectVideoPhone = 0x8E, /* Selector */ - kHIDUsage_Csmr_MediaSelectGames = 0x8F, /* Selector */ - kHIDUsage_Csmr_MediaSelectMessages = 0x90, /* Selector */ - kHIDUsage_Csmr_MediaSelectCD = 0x91, /* Selector */ - kHIDUsage_Csmr_MediaSelectVCR = 0x92, /* Selector */ - kHIDUsage_Csmr_MediaSelectTuner = 0x93, /* Selector */ - kHIDUsage_Csmr_Quit = 0x94, /* One-Shot Control */ - kHIDUsage_Csmr_Help = 0x95, /* On/Off Control */ - kHIDUsage_Csmr_MediaSelectTape = 0x96, /* Selector */ - kHIDUsage_Csmr_MediaSelectCable = 0x97, /* Selector */ - kHIDUsage_Csmr_MediaSelectSatellite = 0x98, /* Selector */ - kHIDUsage_Csmr_MediaSelectSecurity = 0x99, /* Selector */ - kHIDUsage_Csmr_MediaSelectHome = 0x9A, /* Selector */ - kHIDUsage_Csmr_MediaSelectCall = 0x9B, /* Selector */ - kHIDUsage_Csmr_ChannelIncrement = 0x9C, /* One-Shot Control */ - kHIDUsage_Csmr_ChannelDecrement = 0x9D, /* One-Shot Control */ - kHIDUsage_Csmr_Media = 0x9E, /* Selector */ - /* 0x9F Reserved */ - kHIDUsage_Csmr_VCRPlus = 0xA0, /* One-Shot Control */ - kHIDUsage_Csmr_Once = 0xA1, /* One-Shot Control */ - kHIDUsage_Csmr_Daily = 0xA2, /* One-Shot Control */ - kHIDUsage_Csmr_Weekly = 0xA3, /* One-Shot Control */ - kHIDUsage_Csmr_Monthly = 0xA4, /* One-Shot Control */ - /* 0xA5 - 0xAF Reserved */ - kHIDUsage_Csmr_Play = 0xB0, /* On/Off Control */ - kHIDUsage_Csmr_Pause = 0xB1, /* On/Off Control */ - kHIDUsage_Csmr_Record = 0xB2, /* On/Off Control */ - kHIDUsage_Csmr_FastForward = 0xB3, /* On/Off Control */ - kHIDUsage_Csmr_Rewind = 0xB4, /* On/Off Control */ - kHIDUsage_Csmr_ScanNextTrack = 0xB5, /* One-Shot Control */ - kHIDUsage_Csmr_ScanPreviousTrack = 0xB6, /* One-Shot Control */ - kHIDUsage_Csmr_Stop = 0xB7, /* One-Shot Control */ - kHIDUsage_Csmr_Eject = 0xB8, /* One-Shot Control */ - kHIDUsage_Csmr_RandomPlay = 0xB9, /* On/Off Control */ - kHIDUsage_Csmr_SelectDisc = 0xBA, /* Named Array */ - kHIDUsage_Csmr_EnterDisc = 0xBB, /* Momentary Control */ - kHIDUsage_Csmr_Repeat = 0xBC, /* One-Shot Control */ - kHIDUsage_Csmr_Tracking = 0xBD, /* Linear Control */ - kHIDUsage_Csmr_TrackNormal = 0xBE, /* One-Shot Control */ - kHIDUsage_Csmr_SlowTracking = 0xBF, /* Linear Control */ - kHIDUsage_Csmr_FrameForward = 0xC0, /* Re-Trigger Control */ - kHIDUsage_Csmr_FrameBack = 0xC1, /* Re-Trigger Control */ - kHIDUsage_Csmr_Mark = 0xC2, /* One-Shot Control */ - kHIDUsage_Csmr_ClearMark = 0xC3, /* One-Shot Control */ - kHIDUsage_Csmr_RepeatFromMark = 0xC4, /* On/Off Control */ - kHIDUsage_Csmr_ReturnToMark = 0xC5, /* One-Shot Control */ - kHIDUsage_Csmr_SearchMarkForward = 0xC6, /* One-Shot Control */ - kHIDUsage_Csmr_SearchMarkBackwards = 0xC7, /* One-Shot Control */ - kHIDUsage_Csmr_CounterReset = 0xC8, /* One-Shot Control */ - kHIDUsage_Csmr_ShowCounter = 0xC9, /* One-Shot Control */ - kHIDUsage_Csmr_TrackingIncrement = 0xCA, /* Re-Trigger Control */ - kHIDUsage_Csmr_TrackingDecrement = 0xCB, /* Re-Trigger Control */ - kHIDUsage_Csmr_StopOrEject = 0xCC, /* One-Shot Control */ - kHIDUsage_Csmr_PlayOrPause = 0xCD, /* One-Shot Control */ - kHIDUsage_Csmr_PlayOrSkip = 0xCE, /* One-Shot Control */ - /* 0xCF - 0xDF Reserved */ - kHIDUsage_Csmr_Volume = 0xE0, /* Linear Control */ - kHIDUsage_Csmr_Balance = 0xE1, /* Linear Control */ - kHIDUsage_Csmr_Mute = 0xE2, /* On/Off Control */ - kHIDUsage_Csmr_Bass = 0xE3, /* Linear Control */ - kHIDUsage_Csmr_Treble = 0xE4, /* Linear Control */ - kHIDUsage_Csmr_BassBoost = 0xE5, /* On/Off Control */ - kHIDUsage_Csmr_SurroundMode = 0xE6, /* One-Shot Control */ - kHIDUsage_Csmr_Loudness = 0xE7, /* On/Off Control */ - kHIDUsage_Csmr_MPX = 0xE8, /* On/Off Control */ - kHIDUsage_Csmr_VolumeIncrement = 0xE9, /* Re-Trigger Control */ - kHIDUsage_Csmr_VolumeDecrement = 0xEA, /* Re-Trigger Control */ - /* 0xEB - 0xEF Reserved */ - kHIDUsage_Csmr_Speed = 0xF0, /* Selector */ - kHIDUsage_Csmr_PlaybackSpeed = 0xF1, /* Named Array */ - kHIDUsage_Csmr_StandardPlay = 0xF2, /* Selector */ - kHIDUsage_Csmr_LongPlay = 0xF3, /* Selector */ - kHIDUsage_Csmr_ExtendedPlay = 0xF4, /* Selector */ - kHIDUsage_Csmr_Slow = 0xF5, /* One-Shot Control */ - /* 0xF6 - 0xFF Reserved */ - kHIDUsage_Csmr_FanEnable = 0x100, /* On/Off Control */ - kHIDUsage_Csmr_FanSpeed = 0x101, /* Linear Control */ - kHIDUsage_Csmr_LightEnable = 0x102, /* On/Off Control */ - kHIDUsage_Csmr_LightIlluminationLevel = 0x103, /* Linear Control */ - kHIDUsage_Csmr_ClimateControlEnable = 0x104, /* On/Off Control */ - kHIDUsage_Csmr_RoomTemperature = 0x105, /* Linear Control */ - kHIDUsage_Csmr_SecurityEnable = 0x106, /* On/Off Control */ - kHIDUsage_Csmr_FireAlarm = 0x107, /* One-Shot Control */ - kHIDUsage_Csmr_PoliceAlarm = 0x108, /* One-Shot Control */ - /* 0x109 - 0x14F Reserved */ - kHIDUsage_Csmr_BalanceRight = 0x150, /* Re-Trigger Control */ - kHIDUsage_Csmr_BalanceLeft = 0x151, /* Re-Trigger Control */ - kHIDUsage_Csmr_BassIncrement = 0x152, /* Re-Trigger Control */ - kHIDUsage_Csmr_BassDecrement = 0x153, /* Re-Trigger Control */ - kHIDUsage_Csmr_TrebleIncrement = 0x154, /* Re-Trigger Control */ - kHIDUsage_Csmr_TrebleDecrement = 0x155, /* Re-Trigger Control */ - /* 0x156 - 0x15F Reserved */ - kHIDUsage_Csmr_SpeakerSystem = 0x160, /* Logical Collection */ - kHIDUsage_Csmr_ChannelLeft = 0x161, /* Logical Collection */ - kHIDUsage_Csmr_ChannelRight = 0x162, /* Logical Collection */ - kHIDUsage_Csmr_ChannelCenter = 0x163, /* Logical Collection */ - kHIDUsage_Csmr_ChannelFront = 0x164, /* Logical Collection */ - kHIDUsage_Csmr_ChannelCenterFront = 0x165, /* Logical Collection */ - kHIDUsage_Csmr_ChannelSide = 0x166, /* Logical Collection */ - kHIDUsage_Csmr_ChannelSurround = 0x167, /* Logical Collection */ - kHIDUsage_Csmr_ChannelLowFrequencyEnhancement = 0x168, /* Logical Collection */ - kHIDUsage_Csmr_ChannelTop = 0x169, /* Logical Collection */ - kHIDUsage_Csmr_ChannelUnknown = 0x16A, /* Logical Collection */ - /* 0x16B - 0x16F Reserved */ - kHIDUsage_Csmr_SubChannel = 0x170, /* Linear Control */ - kHIDUsage_Csmr_SubChannelIncrement = 0x171, /* One-Shot Control */ - kHIDUsage_Csmr_SubChannelDecrement = 0x172, /* One-Shot Control */ - kHIDUsage_Csmr_AlternateAudioIncrement = 0x173, /* One-Shot Control */ - kHIDUsage_Csmr_AlternateAudioDecrement = 0x174, /* One-Shot Control */ - /* 0x175 - 0x17F Reserved */ - kHIDUsage_Csmr_ApplicationLaunchButtons = 0x180, /* Named Array */ - kHIDUsage_Csmr_ALLaunchButtonConfigurationTool = 0x181, /* Selector */ - kHIDUsage_Csmr_ALProgrammableButtonConfiguration = 0x182, /* Selector */ - kHIDUsage_Csmr_ALConsumerControlConfiguration = 0x183, /* Selector */ - kHIDUsage_Csmr_ALWordProcessor = 0x184, /* Selector */ - kHIDUsage_Csmr_ALTextEditor = 0x185, /* Selector */ - kHIDUsage_Csmr_ALSpreadsheet = 0x186, /* Selector */ - kHIDUsage_Csmr_ALGraphicsEditor = 0x187, /* Selector */ - kHIDUsage_Csmr_ALPresentationApp = 0x188, /* Selector */ - kHIDUsage_Csmr_ALDatabaseApp = 0x189, /* Selector */ - kHIDUsage_Csmr_ALEmailReader = 0x18A, /* Selector */ - kHIDUsage_Csmr_ALNewsreader = 0x18B, /* Selector */ - kHIDUsage_Csmr_ALVoicemail = 0x18C, /* Selector */ - kHIDUsage_Csmr_ALContactsOrAddressBook = 0x18D, /* Selector */ - kHIDUsage_Csmr_ALCalendarOrSchedule = 0x18E, /* Selector */ - kHIDUsage_Csmr_ALTaskOrProjectManager = 0x18F, /* Selector */ - kHIDUsage_Csmr_ALLogOrJournalOrTimecard = 0x190, /* Selector */ - kHIDUsage_Csmr_ALCheckbookOrFinance = 0x191, /* Selector */ - kHIDUsage_Csmr_ALCalculator = 0x192, /* Selector */ - kHIDUsage_Csmr_ALAOrVCaptureOrPlayback = 0x193, /* Selector */ - kHIDUsage_Csmr_ALLocalMachineBrowser = 0x194, /* Selector */ - kHIDUsage_Csmr_ALLANOrWANBrowser = 0x195, /* Selector */ - kHIDUsage_Csmr_ALInternetBrowser = 0x196, /* Selector */ - kHIDUsage_Csmr_ALRemoteNetworkingOrISPConnect = 0x197, /* Selector */ - kHIDUsage_Csmr_ALNetworkConference = 0x198, /* Selector */ - kHIDUsage_Csmr_ALNetworkChat = 0x199, /* Selector */ - kHIDUsage_Csmr_ALTelephonyOrDialer = 0x19A, /* Selector */ - kHIDUsage_Csmr_ALLogon = 0x19B, /* Selector */ - kHIDUsage_Csmr_ALLogoff = 0x19C, /* Selector */ - kHIDUsage_Csmr_ALLogonOrLogoff = 0x19D, /* Selector */ - kHIDUsage_Csmr_ALTerminalLockOrScreensaver = 0x19E, /* Selector */ - kHIDUsage_Csmr_ALControlPanel = 0x19F, /* Selector */ - kHIDUsage_Csmr_ALCommandLineProcessorOrRun = 0x1A0, /* Selector */ - kHIDUsage_Csmr_ALProcessOrTaskManager = 0x1A1, /* Selector */ - kHIDUsage_Csmr_AL = 0x1A2, /* Selector */ - kHIDUsage_Csmr_ALNextTaskOrApplication = 0x143, /* Selector */ - kHIDUsage_Csmr_ALPreviousTaskOrApplication = 0x1A4, /* Selector */ - kHIDUsage_Csmr_ALPreemptiveHaltTaskOrApplication = 0x1A5, /* Selector */ - /* 0x1A6 - 0x1FF Reserved */ - kHIDUsage_Csmr_GenericGUIApplicationControls = 0x200, /* Named Array */ - kHIDUsage_Csmr_ACNew = 0x201, /* Selector */ - kHIDUsage_Csmr_ACOpen = 0x202, /* Selector */ - kHIDUsage_Csmr_ACClose = 0x203, /* Selector */ - kHIDUsage_Csmr_ACExit = 0x204, /* Selector */ - kHIDUsage_Csmr_ACMaximize = 0x205, /* Selector */ - kHIDUsage_Csmr_ACMinimize = 0x206, /* Selector */ - kHIDUsage_Csmr_ACSave = 0x207, /* Selector */ - kHIDUsage_Csmr_ACPrint = 0x208, /* Selector */ - kHIDUsage_Csmr_ACProperties = 0x209, /* Selector */ - kHIDUsage_Csmr_ACUndo = 0x21A, /* Selector */ - kHIDUsage_Csmr_ACCopy = 0x21B, /* Selector */ - kHIDUsage_Csmr_ACCut = 0x21C, /* Selector */ - kHIDUsage_Csmr_ACPaste = 0x21D, /* Selector */ - kHIDUsage_Csmr_AC = 0x21E, /* Selector */ - kHIDUsage_Csmr_ACFind = 0x21F, /* Selector */ - kHIDUsage_Csmr_ACFindandReplace = 0x220, /* Selector */ - kHIDUsage_Csmr_ACSearch = 0x221, /* Selector */ - kHIDUsage_Csmr_ACGoTo = 0x222, /* Selector */ - kHIDUsage_Csmr_ACHome = 0x223, /* Selector */ - kHIDUsage_Csmr_ACBack = 0x224, /* Selector */ - kHIDUsage_Csmr_ACForward = 0x225, /* Selector */ - kHIDUsage_Csmr_ACStop = 0x226, /* Selector */ - kHIDUsage_Csmr_ACRefresh = 0x227, /* Selector */ - kHIDUsage_Csmr_ACPreviousLink = 0x228, /* Selector */ - kHIDUsage_Csmr_ACNextLink = 0x229, /* Selector */ - kHIDUsage_Csmr_ACBookmarks = 0x22A, /* Selector */ - kHIDUsage_Csmr_ACHistory = 0x22B, /* Selector */ - kHIDUsage_Csmr_ACSubscriptions = 0x22C, /* Selector */ - kHIDUsage_Csmr_ACZoomIn = 0x22D, /* Selector */ - kHIDUsage_Csmr_ACZoomOut = 0x22E, /* Selector */ - kHIDUsage_Csmr_ACZoom = 0x22F, /* Selector */ - kHIDUsage_Csmr_ACFullScreenView = 0x230, /* Selector */ - kHIDUsage_Csmr_ACNormalView = 0x231, /* Selector */ - kHIDUsage_Csmr_ACViewToggle = 0x232, /* Selector */ - kHIDUsage_Csmr_ACScrollUp = 0x233, /* Selector */ - kHIDUsage_Csmr_ACScrollDown = 0x234, /* Selector */ - kHIDUsage_Csmr_ACScroll = 0x235, /* Selector */ - kHIDUsage_Csmr_ACPanLeft = 0x236, /* Selector */ - kHIDUsage_Csmr_ACPanRight = 0x237, /* Selector */ - kHIDUsage_Csmr_ACPan = 0x238, /* Selector */ - kHIDUsage_Csmr_ACNewWindow = 0x239, /* Selector */ - kHIDUsage_Csmr_ACTileHorizontally = 0x23A, /* Selector */ - kHIDUsage_Csmr_ACTileVertically = 0x23B, /* Selector */ - kHIDUsage_Csmr_ACFormat = 0x23C, /* Selector */ - /* 0x23D - 0xFFFF Reserved */ - kHIDUsage_Csmr_Reserved = 0xFFFF, -}; - -/* Digitizer Page (0x0D) */ -/* This section provides detailed descriptions of the usages employed by Digitizer Devices. */ -enum -{ - kHIDUsage_Dig_Digitizer = 0x01, /* Application Collection */ - kHIDUsage_Dig_Pen = 0x02, /* Application Collection */ - kHIDUsage_Dig_LightPen = 0x03, /* Application Collection */ - kHIDUsage_Dig_TouchScreen = 0x04, /* Application Collection */ - kHIDUsage_Dig_TouchPad = 0x05, /* Application Collection */ - kHIDUsage_Dig_WhiteBoard = 0x06, /* Application Collection */ - kHIDUsage_Dig_CoordinateMeasuringMachine = 0x07, /* Application Collection */ - kHIDUsage_Dig_3DDigitizer = 0x08, /* Application Collection */ - kHIDUsage_Dig_StereoPlotter = 0x09, /* Application Collection */ - kHIDUsage_Dig_ArticulatedArm = 0x0A, /* Application Collection */ - kHIDUsage_Dig_Armature = 0x0B, /* Application Collection */ - kHIDUsage_Dig_MultiplePointDigitizer = 0x0C, /* Application Collection */ - kHIDUsage_Dig_FreeSpaceWand = 0x0D, /* Application Collection */ - /* 0x0E - 0x1F Reserved */ - kHIDUsage_Dig_Stylus = 0x20, /* Logical Collection */ - kHIDUsage_Dig_Puck = 0x21, /* Logical Collection */ - kHIDUsage_Dig_Finger = 0x22, /* Logical Collection */ - /* 0x23 - 0x2F Reserved */ - kHIDUsage_Dig_TipPressure = 0x30, /* Dynamic Value */ - kHIDUsage_Dig_BarrelPressure = 0x31, /* Dynamic Value */ - kHIDUsage_Dig_InRange = 0x32, /* Momentary Control */ - kHIDUsage_Dig_Touch = 0x33, /* Momentary Control */ - kHIDUsage_Dig_Untouch = 0x34, /* One-Shot Control */ - kHIDUsage_Dig_Tap = 0x35, /* One-Shot Control */ - kHIDUsage_Dig_Quality = 0x36, /* Dynamic Value */ - kHIDUsage_Dig_DataValid = 0x37, /* Momentary Control */ - kHIDUsage_Dig_TransducerIndex = 0x38, /* Dynamic Value */ - kHIDUsage_Dig_TabletFunctionKeys = 0x39, /* Logical Collection */ - kHIDUsage_Dig_ProgramChangeKeys = 0x3A, /* Logical Collection */ - kHIDUsage_Dig_BatteryStrength = 0x3B, /* Dynamic Value */ - kHIDUsage_Dig_Invert = 0x3C, /* Momentary Control */ - kHIDUsage_Dig_XTilt = 0x3D, /* Dynamic Value */ - kHIDUsage_Dig_YTilt = 0x3E, /* Dynamic Value */ - kHIDUsage_Dig_Azimuth = 0x3F, /* Dynamic Value */ - kHIDUsage_Dig_Altitude = 0x40, /* Dynamic Value */ - kHIDUsage_Dig_Twist = 0x41, /* Dynamic Value */ - kHIDUsage_Dig_TipSwitch = 0x42, /* Momentary Control */ - kHIDUsage_Dig_SecondaryTipSwitch = 0x43, /* Momentary Control */ - kHIDUsage_Dig_BarrelSwitch = 0x44, /* Momentary Control */ - kHIDUsage_Dig_Eraser = 0x45, /* Momentary Control */ - kHIDUsage_Dig_TabletPick = 0x46, /* Momentary Control */ - /* 0x47 - 0xFFFF Reserved */ - kHIDUsage_Dig_Reserved = 0xFFFF, -}; - -/* AlphanumericDisplay Page (0x14) */ -/* The Alphanumeric Display page is intended for use by simple alphanumeric displays that are used on consumer devices. */ -enum -{ - kHIDUsage_AD_AlphanumericDisplay = 0x01, /* Application Collection */ - /* 0x02 - 0x1F Reserved */ - kHIDUsage_AD_DisplayAttributesReport = 0x20, /* Logical Collection */ - kHIDUsage_AD_ASCIICharacterSet = 0x21, /* Static Flag */ - kHIDUsage_AD_DataReadBack = 0x22, /* Static Flag */ - kHIDUsage_AD_FontReadBack = 0x23, /* Static Flag */ - kHIDUsage_AD_DisplayControlReport = 0x24, /* Logical Collection */ - kHIDUsage_AD_ClearDisplay = 0x25, /* Dynamic Flag */ - kHIDUsage_AD_DisplayEnable = 0x26, /* Dynamic Flag */ - kHIDUsage_AD_ScreenSaverDelay = 0x27, /* Static Value */ - kHIDUsage_AD_ScreenSaverEnable = 0x28, /* Dynamic Flag */ - kHIDUsage_AD_VerticalScroll = 0x29, /* Static Flag */ - kHIDUsage_AD_HorizontalScroll = 0x2A, /* Static Flag */ - kHIDUsage_AD_CharacterReport = 0x2B, /* Logical Collection */ - kHIDUsage_AD_DisplayData = 0x2C, /* Dynamic Value */ - kHIDUsage_AD_DisplayStatus = 0x2D, /* Logical Collection */ - kHIDUsage_AD_StatNotReady = 0x2E, /* Selector */ - kHIDUsage_AD_StatReady = 0x2F, /* Selector */ - kHIDUsage_AD_ErrNotaloadablecharacter = 0x30, /* Selector */ - kHIDUsage_AD_ErrFontdatacannotberead = 0x31, /* Selector */ - kHIDUsage_AD_CursorPositionReport = 0x32, /* Logical Collection */ - kHIDUsage_AD_Row = 0x33, /* Dynamic Value */ - kHIDUsage_AD_Column = 0x34, /* Dynamic Value */ - kHIDUsage_AD_Rows = 0x35, /* Static Value */ - kHIDUsage_AD_Columns = 0x36, /* Static Value */ - kHIDUsage_AD_CursorPixelPositioning = 0x37, /* Static Flag */ - kHIDUsage_AD_CursorMode = 0x38, /* Dynamic Flag */ - kHIDUsage_AD_CursorEnable = 0x39, /* Dynamic Flag */ - kHIDUsage_AD_CursorBlink = 0x3A, /* Dynamic Flag */ - kHIDUsage_AD_FontReport = 0x3B, /* Logical Collection */ - kHIDUsage_AD_FontData = 0x3C, /* Buffered Byte */ - kHIDUsage_AD_CharacterWidth = 0x3D, /* Static Value */ - kHIDUsage_AD_CharacterHeight = 0x3E, /* Static Value */ - kHIDUsage_AD_CharacterSpacingHorizontal = 0x3F, /* Static Value */ - kHIDUsage_AD_CharacterSpacingVertical = 0x40, /* Static Value */ - kHIDUsage_AD_UnicodeCharacterSet = 0x41, /* Static Flag */ - /* 0x42 - 0xFFFF Reserved */ - kHIDUsage_AD_Reserved = 0xFFFF, -}; - -#endif /* _IOHIDUSAGETABLES_H */ diff --git a/iokit/IOKit/hidsystem/IOHIDevice.h b/iokit/IOKit/hidsystem/IOHIDevice.h deleted file mode 100644 index 3214a0cae..000000000 --- a/iokit/IOKit/hidsystem/IOHIDevice.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * IOHIDevice.h - Common Event Source object class. - * - * HISTORY - * 22 May 1992 Mike Paquette at NeXT - * Created. - * 4 Aug 1993 Erik Kay at NeXT - * API cleanup - * 5 Aug 1993 Erik Kay at NeXT - * added ivar space for future expansion - */ - -#ifndef _IOHIDEVICE_H -#define _IOHIDEVICE_H - -#include <IOKit/IOService.h> -#include <IOKit/IOLocks.h> - -typedef enum { - kHIUnknownDevice = 0, - kHIKeyboardDevice = 1, - kHIRelativePointingDevice = 2 -} IOHIDKind; - -class IOHIDevice : public IOService -{ - OSDeclareDefaultStructors(IOHIDevice); - -public: - virtual bool init(OSDictionary * properties = 0); - virtual void free(); - - virtual UInt32 deviceType(); - virtual IOHIDKind hidKind(); - virtual UInt32 interfaceID(); - virtual bool updateProperties(void); - virtual IOReturn setParamProperties(OSDictionary * dict); - virtual UInt64 getGUID(); -}; - -#endif /* !_IOHIDEVICE_H */ diff --git a/iokit/IOKit/hidsystem/IOHIKeyboard.h b/iokit/IOKit/hidsystem/IOHIKeyboard.h deleted file mode 100644 index 65972a0c5..000000000 --- a/iokit/IOKit/hidsystem/IOHIKeyboard.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * EventSrcPCKeyboard.h - PC Keyboard EventSrc subclass definition - * - * HISTORY - * 28 Aug 1992 Joe Pasqua - * Created. - */ - -#ifndef _IOHIKEYBOARD_H -#define _IOHIKEYBOARD_H - -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHIKeyboardMapper.h> - -/* Start Action Definitions */ - -/* - * HISTORICAL NOTE: - * The following entry points were part of the IOHIKeyboardEvents - * protocol. - */ - -typedef void (*KeyboardEventAction)( OSObject * target, - /* eventFlags */ unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - -typedef void (*KeyboardSpecialEventAction)(OSObject * target, - /* eventType */ unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* specialty */ unsigned flavor, - /* source id */ UInt64 guid, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - -typedef void (*UpdateEventFlagsAction)( OSObject * target, - /* flags */ unsigned flags); - -/* End Action Definitions */ - - - -/* Default key repeat parameters */ -#define EV_DEFAULTINITIALREPEAT 500000000ULL // 1/2 sec in nanoseconds -#define EV_DEFAULTKEYREPEAT 83333333ULL // 1/12 sec in nanoseconds -#define EV_MINKEYREPEAT 16700000ULL // 1/60 sec - -class IOHIKeyboard : public IOHIDevice -{ - OSDeclareDefaultStructors(IOHIKeyboard); - -protected: - IOLock * _deviceLock; // Lock for all device access - IOHIKeyboardMapper * _keyMap; // KeyMap instance - - // The following fields describe the kind of keyboard - UInt32 _interfaceType; - UInt32 _deviceType; - - // The following fields describe the state of the keyboard - UInt32 * _keyState; // kbdBitVector - IOByteCount _keyStateSize; // kbdBitVector allocated size - unsigned _eventFlags; // Current eventFlags - bool _alphaLock; // true means alpha lock is on - bool _numLock; // true means num lock is on - bool _charKeyActive; // true means char gen. key active - - // The following fields are used in performing key repeats - bool _isRepeat; // true means we're generating repeat - unsigned _codeToRepeat; // What we are repeating - bool _calloutPending; // true means we've sched. a callout - AbsoluteTime _lastEventTime; // Time last event was dispatched - AbsoluteTime _downRepeatTime; // Time when we should next repeat - AbsoluteTime _keyRepeat; // Delay between key repeats - AbsoluteTime _initialKeyRepeat; // Delay before initial key repeat - UInt64 _guid; - - OSObject * _keyboardEventTarget; - KeyboardEventAction _keyboardEventAction; - OSObject * _keyboardSpecialEventTarget; - KeyboardSpecialEventAction _keyboardSpecialEventAction; - OSObject * _updateEventFlagsTarget; - UpdateEventFlagsAction _updateEventFlagsAction; - -protected: - virtual void dispatchKeyboardEvent(unsigned int keyCode, - /* direction */ bool goingDown, - /* timeStamp */ AbsoluteTime time); - -public: - virtual bool init(OSDictionary * properties = 0); - virtual bool start(IOService * provider); - virtual void free(); - - virtual bool open(IOService * client, - IOOptionBits options, - KeyboardEventAction keAction, - KeyboardSpecialEventAction kseAction, - UpdateEventFlagsAction uefAction); - virtual void close(IOService * client, IOOptionBits ); - - virtual IOHIDKind hidKind(); - virtual bool updateProperties( void ); - virtual IOReturn setParamProperties(OSDictionary * dict); - -protected: // for subclasses to implement - virtual const unsigned char * defaultKeymapOfLength(UInt32 * length); - virtual void setAlphaLockFeedback(bool val); - virtual void setNumLockFeedback(bool val); - virtual UInt32 maxKeyCodes(); - - -private: - virtual bool resetKeyboard(); - virtual void scheduleAutoRepeat(); - static void _autoRepeat(void * arg, void *); - virtual void autoRepeat(); - virtual void setRepeat(unsigned eventType, unsigned keyCode); - -/* - * HISTORICAL NOTE: - * The following methods were part of the KeyMapDelegate protocol; - * the declarations have now been merged directly into this class. - */ - -public: - virtual void keyboardEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned keyCode, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet); - - virtual void keyboardSpecialEvent(unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned keyCode, - /* specialty */ unsigned flavor); - - virtual void updateEventFlags(unsigned flags); // Does not generate events - - virtual unsigned eventFlags(); // Global event flags - virtual unsigned deviceFlags(); // per-device event flags - virtual void setDeviceFlags(unsigned flags); // Set device event flags - virtual bool alphaLock(); // current alpha-lock state - virtual void setAlphaLock(bool val); // Set current alpha-lock state - virtual bool numLock(); - virtual void setNumLock(bool val); - virtual bool charKeyActive(); // Is a character gen. key down? - virtual void setCharKeyActive(bool val); // Note that a char gen key is down. - virtual bool doesKeyLock(unsigned key); //does key lock physically - virtual unsigned getLEDStatus(); //check hardware for LED status - - -}; - -#endif /* !_IOHIKEYBOARD_H */ diff --git a/iokit/IOKit/hidsystem/IOHIKeyboardMapper.h b/iokit/IOKit/hidsystem/IOHIKeyboardMapper.h deleted file mode 100644 index d5b25859f..000000000 --- a/iokit/IOKit/hidsystem/IOHIKeyboardMapper.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOHIKEYBOARDMAPPER_H -#define _IOHIKEYBOARDMAPPER_H - -#include <IOKit/hidsystem/ev_keymap.h> - -class IOHIKeyboard; - -/* - * Key ip/down state is tracked in a bit list. Bits are set - * for key-down, and cleared for key-up. The bit vector and macros - * for it's manipulation are defined here. - */ - -typedef UInt32 * kbdBitVector; - -#define EVK_BITS_PER_UNIT 32 -#define EVK_BITS_MASK 31 -#define EVK_BITS_SHIFT 5 // 1<<5 == 32, for cheap divide - -#define EVK_KEYDOWN(n, bits) \ - (bits)[((n)>>EVK_BITS_SHIFT)] |= (1 << ((n) & EVK_BITS_MASK)) - -#define EVK_KEYUP(n, bits) \ - (bits)[((n)>>EVK_BITS_SHIFT)] &= ~(1 << ((n) & EVK_BITS_MASK)) - -#define EVK_IS_KEYDOWN(n, bits) \ - (((bits)[((n)>>EVK_BITS_SHIFT)] & (1 << ((n) & EVK_BITS_MASK))) != 0) - -class IOHIKeyboardMapper : public OSObject -{ - OSDeclareDefaultStructors(IOHIKeyboardMapper); - -private: - IOHIKeyboard * _delegate; // KeyMap delegate - bool _mappingShouldBeFreed; // true if map can be IOFree'd - NXParsedKeyMapping _parsedMapping; // current system-wide keymap - -public: - static IOHIKeyboardMapper * keyboardMapper( - IOHIKeyboard * delegate, - const UInt8 * mapping, - UInt32 mappingLength, - bool mappingShouldBeFreed ); - - virtual bool init(IOHIKeyboard * delegate, - const UInt8 * mapping, - UInt32 mappingLength, - bool mappingShouldBeFreed); - virtual void free(); - - virtual const UInt8 * mapping(); - virtual UInt32 mappingLength(); - virtual bool serialize(OSSerialize *s) const; - - virtual void translateKeyCode(UInt8 key, bool keyDown, kbdBitVector keyBits); - virtual UInt8 getParsedSpecialKey(UInt8 logical); //retrieve a key from _parsedMapping - - -private: - virtual bool parseKeyMapping(const UInt8 * mapping, - UInt32 mappingLength, - NXParsedKeyMapping * parsedMapping) const; - - virtual void calcModBit(int bit, kbdBitVector keyBits); - virtual void doModCalc(int key, kbdBitVector keyBits); - virtual void doCharGen(int keyCode, bool down); -}; - -#endif _IOHIKEYBOARDMAPPER_H - -/* - * HISTORICAL NOTE: - * The "delegate" object had to respond to the following protocol; - * this protocol has since been merged into the IOHIKeyboard class. - * - * @protocol KeyMapDelegate - * - * - keyboardEvent :(unsigned)eventType - * flags :(unsigned)flags - * keyCode :(unsigned)keyCode - * charCode:(unsigned)charCode - * charSet :(unsigned)charSet - * originalCharCode:(unsigned)origCharCode - * originalCharSet:(unsigned)origCharSet; - * - * - keyboardSpecialEvent:(unsigned)eventType - * flags :(unsigned)flags - * keyCode :(unsigned)keyCode - * specialty:(unsigned)flavor; - * - * - updateEventFlags:(unsigned)flags; // Does not generate events - * - * - (unsigned)eventFlags; // Global event flags - * - (unsigned)deviceFlags; // per-device event flags - * - setDeviceFlags:(unsigned)flags; // Set device event flags - * - (bool)alphaLock; // current alpha-lock state - * - setAlphaLock:(bool)val; // Set current alpha-lock state - * - (bool)charKeyActive; // Is a character gen. key down? - * - setCharKeyActive:(bool)val; // Note that a char gen key is down. - * - * @end - */ diff --git a/iokit/IOKit/hidsystem/IOHIPointing.h b/iokit/IOKit/hidsystem/IOHIPointing.h deleted file mode 100644 index 37b692add..000000000 --- a/iokit/IOKit/hidsystem/IOHIPointing.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOHIPOINTING_H -#define _IOHIPOINTING_H - -#include <IOKit/hidsystem/IOHIPointing.h> -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHIDTypes.h> - -/* Start Action Definitions */ - -/* - * HISTORICAL NOTE: - * The following entry points were part of the IOHIPointingEvents - * protocol. - */ -typedef void (*RelativePointerEventAction)(OSObject * target, - /* buttons */ int buttons, - /* deltaX */ int dx, - /* deltaY */ int dy, - /* atTime */ AbsoluteTime ts); - -typedef void (*AbsolutePointerEventAction)(OSObject * target, - /* buttons */ int buttons, - /* at */ Point * newLoc, - /* withBounds */ Bounds * bounds, - /* inProximity */ bool proximity, - /* withPressure */ int pressure, - /* withAngle */ int stylusAngle, - /* atTime */ AbsoluteTime ts); - -typedef void (*ScrollWheelEventAction)(OSObject * target, - short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - AbsoluteTime ts); - -/* End Action Definitions */ - -class IOHIPointing : public IOHIDevice -{ - OSDeclareDefaultStructors(IOHIPointing); - -private: - IOLock * _deviceLock; // Lock for all device access - int _buttonMode; // The "handedness" of the pointer - IOFixed _acceleration; - bool _convertAbsoluteToRelative; - bool _contactToMove; - bool _hadContact; - Point _previousLocation; - UInt8 _pressureThresholdToClick; // A scale factor of 0 to 255 to determine how much pressure is necessary to generate a primary mouse click - a value of 255 means no click will be generated - void * _scaleSegments; - IOItemCount _scaleSegCount; - IOFixed _fractX; - IOFixed _fractY; - - OSObject * _relativePointerEventTarget; - RelativePointerEventAction _relativePointerEventAction; - OSObject * _absolutePointerEventTarget; - AbsolutePointerEventAction _absolutePointerEventAction; - OSObject * _scrollWheelEventTarget; - ScrollWheelEventAction _scrollWheelEventAction; - - -protected: - virtual void dispatchRelativePointerEvent(int dx, - int dy, - UInt32 buttonState, - AbsoluteTime ts); - - virtual void dispatchAbsolutePointerEvent(Point * newLoc, - Bounds * bounds, - UInt32 buttonState, - bool proximity, - int pressure, - int pressureMin, - int pressureMax, - int stylusAngle, - AbsoluteTime ts); - - virtual void dispatchScrollWheelEvent(short deltaAxis1, - short deltaAxis2, - short deltaAxis3, - AbsoluteTime ts); - -public: - virtual bool init(OSDictionary * properties = 0); - virtual bool start(IOService * provider); - virtual void free(); - - virtual bool open(IOService * client, - IOOptionBits options, - RelativePointerEventAction rpeAction, - AbsolutePointerEventAction apeAction, - ScrollWheelEventAction sweAction); - virtual void close(IOService * client, IOOptionBits ); - - virtual IOHIDKind hidKind(); - virtual bool updateProperties( void ); - virtual IOReturn setParamProperties(OSDictionary * dict); - IOReturn powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService*); - IOReturn powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService*); - IOService * _rootDomain; //Needs to be public for C function use - - -protected: // for subclasses to implement - virtual OSData * copyAccelerationTable(); - virtual IOItemCount buttonCount(); - virtual IOFixed resolution(); - -private: - virtual bool resetPointer(); - virtual void scalePointer(int * dxp, int * dyp); - virtual void setupForAcceleration(IOFixed accl); -}; - -#endif /* !_IOHIPOINTING_H */ diff --git a/iokit/IOKit/hidsystem/IOHITablet.h b/iokit/IOKit/hidsystem/IOHITablet.h deleted file mode 100644 index 6571127d6..000000000 --- a/iokit/IOKit/hidsystem/IOHITablet.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOHITABLET_H -#define _IOHITABLET_H - -#include <IOKit/hidsystem/IOHIPointing.h> -#include <IOKit/hidsystem/IOLLEvent.h> - -class IOHITabletPointer; - -#define kIOHIVendorID "VendorID" -#define kIOHISystemTabletID "SystemTabletID" -#define kIOHIVendorTabletID "VendorTabletID" - -typedef void (*TabletEventAction)(OSObject *target, - NXEventData *tabletData, // Do we want to parameterize this? - AbsoluteTime ts); - -typedef void (*ProximityEventAction)(OSObject *target, - NXEventData *proximityData, // or this? - AbsoluteTime ts); - -class IOHITablet : public IOHIPointing -{ - OSDeclareDefaultStructors(IOHITablet); - -public: - UInt16 _systemTabletID; - -private: - OSObject * _tabletEventTarget; - TabletEventAction _tabletEventAction; - OSObject * _proximityEventTarget; - ProximityEventAction _proximityEventAction; - -protected: - virtual void dispatchTabletEvent(NXEventData *tabletEvent, - AbsoluteTime ts); - - virtual void dispatchProximityEvent(NXEventData *proximityEvent, - AbsoluteTime ts); - - virtual bool startTabletPointer(IOHITabletPointer *pointer, OSDictionary *properties); - -public: - static UInt16 generateTabletID(); - - virtual bool init(OSDictionary * propTable); - virtual bool open(IOService * client, - IOOptionBits options, - RelativePointerEventAction rpeAction, - AbsolutePointerEventAction apeAction, - ScrollWheelEventAction sweAction, - TabletEventAction tabletAction, - ProximityEventAction proximityAction); - -}; - -#endif /* !_IOHITABLET_H */ diff --git a/iokit/IOKit/hidsystem/IOHITabletPointer.h b/iokit/IOKit/hidsystem/IOHITabletPointer.h deleted file mode 100644 index 4448bd590..000000000 --- a/iokit/IOKit/hidsystem/IOHITabletPointer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOHITABLETPOINTER_H -#define _IOHITABLETPOINTER_H - -#include <IOKit/hidsystem/IOHIDevice.h> -#include <IOKit/hidsystem/IOHITablet.h> -#include <IOKit/hidsystem/IOLLEvent.h> - -#define kIOHITabletPointerID "PointerID" -#define kIOHITabletPointerDeviceID "DeviceID" -#define kIOHITabletPointerVendorType "VendorPointerType" -#define kIOHITabletPointerType "PointerType" -#define kIOHITabletPointerSerialNumber "SerialNumber" -#define kIOHITabletPointerUniqueID "UniqueID" - -class IOHITabletPointer : public IOHIDevice -{ - OSDeclareDefaultStructors(IOHITabletPointer); - -public: - IOHITablet *_tablet; - UInt16 _deviceID; - - static UInt16 generateDeviceID(); - - virtual bool init(OSDictionary *propTable); - virtual bool attach(IOService *provider); - - virtual void dispatchTabletEvent(NXEventData *tabletEvent, - AbsoluteTime ts); - virtual void dispatchProximityEvent(NXEventData *proximityEvent, - AbsoluteTime ts); -}; - -#endif /* !_IOHITABLETPOINTER_H */ diff --git a/iokit/IOKit/hidsystem/IOLLEvent.h b/iokit/IOKit/hidsystem/IOLLEvent.h deleted file mode 100644 index 9d6185bcf..000000000 --- a/iokit/IOKit/hidsystem/IOLLEvent.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/****************************************************************************** - event.h (PostScript side version) - - CONFIDENTIAL - Copyright (c) 1988 NeXT, Inc. as an unpublished work. - All Rights Reserved. - - Created Leo 01Mar88 - - Modified: - 04May88 Leo Final event types and record - 22Aug88 Leo Change short -> int for window, add reserved - 26May90 Ted Added NX_UNDIMMASK to correct triggering of UndoAutoDim - 12Dec91 Mike Brought into sync with dpsclient/event.h, and fixed - the #ifndef interlock with dpsclient/event.h that was - broken during the Great Header Revision. - - The PostScript version of this file differs from the - Window Kit version in that the coordinates here are - ints instead of floats. -******************************************************************************/ - -#ifndef _DEV_EVENT_H -#define _DEV_EVENT_H - -#include <libkern/OSTypes.h> -#include <IOKit/hidsystem/IOHIDTypes.h> - -#ifdef EVENT_H /* Interlock with dpsclient/event.h */ -#if !defined(_NXSIZE_) /* Work around patch for old event.h in Phase 3 projs*/ -#define _NXSIZE_ 1 /* NXCoord, NXPoint, NXSize decl seen */ -#define _NXSize_ NXSize -#endif /* _NXSIZE_ */ -#else /* EVENT_H */ /* Haven't seen dpsclient/event.h, so define away */ -#define EVENT_H - -#ifdef KERNEL -#else /* KERNEL */ - -#if !defined(_NXSIZE_) /* Work around patch for old event.h in Phase 3 projs*/ -#define _NXSIZE_ 1 /* NXCoord, NXPoint, NXSize decl seen */ -typedef float NXCoord; - -typedef struct _NXPoint { /* point */ - NXCoord x, y; -} NXPoint; - -typedef struct _NXSize { /* size */ - NXCoord width, height; -} NXSize; -#define _NXSize_ NXSize /* Correct usage in event_status_driver.h */ -#endif /* _NXSIZE_ */ - -#endif /* KERNEL */ - -/* Event types */ - -#define NX_NULLEVENT 0 /* internal use */ - -/* mouse events */ - -#define NX_LMOUSEDOWN 1 /* left mouse-down event */ -#define NX_LMOUSEUP 2 /* left mouse-up event */ -#define NX_RMOUSEDOWN 3 /* right mouse-down event */ -#define NX_RMOUSEUP 4 /* right mouse-up event */ -#define NX_MOUSEMOVED 5 /* mouse-moved event */ -#define NX_LMOUSEDRAGGED 6 /* left mouse-dragged event */ -#define NX_RMOUSEDRAGGED 7 /* right mouse-dragged event */ -#define NX_MOUSEENTERED 8 /* mouse-entered event */ -#define NX_MOUSEEXITED 9 /* mouse-exited event */ - -/* keyboard events */ - -#define NX_KEYDOWN 10 /* key-down event */ -#define NX_KEYUP 11 /* key-up event */ -#define NX_FLAGSCHANGED 12 /* flags-changed event */ - -/* composite events */ - -#define NX_KITDEFINED 13 /* application-kit-defined event */ -#define NX_SYSDEFINED 14 /* system-defined event */ -#define NX_APPDEFINED 15 /* application-defined event */ -/* There are additional DPS client defined events past this point. */ - -/* Scroll wheel events */ - -#define NX_SCROLLWHEELMOVED 22 - -/* tablet events */ - -#define NX_TABLETPOINTER 23 -#define NX_TABLETPROXIMITY 24 - -#define NX_FIRSTEVENT 0 -#define NX_LASTEVENT 24 -#define NX_NUMPROCS (NX_LASTEVENT-NX_FIRSTEVENT+1) - -/* Event masks */ - -#define NX_LMOUSEDOWNMASK (1 << NX_LMOUSEDOWN) /* left mouse-down */ -#define NX_LMOUSEUPMASK (1 << NX_LMOUSEUP) /* left mouse-up */ -#define NX_RMOUSEDOWNMASK (1 << NX_RMOUSEDOWN) /* right mouse-down */ -#define NX_RMOUSEUPMASK (1 << NX_RMOUSEUP) /* right mouse-up */ -#define NX_MOUSEMOVEDMASK (1 << NX_MOUSEMOVED) /* mouse-moved */ -#define NX_LMOUSEDRAGGEDMASK (1 << NX_LMOUSEDRAGGED) /* left-dragged */ -#define NX_RMOUSEDRAGGEDMASK (1 << NX_RMOUSEDRAGGED) /* right-dragged */ -#define NX_MOUSEENTEREDMASK (1 << NX_MOUSEENTERED) /* mouse-entered */ -#define NX_MOUSEEXITEDMASK (1 << NX_MOUSEEXITED) /* mouse-exited */ -#define NX_KEYDOWNMASK (1 << NX_KEYDOWN) /* key-down */ -#define NX_KEYUPMASK (1 << NX_KEYUP) /* key-up */ -#define NX_FLAGSCHANGEDMASK (1 << NX_FLAGSCHANGED) /* flags-changed */ -#define NX_KITDEFINEDMASK (1 << NX_WINCHANGED) /* kit-defined */ -#define NX_SYSDEFINEDMASK (1 << NX_SYSDEFINED) /* system-defined */ -#define NX_APPDEFINEDMASK (1 << NX_APPDEFINED) /* app-defined */ -#define NX_SCROLLWHEELMOVEDMASK (1 << NX_SCROLLWHEELMOVED) /* scroll wheel moved */ -#define NX_TABLETPOINTERMASK (1 << NX_TABLETPOINTER) /* tablet pointer moved */ -#define NX_TABLETPROXIMITYMASK (1 << NX_TABLETPROXIMITY) /* tablet pointer proximity */ - -#define EventCodeMask(type) (1 << (type)) -#define NX_ALLEVENTS -1 /* Check for all events */ - -/* sub types for system defined events */ - -#define NX_SUBTYPE_POWER_KEY 1 -#define NX_SUBTYPE_AUX_MOUSE_BUTTONS 7 -#define NX_SUBTYPE_AUX_CONTROL_BUTTONS 8 - -#define NX_SUBTYPE_EJECT_KEY 10 -#define NX_SUBTYPE_SLEEP_EVENT 11 -#define NX_SUBTYPE_RESTART_EVENT 12 -#define NX_SUBTYPE_SHUTDOWN_EVENT 13 - -/* Masks for the bits in event.flags */ - -/* device-independent */ - -#define NX_ALPHASHIFTMASK 0x00010000 -#define NX_SHIFTMASK 0x00020000 -#define NX_CONTROLMASK 0x00040000 -#define NX_ALTERNATEMASK 0x00080000 -#define NX_COMMANDMASK 0x00100000 -#define NX_NUMERICPADMASK 0x00200000 -#define NX_HELPMASK 0x00400000 -#define NX_SECONDARYFNMASK 0x00800000 - -/* device-dependent (really?) */ - -//#define NX_NEXTCTLKEYMASK 0x00000001 -//#define NX_NEXTLSHIFTKEYMASK 0x00000002 -//#define NX_NEXTRSHIFTKEYMASK 0x00000004 -//#define NX_NEXTLCMDKEYMASK 0x00000008 -//#define NX_NEXTRCMDKEYMASK 0x00000010 -//#define NX_NEXTLALTKEYMASK 0x00000020 -//#define NX_NEXTRALTKEYMASK 0x00000040 - -/* - * Additional reserved bits in event.flags - */ - -#define NX_STYLUSPROXIMITYMASK 0x00000080 -#define NX_NONCOALSESCEDMASK 0x00000100 - -/* click state values - * If you have the following events in close succession, the click - * field has the indicated value: - * - * Event Click Value Comments - * mouse-down 1 Not part of any click yet - * mouse-up 1 Aha! A click! - * mouse-down 2 Doing a double-click - * mouse-up 2 It's finished - * mouse-down 3 A triple - * mouse-up 3 - */ - -/* Values for the character set in event.data.key.charSet */ - -#define NX_ASCIISET 0 -#define NX_SYMBOLSET 1 -#define NX_DINGBATSSET 2 - -/* EventData type: defines the data field of an event */ - -typedef union { - struct { /* For mouse-down and mouse-up events */ - unsigned char subx; /* sub-pixel position for x */ - unsigned char suby; /* sub-pixel position for y */ - short eventNum; /* unique identifier for this button */ - int click; /* click state of this event */ - unsigned char pressure; /* pressure value: 0=none, 255=full */ - char reserved1; - short reserved2; - int reserved3; - int reserved4; - int reserved5; - int reserved6; - int reserved7; - } mouse; - struct { - int dx; - int dy; - int reserved1; - int reserved2; - int reserved3; - int reserved4; - int reserved5; - int reserved6; - } mouseMove; - struct { /* For key-down and key-up events */ - unsigned short origCharSet; /* unmodified character set code */ - short repeat; /* for key-down: nonzero if really a repeat */ - unsigned short charSet; /* character set code */ - unsigned short charCode; /* character code in that set */ - unsigned short keyCode; /* device-dependent key number */ - unsigned short origCharCode; /* unmodified character code */ - int reserved1; - unsigned int keyboardType; - int reserved2; - int reserved3; - int reserved4; - } key; - struct { /* For mouse-entered and mouse-exited events */ - short reserved; - short eventNum; /* unique identifier from mouse down event */ - int trackingNum; /* unique identifier from settrackingrect */ - int userData; /* uninterpreted integer from settrackingrect */ - int reserved1; - int reserved2; - int reserved3; - int reserved4; - int reserved5; - } tracking; - struct { - short deltaAxis1; - short deltaAxis2; - short deltaAxis3; - short reserved1; - int reserved2; - int reserved3; - int reserved4; - int reserved5; - int reserved6; - int reserved7; - } scrollWheel; - struct { /* For window-changed, sys-defined, and app-defined events */ - short reserved; - short subType; /* event subtype for compound events */ - union { - float F[7]; /* for use in compound events */ - long L[7]; /* for use in compound events */ - short S[14]; /* for use in compound events */ - char C[28]; /* for use in compound events */ - } misc; - } compound; - struct { - SInt32 x; /* absolute x coordinate in tablet space at full tablet resolution */ - SInt32 y; /* absolute y coordinate in tablet space at full tablet resolution */ - SInt32 z; /* absolute z coordinate in tablet space at full tablet resolution */ - UInt16 buttons; /* one bit per button - bit 0 is first button - 1 = closed */ - UInt16 pressure; /* scaled pressure value; MAXPRESSURE=(2^16)-1, MINPRESSURE=0 */ - struct { - SInt16 x; /* scaled tilt x value; range is -((2^15)-1) to (2^15)-1 (-32767 to 32767) */ - SInt16 y; /* scaled tilt y value; range is -((2^15)-1) to (2^15)-1 (-32767 to 32767) */ - } tilt; - UInt16 rotation; /* Fixed-point representation of device rotation in a 10.6 format */ - SInt16 tangentialPressure; /* tangential pressure on the device; range same as tilt */ - UInt16 deviceID; /* system-assigned unique device ID - matches to deviceID field in proximity event */ - SInt16 vendor1; /* vendor-defined signed 16-bit integer */ - SInt16 vendor2; /* vendor-defined signed 16-bit integer */ - SInt16 vendor3; /* vendor-defined signed 16-bit integer */ - } tablet; - struct { - UInt16 vendorID; /* vendor-defined ID - typically will be USB vendor ID */ - UInt16 tabletID; /* vendor-defined tablet ID - typically will be USB product ID for the tablet */ - UInt16 pointerID; /* vendor-defined ID of the specific pointing device */ - UInt16 deviceID; /* system-assigned unique device ID - matches to deviceID field in tablet event */ - UInt16 systemTabletID; /* system-assigned unique tablet ID */ - UInt16 vendorPointerType; /* vendor-defined pointer type */ - UInt32 pointerSerialNumber; /* vendor-defined serial number of the specific pointing device */ - UInt64 uniqueID; /* vendor-defined unique ID for this pointer */ - UInt32 capabilityMask; /* mask representing the capabilities of the device */ - UInt8 pointerType; /* type of pointing device - enum to be defined */ - UInt8 enterProximity; /* non-zero = entering; zero = leaving */ - SInt16 reserved1; - } proximity; -} NXEventData; - -/* Finally! The event record! */ -typedef struct _NXEvent { - int type; /* An event type from above */ - struct { - int x, y; /* Base coordinates in window, */ - } location; /* from bottom left */ - unsigned long long time; /* time since launch */ - int flags; /* key state flags */ - unsigned int window; /* window number of assigned window */ - NXEventData data; /* type-dependent data */ -} NXEvent, *NXEventPtr; - - -/* How to pick window(s) for event (for PostEvent) */ -#define NX_NOWINDOW -1 -#define NX_BYTYPE 0 -#define NX_BROADCAST 1 -#define NX_TOPWINDOW 2 -#define NX_FIRSTWINDOW 3 -#define NX_MOUSEWINDOW 4 -#define NX_NEXTWINDOW 5 -#define NX_LASTLEFT 6 -#define NX_LASTRIGHT 7 -#define NX_LASTKEY 8 -#define NX_EXPLICIT 9 -#define NX_TRANSMIT 10 -#define NX_BYPSCONTEXT 11 - -#endif /* EVENT_H */ /* End of defs common with dpsclient/event.h */ - -/* Mask of events that cause screen to undim */ - -#define NX_UNDIMMASK (NX_KEYDOWNMASK | NX_KEYUPMASK | \ - NX_LMOUSEDOWNMASK | NX_LMOUSEUPMASK | \ - NX_RMOUSEDOWNMASK | NX_RMOUSEUPMASK | \ - NX_MOUSEMOVEDMASK | NX_FLAGSCHANGEDMASK | \ - NX_MOUSEENTEREDMASK | NX_MOUSEEXITEDMASK | \ - NX_LMOUSEDRAGGEDMASK | NX_RMOUSEDRAGGEDMASK | \ - NX_SCROLLWHEELMOVEDMASK | NX_TABLETPOINTERMASK | \ - NX_TABLETPROXIMITYMASK) - -#endif /* !_DEV_EVENT_H */ - diff --git a/iokit/IOKit/hidsystem/Makefile b/iokit/IOKit/hidsystem/Makefile deleted file mode 100644 index 13e02f6ef..000000000 --- a/iokit/IOKit/hidsystem/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = hidsystem -NOT_EXPORT_HEADERS = ev_private.h - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = IOHIDTypes.h IOHIDShared.h IOHIDParameter.h IOLLEvent.h ev_keymap.h -INSTALL_MI_LCL_LIST = "" - -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/hidsystem/ev_keymap.h b/iokit/IOKit/hidsystem/ev_keymap.h deleted file mode 100644 index a5f74dcee..000000000 --- a/iokit/IOKit/hidsystem/ev_keymap.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. - * - * ev_keymap.h - * Defines the structure used for parsing keymappings. These structures - * and definitions are used by event sources in the kernel and by - * applications and utilities which manipulate keymaps. - * - * HISTORY - * 02-Jun-1992 Mike Paquette at NeXT - * Created. - */ - -#ifndef _DEV_EV_KEYMAP_H -#define _DEV_EV_KEYMAP_H - -#define NX_NUMKEYCODES 128 /* Highest key code is 0x7f */ -#define NX_NUMSEQUENCES 128 /* Maximum possible number of sequences */ -#define NX_NUMMODIFIERS 16 /* Maximum number of modifier bits */ -#define NX_BYTE_CODES 0 /* If first short 0, all are bytes (else shorts) */ - -#define NX_WHICHMODMASK 0x0f /* bits out of keyBits for bucky bits */ -#define NX_MODMASK 0x10 /* Bit out of keyBits indicates modifier bit */ -#define NX_CHARGENMASK 0x20 /* bit out of keyBits for char gen */ -#define NX_SPECIALKEYMASK 0x40 /* bit out of keyBits for specialty key */ -#define NX_KEYSTATEMASK 0x80 /* OBSOLETE - DO NOT USE IN NEW DESIGNS */ - -/* - * Special keys currently known to and understood by the system. - * If new specialty keys are invented, extend this list as appropriate. - * The presence of these keys in a particular implementation is not - * guaranteed. - */ -#define NX_NOSPECIALKEY 0xFFFF -#define NX_KEYTYPE_SOUND_UP 0 -#define NX_KEYTYPE_SOUND_DOWN 1 -#define NX_KEYTYPE_BRIGHTNESS_UP 2 -#define NX_KEYTYPE_BRIGHTNESS_DOWN 3 -#define NX_KEYTYPE_CAPS_LOCK 4 -#define NX_KEYTYPE_HELP 5 -#define NX_POWER_KEY 6 -#define NX_KEYTYPE_MUTE 7 -#define NX_UP_ARROW_KEY 8 -#define NX_DOWN_ARROW_KEY 9 -#define NX_KEYTYPE_NUM_LOCK 10 - -#define NX_KEYTYPE_CONTRAST_UP 11 -#define NX_KEYTYPE_CONTRAST_DOWN 12 -#define NX_KEYTYPE_LAUNCH_PANEL 13 -#define NX_KEYTYPE_EJECT 14 - -#define NX_NUMSPECIALKEYS 15 /* Maximum number of special keys */ -#define NX_NUM_SCANNED_SPECIALKEYS 15 /* First 15 special keys are */ - /* actively scanned in kernel */ - -/* Mask of special keys that are posted as events */ - -#define NX_SPECIALKEY_POST_MASK \ - ((1 << NX_KEYTYPE_SOUND_UP) | (1 << NX_KEYTYPE_SOUND_DOWN) | \ - (1 << NX_POWER_KEY) | (1 << NX_KEYTYPE_MUTE) | \ - (1 << NX_KEYTYPE_BRIGHTNESS_UP) | (1 << NX_KEYTYPE_BRIGHTNESS_DOWN) | \ - (1 << NX_KEYTYPE_CONTRAST_UP) | (1 << NX_KEYTYPE_CONTRAST_UP) | \ - (1 << NX_KEYTYPE_LAUNCH_PANEL) | (1 << NX_KEYTYPE_EJECT) | \ - 0) - -/* Modifier key indices into modDefs[] */ -#define NX_MODIFIERKEY_ALPHALOCK 0 -#define NX_MODIFIERKEY_SHIFT 1 -#define NX_MODIFIERKEY_CONTROL 2 -#define NX_MODIFIERKEY_ALTERNATE 3 -#define NX_MODIFIERKEY_COMMAND 4 -#define NX_MODIFIERKEY_NUMERICPAD 5 -#define NX_MODIFIERKEY_HELP 6 -#define NX_MODIFIERKEY_SECONDARYFN 7 -#define NX_MODIFIERKEY_NUMLOCK 8 - - -typedef struct _NXParsedKeyMapping_ { - /* If nonzero, all numbers are shorts; if zero, all numbers are bytes*/ - short shorts; - - /* - * For each keycode, low order bit says if the key - * generates characters. - * High order bit says if the key is assigned to a modifier bit. - * The second to low order bit gives the current state of the key. - */ - char keyBits[NX_NUMKEYCODES]; - - /* Bit number of highest numbered modifier bit */ - int maxMod; - - /* Pointers to where the list of keys for each modifiers bit begins, - * or NULL. - */ - unsigned char *modDefs[NX_NUMMODIFIERS]; - - /* Key code of highest key deinfed to generate characters */ - int numDefs; - - /* Pointer into the keyMapping where this key's definitions begin */ - unsigned char *keyDefs[NX_NUMKEYCODES]; - - /* number of sequence definitions */ - int numSeqs; - - /* pointers to sequences */ - unsigned char *seqDefs[NX_NUMSEQUENCES]; - - /* Special key definitions */ - int numSpecialKeys; - - /* Special key values, or 0xFFFF if none */ - unsigned short specialKeys[NX_NUMSPECIALKEYS]; - - /* Pointer to the original keymapping string */ - const unsigned char *mapping; - - /* Length of the original string */ - int mappingLen; -} NXParsedKeyMapping; - -#endif /* !_DEV_EV_KEYMAP_H */ diff --git a/iokit/IOKit/hidsystem/ev_private.h b/iokit/IOKit/hidsystem/ev_private.h deleted file mode 100644 index 596dfbae2..000000000 --- a/iokit/IOKit/hidsystem/ev_private.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/****************************************************************************** - - ev_private.h - Internal defs for the events driver. The contents of this module - may need to be tweaked slightly from one architecture to the next. - 22 May 1992 Mike Paquette at NeXT Computers, Inc. - - Copyright 1992 NeXT, Inc. - - Modified: - - -******************************************************************************/ - -#ifndef _DEV_EV_PRIVATE_H -#define _DEV_EV_PRIVATE_H - -#include <IOKit/hidsystem/IOLLEvent.h> - -/* Initial cursor position */ -#define INIT_CURSOR_X 16 -#define INIT_CURSOR_Y 16 - -/* Default mouse click time and motion constants */ -#define EV_DCLICKTIME 500000000 /* Default nanoseconds for a double-click */ -#define EV_DCLICKSPACE 3 /* Default pixel threshold for double-clicks */ - -/* Default Wait Cursor Timing Constants (in nanoseconds) */ -#define DefaultWCSustain 300000000 /* 0.3 seconds */ -#define DefaultWCFrameRate 75000000 /* 13.3 frames/second */ -#define DefaultWCThreshold 1200000000ULL /* 1.2 seconds */ - -#define EV_STD_CURSOR 0 -#define EV_WAITCURSOR 1 -#define EV_WAITCURSOR_1 2 -#define EV_WAITCURSOR_2 3 -#define EV_MAXCURSOR (EV_WAITCURSOR_2) - -/* Default dim time is 5 minutes, nanoseconds */ -#define DAUTODIMPERIOD (1000ULL*1000ULL*1000ULL*60*5) -/* Default dim level is one-fourth */ -#define DDIMBRIGHTNESS (EV_SCREEN_MAX_BRIGHTNESS/4) - - -/* Where event numbers start */ -#define INITEVENTNUM 13 -#define NULLEVENTNUM 0 /* The event number that never was */ - -#define MOVEDEVENTMASK \ - (NX_MOUSEMOVEDMASK | NX_LMOUSEDRAGGEDMASK | NX_RMOUSEDRAGGEDMASK ) -#define COALESCEEVENTMASK \ - (MOVEDEVENTMASK | NX_MOUSEEXITEDMASK) -#define MOUSEEVENTMASK \ - (NX_LMOUSEDOWNMASK|NX_RMOUSEDOWNMASK|NX_LMOUSEUPMASK|NX_RMOUSEUPMASK) -#define PRESSUREEVENTMASK \ - (NX_LMOUSEDOWNMASK|NX_LMOUSEUPMASK|NX_MOUSEMOVEDMASK|NX_LMOUSEDRAGGEDMASK) - -/* Flags which can modify meaning of special volume/brightness keys */ -#define SPECIALKEYS_MODIFIER_MASK \ - (NX_COMMANDMASK|NX_ALTERNATEMASK|NX_CONTROLMASK) - -/* Bits in evg->eventFlags owned by keyboard devices */ -#define KEYBOARD_FLAGSMASK \ - (NX_ALPHASHIFTMASK | NX_SHIFTMASK | NX_CONTROLMASK | NX_ALTERNATEMASK \ - | NX_COMMANDMASK | NX_NUMERICPADMASK | NX_HELPMASK | NX_SECONDARYFNMASK) -// | NX_NEXTCTLKEYMASK \ -// | NX_NEXTLSHIFTKEYMASK | NX_NEXTRSHIFTKEYMASK | NX_NEXTLCMDKEYMASK \ -// | NX_NEXTRCMDKEYMASK | NX_NEXTLALTKEYMASK | NX_NEXTRALTKEYMASK) - -/* Some non-zero token to or with screen number */ -#define SCREENTOKEN 256 - -/* A macro to report if the event queue is not empty */ -#define EventsInQueue() \ - (eventsOpen && (((EvGlobals*)evg)->LLEHead != ((EvGlobals*)evg)->LLETail)) - -struct _eventMsg { - mach_msg_header_t h; -#ifdef mach3xxx // this is not needed anymore? - msg_type_t t; -#endif -}; - -/****************************************************************************** - EvScreen - This structure is used by the ev driver. - It holds information about a single screen: how much private shmem it owns, - where its private shmem region starts, its global bounds and four procedure - vectors. This structure is allocated by the ev driver and is filled in - when a driver calls ev_register_screen(). -******************************************************************************/ - -typedef volatile struct _evScreen { - IOGraphicsDevice * instance;/* Driver instance owning this screen. */ -// void *shmemPtr; /* Ptr to private shmem (if non-zero size) */ -// int shmemSize; /* Size of private shmem */ - Bounds * bounds; /* Screen's bounds in device coordinates */ -} EvScreen; - -/* - * We maintain a queue of EventSrc instances attached to the Event - * Driver. These sources are dynamically checked in with the Event - * Driver. When the driver is closed (as on Window Server exit) we - * post a relinquishOwnership:client message to the drivers. - */ -typedef struct { - IOHIDevice * eventSrc; -} eventSrcInfo; - -typedef struct { - eventSrcInfo info; - queue_chain_t link; -} attachedEventSrc; - -// No-op XPR stuff -#define xpr_ev_cursor(x, a, b, c, d, e) -#define xpr_ev_post(x, a, b, c, d, e) - -#endif /* !_DEV_EV_PRIVATE_H */ - diff --git a/iokit/IOKit/ndrvsupport/IOMacOSTypes.h b/iokit/IOKit/ndrvsupport/IOMacOSTypes.h deleted file mode 100644 index dbf127856..000000000 --- a/iokit/IOKit/ndrvsupport/IOMacOSTypes.h +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 21 July 98 - start IOKit - */ - -/* - File: Types.h - - Contains: Basic Macintosh data types. - - Version: Technology: PowerSurge 1.0.2. - Package: Universal Interfaces 2.1.2 on ETO #20 - - Copyright: © 1984-1995 by Apple Computer, Inc. - All rights reserved. - - Bugs?: If you find a problem with this file, use the Apple Bug Reporter - stack. Include the file and version information (from above) - in the problem description and send to: - Internet: apple.bugs@applelink.apple.com - AppleLink: APPLE.BUGS - -*/ - -#ifndef _IOKIT_IOMACOSTYPES_H -#define _IOKIT_IOMACOSTYPES_H -#ifndef __MACTYPES__ - -#include <IOKit/IOTypes.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma options align=mac68k - -#ifndef NULL -#if !defined(__cplusplus) && (defined(__SC__) || defined(THINK_C)) -#define NULL ((void *) 0) -#else -#define NULL 0 -#endif -#endif - -enum { - noErr = 0 -}; - -typedef unsigned long KernelProcessID; -typedef unsigned long AddressSpaceID; - -#if 0 -#ifndef __cplusplus -enum { false, true }; -#endif -#endif - -typedef unsigned char Byte; - -typedef signed char SignedByte; - -typedef UInt16 UniChar; - -typedef char *Ptr; - -typedef Ptr *Handle; - -typedef long Fixed; - -typedef Fixed *FixedPtr; - -typedef long Fract; - -typedef Fract *FractPtr; - -struct _extended80 { - short exp; - short man[4]; -}; -struct _extended96 { - short exp[2]; - short man[4]; -}; -typedef struct wide *WidePtr; - -typedef struct UnsignedWide *UnsignedWidePtr; - - -/* -enum { - false, - true -}; -#if !__option(bool) - #ifndef true - #define true 1 - #endif - #ifndef false - #define false 0 - #endif -#endif - -typedef unsigned char Boolean; -*/ - - -typedef short OSErr; - -typedef unsigned int FourCharCode; - -typedef FourCharCode OSType; - -typedef FourCharCode ResType; - -typedef OSType *OSTypePtr; - -typedef ResType *ResTypePtr; - -struct Rect { - short top; - short left; - short bottom; - short right; -}; -typedef struct Rect Rect; - -typedef Rect *RectPtr; - -// Quickdraw.i - -/* - kVariableLengthArray is used in array bounds to specify a variable length array. - It is ususally used in variable length structs when the last field is an array - of any size. Before ANSI C, we used zero as the bounds of variable length - array, but that is illegal in ANSI C. Example: - - struct FooList - { - short listLength; - Foo elements[kVariableLengthArray]; - }; -*/ - -enum { - kVariableLengthArray = 1 -}; - -/* Numeric version part of 'vers' resource */ -struct NumVersion { - UInt8 majorRev; /*1st part of version number in BCD*/ - UInt8 minorAndBugRev; /*2nd & 3rd part of version number share a byte*/ - UInt8 stage; /*stage code: dev, alpha, beta, final*/ - UInt8 nonRelRev; /*revision level of non-released version*/ -}; -typedef struct NumVersion NumVersion; - -typedef struct OpaqueRef *KernelID; - -typedef UInt8 *BytePtr; - -typedef UInt32 ByteCount; - -typedef UInt32 ItemCount; - -typedef void *LogicalAddress; - -typedef void *PhysicalAddress; - -typedef UInt32 PBVersion; - -typedef SInt32 Duration; - -#define kInvalidID 0 - -enum { - kNilOptions = 0 -}; - - -typedef unsigned char Str31[32]; - - -/* -From: - File: DriverFamilyMatching.i <18> - Copyright: © 1995-1996 by Apple Computer, Inc., all rights reserved. -*/ - -//############################################## -// Well known properties in the Name Registry -//############################################## - -#define kPropertyName "name" -#define kPropertyCompatible "compatible" -#define kPropertyDriverPtr "driver-ptr" -#define kPropertyDriverDesc "driver-description" -#define kPropertyReg "reg" -#define kPropertyAAPLAddress "AAPL,address" -#define kPropertyMatching "matching" - - -//######################################################### -// Descriptor for Drivers and NDRVs -//######################################################### -/* Driver Typing Information Used to Match Drivers With Devices */ -struct DriverType { - Str31 nameInfoStr; /* Driver Name/Info String*/ - NumVersion version; /* Driver Version Number*/ -}; -typedef struct DriverType DriverType; -typedef DriverType * DriverTypePtr; - -/* OS Runtime Information Used to Setup and Maintain a Driver's Runtime Environment */ -typedef OptionBits RuntimeOptions; - - -enum { - kDriverIsLoadedUponDiscovery = 0x00000001, /* auto-load driver when discovered*/ - kDriverIsOpenedUponLoad = 0x00000002, /* auto-open driver when loaded*/ - kDriverIsUnderExpertControl = 0x00000004, /* I/O expert handles loads/opens*/ - kDriverIsConcurrent = 0x00000008, /* supports concurrent requests*/ - kDriverQueuesIOPB = 0x00000010, /* device manager doesn't queue IOPB*/ - kDriverIsLoadedAtBoot = 0x00000020, /* Driver is loaded at the boot time */ - kDriverIsForVirtualDevice = 0x00000040, /* Driver is for a virtual Device */ - kDriverSupportDMSuspendAndResume = 0x00000080 /* Driver supports Device Manager Suspend and Resume command */ -}; - -struct DriverOSRuntime { - RuntimeOptions driverRuntime; /* Options for OS Runtime*/ - Str31 driverName; /* Driver's name to the OS*/ - UInt32 driverDescReserved[8]; /* Reserved area*/ -}; -typedef struct DriverOSRuntime DriverOSRuntime; -typedef DriverOSRuntime * DriverOSRuntimePtr; - -/* OS Service Information Used To Declare What APIs a Driver Supports */ -typedef UInt32 ServiceCount; - -struct DriverServiceInfo { - OSType serviceCategory; /* Service Category Name*/ - OSType serviceType; /* Type within Category*/ - NumVersion serviceVersion; /* Version of service*/ -}; -typedef struct DriverServiceInfo DriverServiceInfo; -typedef DriverServiceInfo * DriverServiceInfoPtr; - -struct DriverOSService { - ServiceCount nServices; /* Number of Services Supported*/ - DriverServiceInfo service[1]; /* The List of Services (at least one)*/ -}; -typedef struct DriverOSService DriverOSService; -typedef DriverOSService * DriverOSServicePtr; - -/* Categories */ - -enum { - kServiceCategoryDisplay = 'disp', /* Display Manager*/ - kServiceCategoryOpenTransport = 'otan', /* Open Transport*/ - kServiceCategoryBlockStorage = 'blok', /* Block Storage*/ - kServiceCategoryNdrvDriver = 'ndrv', /* Generic Native Driver*/ - kServiceCategoryScsiSIM = 'scsi', /* SCSI */ - kServiceCategoryFileManager = 'file', /* File Manager */ - kServiceCategoryIDE = 'ide-', /* ide */ - kServiceCategoryADB = 'adb-', /* adb */ - kServiceCategoryPCI = 'pci-', /* pci bus */ - /* Nu Bus */ - kServiceCategoryDFM = 'dfm-', /* DFM */ - kServiceCategoryMotherBoard = 'mrbd', /* mother Board */ - kServiceCategoryKeyboard = 'kybd', /* Keyboard */ - kServiceCategoryPointing = 'poit', /* Pointing */ - kServiceCategoryRTC = 'rtc-', /* RTC */ - kServiceCategoryNVRAM = 'nram', /* NVRAM */ - kServiceCategorySound = 'sond', /* Sound (1/3/96 MCS) */ - kServiceCategoryPowerMgt = 'pgmt', /* Power Management */ - kServiceCategoryGeneric = 'genr' /* Generic Service Category to receive general Events */ -}; - -/* Ndrv ServiceCategory Types */ -enum { - kNdrvTypeIsGeneric = 'genr', /* generic*/ - kNdrvTypeIsVideo = 'vido', /* video*/ - kNdrvTypeIsBlockStorage = 'blok', /* block storage*/ - kNdrvTypeIsNetworking = 'netw', /* networking*/ - kNdrvTypeIsSerial = 'serl', /* serial*/ - kNdrvTypeIsParallel = 'parl', /* parallel */ - kNdrvTypeIsSound = 'sond', /* sound*/ - kNdrvTypeIsBusBridge = 'brdg' -}; - -typedef UInt32 DriverDescVersion; - -/* The Driver Description */ -enum { - kInitialDriverDescriptor = 0, - kVersionOneDriverDescriptor = 1 -}; - -enum { - kTheDescriptionSignature = 'mtej', - kDriverDescriptionSignature = 'pdes' -}; - - -struct DriverDescription { - OSType driverDescSignature; /* Signature field of this structure*/ - DriverDescVersion driverDescVersion; /* Version of this data structure*/ - DriverType driverType; /* Type of Driver*/ - DriverOSRuntime driverOSRuntimeInfo; /* OS Runtime Requirements of Driver*/ - DriverOSService driverServices; /* Apple Service API Membership*/ -}; -typedef struct DriverDescription DriverDescription; -typedef DriverDescription * DriverDescriptionPtr; - - -#pragma options align=reset - -#ifdef __cplusplus -} -#endif - -#endif /* __MACTYPES__ */ - -#ifndef __QUICKDRAW__ - -#ifdef __cplusplus -extern "C" { -#endif - -#pragma options align=mac68k - -struct RGBColor { - unsigned short red; /*magnitude of red component*/ - unsigned short green; /*magnitude of green component*/ - unsigned short blue; /*magnitude of blue component*/ -}; -typedef struct RGBColor RGBColor; -typedef RGBColor *RGBColorPtr; -typedef RGBColorPtr *RGBColorHdl; - -struct ColorSpec { - short value; /*index or other value*/ - RGBColor rgb; /*true color*/ -}; - -typedef struct ColorSpec ColorSpec; -typedef ColorSpec *ColorSpecPtr; - -struct GammaTbl { - short gVersion; /*gamma version number*/ - short gType; /*gamma data type*/ - short gFormulaSize; /*Formula data size*/ - short gChanCnt; /*number of channels of data*/ - short gDataCnt; /*number of values/channel*/ - short gDataWidth; /*bits/corrected value (data packed to next larger byte size)*/ - short gFormulaData[1]; /*data for formulas followed by gamma values*/ -}; -typedef struct GammaTbl GammaTbl; -typedef GammaTbl *GammaTblPtr; - -#pragma options align=reset - -#ifdef __cplusplus -} -#endif - -#endif /* __QUICKDRAW__ */ - -#endif /* _IOKIT_IOMACOSTYPES_H */ diff --git a/iokit/IOKit/ndrvsupport/IOMacOSVideo.h b/iokit/IOKit/ndrvsupport/IOMacOSVideo.h deleted file mode 100644 index e18339ca5..000000000 --- a/iokit/IOKit/ndrvsupport/IOMacOSVideo.h +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - File: Video.h - - Contains: Video Driver Interfaces. - - Copyright: (c) 1986-2000 by Apple Computer, Inc., all rights reserved - - Bugs?: For bug reports, consult the following page on - the World Wide Web: - - http://developer.apple.com/bugreporter/ - -*/ -#ifndef __IOMACOSVIDEO__ -#define __IOMACOSVIDEO__ - -#ifdef IOKIT - -#define PRAGMA_STRUCT_ALIGN 1 -#define FOUR_CHAR_CODE(x) (x) -#include <IOKit/ndrvsupport/IOMacOSTypes.h> - -#else /* IOKIT */ - -#ifndef __QUICKDRAW__ -#include <Quickdraw.h> -#endif - -#endif /* IOKIT */ - -#if PRAGMA_ONCE -#pragma once -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#if PRAGMA_IMPORT -#pragma import on -#endif - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=mac68k -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(push, 2) -#elif PRAGMA_STRUCT_PACK - #pragma pack(2) -#endif - -enum { - mBaseOffset = 1, /*Id of mBaseOffset.*/ - mRowBytes = 2, /*Video sResource parameter Id's */ - mBounds = 3, /*Video sResource parameter Id's */ - mVersion = 4, /*Video sResource parameter Id's */ - mHRes = 5, /*Video sResource parameter Id's */ - mVRes = 6, /*Video sResource parameter Id's */ - mPixelType = 7, /*Video sResource parameter Id's */ - mPixelSize = 8, /*Video sResource parameter Id's */ - mCmpCount = 9, /*Video sResource parameter Id's */ - mCmpSize = 10, /*Video sResource parameter Id's */ - mPlaneBytes = 11, /*Video sResource parameter Id's */ - mVertRefRate = 14, /*Video sResource parameter Id's */ - mVidParams = 1, /*Video parameter block id.*/ - mTable = 2, /*Offset to the table.*/ - mPageCnt = 3, /*Number of pages*/ - mDevType = 4, /*Device Type*/ - oneBitMode = 128, /*Id of OneBitMode Parameter list.*/ - twoBitMode = 129, /*Id of TwoBitMode Parameter list.*/ - fourBitMode = 130, /*Id of FourBitMode Parameter list.*/ - eightBitMode = 131 /*Id of EightBitMode Parameter list.*/ -}; - -enum { - sixteenBitMode = 132, /*Id of SixteenBitMode Parameter list.*/ - thirtyTwoBitMode = 133, /*Id of ThirtyTwoBitMode Parameter list.*/ - firstVidMode = 128, /*The new, better way to do the above. */ - secondVidMode = 129, /* QuickDraw only supports six video */ - thirdVidMode = 130, /* at this time. */ - fourthVidMode = 131, - fifthVidMode = 132, - sixthVidMode = 133, - spGammaDir = 64, - spVidNamesDir = 65 -}; - - -/* csTimingFormat values in VDTimingInfo */ -/* look in the declaration rom for timing info */ -enum { - kDeclROMtables = FOUR_CHAR_CODE('decl'), - kDetailedTimingFormat = FOUR_CHAR_CODE('arba') /* Timing is a detailed timing*/ -}; - -/* Size of a block of EDID (Extended Display Identification Data) */ -enum { - kDDCBlockSize = 128 -}; - -/* ddcBlockType constants*/ -enum { - kDDCBlockTypeEDID = 0 /* EDID block type. */ -}; - -/* ddcFlags constants*/ -enum { - kDDCForceReadBit = 0, /* Force a new read of the EDID. */ - kDDCForceReadMask = (1 << kDDCForceReadBit) /* Mask for kddcForceReadBit. */ -}; - - -/* Timing mode constants for Display Manager MultiMode support - Corresponding .h equates are in Video.h - .a equates are in Video.a - .r equates are in DepVideoEqu.r - - The second enum is the old names (for compatibility). - The first enum is the new names. -*/ -enum { - timingInvalid = 0, /* Unknown timing... force user to confirm. */ - timingInvalid_SM_T24 = 8, /* Work around bug in SM Thunder24 card.*/ - timingApple_FixedRateLCD = 42, /* Lump all fixed-rate LCDs into one category.*/ - timingApple_512x384_60hz = 130, /* 512x384 (60 Hz) Rubik timing. */ - timingApple_560x384_60hz = 135, /* 560x384 (60 Hz) Rubik-560 timing. */ - timingApple_640x480_67hz = 140, /* 640x480 (67 Hz) HR timing. */ - timingApple_640x400_67hz = 145, /* 640x400 (67 Hz) HR-400 timing. */ - timingVESA_640x480_60hz = 150, /* 640x480 (60 Hz) VGA timing. */ - timingVESA_640x480_72hz = 152, /* 640x480 (72 Hz) VGA timing. */ - timingVESA_640x480_75hz = 154, /* 640x480 (75 Hz) VGA timing. */ - timingVESA_640x480_85hz = 158, /* 640x480 (85 Hz) VGA timing. */ - timingGTF_640x480_120hz = 159, /* 640x480 (120 Hz) VESA Generalized Timing Formula */ - timingApple_640x870_75hz = 160, /* 640x870 (75 Hz) FPD timing.*/ - timingApple_640x818_75hz = 165, /* 640x818 (75 Hz) FPD-818 timing.*/ - timingApple_832x624_75hz = 170, /* 832x624 (75 Hz) GoldFish timing.*/ - timingVESA_800x600_56hz = 180, /* 800x600 (56 Hz) SVGA timing. */ - timingVESA_800x600_60hz = 182, /* 800x600 (60 Hz) SVGA timing. */ - timingVESA_800x600_72hz = 184, /* 800x600 (72 Hz) SVGA timing. */ - timingVESA_800x600_75hz = 186, /* 800x600 (75 Hz) SVGA timing. */ - timingVESA_800x600_85hz = 188, /* 800x600 (85 Hz) SVGA timing. */ - timingVESA_1024x768_60hz = 190, /* 1024x768 (60 Hz) VESA 1K-60Hz timing. */ - timingVESA_1024x768_70hz = 200, /* 1024x768 (70 Hz) VESA 1K-70Hz timing. */ - timingVESA_1024x768_75hz = 204, /* 1024x768 (75 Hz) VESA 1K-75Hz timing (very similar to timingApple_1024x768_75hz). */ - timingVESA_1024x768_85hz = 208, /* 1024x768 (85 Hz) VESA timing. */ - timingApple_1024x768_75hz = 210, /* 1024x768 (75 Hz) Apple 19" RGB. */ - timingApple_1152x870_75hz = 220, /* 1152x870 (75 Hz) Apple 21" RGB. */ - timingAppleNTSC_ST = 230, /* 512x384 (60 Hz, interlaced, non-convolved). */ - timingAppleNTSC_FF = 232, /* 640x480 (60 Hz, interlaced, non-convolved). */ - timingAppleNTSC_STconv = 234, /* 512x384 (60 Hz, interlaced, convolved). */ - timingAppleNTSC_FFconv = 236, /* 640x480 (60 Hz, interlaced, convolved). */ - timingApplePAL_ST = 238, /* 640x480 (50 Hz, interlaced, non-convolved). */ - timingApplePAL_FF = 240, /* 768x576 (50 Hz, interlaced, non-convolved). */ - timingApplePAL_STconv = 242, /* 640x480 (50 Hz, interlaced, convolved). */ - timingApplePAL_FFconv = 244, /* 768x576 (50 Hz, interlaced, convolved). */ - timingVESA_1280x960_75hz = 250, /* 1280x960 (75 Hz) */ - timingVESA_1280x960_60hz = 252, /* 1280x960 (60 Hz) */ - timingVESA_1280x960_85hz = 254, /* 1280x960 (85 Hz) */ - timingVESA_1280x1024_60hz = 260, /* 1280x1024 (60 Hz) */ - timingVESA_1280x1024_75hz = 262, /* 1280x1024 (75 Hz) */ - timingVESA_1280x1024_85hz = 268, /* 1280x1024 (85 Hz) */ - timingVESA_1600x1200_60hz = 280, /* 1600x1200 (60 Hz) VESA timing. */ - timingVESA_1600x1200_65hz = 282, /* 1600x1200 (65 Hz) VESA timing. */ - timingVESA_1600x1200_70hz = 284, /* 1600x1200 (70 Hz) VESA timing. */ - timingVESA_1600x1200_75hz = 286, /* 1600x1200 (75 Hz) VESA timing (pixel clock is 189.2 Mhz dot clock). */ - timingVESA_1600x1200_80hz = 288, /* 1600x1200 (80 Hz) VESA timing (pixel clock is 216>? Mhz dot clock) - proposed only. */ - timingVESA_1600x1200_85hz = 289, /* 1600x1200 (85 Hz) VESA timing (pixel clock is 229.5 Mhz dot clock). */ - timingVESA_1792x1344_60hz = 296, /* 1792x1344 (60 Hz) VESA timing (204.75 Mhz dot clock). */ - timingVESA_1792x1344_75hz = 298, /* 1792x1344 (75 Hz) VESA timing (261.75 Mhz dot clock). */ - timingVESA_1856x1392_60hz = 300, /* 1856x1392 (60 Hz) VESA timing (218.25 Mhz dot clock). */ - timingVESA_1856x1392_75hz = 302, /* 1856x1392 (75 Hz) VESA timing (288 Mhz dot clock). */ - timingVESA_1920x1440_60hz = 304, /* 1920x1440 (60 Hz) VESA timing (234 Mhz dot clock). */ - timingVESA_1920x1440_75hz = 306, /* 1920x1440 (75 Hz) VESA timing (297 Mhz dot clock). */ - timingSMPTE240M_60hz = 400, /* 60Hz V, 33.75KHz H, interlaced timing, 16:9 aspect, typical resolution of 1920x1035. */ - timingFilmRate_48hz = 410, /* 48Hz V, 25.20KHz H, non-interlaced timing, typical resolution of 640x480. */ - timingSony_1600x1024_76hz = 500, /* 1600x1024 (76 Hz) Sony timing (pixel clock is 170.447 Mhz dot clock). */ - timingSony_1920x1080_60hz = 510, /* 1920x1080 (60 Hz) Sony timing (pixel clock is 159.84 Mhz dot clock). */ - timingSony_1920x1080_72hz = 520, /* 1920x1080 (72 Hz) Sony timing (pixel clock is 216.023 Mhz dot clock). */ - timingSony_1920x1200_76hz = 540, /* 1900x1200 (76 Hz) Sony timing (pixel clock is 243.20 Mhz dot clock). */ - timingApple_0x0_0hz_Offline = 550 /* Indicates that this timing will take the display off-line and remove it from the system. */ -}; - - -/* Deprecated timing names.*/ -enum { - timingApple12 = timingApple_512x384_60hz, - timingApple12x = timingApple_560x384_60hz, - timingApple13 = timingApple_640x480_67hz, - timingApple13x = timingApple_640x400_67hz, - timingAppleVGA = timingVESA_640x480_60hz, - timingApple15 = timingApple_640x870_75hz, - timingApple15x = timingApple_640x818_75hz, - timingApple16 = timingApple_832x624_75hz, - timingAppleSVGA = timingVESA_800x600_56hz, - timingApple1Ka = timingVESA_1024x768_60hz, - timingApple1Kb = timingVESA_1024x768_70hz, - timingApple19 = timingApple_1024x768_75hz, - timingApple21 = timingApple_1152x870_75hz, - timingSony_1900x1200_74hz = 530, /* 1900x1200 (74 Hz) Sony timing (pixel clock is 236.25 Mhz dot clock). */ - timingSony_1900x1200_76hz = timingSony_1920x1200_76hz /* 1900x1200 (76 Hz) Sony timing (pixel clock is 245.48 Mhz dot clock). */ -}; - -/* csConnectFlags values in VDDisplayConnectInfo */ -enum { - kAllModesValid = 0, /* All modes not trimmed by primary init are good close enough to try */ - kAllModesSafe = 1, /* All modes not trimmed by primary init are know to be safe */ - kReportsTagging = 2, /* Can detect tagged displays (to identify smart monitors) */ - kHasDirectConnection = 3, /* True implies that driver can talk directly to device (e.g. serial data link via sense lines) */ - kIsMonoDev = 4, /* Says whether there's an RGB (0) or Monochrome (1) connection. */ - kUncertainConnection = 5, /* There may not be a display (no sense lines?). */ - kTaggingInfoNonStandard = 6, /* Set when csConnectTaggedType/csConnectTaggedData are non-standard (i.e., not the Apple CRT sense codes). */ - kReportsDDCConnection = 7, /* Card can do ddc (set kHasDirectConnect && kHasDDCConnect if you actually found a ddc display). */ - kHasDDCConnection = 8, /* Card has ddc connect now. */ - kConnectionInactive = 9, /* Set when the connection is NOT currently active (generally used in a multiconnection environment). */ - kDependentConnection = 10, /* Set when some ascpect of THIS connection depends on another (will generally be set in a kModeSimulscan environment). */ - kBuiltInConnection = 11, /* Set when connection is KNOWN to be built-in (this is not the same as kHasDirectConnection). */ - kOverrideConnection = 12, /* Set when the reported connection is not the true one, but is one that has been forced through a SetConnection call */ - kFastCheckForDDC = 13, /* Set when all 3 are true: 1) sense codes indicate DDC display could be attached 2) attempted fast check 3) DDC failed */ - kReportsHotPlugging = 14 /* Detects and reports hot pluggging on connector (via VSL also implies DDC will be up to date w/o force read) */ -}; - - -/* csDisplayType values in VDDisplayConnectInfo */ -enum { - kUnknownConnect = 1, /* Not sure how we'll use this, but seems like a good idea. */ - kPanelConnect = 2, /* For use with fixed-in-place LCD panels. */ - kPanelTFTConnect = 2, /* Alias for kPanelConnect */ - kFixedModeCRTConnect = 3, /* For use with fixed-mode (i.e., very limited range) displays. */ - kMultiModeCRT1Connect = 4, /* 320x200 maybe, 12" maybe, 13" (default), 16" certain, 19" maybe, 21" maybe */ - kMultiModeCRT2Connect = 5, /* 320x200 maybe, 12" maybe, 13" certain, 16" (default), 19" certain, 21" maybe */ - kMultiModeCRT3Connect = 6, /* 320x200 maybe, 12" maybe, 13" certain, 16" certain, 19" default, 21" certain */ - kMultiModeCRT4Connect = 7, /* Expansion to large multi mode (not yet used) */ - kModelessConnect = 8, /* Expansion to modeless model (not yet used) */ - kFullPageConnect = 9, /* 640x818 (to get 8bpp in 512K case) and 640x870 (these two only) */ - kVGAConnect = 10, /* 640x480 VGA default -- question everything else */ - kNTSCConnect = 11, /* NTSC ST (default), FF, STconv, FFconv */ - kPALConnect = 12, /* PAL ST (default), FF, STconv, FFconv */ - kHRConnect = 13, /* Straight-6 connect -- 640x480 and 640x400 (to get 8bpp in 256K case) (these two only) */ - kPanelFSTNConnect = 14, /* For use with fixed-in-place LCD FSTN (aka "Supertwist") panels */ - kMonoTwoPageConnect = 15, /* 1152x870 Apple color two-page display */ - kColorTwoPageConnect = 16, /* 1152x870 Apple B&W two-page display */ - kColor16Connect = 17, /* 832x624 Apple B&W two-page display */ - kColor19Connect = 18, /* 1024x768 Apple B&W two-page display */ - kGenericCRT = 19, /* Indicates nothing except that connection is CRT in nature. */ - kGenericLCD = 20, /* Indicates nothing except that connection is LCD in nature. */ - kDDCConnect = 21, /* DDC connection, always set kHasDDCConnection */ - kNoConnect = 22 /* No display is connected - load sensing or similar level of hardware detection is assumed (used by resident drivers that support hot plugging when nothing is currently connected) */ -}; - -/* csTimingFlags values in VDTimingInfoRec */ -enum { - kModeValid = 0, /* Says that this mode should NOT be trimmed. */ - kModeSafe = 1, /* This mode does not need confirmation */ - kModeDefault = 2, /* This is the default mode for this type of connection */ - kModeShowNow = 3, /* This mode should always be shown (even though it may require a confirm) */ - kModeNotResize = 4, /* This mode should not be used to resize the display (eg. mode selects a different connector on card) */ - kModeRequiresPan = 5, /* This mode has more pixels than are actually displayed */ - kModeInterlaced = 6, /* This mode is interlaced (single pixel lines look bad). */ - kModeShowNever = 7, /* This mode should not be shown in the user interface. */ - kModeSimulscan = 8, /* Indicates that more than one display connection can be driven from a single framebuffer controller. */ - kModeNotPreset = 9, /* Indicates that the timing is not a factory preset for the current display (geometry may need correction) */ - kModeBuiltIn = 10, /* Indicates that the display mode is for the built-in connect only (on multiconnect devices like the PB 3400) Only the driver is quieried */ - kModeStretched = 11 /* Indicates that the display mode will be stretched/distorted to match the display aspect ratio */ -}; - -/* csDepthFlags in VDVideoParametersInfoRec */ -enum { - kDepthDependent = 0 /* Says that this depth mode may cause dependent changes in other framebuffers (and . */ -}; - -/* csResolutionFlags bit flags for VDResolutionInfoRec */ -enum { - kResolutionHasMultipleDepthSizes = 0 /* Says that this mode has different csHorizontalPixels, csVerticalLines at different depths (usually slightly larger at lower depths) */ -}; - - -enum { - /* Power Mode constants for VDPowerStateRec.powerState. Note the numeric order does not match the power state order */ - kAVPowerOff = 0, /* Power fully off*/ - kAVPowerStandby = 1, - kAVPowerSuspend = 2, - kAVPowerOn = 3, - kHardwareSleep = 128, - kHardwareWake = 129, - kHardwareWakeFromSuspend = 130, - kHardwareWakeToDoze = 131, - kHardwareWakeToDozeFromSuspend = 132 -}; - -enum { - /* Power Mode masks and bits for VDPowerStateRec.powerFlags. */ - kPowerStateNeedsRefresh = 0, /* When leaving this power mode, a display will need refreshing */ - kPowerStateSleepAwareBit = 1, /* if gestaltPCCardDockingSelectorFix, Docking mgr checks this bit before checking kPowerStateSleepAllowedBit */ - kPowerStateSleepForbiddenBit = 2, /* if kPowerStateSleepAwareBit, Docking mgr checks this bit before sleeping */ - kPowerStateSleepCanPowerOffBit = 3, /* supports power down sleep (ie PCI power off)*/ - kPowerStateSleepNoDPMSBit = 4, /* Bug #2425210. Do not use DPMS with this display.*/ - kPowerStateSleepWaketoDozeBit = 5, /* Supports Wake to Doze */ - kPowerStateNeedsRefreshMask = (1L << kPowerStateNeedsRefresh), - kPowerStateSleepAwareMask = (1L << kPowerStateSleepAwareBit), - kPowerStateSleepForbiddenMask = (1L << kPowerStateSleepForbiddenBit), - kPowerStateSleepCanPowerOffMask = (1L << kPowerStateSleepCanPowerOffBit), - kPowerStateSleepNoDPMSMask = (1L << kPowerStateSleepNoDPMSBit), - kPowerStateSleepWaketoDozeMask = (1L << kPowerStateSleepWaketoDozeBit) -}; - - -enum { - /* Control Codes */ - cscReset = 0, - cscKillIO = 1, - cscSetMode = 2, - cscSetEntries = 3, - cscSetGamma = 4, - cscGrayPage = 5, - cscGrayScreen = 5, - cscSetGray = 6, - cscSetInterrupt = 7, - cscDirectSetEntries = 8, - cscSetDefaultMode = 9, - cscSwitchMode = 10, - cscSetSync = 11, - cscSavePreferredConfiguration = 16, - cscSetHardwareCursor = 22, - cscDrawHardwareCursor = 23, - cscSetConvolution = 24, - cscSetPowerState = 25, - cscPrivateControlCall = 26, /* Takes a VDPrivateSelectorDataRec*/ - cscSetMultiConnect = 28, /* From a GDI point of view, this call should be implemented completely in the HAL and not at all in the core.*/ - cscSetClutBehavior = 29, /* Takes a VDClutBehavior */ - cscSetDetailedTiming = 31, /* Takes a VDDetailedTimingPtr */ - cscDoCommunication = 33, /* Takes a VDCommunicationPtr */ - cscUnusedCall = 127 /* This call used to expend the scrn resource. Its imbedded data contains more control info */ -}; - -enum { - /* Status Codes */ - cscGetMode = 2, - cscGetEntries = 3, - cscGetPageCnt = 4, - cscGetPages = 4, /* This is what C&D 2 calls it. */ - cscGetPageBase = 5, - cscGetBaseAddr = 5, /* This is what C&D 2 calls it. */ - cscGetGray = 6, - cscGetInterrupt = 7, - cscGetGamma = 8, - cscGetDefaultMode = 9, - cscGetCurMode = 10, - cscGetSync = 11, - cscGetConnection = 12, /* Return information about the connection to the display */ - cscGetModeTiming = 13, /* Return timing info for a mode */ - cscGetModeBaseAddress = 14, /* Return base address information about a particular mode */ - cscGetScanProc = 15, /* QuickTime scan chasing routine */ - cscGetPreferredConfiguration = 16, - cscGetNextResolution = 17, - cscGetVideoParameters = 18, - cscGetGammaInfoList = 20, - cscRetrieveGammaTable = 21, - cscSupportsHardwareCursor = 22, - cscGetHardwareCursorDrawState = 23, - cscGetConvolution = 24, - cscGetPowerState = 25, - cscPrivateStatusCall = 26, /* Takes a VDPrivateSelectorDataRec*/ - cscGetDDCBlock = 27, /* Takes a VDDDCBlockRec */ - cscGetMultiConnect = 28, /* From a GDI point of view, this call should be implemented completely in the HAL and not at all in the core.*/ - cscGetClutBehavior = 29, /* Takes a VDClutBehavior */ - cscGetTimingRanges = 30, /* Takes a VDDisplayTimingRangePtr */ - cscGetDetailedTiming = 31, /* Takes a VDDetailedTimingPtr */ - cscGetCommunicationInfo = 32 /* Takes a VDCommunicationInfoPtr */ -}; - -/* Bit definitions for the Get/Set Sync call*/ -enum { - kDisableHorizontalSyncBit = 0, - kDisableVerticalSyncBit = 1, - kDisableCompositeSyncBit = 2, - kEnableSyncOnBlue = 3, - kEnableSyncOnGreen = 4, - kEnableSyncOnRed = 5, - kNoSeparateSyncControlBit = 6, - kTriStateSyncBit = 7, - kHorizontalSyncMask = 0x01, - kVerticalSyncMask = 0x02, - kCompositeSyncMask = 0x04, - kDPMSSyncMask = 0x07, - kTriStateSyncMask = 0x80, - kSyncOnBlueMask = 0x08, - kSyncOnGreenMask = 0x10, - kSyncOnRedMask = 0x20, - kSyncOnMask = 0x38 -}; - -enum { - /* Power Mode constants for translating DPMS modes to Get/SetSync calls. */ - kDPMSSyncOn = 0, - kDPMSSyncStandby = 1, - kDPMSSyncSuspend = 2, - kDPMSSyncOff = 7 -}; - -/* Bit definitions for the Get/Set Convolution call*/ -enum { - kConvolved = 0, - kLiveVideoPassThru = 1, - kConvolvedMask = 0x01, - kLiveVideoPassThruMask = 0x02 -}; - - - -struct VPBlock { - long vpBaseOffset; /*Offset to page zero of video RAM (From minorBaseOS).*/ - short vpRowBytes; /*Width of each row of video memory.*/ - Rect vpBounds; /*BoundsRect for the video display (gives dimensions).*/ - short vpVersion; /*PixelMap version number.*/ - short vpPackType; - long vpPackSize; - long vpHRes; /*Horizontal resolution of the device (pixels per inch).*/ - long vpVRes; /*Vertical resolution of the device (pixels per inch).*/ - short vpPixelType; /*Defines the pixel type.*/ - short vpPixelSize; /*Number of bits in pixel.*/ - short vpCmpCount; /*Number of components in pixel.*/ - short vpCmpSize; /*Number of bits per component*/ - long vpPlaneBytes; /*Offset from one plane to the next.*/ -}; -typedef struct VPBlock VPBlock; -typedef VPBlock * VPBlockPtr; - -struct VDEntryRecord { - Ptr csTable; /*(long) pointer to color table entry=value, r,g,b:INTEGER*/ -}; -typedef struct VDEntryRecord VDEntryRecord; - -typedef VDEntryRecord * VDEntRecPtr; -/* Parm block for SetGray control call */ - -struct VDGrayRecord { - Boolean csMode; /*Same as GDDevType value (0=color, 1=mono)*/ - SInt8 filler; -}; -typedef struct VDGrayRecord VDGrayRecord; - -typedef VDGrayRecord * VDGrayPtr; -/* Parm block for SetInterrupt call */ - -struct VDFlagRecord { - SInt8 csMode; - SInt8 filler; -}; -typedef struct VDFlagRecord VDFlagRecord; - -typedef VDFlagRecord * VDFlagRecPtr; -/* Parm block for SetEntries control call */ - -struct VDSetEntryRecord { - ColorSpec * csTable; /*Pointer to an array of color specs*/ - short csStart; /*Which spec in array to start with, or -1*/ - short csCount; /*Number of color spec entries to set*/ -}; -typedef struct VDSetEntryRecord VDSetEntryRecord; - -typedef VDSetEntryRecord * VDSetEntryPtr; -/* Parm block for SetGamma control call */ - -struct VDGammaRecord { - Ptr csGTable; /*pointer to gamma table*/ -}; -typedef struct VDGammaRecord VDGammaRecord; - -typedef VDGammaRecord * VDGamRecPtr; - -struct VDBaseAddressInfoRec { - long csDevData; /* LONGINT - (long) timing mode */ - long csDevBase; /* LONGINT - (long) base address of the mode */ - short csModeReserved; /* INTEGER - (short) will some day be the depth */ - long csModeBase; /* LONGINT - (long) reserved */ -}; -typedef struct VDBaseAddressInfoRec VDBaseAddressInfoRec; - -typedef VDBaseAddressInfoRec * VDBaseAddressInfoPtr; - -struct VDSwitchInfoRec { - unsigned short csMode; /*(word) mode depth*/ - unsigned long csData; /*(long) functional sResource of mode*/ - unsigned short csPage; /*(word) page to switch in*/ - Ptr csBaseAddr; /*(long) base address of page (return value)*/ - unsigned long csReserved; /*(long) Reserved (set to 0) */ -}; -typedef struct VDSwitchInfoRec VDSwitchInfoRec; - -typedef VDSwitchInfoRec * VDSwitchInfoPtr; - -struct VDTimingInfoRec { - unsigned long csTimingMode; /* LONGINT - (long) timing mode (a la InitGDevice) */ - unsigned long csTimingReserved; /* LONGINT - (long) reserved */ - unsigned long csTimingFormat; /* LONGINT - (long) what format is the timing info */ - unsigned long csTimingData; /* LONGINT - (long) data supplied by driver */ - unsigned long csTimingFlags; /* LONGINT - (long) mode within device */ -}; -typedef struct VDTimingInfoRec VDTimingInfoRec; - -typedef VDTimingInfoRec * VDTimingInfoPtr; - -struct VDDisplayConnectInfoRec { - unsigned short csDisplayType; /* INTEGER - (word) Type of display connected */ - unsigned char csConnectTaggedType; /* BYTE - type of tagging */ - unsigned char csConnectTaggedData; /* BYTE - tagging data */ - unsigned long csConnectFlags; /* LONGINT - (long) tell us about the connection */ - unsigned long csDisplayComponent; /* LONGINT - (long) if the card has a direct connection to the display, it returns the display component here (FUTURE) */ - unsigned long csConnectReserved; /* LONGINT - (long) reserved */ -}; -typedef struct VDDisplayConnectInfoRec VDDisplayConnectInfoRec; - -typedef VDDisplayConnectInfoRec * VDDisplayConnectInfoPtr; - -struct VDMultiConnectInfoRec { - unsigned long csDisplayCountOrNumber; /* For GetMultiConnect, returns count n of 1..n connections; otherwise, indicates the ith connection.*/ - VDDisplayConnectInfoRec csConnectInfo; /* Standard VDDisplayConnectionInfo for connection i.*/ -}; -typedef struct VDMultiConnectInfoRec VDMultiConnectInfoRec; - -typedef VDMultiConnectInfoRec * VDMultiConnectInfoPtr; -/* RawSenseCode - This abstract data type is not exactly abstract. Rather, it is merely enumerated constants - for the possible raw sense code values when 'standard' sense code hardware is implemented. - - For 'standard' sense code hardware, the raw sense is obtained as follows: - o Instruct the frame buffer controller NOT to actively drive any of the monitor sense lines - o Read the state of the monitor sense lines 2, 1, and 0. (2 is the MSB, 0 the LSB) - - IMPORTANT Note: - When the 'kTaggingInfoNonStandard' bit of 'csConnectFlags' is FALSE, then these constants - are valid 'csConnectTaggedType' values in 'VDDisplayConnectInfo' - -*/ -typedef unsigned char RawSenseCode; -enum { - kRSCZero = 0, - kRSCOne = 1, - kRSCTwo = 2, - kRSCThree = 3, - kRSCFour = 4, - kRSCFive = 5, - kRSCSix = 6, - kRSCSeven = 7 -}; - - -/* ExtendedSenseCode - This abstract data type is not exactly abstract. Rather, it is merely enumerated constants - for the values which are possible when the extended sense algorithm is applied to hardware - which implements 'standard' sense code hardware. - - For 'standard' sense code hardware, the extended sense code algorithm is as follows: - (Note: as described here, sense line 'A' corresponds to '2', 'B' to '1', and 'C' to '0') - o Drive sense line 'A' low and read the values of 'B' and 'C'. - o Drive sense line 'B' low and read the values of 'A' and 'C'. - o Drive sense line 'C' low and read the values of 'A' and 'B'. - - In this way, a six-bit number of the form BC/AC/AB is generated. - - IMPORTANT Note: - When the 'kTaggingInfoNonStandard' bit of 'csConnectFlags' is FALSE, then these constants - are valid 'csConnectTaggedData' values in 'VDDisplayConnectInfo' - -*/ -typedef unsigned char ExtendedSenseCode; -enum { - kESCZero21Inch = 0x00, /* 21" RGB */ - kESCOnePortraitMono = 0x14, /* Portrait Monochrome */ - kESCTwo12Inch = 0x21, /* 12" RGB */ - kESCThree21InchRadius = 0x31, /* 21" RGB (Radius) */ - kESCThree21InchMonoRadius = 0x34, /* 21" Monochrome (Radius) */ - kESCThree21InchMono = 0x35, /* 21" Monochrome */ - kESCFourNTSC = 0x0A, /* NTSC */ - kESCFivePortrait = 0x1E, /* Portrait RGB */ - kESCSixMSB1 = 0x03, /* MultiScan Band-1 (12" thru 1Six") */ - kESCSixMSB2 = 0x0B, /* MultiScan Band-2 (13" thru 19") */ - kESCSixMSB3 = 0x23, /* MultiScan Band-3 (13" thru 21") */ - kESCSixStandard = 0x2B, /* 13"/14" RGB or 12" Monochrome */ - kESCSevenPAL = 0x00, /* PAL */ - kESCSevenNTSC = 0x14, /* NTSC */ - kESCSevenVGA = 0x17, /* VGA */ - kESCSeven16Inch = 0x2D, /* 16" RGB (GoldFish) */ - kESCSevenPALAlternate = 0x30, /* PAL (Alternate) */ - kESCSeven19Inch = 0x3A, /* Third-Party 19" */ - kESCSevenDDC = 0x3E, /* DDC display */ - kESCSevenNoDisplay = 0x3F /* No display connected */ -}; - -/* DepthMode - This abstract data type is used to to reference RELATIVE pixel depths. - Its definition is largely derived from its past usage, analogous to 'xxxVidMode' - - Bits per pixel DOES NOT directly map to 'DepthMode' For example, on some - graphics hardware, 'kDepthMode1' may represent 1 BPP, whereas on other - hardware, 'kDepthMode1' may represent 8BPP. - - DepthMode IS considered to be ordinal, i.e., operations such as <, >, ==, etc. - behave as expected. The values of the constants which comprise the set are such - that 'kDepthMode4 < kDepthMode6' behaves as expected. -*/ -typedef unsigned short DepthMode; -enum { - kDepthMode1 = 128, - kDepthMode2 = 129, - kDepthMode3 = 130, - kDepthMode4 = 131, - kDepthMode5 = 132, - kDepthMode6 = 133 -}; - -enum { - kFirstDepthMode = 128, /* These constants are obsolete, and just included */ - kSecondDepthMode = 129, /* for clients that have converted to the above */ - kThirdDepthMode = 130, /* kDepthModeXXX constants. */ - kFourthDepthMode = 131, - kFifthDepthMode = 132, - kSixthDepthMode = 133 -}; - - - -struct VDPageInfo { - short csMode; /*(word) mode within device*/ - long csData; /*(long) data supplied by driver*/ - short csPage; /*(word) page to switch in*/ - Ptr csBaseAddr; /*(long) base address of page*/ -}; -typedef struct VDPageInfo VDPageInfo; - -typedef VDPageInfo * VDPgInfoPtr; - -struct VDSizeInfo { - short csHSize; /*(word) desired/returned h size*/ - short csHPos; /*(word) desired/returned h position*/ - short csVSize; /*(word) desired/returned v size*/ - short csVPos; /*(word) desired/returned v position*/ -}; -typedef struct VDSizeInfo VDSizeInfo; - -typedef VDSizeInfo * VDSzInfoPtr; - -struct VDSettings { - short csParamCnt; /*(word) number of params*/ - short csBrightMax; /*(word) max brightness*/ - short csBrightDef; /*(word) default brightness*/ - short csBrightVal; /*(word) current brightness*/ - short csCntrstMax; /*(word) max contrast*/ - short csCntrstDef; /*(word) default contrast*/ - short csCntrstVal; /*(word) current contrast*/ - short csTintMax; /*(word) max tint*/ - short csTintDef; /*(word) default tint*/ - short csTintVal; /*(word) current tint*/ - short csHueMax; /*(word) max hue*/ - short csHueDef; /*(word) default hue*/ - short csHueVal; /*(word) current hue*/ - short csHorizDef; /*(word) default horizontal*/ - short csHorizVal; /*(word) current horizontal*/ - short csHorizMax; /*(word) max horizontal*/ - short csVertDef; /*(word) default vertical*/ - short csVertVal; /*(word) current vertical*/ - short csVertMax; /*(word) max vertical*/ -}; -typedef struct VDSettings VDSettings; -typedef VDSettings * VDSettingsPtr; - -struct VDDefMode { - UInt8 csID; - SInt8 filler; -}; -typedef struct VDDefMode VDDefMode; -typedef VDDefMode * VDDefModePtr; - -struct VDSyncInfoRec { - UInt8 csMode; - UInt8 csFlags; -}; -typedef struct VDSyncInfoRec VDSyncInfoRec; - -typedef VDSyncInfoRec * VDSyncInfoPtr; -typedef UInt32 AVIDType; -typedef AVIDType DisplayIDType; -typedef UInt32 DisplayModeID; -typedef UInt32 VideoDeviceType; -typedef UInt32 GammaTableID; -/* - All displayModeID values from 0x80000000 to 0xFFFFFFFF and 0x00 - are reserved for Apple Computer. -*/ -/* Constants for the cscGetNextResolution call */ -enum { - kDisplayModeIDCurrent = 0x00, /* Reference the Current DisplayModeID */ - kDisplayModeIDInvalid = (long)0xFFFFFFFF, /* A bogus DisplayModeID in all cases */ - kDisplayModeIDFindFirstResolution = (long)0xFFFFFFFE, /* Used in cscGetNextResolution to reset iterator */ - kDisplayModeIDNoMoreResolutions = (long)0xFFFFFFFD, /* Used in cscGetNextResolution to indicate End Of List */ - kDisplayModeIDFindFirstProgrammable = (long)0xFFFFFFFC, /* Used in cscGetNextResolution to find unused programmable timing */ - kDisplayModeIDBootProgrammable = (long)0xFFFFFFFB, /* This is the ID given at boot time by the OF driver to a programmable timing */ - kDisplayModeIDReservedBase = (long)0x80000000 /* Lowest (unsigned) DisplayModeID reserved by Apple */ -}; - -/* Constants for the GetGammaInfoList call */ -enum { - kGammaTableIDFindFirst = (long)0xFFFFFFFE, /* Get the first gamma table ID */ - kGammaTableIDNoMoreTables = (long)0xFFFFFFFD, /* Used to indicate end of list */ - kGammaTableIDSpecific = 0x00 /* Return the info for the given table id */ -}; - -/* Constants for GetMultiConnect call*/ -enum { - kGetConnectionCount = (long)0xFFFFFFFF, /* Used to get the number of possible connections in a "multi-headed" framebuffer environment.*/ - kActivateConnection = (0 << kConnectionInactive), /* Used for activating a connection (csConnectFlags value).*/ - kDeactivateConnection = (1 << kConnectionInactive) /* Used for deactivating a connection (csConnectFlags value.)*/ -}; - -/* VDCommunicationRec.csBusID values*/ -enum { - kVideoDefaultBus = 0 -}; - - -/* VDCommunicationInfoRec.csBusType values*/ -enum { - kVideoBusTypeInvalid = 0, - kVideoBusTypeI2C = 1 -}; - - -/* VDCommunicationRec.csSendType and VDCommunicationRec.csReplyType values*/ -enum { - kVideoNoTransactionType = 0, /* No transaction*/ - kVideoSimpleI2CType = 1, /* Simple I2C message*/ - kVideoDDCciReplyType = 2 /* DDC/ci message (with imbedded length)*/ -}; - -// VDCommunicationRec.csCommFlags and VDCommunicationInfoRec.csSupportedCommFlags -enum { - kVideoReplyMicroSecDelayMask = (1<<0) /* If set, the driver should delay csMinReplyDelay micro seconds between send and receive*/ -}; - - -struct VDResolutionInfoRec { - DisplayModeID csPreviousDisplayModeID; /* ID of the previous resolution in a chain */ - DisplayModeID csDisplayModeID; /* ID of the next resolution */ - unsigned long csHorizontalPixels; /* # of pixels in a horizontal line at the max depth */ - unsigned long csVerticalLines; /* # of lines in a screen at the max depth */ - Fixed csRefreshRate; /* Vertical Refresh Rate in Hz */ - DepthMode csMaxDepthMode; /* 0x80-based number representing max bit depth */ - unsigned long csResolutionFlags; /* Reserved - flag bits */ - unsigned long csReserved; /* Reserved */ -}; -typedef struct VDResolutionInfoRec VDResolutionInfoRec; - -typedef VDResolutionInfoRec * VDResolutionInfoPtr; - -struct VDVideoParametersInfoRec { - DisplayModeID csDisplayModeID; /* the ID of the resolution we want info on */ - DepthMode csDepthMode; /* The bit depth we want the info on (0x80 based) */ - VPBlockPtr csVPBlockPtr; /* Pointer to a video parameter block */ - unsigned long csPageCount; /* Number of pages supported by the resolution */ - VideoDeviceType csDeviceType; /* Device Type: Direct, Fixed or CLUT; */ - UInt32 csDepthFlags; /* Flags */ -}; -typedef struct VDVideoParametersInfoRec VDVideoParametersInfoRec; - -typedef VDVideoParametersInfoRec * VDVideoParametersInfoPtr; - -struct VDGammaInfoRec { - GammaTableID csLastGammaID; /* the ID of the previous gamma table */ - GammaTableID csNextGammaID; /* the ID of the next gamma table */ - Ptr csGammaPtr; /* Ptr to a gamma table data */ - unsigned long csReserved; /* Reserved */ -}; -typedef struct VDGammaInfoRec VDGammaInfoRec; - -typedef VDGammaInfoRec * VDGammaInfoPtr; - -struct VDGetGammaListRec { - GammaTableID csPreviousGammaTableID; /* ID of the previous gamma table */ - GammaTableID csGammaTableID; /* ID of the gamma table following csPreviousDisplayModeID */ - unsigned long csGammaTableSize; /* Size of the gamma table in bytes */ - char * csGammaTableName; /* Gamma table name (c-string) */ -}; -typedef struct VDGetGammaListRec VDGetGammaListRec; - -typedef VDGetGammaListRec * VDGetGammaListPtr; - -struct VDRetrieveGammaRec { - GammaTableID csGammaTableID; /* ID of gamma table to retrieve */ - GammaTbl * csGammaTablePtr; /* Location to copy desired gamma to */ -}; -typedef struct VDRetrieveGammaRec VDRetrieveGammaRec; - -typedef VDRetrieveGammaRec * VDRetrieveGammaPtr; - -struct VDSetHardwareCursorRec { - void * csCursorRef; /* reference to cursor data */ - UInt32 csReserved1; /* reserved for future use */ - UInt32 csReserved2; /* should be ignored */ -}; -typedef struct VDSetHardwareCursorRec VDSetHardwareCursorRec; - -typedef VDSetHardwareCursorRec * VDSetHardwareCursorPtr; - -struct VDDrawHardwareCursorRec { - SInt32 csCursorX; /* x coordinate */ - SInt32 csCursorY; /* y coordinate */ - UInt32 csCursorVisible; /* true if cursor is must be visible */ - UInt32 csReserved1; /* reserved for future use */ - UInt32 csReserved2; /* should be ignored */ -}; -typedef struct VDDrawHardwareCursorRec VDDrawHardwareCursorRec; - -typedef VDDrawHardwareCursorRec * VDDrawHardwareCursorPtr; - -struct VDSupportsHardwareCursorRec { - UInt32 csSupportsHardwareCursor; - /* true if hardware cursor is supported */ - UInt32 csReserved1; /* reserved for future use */ - UInt32 csReserved2; /* must be zero */ -}; -typedef struct VDSupportsHardwareCursorRec VDSupportsHardwareCursorRec; - -typedef VDSupportsHardwareCursorRec * VDSupportsHardwareCursorPtr; - -struct VDHardwareCursorDrawStateRec { - SInt32 csCursorX; /* x coordinate */ - SInt32 csCursorY; /* y coordinate */ - UInt32 csCursorVisible; /* true if cursor is visible */ - UInt32 csCursorSet; /* true if cursor successfully set by last set control call */ - UInt32 csReserved1; /* reserved for future use */ - UInt32 csReserved2; /* must be zero */ -}; -typedef struct VDHardwareCursorDrawStateRec VDHardwareCursorDrawStateRec; - -typedef VDHardwareCursorDrawStateRec * VDHardwareCursorDrawStatePtr; - -struct VDConvolutionInfoRec { - DisplayModeID csDisplayModeID; /* the ID of the resolution we want info on */ - DepthMode csDepthMode; /* The bit depth we want the info on (0x80 based) */ - unsigned long csPage; - UInt32 csFlags; - UInt32 csReserved; -}; -typedef struct VDConvolutionInfoRec VDConvolutionInfoRec; - -typedef VDConvolutionInfoRec * VDConvolutionInfoPtr; - -struct VDPowerStateRec { - unsigned long powerState; - unsigned long powerFlags; - - unsigned long powerReserved1; - unsigned long powerReserved2; -}; -typedef struct VDPowerStateRec VDPowerStateRec; - -typedef VDPowerStateRec * VDPowerStatePtr; -/* - Private Data to video drivers. - - In versions of MacOS with multiple address spaces (System 8), the OS - must know the extent of parameters in order to move them between the caller - and driver. The old private-selector model for video drivers does not have - this information so: - - For post-7.x Systems private calls should be implemented using the cscPrivateCall -*/ - -struct VDPrivateSelectorDataRec { - LogicalAddress privateParameters; /* Caller's parameters*/ - ByteCount privateParametersSize; /* Size of data sent from caller to driver*/ - LogicalAddress privateResults; /* Caller's return area. Can be nil, or same as privateParameters.*/ - ByteCount privateResultsSize; /* Size of data driver returns to caller. Can be nil, or same as privateParametersSize.*/ -}; -typedef struct VDPrivateSelectorDataRec VDPrivateSelectorDataRec; - - -struct VDPrivateSelectorRec { - UInt32 reserved; /* Reserved (set to 0). */ - VDPrivateSelectorDataRec data[1]; -}; -typedef struct VDPrivateSelectorRec VDPrivateSelectorRec; - -struct VDDDCBlockRec { - UInt32 ddcBlockNumber; /* Input -- DDC EDID (Extended Display Identification Data) number (1-based) */ - ResType ddcBlockType; /* Input -- DDC block type (EDID/VDIF) */ - UInt32 ddcFlags; /* Input -- DDC Flags*/ - UInt32 ddcReserved; /* Reserved */ - Byte ddcBlockData[128]; /* Output -- DDC EDID/VDIF data (kDDCBlockSize) */ -}; -typedef struct VDDDCBlockRec VDDDCBlockRec; - -typedef VDDDCBlockRec * VDDDCBlockPtr; - -enum { - /* timingSyncConfiguration*/ - kSyncInterlaceMask = (1 << 7), - kSyncAnalogCompositeMask = 0, - kSyncAnalogCompositeSerrateMask = (1 << 2), - kSyncAnalogCompositeRGBSyncMask = (1 << 1), - kSyncAnalogBipolarMask = (1 << 3), - kSyncAnalogBipolarSerrateMask = (1 << 2), - kSyncAnalogBipolarSRGBSyncMask = (1 << 1), - kSyncDigitalCompositeMask = (1 << 4), - kSyncDigitalCompositeSerrateMask = (1 << 2), - kSyncDigitalCompositeMatchHSyncMask = (1 << 2), - kSyncDigitalSeperateMask = (1 << 4) + (1 << 3), - kSyncDigitalVSyncPositiveMask = (1 << 2), - kSyncDigitalHSyncPositiveMask = (1 << 1) -}; - - - - -struct VDDisplayTimingRangeRec { - UInt32 csRangeSize; /* Init to sizeof(VDDisplayTimingRangeRec) */ - UInt32 csRangeType; /* Init to 0 */ - UInt32 csRangeVersion; /* Init to 0 */ - UInt32 csRangeReserved; /* Init to 0 */ - - UInt32 csRangeBlockIndex; /* Requested block (first index is 0)*/ - UInt32 csRangeGroup; /* set to 0 */ - UInt32 csRangeBlockCount; /* # blocks */ - UInt32 csRangeFlags; /* dependent video */ - - UInt64 csMinPixelClock; /* Min dot clock in Hz */ - UInt64 csMaxPixelClock; /* Max dot clock in Hz */ - - UInt32 csMaxPixelError; /* Max dot clock error */ - UInt32 csTimingRangeSyncFlags; - UInt32 csTimingRangeSignalLevels; - UInt32 csReserved0; - - UInt32 csMinFrameRate; /* Hz */ - UInt32 csMaxFrameRate; /* Hz */ - UInt32 csMinLineRate; /* Hz */ - UInt32 csMaxLineRate; /* Hz */ - - - UInt32 csMaxHorizontalTotal; /* Clocks - Maximum total (active + blanking) */ - UInt32 csMaxVerticalTotal; /* Clocks - Maximum total (active + blanking) */ - UInt32 csMaxTotalReserved1; /* Reserved */ - UInt32 csMaxTotalReserved2; /* Reserved */ - - - - /* Some cards require that some timing elements*/ - /* be multiples of a "character size" (often 8*/ - /* clocks). The "xxxxCharSize" fields document*/ - /* those requirements.*/ - - - UInt8 csCharSizeHorizontalActive; /* Character size */ - UInt8 csCharSizeHorizontalBlanking; /* Character size */ - UInt8 csCharSizeHorizontalSyncOffset; /* Character size */ - UInt8 csCharSizeHorizontalSyncPulse; /* Character size */ - - UInt8 csCharSizeVerticalActive; /* Character size */ - UInt8 csCharSizeVerticalBlanking; /* Character size */ - UInt8 csCharSizeVerticalSyncOffset; /* Character size */ - UInt8 csCharSizeVerticalSyncPulse; /* Character size */ - - UInt8 csCharSizeHorizontalBorderLeft; /* Character size */ - UInt8 csCharSizeHorizontalBorderRight; /* Character size */ - UInt8 csCharSizeVerticalBorderTop; /* Character size */ - UInt8 csCharSizeVerticalBorderBottom; /* Character size */ - - UInt8 csCharSizeHorizontalTotal; /* Character size for active + blanking */ - UInt8 csCharSizeVerticalTotal; /* Character size for active + blanking */ - UInt16 csCharSizeReserved1; /* Reserved (Init to 0) */ - - - UInt32 csMinHorizontalActiveClocks; - UInt32 csMaxHorizontalActiveClocks; - UInt32 csMinHorizontalBlankingClocks; - UInt32 csMaxHorizontalBlankingClocks; - - UInt32 csMinHorizontalSyncOffsetClocks; - UInt32 csMaxHorizontalSyncOffsetClocks; - UInt32 csMinHorizontalPulseWidthClocks; - UInt32 csMaxHorizontalPulseWidthClocks; - - UInt32 csMinVerticalActiveClocks; - UInt32 csMaxVerticalActiveClocks; - UInt32 csMinVerticalBlankingClocks; - UInt32 csMaxVerticalBlankingClocks; - - UInt32 csMinVerticalSyncOffsetClocks; - UInt32 csMaxVerticalSyncOffsetClocks; - UInt32 csMinVerticalPulseWidthClocks; - UInt32 csMaxVerticalPulseWidthClocks; - - - UInt32 csMinHorizontalBorderLeft; - UInt32 csMaxHorizontalBorderLeft; - UInt32 csMinHorizontalBorderRight; - UInt32 csMaxHorizontalBorderRight; - - UInt32 csMinVerticalBorderTop; - UInt32 csMaxVerticalBorderTop; - UInt32 csMinVerticalBorderBottom; - UInt32 csMaxVerticalBorderBottom; - - UInt32 csReserved1; /* Reserved (Init to 0)*/ - UInt32 csReserved2; /* Reserved (Init to 0)*/ - UInt32 csReserved3; /* Reserved (Init to 0)*/ - UInt32 csReserved4; /* Reserved (Init to 0)*/ - - UInt32 csReserved5; /* Reserved (Init to 0)*/ - UInt32 csReserved6; /* Reserved (Init to 0)*/ - UInt32 csReserved7; /* Reserved (Init to 0)*/ - UInt32 csReserved8; /* Reserved (Init to 0)*/ -}; -typedef struct VDDisplayTimingRangeRec VDDisplayTimingRangeRec; - -typedef VDDisplayTimingRangeRec * VDDisplayTimingRangePtr; - -enum { - /* csDisplayModeState*/ - kDMSModeReady = 0, /* Display Mode ID is configured and ready*/ - kDMSModeNotReady = 1, /* Display Mode ID is is being programmed*/ - kDMSModeFree = 2 /* Display Mode ID is not associated with a timing*/ -}; - - -/* Video driver Errors -10930 to -10959 */ -enum { - kTimingChangeRestrictedErr = -10930, - kVideoI2CReplyPendingErr = -10931, - kVideoI2CTransactionErr = -10932, - kVideoI2CBusyErr = -10933, - kVideoI2CTransactionTypeErr = -10934, - kVideoBufferSizeErr = -10935 -}; - - -enum { - /* csTimingRangeSignalLevels*/ - kRangeSupportsSignal_0700_0300_Bit = 0, - kRangeSupportsSignal_0714_0286_Bit = 1, - kRangeSupportsSignal_1000_0400_Bit = 2, - kRangeSupportsSignal_0700_0000_Bit = 3, - kRangeSupportsSignal_0700_0300_Mask = (1 << kRangeSupportsSignal_0700_0300_Bit), - kRangeSupportsSignal_0714_0286_Mask = (1 << kRangeSupportsSignal_0714_0286_Bit), - kRangeSupportsSignal_1000_0400_Mask = (1 << kRangeSupportsSignal_1000_0400_Bit), - kRangeSupportsSignal_0700_0000_Mask = (1 << kRangeSupportsSignal_0700_0000_Bit) -}; - - -enum { - /* csSignalConfig*/ - kDigitalSignalBit = 0, /* Do not set. Mac OS does not currently support arbitrary digital timings*/ - kAnalogSetupExpectedBit = 1, /* Analog displays - display expects a blank-to-black setup or pedestal. See VESA signal standards.*/ - kDigitalSignalMask = (1 << kDigitalSignalBit), - kAnalogSetupExpectedMask = (1 << kAnalogSetupExpectedBit) -}; - - -enum { - /* csSignalLevels for analog*/ - kAnalogSignalLevel_0700_0300 = 0, - kAnalogSignalLevel_0714_0286 = 1, - kAnalogSignalLevel_1000_0400 = 2, - kAnalogSignalLevel_0700_0000 = 3 -}; - - -enum { - /* csTimingRangeSyncFlags*/ - kRangeSupportsSeperateSyncsBit = 0, - kRangeSupportsSyncOnGreenBit = 1, - kRangeSupportsCompositeSyncBit = 2, - kRangeSupportsVSyncSerrationBit = 3, - kRangeSupportsSeperateSyncsMask = (1 << kRangeSupportsSeperateSyncsBit), - kRangeSupportsSyncOnGreenMask = (1 << kRangeSupportsSyncOnGreenBit), - kRangeSupportsCompositeSyncMask = (1 << kRangeSupportsCompositeSyncBit), - kRangeSupportsVSyncSerrationMask = (1 << kRangeSupportsVSyncSerrationBit) -}; - - - -enum { - /* csHorizontalSyncConfig and csVerticalSyncConfig*/ - kSyncPositivePolarityBit = 0, /* Digital separate sync polarity for analog interfaces (0 => negative polarity)*/ - kSyncPositivePolarityMask = (1 << kSyncPositivePolarityBit) -}; - - - - -/* For timings with kDetailedTimingFormat.*/ - -struct VDDetailedTimingRec { - UInt32 csTimingSize; /* Init to sizeof(VDDetailedTimingRec)*/ - UInt32 csTimingType; /* Init to 0*/ - UInt32 csTimingVersion; /* Init to 0*/ - UInt32 csTimingReserved; /* Init to 0*/ - - DisplayModeID csDisplayModeID; /* Init to 0*/ - UInt32 csDisplayModeSeed; /* */ - UInt32 csDisplayModeState; /* Display Mode state*/ - UInt32 csDisplayModeAlias; /* Mode to use when programmed.*/ - - UInt32 csSignalConfig; - UInt32 csSignalLevels; - - UInt64 csPixelClock; /* Hz*/ - - UInt64 csMinPixelClock; /* Hz - With error what is slowest actual clock */ - UInt64 csMaxPixelClock; /* Hz - With error what is fasted actual clock */ - - - UInt32 csHorizontalActive; /* Pixels*/ - UInt32 csHorizontalBlanking; /* Pixels*/ - UInt32 csHorizontalSyncOffset; /* Pixels*/ - UInt32 csHorizontalSyncPulseWidth; /* Pixels*/ - - UInt32 csVerticalActive; /* Lines*/ - UInt32 csVerticalBlanking; /* Lines*/ - UInt32 csVerticalSyncOffset; /* Lines*/ - UInt32 csVerticalSyncPulseWidth; /* Lines*/ - - UInt32 csHorizontalBorderLeft; /* Pixels*/ - UInt32 csHorizontalBorderRight; /* Pixels*/ - UInt32 csVerticalBorderTop; /* Lines*/ - UInt32 csVerticalBorderBottom; /* Lines*/ - - UInt32 csHorizontalSyncConfig; - UInt32 csHorizontalSyncLevel; /* Future use (init to 0)*/ - UInt32 csVerticalSyncConfig; - UInt32 csVerticalSyncLevel; /* Future use (init to 0)*/ - - UInt32 csReserved1; /* Init to 0*/ - UInt32 csReserved2; /* Init to 0*/ - UInt32 csReserved3; /* Init to 0*/ - UInt32 csReserved4; /* Init to 0*/ - - UInt32 csReserved5; /* Init to 0*/ - UInt32 csReserved6; /* Init to 0*/ - UInt32 csReserved7; /* Init to 0*/ - UInt32 csReserved8; /* Init to 0*/ -}; -typedef struct VDDetailedTimingRec VDDetailedTimingRec; - -typedef VDDetailedTimingRec * VDDetailedTimingPtr; -typedef UInt32 VDClutBehavior; -typedef VDClutBehavior * VDClutBehaviorPtr; -enum { - kSetClutAtSetEntries = 0, /* SetEntries behavior is to update clut during SetEntries call*/ - kSetClutAtVBL = 1 /* SetEntries behavior is to upate clut at next vbl*/ -}; - - - -struct VDCommunicationRec { - SInt32 csBusID; /* kVideoDefaultBus for single headed cards.*/ - UInt32 csCommFlags; /* Always zero*/ - UInt32 csMinReplyDelay; /* Minimum delay between send and reply transactions (units depend on csCommFlags)*/ - UInt32 csReserved2; /* Always zero*/ - - UInt32 csSendAddress; /* Usually I2C address (eg 0x6E)*/ - UInt32 csSendType; /* See kVideoSimpleI2CType etc.*/ - LogicalAddress csSendBuffer; /* Pointer to the send buffer*/ - ByteCount csSendSize; /* Number of bytes to send*/ - - UInt32 csReplyAddress; /* Address from which to read (eg 0x6F for kVideoDDCciReplyType I2C address)*/ - UInt32 csReplyType; /* See kVideoDDCciReplyType etc.*/ - LogicalAddress csReplyBuffer; /* Pointer to the reply buffer*/ - ByteCount csReplySize; /* Max bytes to reply (size of csReplyBuffer)*/ - - UInt32 csReserved3; - UInt32 csReserved4; - UInt32 csReserved5; /* Always zero*/ - UInt32 csReserved6; /* Always zero*/ -}; -typedef struct VDCommunicationRec VDCommunicationRec; - -typedef VDCommunicationRec * VDCommunicationPtr; - -struct VDCommunicationInfoRec { - SInt32 csBusID; /* kVideoDefaultBus for single headed cards. */ - UInt32 csBusType; /* See kVideoBusI2C etc.*/ - SInt32 csMinBus; /* Minimum bus (usually kVideoDefaultBus). Used to probe additional busses*/ - SInt32 csMaxBus; /* Max bus (usually kVideoDefaultBus). Used to probe additional busses*/ - - UInt32 csSupportedTypes; /* Bit field for first 32 supported transaction types. Eg. 0x07 => support for kVideoNoTransactionType, kVideoSimpleI2CType and kVideoDDCciReplyType.*/ - UInt32 csSupportedCommFlags; /* Return the flags csCommFlags understood by this driver. */ - UInt32 csReserved2; /* Always zero*/ - UInt32 csReserved3; /* Always zero*/ - - UInt32 csReserved4; /* Always zero*/ - UInt32 csReserved5; /* Always zero*/ - UInt32 csReserved6; /* Always zero*/ - UInt32 csReserved7; /* Always zero*/ -}; -typedef struct VDCommunicationInfoRec VDCommunicationInfoRec; - -typedef VDCommunicationInfoRec * VDCommunicationInfoPtr; - -#if PRAGMA_STRUCT_ALIGN - #pragma options align=reset -#elif PRAGMA_STRUCT_PACKPUSH - #pragma pack(pop) -#elif PRAGMA_STRUCT_PACK - #pragma pack() -#endif - -#ifdef PRAGMA_IMPORT_OFF -#pragma import off -#elif PRAGMA_IMPORT -#pragma import reset -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* __IOMACOSVIDEO__ */ - diff --git a/iokit/IOKit/ndrvsupport/IONDRVFramebuffer.h b/iokit/IOKit/ndrvsupport/IONDRVFramebuffer.h deleted file mode 100644 index f285d98be..000000000 --- a/iokit/IOKit/ndrvsupport/IONDRVFramebuffer.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1997-1998 Apple Computer, Inc. - * - * - * HISTORY - * - * sdouglas 22 Oct 97 - first checked in. - * sdouglas 24 Jul 98 - start IOKit. - * sdouglas 15 Dec 98 - cpp. - * - */ - -#ifndef _IOKIT_IONDRVFRAMEBUFFER_H -#define _IOKIT_IONDRVFRAMEBUFFER_H - -#include <IOKit/graphics/IOFramebuffer.h> -#include <IOKit/ndrvsupport/IOMacOSVideo.h> -#include <IOKit/ndrvsupport/IONDRVSupport.h> - - -#define kIONDRVDisableKey "AAPL,disable-ndrv" - - -class IONDRVFramebuffer : public IOFramebuffer -{ - OSDeclareDefaultStructors(IONDRVFramebuffer) - -protected: -/*! @struct ExpansionData - @discussion This structure will be used to expand the capablilties of this class in the future. - */ - struct ExpansionData { }; - -/*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * reserved; - -protected: - - IOService * nub; - class IONDRV * ndrv; - - // current configuration - IODisplayModeID currentDisplayMode; - IOIndex currentDepth; - IOIndex currentPage; - bool directMode; - - IOPhysicalAddress physicalFramebuffer; - IODeviceMemory * vramRange; - - UInt8 startAt8; - UInt8 grayMode; - UInt8 lastGrayMode; - VDClutBehavior lastClutSetting; - UInt8 platformDeepSleep; - - bool consoleDevice; - UInt32 powerState; - UInt32 ndrvState; - SInt32 ndrvEnter; - OSArray * detailedTimings; - UInt32 detailedTimingsSeed; - UInt32 * detailedTimingsCurrent; - - IODeviceMemory * vramMemory; - - VDResolutionInfoRec cachedVDResolution; - - struct _VSLService * vslServices; - - UInt32 accessFlags; - UInt8 shouldDoI2CPower; - - UInt8 __reservedB[3]; - UInt32 __reservedA[31]; - -private: - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 0); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 1); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 2); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 3); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 4); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 5); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 6); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 7); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 8); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 9); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 10); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 11); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 12); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 13); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 14); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 15); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 16); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 17); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 18); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 19); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 20); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 21); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 22); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 23); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 24); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 25); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 26); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 27); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 28); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 29); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 30); - OSMetaClassDeclareReservedUnused(IONDRVFramebuffer, 31); - -private: - - void initForPM ( void ); - IOReturn setPowerState( unsigned long, IOService* ); - unsigned long maxCapabilityForDomainState( IOPMPowerFlags ); - unsigned long initialPowerStateForDomainState( IOPMPowerFlags ); - unsigned long powerStateForDomainState( IOPMPowerFlags ); - - virtual IOReturn checkDriver( void ); - virtual UInt32 iterateAllModes( IODisplayModeID * displayModeIDs ); - virtual IOReturn getResInfoForMode( IODisplayModeID modeID, - IODisplayModeInformation * theInfo ); - virtual IOReturn getResInfoForArbMode( IODisplayModeID modeID, - IODisplayModeInformation * theInfo ); - virtual IOReturn validateDisplayMode( - IODisplayModeID mode, IOOptionBits flags, - VDDetailedTimingRec ** detailed ); - virtual IOReturn setDetailedTiming( - IODisplayModeID mode, IOOptionBits options, - void * description, IOByteCount descripSize ); - virtual void getCurrentConfiguration( void ); - static const IOTVector * _undefinedSymbolHandler( void * self, - const char * libraryName, const char * symbolName ); - void displayI2CPower( bool enable ); - static bool _videoJackStateChangeHandler( void * target, void * ref, - IOService * resourceService ); - -public: - virtual IOReturn doControl( UInt32 code, void * params ); - virtual IOReturn doStatus( UInt32 code, void * params ); - -public: - - virtual IOService * probe( IOService * provider, - SInt32 * score ); - - virtual bool start( IOService * provider ); - - virtual void free( void ); - - virtual IOReturn setProperties( OSObject * properties ); - - virtual IOReturn enableController( void ); - - virtual IODeviceMemory * makeSubRange( IOPhysicalAddress start, - IOPhysicalLength length ); - virtual IODeviceMemory * getApertureRange( IOPixelAperture aperture ); - virtual IODeviceMemory * getVRAMRange( void ); - - virtual IODeviceMemory * findVRAM( void ); - - virtual bool isConsoleDevice( void ); - - virtual const IOTVector * undefinedSymbolHandler( const char * libraryName, - const char * symbolName ); - - virtual const char * getPixelFormats( void ); - - // Array of supported display modes - virtual IOItemCount getDisplayModeCount( void ); - virtual IOReturn getDisplayModes( IODisplayModeID * allDisplayModes ); - - // Info about a display mode - virtual IOReturn getInformationForDisplayMode( IODisplayModeID displayMode, - IODisplayModeInformation * info ); - - // Mask of pixel formats available in mode and depth - virtual UInt64 getPixelFormatsForDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - - virtual IOReturn getPixelInformation( - IODisplayModeID displayMode, IOIndex depth, - IOPixelAperture aperture, IOPixelInformation * pixelInfo ); - - // Framebuffer info - - // Current display mode and depth - virtual IOReturn getCurrentDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ); - - // Set display mode and depth - virtual IOReturn setDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - - // For pages - virtual IOReturn setApertureEnable( IOPixelAperture aperture, - IOOptionBits enable ); - - virtual IOReturn setStartupDisplayMode( IODisplayModeID displayMode, - IOIndex depth ); - virtual IOReturn getStartupDisplayMode( IODisplayModeID * displayMode, - IOIndex * depth ); - - //// CLUTs - - virtual IOReturn setCLUTWithEntries( IOColorEntry * colors, UInt32 index, - UInt32 numEntries, IOOptionBits options ); - - //// Gamma - - virtual IOReturn setGammaTable( UInt32 channelCount, UInt32 dataCount, - UInt32 dataWidth, void * data ); - - //// Display mode timing information - - virtual IOReturn getTimingInfoForDisplayMode( IODisplayModeID displayMode, - IOTimingInformation * info ); - - //// Detailed timing information - - virtual IOReturn validateDetailedTiming( - void * description, IOByteCount descripSize ); - - virtual IOReturn setDetailedTimings( OSArray * array ); - - //// Controller attributes - - virtual IOReturn getAttribute( IOSelect attribute, UInt32 * value ); - - //// Connections - - virtual IOItemCount getConnectionCount( void ); - - virtual IOReturn getAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 * value ); - - virtual IOReturn setAttributeForConnection( IOIndex connectIndex, - IOSelect attribute, UInt32 info ); - - // Apple sensing - - virtual IOReturn getAppleSense( IOIndex connectIndex, - UInt32 * senseType, - UInt32 * primary, - UInt32 * extended, - UInt32 * displayType ); - - virtual IOReturn connectFlags( IOIndex connectIndex, - IODisplayModeID displayMode, IOOptionBits * flags ); - - //// IOHighLevelDDCSense - - virtual bool hasDDCConnect( IOIndex connectIndex ); - virtual IOReturn getDDCBlock( IOIndex connectIndex, UInt32 blockNumber, - IOSelect blockType, IOOptionBits options, - UInt8 * data, IOByteCount * length ); - - //// Interrupts - - virtual IOReturn registerForInterruptType( IOSelect interruptType, - IOFBInterruptProc proc, OSObject * target, void * ref, - void ** interruptRef ); - virtual IOReturn unregisterInterrupt( void * interruptRef ); - virtual IOReturn setInterruptState( void * interruptRef, UInt32 state ); - - //// HW Cursors - - virtual IOReturn setCursorImage( void * cursorImage ); - virtual IOReturn setCursorState( SInt32 x, SInt32 y, bool visible ); - - //// VSL calls - - static OSStatus VSLNewInterruptService( - void * entryID, - UInt32 serviceType, - _VSLService ** serviceID ); - static OSStatus VSLDisposeInterruptService( _VSLService * serviceID ); - static OSStatus VSLDoInterruptService( _VSLService * serviceID ); - static Boolean VSLPrepareCursorForHardwareCursor( - void * cursorRef, - IOHardwareCursorDescriptor * hwDesc, - IOHardwareCursorInfo * hwCursorInfo ); -}; - -#endif /* ! _IOKIT_IONDRVFRAMEBUFFER_H */ - - diff --git a/iokit/IOKit/ndrvsupport/IONDRVSupport.h b/iokit/IOKit/ndrvsupport/IONDRVSupport.h deleted file mode 100644 index 7763c4412..000000000 --- a/iokit/IOKit/ndrvsupport/IONDRVSupport.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef __IONDRVSUPPORT__ -#define __IONDRVSUPPORT__ - -#include <libkern/OSTypes.h> - -#pragma options align=mac68k - -#ifdef __cplusplus -extern "C" { -#endif - -#define kIONDRVIgnoreKey "AAPL,iokit-ignore-ndrv" -#define kIONDRVForXKey "AAPL,iokit-ndrv" - -struct IOTVector { - void * pc; - UInt32 toc; -}; -typedef struct IOTVector IOTVector; - -struct IONDRVInterruptSetMember { - void * setID; - UInt32 member; -}; -typedef struct IONDRVInterruptSetMember IONDRVInterruptSetMember; - -typedef SInt32 (*IONDRVInterruptHandler)( IONDRVInterruptSetMember setMember, void *refCon, UInt32 theIntCount); -typedef void (*IONDRVInterruptEnabler)( IONDRVInterruptSetMember setMember, void *refCon); -typedef Boolean (*IONDRVInterruptDisabler)( IONDRVInterruptSetMember setMember, void *refCon); - -enum { - kIONDRVFirstMemberNumber = 1, - kIONDRVIsrIsComplete = 0, - kIONDRVIsrIsNotComplete = -1, - kIONDRVMemberNumberParent = -2 -}; - -enum { - kIONDRVReturnToParentWhenComplete = 0x00000001, - kIONDRVReturnToParentWhenNotComplete = 0x00000002 -}; - -enum { - kIONDRVISTChipInterruptSource = 0, - kIONDRVISTOutputDMAInterruptSource = 1, - kIONDRVISTInputDMAInterruptSource = 2, - kIONDRVISTPropertyMemberCount = 3 -}; - -#define kIONDRVISTPropertyName "driver-ist" - -IOReturn -IONDRVInstallInterruptFunctions(void * setID, - UInt32 member, - void * refCon, - IOTVector * handler, - IOTVector * enabler, - IOTVector * disabler ); - -typedef const IOTVector * (*IONDRVUndefinedSymbolHandler)( void * self, - const char * libraryName, const char * symbolName ); - -#pragma options align=reset - -#ifdef __cplusplus -} -#endif - -#endif /* __IONDRVSUPPORT__ */ diff --git a/iokit/IOKit/ndrvsupport/Makefile b/iokit/IOKit/ndrvsupport/Makefile deleted file mode 100644 index c3e4ddf8d..000000000 --- a/iokit/IOKit/ndrvsupport/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MD_DIR = ndrvsupport -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MD_LIST = IOMacOSTypes.h IOMacOSVideo.h -INSTALL_MD_LCL_LIST = "" -INSTALL_MD_DIR = $(MD_DIR) - -EXPORT_MD_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MD_DIR = IOKit/$(MD_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/network/IOBasicOutputQueue.h b/iokit/IOKit/network/IOBasicOutputQueue.h deleted file mode 100644 index aa3f83c2d..000000000 --- a/iokit/IOKit/network/IOBasicOutputQueue.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOBasicOutputQueue.h - * - * HISTORY - * - */ - -#ifndef _IOBASICOUTPUTQUEUE_H -#define _IOBASICOUTPUTQUEUE_H - -#include <IOKit/IOLocks.h> -#include <IOKit/network/IOOutputQueue.h> -#include <IOKit/network/IOPacketQueue.h> // FIXME - remove - -struct IOMbufQueue; - -/*! @class IOBasicOutputQueue : public IOOutputQueue - @abstract A concrete implementation of an IOOutputQueue. This object - uses a spinlock to protect the packet queue from multiple producers. - A single producer is promoted to become a consumer when the queue is - not active. Otherwise, the producer will simply queue the packet and - return without blocking. - - The flow of packets from the queue to its target can be controlled - by calling methods such as start(), stop(), or service(). The target - is expected to call those methods from a single threaded context, - i.e. the work loop context in a network driver. In addition, the - target must also return a status for every packet delivered by the - consumer thread. This return value is the only mechanism that the - target can use to manage the queue when it is running on the - consumer thread. */ - -class IOBasicOutputQueue : public IOOutputQueue -{ - OSDeclareDefaultStructors( IOBasicOutputQueue ) - -private: - static IOReturn dispatchNetworkDataNotification(void * target, - void * param, - IONetworkData * data, - UInt32 type); - - void dequeue(); - -protected: - OSObject * _target; - IOOutputAction _action; - IOOutputQueueStats * _stats; - IONetworkData * _statsData; - IOSimpleLock * _spinlock; - IOMbufQueue * _inQueue; - IOMbufQueue * _queues[2]; - volatile bool _waitDequeueDone; - volatile UInt32 _state; - volatile UInt32 _serviceCount; - -/*! @function serviceThread - @abstract Method called by the scheduled service thread when it - starts to run. - @discussion Provide an implementation for the serviceThread() method - defined in IOOutputQueue. The service thread is scheduled by service() - to restart a stalled queue when the kServiceAsync options is given. - @param A parameter that was given to scheduleServiceThread(). - This parameter is not used. */ - - virtual void serviceThread(void * param); - -/*! @function output - @abstract Transfer all packets in the mbuf queue to the target. - @param queue A queue of output packets. - @param state Return a state bit defined by IOBasicOutputQueue that - declares the new state of the queue following this method call. - A kStateStalled is returned if the queue should stall, otherwise 0 - is returned. */ - - virtual void output(IOMbufQueue * queue, UInt32 * state); - -/*! @function free - @abstract Free the IOBasicOutputQueue object. - @discussion Release allocated resources, then call super::free(). */ - - virtual void free(); - -/*! @function handleNetworkDataAccess - @abstract Handle an external access to the IONetworkData object - returned by getStatisticsData(). - @param data The IONetworkData object being accessed. - @param type Describes the type of access being performed. - @param param An optional parameter for the handler. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn handleNetworkDataAccess(IONetworkData * data, - UInt32 type, - void * param); - -public: - -/*! @function init - @abstract Initialize an IOBasicOutputQueue object. - @param target The object that will handle packets removed from the - queue, and is usually a subclass of IONetworkController. - @param action The function that will handle packets removed from the - queue. - @param capacity The initial capacity of the output queue. - @result true if initialized successfully, false otherwise. */ - - virtual bool init(OSObject * target, - IOOutputAction action, - UInt32 capacity = 0); - -/*! @function withTarget - @abstract Factory method that will construct and initialize an - IOBasicOutputQueue object. - @param target An IONetworkController object that will handle packets - removed from the queue. - @param capacity The initial capacity of the output queue. - @result An IOBasicOutputQueue object on success, or 0 otherwise. */ - - static IOBasicOutputQueue * withTarget(IONetworkController * target, - UInt32 capacity = 0); - -/*! @function withTarget - @abstract Factory method that will construct and initialize an - IOBasicOutputQueue object. - @param target The object that will handle packets removed from the - queue. - @param action The function that will handle packets removed from the - queue. - @param capacity The initial capacity of the output queue. - @result An IOBasicOutputQueue object on success, or 0 otherwise. */ - - static IOBasicOutputQueue * withTarget(OSObject * target, - IOOutputAction action, - UInt32 capacity = 0); - -/*! @function enqueue - @abstract Called by a client to add a packet, or a chain of packets, - to the queue. - @discussion A packet is described by a mbuf chain, while a chain - of packets is constructed by linking multiple mbuf chains via the - m_nextpkt field. This method can be called by multiple client - threads. - @param m A single packet, or a chain of packets. - @param param A parameter provided by the caller. - @result Always return 0. */ - - virtual UInt32 enqueue(struct mbuf * m, void * param); - -/*! @function start - @abstract Start up the packet flow between the queue and its target. - @discussion Called by the target to start the queue. This will allow - packets to be removed from the queue, and then delivered to the target. - @result true if the queue was started successfully, false otherwise. */ - - virtual bool start(); - -/*! @function stop - @abstract Stop the packet flow between the queue and its target. - @discussion Stop the queue and prevent it from sending packets to its - target. This call is synchronous and it may block. After this method - returns, the queue will no longer call the registered target/action, - even as new packets are added to the queue. The queue will continue to - absorb new packets until the size of the queue reaches its capacity. - The registered action must never call stop(), or a deadlock will occur. - @result Returns the previous running state of the queue, - true if the queue was running, false if the queue was already stopped. */ - - virtual bool stop(); - -/*! @enum An enumeration of the option bits recognized by service(). - @constant kServiceAsync Set this option to service the queue in - an asynchronous manner. The service() call will not block, but a - scheduling latency will be introduced before the queue is serviced. */ - - enum { - kServiceAsync = 0x1 - }; - -/*! @function service - @abstract Service a queue that was stalled by the target. - @discussion A target that stalls the queue must call service() when - it becomes ready to accept more packets. Calling this methods when the - queue is not stalled is harmless. - @result true if the queue was stalled and there were packets sitting in - the queue awaiting delivery, false otherwise. */ - - virtual bool service(IOOptionBits options = 0); - -/*! @function flush - @abstract Drop and free all packets currently held by the queue. - @discussion To ensure that all packets are removed from the queue, - stop() should be called prior to flush(), to make sure there are - no packets in-flight and being delivered to the target. - @result The number of packets that were dropped and freed. */ - - virtual UInt32 flush(); - -/*! @function setCapacity - @abstract Change the number of packets that the queue can hold - before it begins to drop excess packets. - @param capacity The new desired capacity. - @result true if the new capacity was accepted, false otherwise. */ - - virtual bool setCapacity(UInt32 capacity); - -/*! @function getCapacity - @abstract Get the number of packets that the queue can hold. - @discussion The queue will begin to drop incoming packets when the - size of queue reaches its capacity. - @result The current queue capacity. */ - - virtual UInt32 getCapacity() const; - -/*! @function getSize - @abstract Get the number of packets currently held in the queue. - @result The size of the queue. */ - - virtual UInt32 getSize() const; - -/*! @function getDropCount - @abstract Get the number of packets dropped by the queue. - @result The number of packets dropped due to over-capacity, or by - external calls to the flush() method. */ - - virtual UInt32 getDropCount(); - -/*! @function getOutputCount - @sbstract Get the number of packets accepted by the target. - @result The number of times that kIOOutputStatusAccepted is returned by - the target. */ - - virtual UInt32 getOutputCount(); - -/*! @function getRetryCount - @abstract Get the number of instances when the target has refused to - accept the packet provided. - @result The number of times that kIOOutputStatusRetry is returned by the - target. */ - - virtual UInt32 getRetryCount(); - -/*! @function getStallCount - @abstract Get the number of instances when the target has stalled the - queue. - @result The number of times that kIOOutputCommandStall is returned by the - target. */ - - virtual UInt32 getStallCount(); - -/*! @enum An enumeration of the bits in the value returned by getState(). - @constant kStateRunning Set when the queue is running. Calling start() - and stop() will set or clear this bit. - @constant kStateStalled Set when the queue is stalled by the target. - @constant kStateActive Set when a consumer thread is actively removing - packets from the queue and passing them to the target. */ - - enum { - kStateRunning = 0x1, - kStateOutputStalled = 0x2, - kStateOutputActive = 0x4, - kStateOutputServiceMask = 0xff00 - }; - -/*! @function getState - @abstract Get the state of the queue object. - @result The current state of the queue object. */ - - virtual UInt32 getState() const; - -/*! @function getStatisticsData - @abstract Return an IONetworkData object containing statistics counters - updated by the queue. - @result An IONetworkData object. */ - - virtual IONetworkData * getStatisticsData() const; -}; - -#endif /* !_IOBASICOUTPUTQUEUE_H */ diff --git a/iokit/IOKit/network/IOEthernetController.h b/iokit/IOKit/network/IOEthernetController.h deleted file mode 100644 index 10c577aaf..000000000 --- a/iokit/IOKit/network/IOEthernetController.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOEthernetController.h - * - * HISTORY - * - * Dec 3, 1998 jliu - C++ conversion. - */ - -#ifndef _IOETHERNETCONTROLLER_H -#define _IOETHERNETCONTROLLER_H - -#include <IOKit/network/IONetworkController.h> - -/*! @defined kIOEthernetControllerClass - @abstract kIOEthernetControllerClass is the name of the - IOEthernetController class. */ - -#define kIOEthernetControllerClass "IOEthernetController" - -/*! @defined kIOEthernetAddressSize - @abstract The number of bytes in an Ethernet hardware address. */ - -#define kIOEthernetAddressSize 6 - -/*! @defined kIOEthernetMaxPacketSize - @abstract The maximum size of an Ethernet packet, including - the FCS bytes. */ - -#define kIOEthernetMaxPacketSize 1518 - -/*! @defined kIOEthernetMinPacketSize - @abstract The minimum size of an Ethernet packet, including - the FCS bytes. */ - -#define kIOEthernetMinPacketSize 64 - -/*! @defined kIOEthernetCRCSize - @abstract The size in bytes of the 32-bit CRC value appended - to the end of each Ethernet frame. */ - -#define kIOEthernetCRCSize 4 - -/*! @defined kIOEthernetWakeOnLANFilterGroup - @abstract kIOEthernetWakeOnLANFilterGroup describes the name assigned - to the Ethernet wake-On-LAN filter group. */ - -#define kIOEthernetWakeOnLANFilterGroup "IOEthernetWakeOnLANFilterGroup" - -/*! @enum Enumeration of wake-On-LAN filters. - @discussion An enumeration of all filters in the wake-on-LAN filter - group. Each filter listed will respond to a network event that - will trigger a system wake-up. - @constant kIOEthernetWakeOnMagicPacket Reception of a Magic Packet. */ - -enum { - kIOEthernetWakeOnMagicPacket = 0x1 -}; - -/* - * Kernel - */ -#if defined(KERNEL) && defined(__cplusplus) - -struct IOEthernetAddress { - UInt8 bytes[kIOEthernetAddressSize]; -}; - -extern "C" { // FIXME - remove -#include <sys/socket.h> -#include <net/if.h> -#include <net/etherdefs.h> -} - -/*! @defined gIOEthernetWakeOnLANFilterGroup - @discussion gIOEthernetWakeOnLANFilterGroup is an OSSymbol object - that contains the name of the Ethernet wake-on-LAN filter group - defined by kIOEthernetWakeOnLANFilterGroup. */ - -extern const OSSymbol * gIOEthernetWakeOnLANFilterGroup; - -/*! @class IOEthernetController : public IONetworkController - @abstract An abstract superclass for Ethernet controllers. Ethernet - controller drivers should subclass IOEthernetController, and implement - or override the hardware specific methods to create an Ethernet driver. - An interface object (an IOEthernetInterface instance) must be - instantiated by the driver, through attachInterface(), to connect - the controller driver to the data link layer. */ - -class IOEthernetController : public IONetworkController -{ - OSDeclareAbstractStructors( IOEthernetController ) - -protected: - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - -public: - -/*! @function initialize - @abstract IOEthernetController class initializer. - @discussion Create global OSSymbol objects that are used as keys. */ - - static void initialize(); - -/*! @function init - @abstract Initialize an IOEthernetController object. - @param properties A dictionary object containing a property table - associated with this instance. - @result true on success, false otherwise. */ - - virtual bool init(OSDictionary * properties); - -/*! @function getPacketFilters - @abstract Get the set of packet filters supported by the Ethernet - controller in the given filter group. - @discussion The default implementation of the abstract method inherited - from IONetworkController. When the filter group specified is - gIONetworkFilterGroup, then this method will return a value formed by - a bitwise OR of kIOPacketFilterUnicast, kIOPacketFilterBroadcast, - kIOPacketFilterMulticast, kIOPacketFilterPromiscuous. Otherwise, the - return value will be set to zero (0). Subclasses must override this - method if their filtering capability differs from what is reported by - this default implementation. This method is called from the workloop - context, and the result is published to the I/O Kit registry. - @param group The name of the filter group. - @param filters Pointer to the mask of supported filters returned by - this method. - @result kIOReturnSuccess. Drivers that override this - method must return kIOReturnSuccess to indicate success, or an error - return code otherwise. */ - - virtual IOReturn getPacketFilters(const OSSymbol * group, - UInt32 * filters) const; - -/*! @function enablePacketFilter - @abstract Enable one of the supported packet filters from the - given filter group. - @discussion The default implementation of the abstract method inherited - from IONetworkController. This method will call setMulticastMode() or - setPromiscuousMode() when the multicast or the promiscuous filter is to be - enabled. Requests to disable the Unicast or Broadcast filters are handled - silently, without informing the subclass. Subclasses can override this - method to change this default behavior, or to extend it to handle - additional filter types or filter groups. This method call is synchronized - by the workloop's gate. - @param group The name of the filter group containing the filter to be - enabled. - @param aFilter The filter to enable. - @param enabledFilters All filters currently enabled by the client. - @param options Optional flags for the enable request. - @result The return from setMulticastMode() or setPromiscuousMode() if - either of those two methods are called. kIOReturnSuccess if the filter - specified is kIOPacketFilterUnicast or kIOPacketFilterBroadcast. - kIOReturnUnsupported if the filter group specified is not - gIONetworkFilterGroup. */ - - virtual IOReturn enablePacketFilter(const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0); - -/*! @function disablePacketFilter - @abstract Disable a packet filter that is currently enabled from the - given filter group. - @discussion The default implementation of the abstract method inherited - from IONetworkController. This method will call setMulticastMode() or - setPromiscuousMode() when the multicast or the promiscuous filter is to be - disabled. Requests to disable the Unicast or Broadcast filters are handled - silently, without informing the subclass. Subclasses can override this - method to change this default behavior, or to extend it to handle - additional filter types or filter groups. This method call is synchronized - by the workloop's gate. - @param group The name of the filter group containing the filter to be - disabled. - @param aFilter The filter to disable. - @param enabledFilters All filters currently enabled by the client. - @param options Optional flags for the disable request. - @result The return from setMulticastMode() or setPromiscuousMode() if - either of those two methods are called. kIOReturnSuccess if the filter - specified is kIOPacketFilterUnicast or kIOPacketFilterBroadcast. - kIOReturnUnsupported if the filter group specified is not - gIONetworkFilterGroup. */ - - virtual IOReturn disablePacketFilter(const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0); - -/*! @function getHardwareAddress - @abstract Get the Ethernet controller's station address. - @discussion The default implementation of the abstract method inherited - from IONetworkController. This method will call the overloaded form - IOEthernetController::getHardwareAddress() that subclasses are expected - to override. - @param addr The buffer where the controller's hardware address should - be written. - @param inOutAddrBytes The size of the address buffer provided by the - client, and replaced by this method with the actual size of - the hardware address in bytes. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn getHardwareAddress(void * addr, - UInt32 * inOutAddrBytes); - -/*! @function setHardwareAddress - @abstract Set or change the station address used by the Ethernet - controller. - @discussion The default implementation of the abstract method inherited - from IONetworkController. This method will call the overloaded form - IOEthernetController::setHardwareAddress() that subclasses are expected - to override. - @param addr The buffer containing the hardware address provided by - the client. - @param addrBytes The size of the address buffer provided by the - client in bytes. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn setHardwareAddress(const void * addr, - UInt32 addrBytes); - -/*! @function getMaxPacketSize - @abstract Get the maximum packet size supported by the Ethernet - controller, including the frame header and FCS. - @param maxSize Pointer to the return value. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn getMaxPacketSize(UInt32 * maxSize) const; - -/*! @function getMinPacketSize - @abstract Get the minimum packet size supported by the Ethernet - controller, including the frame header and FCS. - @param minSize Pointer to the return value. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn getMinPacketSize(UInt32 * minSize) const; - -/*! @function getPacketFilters - @abstract Get the set of packet filters supported by the Ethernet - controller in the network filter group. - @param filters Pointer to the return value containing a mask of - supported filters. - @result kIOReturnSuccess. Drivers that override this - method must return kIOReturnSuccess to indicate success, or an error - return code otherwise. */ - - virtual IOReturn getPacketFilters(UInt32 * filters) const; - -/*! @function getHardwareAddress - @abstract Get the Ethernet controller's permanent station address. - @discussion. Ethernet drivers must implement this method, by reading the - address from hardware and writing it to the buffer provided. This method - is called from the workloop context. - @param addrP Pointer to an IOEthernetAddress where the hardware address - should be returned. - @result kIOReturnSuccess on success, or an error return code otherwise. */ - - virtual IOReturn getHardwareAddress(IOEthernetAddress * addrP) = 0; - -/*! @function setHardwareAddress - @abstract Set or change the station address used by the Ethernet - controller. - @discussion This method is called in response to a client command to - change the station address used by the Ethernet controller. Implementation - of this method is optional. This method is called from the workloop context. - @param addrP Pointer to an IOEthernetAddress containing the new station - address. - @result The default implementation will always return kIOReturnUnsupported. - If overridden, drivers must return kIOReturnSuccess on success, or an error - return code otherwise. */ - - virtual IOReturn setHardwareAddress(const IOEthernetAddress * addrP); - -/*! @function setMulticastMode - @abstract Enable or disable multicast mode. - @discussion Called by enablePacketFilter() or disablePacketFilter() - when there is a change in the activation state of the multicast filter - identified by kIOPacketFilterMulticast. This method is called from the - workloop context. - @param active True to enable multicast mode, false to disable it. - @result kIOReturnUnsupported. If overridden, drivers must return - kIOReturnSuccess on success, or an error return code otherwise. */ - - virtual IOReturn setMulticastMode(bool active); - -/*! @function setMulticastList - @abstract Set the list of multicast addresses that the multicast filter - should use to match against the destination address of an incoming frame. - The frame should be accepted when a match occurs. - @discussion Called when the multicast group membership of an interface - object is changed. Drivers that support kIOPacketFilterMulticast should - override this method and update the hardware multicast filter using the - list of Ethernet addresses provided. Perfect multicast filtering is - preferred if supported by the hardware, to order to reduce the number of - unwanted packets received. If the number of multicast addresses in the - list exceeds what the hardware is capable of supporting, or if perfect - filtering is not supported, then ideally the hardware should be programmed - to perform imperfect filtering, thorugh some form of hash filtering - mechanism. Only at the last resort should the driver enable reception of - all multicast packets to satisfy this request. This method is called - from the workloop context, and only if the driver reports - kIOPacketFilterMulticast support in getPacketFilters(). - @param addrs An array of Ethernet addresses. This argument must be - ignored if the count argument is 0. - @param count The number of Ethernet addresses in the list. This value - will be zero when the list becomes empty. - @result kIOReturnUnsupported. Drivers must return kIOReturnSuccess to - indicate success, or an error return code otherwise. */ - - virtual IOReturn setMulticastList(IOEthernetAddress * addrs, - UInt32 count); - -/*! @function setPromiscuousMode - @abstract Enable or disable promiscuous mode. - @discussion Called by enablePacketFilter() or disablePacketFilter() - when there is a change in the activation state of the promiscuous - filter identified by kIOPacketFilterPromiscuous. This method is - called from the workloop context. - @param active True to enable promiscuous mode, false to disable it. - @result kIOReturnUnsupported. If overridden, drivers must return - kIOReturnSuccess on success, or an error return code otherwise. */ - - virtual IOReturn setPromiscuousMode(bool active); - -/*! @function setWakeOnMagicPacket - @abstract Enable or disable the wake on Magic Packet support. - @discussion Called by enablePacketFilter() or disablePacketFilter() - when there is a change in the activation state of the wake-on-LAN - filter identified by kIOEthernetWakeOnMagicPacket. This method is - called from the workloop context. - @param active True to enable support for system wake on reception - of a Magic Packet, false to disable it. - @result kIOReturnUnsupported. If overridden, drivers must return - kIOReturnSuccess on success, or an error return code otherwise. */ - - virtual IOReturn setWakeOnMagicPacket(bool active); - -protected: - -/*! @function createInterface - @abstract Create an IOEthernetInterface object. - @discussion Allocate and return a new IOEthernetInterface instance. - A subclass of IONetworkController must implement this method and return - a matching interface object. The implementation in IOEthernetController - will return an IOEthernetInterface object. Subclasses of - IOEthernetController, such as Ethernet controller drivers, will have - little reason to override this implementation. - @result A newly allocated and initialized IOEthernetInterface object. */ - - virtual IONetworkInterface * createInterface(); - -/*! @function free - @abstract Free the IOEthernetController instance. Release resources, - then followed by a call to super::free(). */ - - virtual void free(); - -/*! @function publishProperties - @abstract Publish Ethernet controller properties and capabilities. - @discussion Publish Ethernet controller properties to the property - table. For instance, getHardwareAddress() is called to fetch the - hardware address, and the address is then published to the property - table. This method call is synchronized by the workloop's gate, - and must never be called directly by subclasses. - @result true if all properties and capabilities were discovered, - and published successfully, false otherwise. Returning false will - prevent client objects from attaching to the Ethernet controller - since a property that a client relies upon may be missing. */ - - virtual bool publishProperties(); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IOEthernetController, 0); - OSMetaClassDeclareReservedUnused( IOEthernetController, 1); - OSMetaClassDeclareReservedUnused( IOEthernetController, 2); - OSMetaClassDeclareReservedUnused( IOEthernetController, 3); - OSMetaClassDeclareReservedUnused( IOEthernetController, 4); - OSMetaClassDeclareReservedUnused( IOEthernetController, 5); - OSMetaClassDeclareReservedUnused( IOEthernetController, 6); - OSMetaClassDeclareReservedUnused( IOEthernetController, 7); - OSMetaClassDeclareReservedUnused( IOEthernetController, 8); - OSMetaClassDeclareReservedUnused( IOEthernetController, 9); - OSMetaClassDeclareReservedUnused( IOEthernetController, 10); - OSMetaClassDeclareReservedUnused( IOEthernetController, 11); - OSMetaClassDeclareReservedUnused( IOEthernetController, 12); - OSMetaClassDeclareReservedUnused( IOEthernetController, 13); - OSMetaClassDeclareReservedUnused( IOEthernetController, 14); - OSMetaClassDeclareReservedUnused( IOEthernetController, 15); - OSMetaClassDeclareReservedUnused( IOEthernetController, 16); - OSMetaClassDeclareReservedUnused( IOEthernetController, 17); - OSMetaClassDeclareReservedUnused( IOEthernetController, 18); - OSMetaClassDeclareReservedUnused( IOEthernetController, 19); - OSMetaClassDeclareReservedUnused( IOEthernetController, 20); - OSMetaClassDeclareReservedUnused( IOEthernetController, 21); - OSMetaClassDeclareReservedUnused( IOEthernetController, 22); - OSMetaClassDeclareReservedUnused( IOEthernetController, 23); - OSMetaClassDeclareReservedUnused( IOEthernetController, 24); - OSMetaClassDeclareReservedUnused( IOEthernetController, 25); - OSMetaClassDeclareReservedUnused( IOEthernetController, 26); - OSMetaClassDeclareReservedUnused( IOEthernetController, 27); - OSMetaClassDeclareReservedUnused( IOEthernetController, 28); - OSMetaClassDeclareReservedUnused( IOEthernetController, 29); - OSMetaClassDeclareReservedUnused( IOEthernetController, 30); - OSMetaClassDeclareReservedUnused( IOEthernetController, 31); -}; - -/* - * FIXME: remove this. - */ -enum { - kIOEnetPromiscuousModeOff = false, - kIOEnetPromiscuousModeOn = true, - kIOEnetPromiscuousModeAll = true, - kIOEnetMulticastModeOff = false, - kIOEnetMulticastModeFilter = true -}; -typedef bool IOEnetPromiscuousMode; -typedef bool IOEnetMulticastMode; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOETHERNETCONTROLLER_H */ diff --git a/iokit/IOKit/network/IOEthernetInterface.h b/iokit/IOKit/network/IOEthernetInterface.h deleted file mode 100644 index 805a01a1f..000000000 --- a/iokit/IOKit/network/IOEthernetInterface.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOEthernetInterface.h - * - * HISTORY - * 8-Jan-1999 Joe Liu (jliu) created. - */ - -#ifndef _IOETHERNETINTERFACE_H -#define _IOETHERNETINTERFACE_H - -/*! @defined kIOEthernetInterfaceClass - @abstract kIOEthernetInterfaceClass is the name of the - IOEthernetInterface class. */ - -#define kIOEthernetInterfaceClass "IOEthernetInterface" - -/*! @defined kIOActivePacketFilters - @abstract kIOActivePacketFilters is a property of IOEthernetInterface - objects. It has an OSDictionary value. - @discussion The kIOActivePacketFilters property describes the current - set of packet filters that have been successfully activated. Each - entry in the dictionary is a key/value pair consisting of the filter - group name, and an OSNumber describing the set of active filters for - that group. Entries in this dictionary will mirror those in - kIORequiredPacketFilters if the controller has reported success for - all filter change requests from the IOEthernetInterface object. */ - -#define kIOActivePacketFilters "IOActivePacketFilters" - -/*! @defined kIORequiredPacketFilters - @abstract kIORequiredPacketFilters is a property of IOEthernetInterface - objects. It has an OSDictionary value. - @discussion The kIORequiredPacketFilters property describes the current - set of required packet filters. Each entry in the dictionary is a - key/value pair consisting of the filter group name, and an OSNumber - describing the set of required filters for that group. */ - -#define kIORequiredPacketFilters "IORequiredPacketFilters" - -/*! @defined kIOMulticastAddressList - @abstract kIOMulticastAddressList is a property of IOEthernetInterface - objects. It is an OSData object. - @discussion The kIOMulticastAddressList property describes the - list of multicast addresses that are being used by the - controller to match against the destination address of an - incoming frame. */ - -#define kIOMulticastAddressList "IOMulticastAddressList" -#define kIOMulticastFilterData kIOMulticastAddressList - -/* - * Kernel - */ -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/network/IONetworkInterface.h> -#include <IOKit/network/IOEthernetController.h> -#include <IOKit/network/IOEthernetStats.h> - -/*! @class IOEthernetInterface : public IONetworkInterface - @abstract The Ethernet interface object. An Ethernet controller driver, - that is a subclass of IOEthernetController, will instantiate an object - of this class when the driver calls the attachInterface() method. - This interface object will then vend an Ethernet interface to DLIL, - and manage the connection between the controller driver and the upper - networking layers. Drivers will seldom need to subclass - IOEthernetInterface. */ - -class IOEthernetInterface : public IONetworkInterface -{ - OSDeclareDefaultStructors( IOEthernetInterface ) - -private: - struct arpcom * _arpcom; // Arpcom struct allocated - UInt32 _mcAddrCount; // # of multicast addresses - bool _ctrEnabled; // Is controller enabled? - OSDictionary * _supportedFilters; // Controller's supported filters - OSDictionary * _requiredFilters; // The required filters - OSDictionary * _activeFilters; // Currently active filters - bool _controllerLostPower; // true if controller is unusable - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - - IOReturn enableController(IONetworkController * ctr); - IOReturn setupMulticastFilter(IONetworkController * ctr); - - UInt32 getFilters(const OSDictionary * dict, - const OSSymbol * group); - - bool setFilters(OSDictionary * dict, - const OSSymbol * group, - UInt32 filters); - - IOReturn disableFilter(IONetworkController * ctr, - const OSSymbol * group, - UInt32 filter, - IOOptionBits options = 0); - - IOReturn enableFilter(IONetworkController * ctr, - const OSSymbol * group, - UInt32 filter, - IOOptionBits options = 0); - - int syncSIOCSIFFLAGS(IONetworkController * ctr); - int syncSIOCSIFADDR(IONetworkController * ctr); - int syncSIOCADDMULTI(IONetworkController * ctr); - int syncSIOCDELMULTI(IONetworkController * ctr); - - static int performGatedCommand(void *, void *, void *, void *, void *); - -public: - -/*! @function init - @abstract Initialize an IOEthernetInterface instance. - @discussion Instance variables are initialized, and an arpcom - structure is allocated. - @param controller A network controller object that will service - the interface object being initialized. - @result true on success, false otherwise. */ - - virtual bool init( IONetworkController * controller ); - -/*! @function getNamePrefix - @abstract Return a string containing the prefix to use when - creating a BSD name for this interface. - @discussion The BSD name for each interface object is created by - concatenating a string returned by this method, with an unique - unit number assigned by IONetworkStack. - @result A pointer to a constant C string "en". Therefore, Ethernet - interfaces will be registered with BSD as en0, en1, etc. */ - - virtual const char * getNamePrefix() const; - -protected: - -/*! @function free - @abstract Free the IOEthernetInterface instance. - @discussion The memory allocated for the arpcom structure is released, - followed by a call to super::free(). */ - - virtual void free(); - -/*! @function performCommand - @abstract Handle an ioctl command sent to the Ethernet interface. - @discussion This method handles socket ioctl commands sent to the Ethernet - interface from DLIL. Commands recognized and processed by this method are - SIOCSIFADDR, SIOCSIFFLAGS, SIOCADDMULTI, and SIOCDELMULTI. Other commands - are passed to the superclass. - @param controller The controller object. - @param cmd The ioctl command code. - @param arg0 Command argument 0. Generally a pointer to an ifnet structure - associated with the interface. - @param arg1 Command argument 1. - @result A BSD return value defined in bsd/sys/errno.h. */ - - virtual SInt32 performCommand(IONetworkController * controller, - UInt32 cmd, - void * arg0, - void * arg1); - -/*! @function controllerDidOpen - @abstract A notification that the interface has opened the network - controller. - @discussion This method will be called by IONetworkInterface after a - network controller has accepted an open from this interface object. - IOEthernetInterface will first call the implementation in its - superclass, then inspect the controller through properties published - in the registry. This method is called with the arbitration lock held. - @param controller The controller object that was opened. - @result true on success, false otherwise. Returning false will - cause the controller to be closed, and any pending client opens to be - rejected. */ - - virtual bool controllerDidOpen(IONetworkController * controller); - -/*! @function controllerWillClose - @abstract A notification that the interface will close the network - controller. - @discussion This method will simply call super to propagate the method - call. This method is called with the arbitration lock held. - @param controller The controller that is about to be closed. */ - - virtual void controllerWillClose(IONetworkController * controller); - -/*! @function initIfnet - @abstract Initialize the ifnet structure given. - @discussion IOEthernetInterface will initialize this structure in a manner - that is appropriate for Ethernet interfaces, then call super::initIfnet() - to allow the superclass to perform generic interface initialization. - @param ifp Pointer to an ifnet structure obtained earlier through - the getIfnet() method call. - @result true on success, false otherwise. */ - - virtual bool initIfnet(struct ifnet * ifp); - -/*! @function getIfnet - @abstract Get the ifnet structure allocated by the interface object. - @discussion This method returns a pointer to an ifnet structure - that was allocated by a concrete subclass of IONetworkInterface. - IOEthernetInterface will allocate an arpcom structure during init(), - and returns a pointer to that structure when this method is called. - @result Pointer to an ifnet structure. */ - - virtual struct ifnet * getIfnet() const; - -/*! @function controllerWillChangePowerState - @abstract Handle a notification that the network controller which is - servicing this interface object is about to transition to a new power state. - @discussion If the controller is about to transition to an unusable state, - and it is currently enabled, then the disable() method on the controller is - called. - @param controller The network controller object. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller is switching to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return value is always kIOReturnSuccess. */ - - virtual IOReturn controllerWillChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker); - -/*! @function controllerDidChangePowerState - @abstract Handle a notification that the network controller which is servicing - this interface object has transitioned to a new power state. - @discussion If the controller did transition to a usable state, and it was - previously disabled due to a previous power change, then it is re-enabled. - @param controller The network controller object. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller has switched to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return value is always kIOReturnSuccess. */ - - virtual IOReturn controllerDidChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker); - - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 0); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 1); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 2); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 3); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 4); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 5); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 6); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 7); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 8); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 9); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 10); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 11); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 12); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 13); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 14); - OSMetaClassDeclareReservedUnused( IOEthernetInterface, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOETHERNETINTERFACE_H */ diff --git a/iokit/IOKit/network/IOEthernetStats.h b/iokit/IOKit/network/IOEthernetStats.h deleted file mode 100644 index 15cc89325..000000000 --- a/iokit/IOKit/network/IOEthernetStats.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOEthernetStats.h - Ethernet MIB statistics definitions. - * - * HISTORY - */ - -#ifndef _IOETHERNETSTATS_H -#define _IOETHERNETSTATS_H - -/*! @header IOEthernetStats.h - @discussion Ethernet statistics. */ - -//--------------------------------------------------------------------------- -// Ethernet-like statistics group. - -/*! @typedef IODot3StatsEntry - @discussion Ethernet MIB statistics structure. - @field alignmentErrors dot3StatsAlignmentErrors. - @field fcsErrors dot3StatsFCSErrors. - @field singleCollisionFrames dot3StatsSingleCollisionFrames. - @field multipleCollisionFrames dot3StatsMultipleCollisionFrames. - @field sqeTestErrors dot3StatsSQETestErrors. - @field deferredTransmissions dot3StatsDeferredTransmissions. - @field lateCollisions dot3StatsLateCollisions. - @field excessiveCollisions dot3StatsExcessiveCollisions. - @field internalMacTransmitErrors dot3StatsInternalMacTransmitErrors. - @field carrierSenseErrors dot3StatsCarrierSenseErrors. - @field frameTooLongs dot3StatsFrameTooLongs. - @field internalMacReceiveErrors dot3StatsInternalMacReceiveErrors. - @field etherChipSet dot3StatsEtherChipSet. - @field missedFrames dot3StatsMissedFrames (not in RFC1650). - */ - -typedef struct { - UInt32 alignmentErrors; - UInt32 fcsErrors; - UInt32 singleCollisionFrames; - UInt32 multipleCollisionFrames; - UInt32 sqeTestErrors; - UInt32 deferredTransmissions; - UInt32 lateCollisions; - UInt32 excessiveCollisions; - UInt32 internalMacTransmitErrors; - UInt32 carrierSenseErrors; - UInt32 frameTooLongs; - UInt32 internalMacReceiveErrors; - UInt32 etherChipSet; - UInt32 missedFrames; -} IODot3StatsEntry; - -//--------------------------------------------------------------------------- -// Ethernet-like collision statistics group (optional). - -/*! @typedef IODot3CollEntry - @discussion Collision statistics structure. - @field collFrequencies dot3StatsCollFrequencies. */ - -typedef struct { - UInt32 collFrequencies[16]; -} IODot3CollEntry; - -//--------------------------------------------------------------------------- -// Receiver extra statistics group (not defined by RFC 1650). - -/*! @typedef IODot3RxExtraEntry - @discussion Extra receiver statistics not defined by RFC1650. - @field overruns receiver overruns. - @field watchdogTimeouts watchdog timer expirations. - @field frameTooShorts runt frames. - @field collisionErrors frames damages by late collision. - @field phyErrors PHY receive errors. - @field timeouts receiver timeouts. - @field interrupts receiver interrupts. - @field resets receiver resets. - @field resourceErrors receiver resource shortages. - */ - -typedef struct { - UInt32 overruns; - UInt32 watchdogTimeouts; - UInt32 frameTooShorts; - UInt32 collisionErrors; - UInt32 phyErrors; - UInt32 timeouts; - UInt32 interrupts; - UInt32 resets; - UInt32 resourceErrors; - UInt32 reserved[4]; -} IODot3RxExtraEntry; - -//--------------------------------------------------------------------------- -// Transmitter extra statistics group (not defined by RFC 1650). - -/*! @typedef IODot3TxExtraEntry - @discussion Extra transmitter statistics not defined by RFC1650. - @field underruns transmit underruns. - @field jabbers jabber events. - @field phyErrors PHY transmit errors. - @field timeouts transmitter timeouts. - @field interrupts transmitter interrupts. - @field resets transmitter resets. - @field resourceErrors transmitter resource shortages. - */ - -typedef struct { - UInt32 underruns; - UInt32 jabbers; - UInt32 phyErrors; - UInt32 timeouts; - UInt32 interrupts; - UInt32 resets; - UInt32 resourceErrors; - UInt32 reserved[4]; -} IODot3TxExtraEntry; - -//--------------------------------------------------------------------------- -// Aggregate Ethernet statistics. - -/*! @typedef IOEthernetStats - @discussion Aggregate Ethernet statistics structure. - @field dot3StatsEntry IODot3StatsEntry statistics group. - @field dot3CollEntry IODot3CollEntry statistics group. - @field dot3RxExtraEntry IODot3RxExtraEntry statistics group. - @field dot3TxExtraEntry IODot3TxExtraEntry statistics group. - */ - -typedef struct { - IODot3StatsEntry dot3StatsEntry; - IODot3CollEntry dot3CollEntry; - IODot3RxExtraEntry dot3RxExtraEntry; - IODot3TxExtraEntry dot3TxExtraEntry; -} IOEthernetStats; - -/*! @defined kIOEthernetStatsKey - @discussion Defines the name of an IONetworkData that contains - an IOEthernetStats. */ - -#define kIOEthernetStatsKey "IOEthernetStatsKey" - -#endif /* !_IOETHERNETSTATS_H */ diff --git a/iokit/IOKit/network/IOGatedOutputQueue.h b/iokit/IOKit/network/IOGatedOutputQueue.h deleted file mode 100644 index 37f887fc9..000000000 --- a/iokit/IOKit/network/IOGatedOutputQueue.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOGatedOutputQueue.h - * - * HISTORY - * - */ - -#ifndef _IOGATEDOUTPUTQUEUE_H -#define _IOGATEDOUTPUTQUEUE_H - -#include <IOKit/IOWorkLoop.h> -#include <IOKit/IOCommandGate.h> -#include <IOKit/IOInterruptEventSource.h> -#include <IOKit/network/IOBasicOutputQueue.h> - -/*! @class IOGatedOutputQueue : public IOBasicOutputQueue - @abstract An extension of an IOBasicOutputQueue. An IOCommandGate - object is created by this queue and added to a work loop as an - event source. All calls to the target by the consumer thread must - occur with the gate closed. Therefore, all calls to the target of - this type of queue will be serialized with any other thread that - runs on the same work loop context. This is useful for network - drivers that have a tight hardware coupling between the transmit - and receive engines, and a single-threaded hardware access model - is desirable. */ - -class IOGatedOutputQueue : public IOBasicOutputQueue -{ - OSDeclareDefaultStructors( IOGatedOutputQueue ) - -private: - static void gatedOutput(OSObject * owner, - IOGatedOutputQueue * self, - IOMbufQueue * queue, - UInt32 * state); - - static void restartDeferredOutput(OSObject * owner, - IOInterruptEventSource * sender, - int count); - -protected: - IOCommandGate * _gate; - IOInterruptEventSource * _interruptSrc; - -/*! @function output - @abstract Transfer all packets in the mbuf queue to the target. - @param queue A queue of output packets. - @param state Return a state bit defined by IOBasicOutputQueue that - declares the new state of the queue following this method call. - A kStateStalled is returned if the queue should stall, otherwise 0 - is returned. */ - - virtual void output(IOMbufQueue * queue, UInt32 * state); - -/*! @function free - @abstract Free the IOGatedOutputQueue object. - @discussion Release allocated resources, then call super::free(). */ - - virtual void free(); - -/*! @function output - @abstract Override the method inherited from IOOutputQueue. - @result true if a thread was successfully scheduled to service - the queue. */ - - virtual bool scheduleServiceThread(void * param); - -public: - -/*! @function init - @abstract Initialize an IOGatedOutputQueue object. - @param target The object that will handle packets removed from the - queue, and is usually a subclass of IONetworkController. - @param action The function that will handle packets removed from the - queue. - @param workloop A workloop object. An IOCommandGate object is created - and added to this workloop as an event source. - @param capacity The initial capacity of the output queue. - @result true if initialized successfully, false otherwise. */ - - virtual bool init(OSObject * target, - IOOutputAction action, - IOWorkLoop * workloop, - UInt32 capacity = 0); - -/*! @function withTarget - @abstract Factory method that will construct and initialize an - IOGatedOutputQueue object. - @param target An IONetworkController object that will handle packets - removed from the queue. - @param workloop A workloop object. An IOCommandGate object is created - and added to this workloop as an event source. - @param capacity The initial capacity of the output queue. - @result An IOGatedOutputQueue object on success, or 0 otherwise. */ - - static IOGatedOutputQueue * withTarget(IONetworkController * target, - IOWorkLoop * workloop, - UInt32 capacity = 0); - -/*! @function withTarget - @abstract Factory method that will construct and initialize an - IOGatedOutputQueue object. - @param target The object that will handle packets removed from the - queue. - @param action The function that will handle packets removed from the - queue. - @param workloop A workloop object. An IOCommandGate object is created - and added to this workloop as an event source. - @param capacity The initial capacity of the output queue. - @result An IOGatedOutputQueue object on success, or 0 otherwise. */ - - static IOGatedOutputQueue * withTarget(OSObject * target, - IOOutputAction action, - IOWorkLoop * workloop, - UInt32 capacity = 0); -}; - -#endif /* !_IOGATEDOUTPUTQUEUE_H */ diff --git a/iokit/IOKit/network/IOKernelDebugger.h b/iokit/IOKit/network/IOKernelDebugger.h deleted file mode 100644 index 967e56bbb..000000000 --- a/iokit/IOKit/network/IOKernelDebugger.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOKernelDebugger.cpp - * - * HISTORY - * - */ - -#ifndef _IOKERNELDEBUGGER_H -#define _IOKERNELDEBUGGER_H - -#include <IOKit/IOService.h> - -/*! @typedef IODebuggerRxHandler - @discussion Defines the receive handler that must be implemented - by the target to service KDP receive requests. This handler is called - by kdpReceiveDispatcher(). - @param target The target object. - @param buffer KDP receive buffer. The buffer allocated has room for - 1518 bytes. The receive handler must not overflow this buffer. - @param length The amount of data received and placed into the buffer. - Set to 0 if no frame was received during the poll interval. - @param timeout The amount of time to poll in milliseconds while waiting - for a frame to arrive. */ - -typedef void (*IODebuggerRxHandler)( IOService * target, - void * buffer, - UInt32 * length, - UInt32 timeout ); - -/*! @typedef IODebuggerTxHandler - @discussion Defines the transmit handler that must be implemented - by the target to service KDP transmit requests. This handler is called - by kdpTransmitDispatcher(). - @param target The target object. - @param buffer KDP transmit buffer. This buffer contains a KDP frame - to be sent on the network. - @param length The number of bytes in the transmit buffer. */ - -typedef void (*IODebuggerTxHandler)( IOService * target, - void * buffer, - UInt32 length ); - -/*! @typedef IODebuggerLockState - @discussion Defines flags returned by IOKernelDebugger::lock(). - @constant kIODebuggerLockTaken Set if the debugger lock was taken. */ - -typedef enum { - kIODebuggerLockTaken = 0x1, -} IODebuggerLockState; - -/*! class IOKernelDebugger : public IOService - @abstract Kernel debugger nub. - @discussion This object interfaces with the KDP - (kernel debugger protocol) module and dispatches KDP requests to its - target (provider). The target, designated as the debugger device, must - implement a pair of handler functions that are called to handle KDP - transmit and receive requests during a debugging session. Only a single - IOKernelDebugger in the system can be active at a given time. The - active IOKernelDebugger is the one that has an IOKDP object attached - as a client. - - The debugger device is usually a subclass of IOEthernetController. - However, any IOService can service an IOKernelDebugger client, - implement the two polled mode handlers, and transport the KDP - packets through a data channel. However, KDP assumes that the - debugger device is an Ethernet interface and therefore it will - always send, and expect to receive, an Ethernet frame. */ - -class IOKernelDebugger : public IOService -{ - OSDeclareDefaultStructors( IOKernelDebugger ) - -protected: - IOService * _target; // target (provider) - IODebuggerTxHandler _txHandler; // target's transmit handler. - IODebuggerRxHandler _rxHandler; // target's receive handler. - IOService * _client; // client that has opened us. - bool _pmDisabled; // true if disabled by PM. - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - - static void pmEnableDebugger( IOKernelDebugger * debugger ); - static void pmDisableDebugger( IOKernelDebugger * debugger ); - -/*! @function kdpReceiveDispatcher - @abstract The KDP receive dispatch function. - @discussion Field KDP receive requests, then dispatches the call to the - registered receiver handler. - @param buffer KDP receive buffer. The buffer allocated by KDP has room - for 1518 bytes. The receive handler must not overflow this buffer. - @param length The amount of data received and placed into the buffer. - Set to 0 if a frame was not received during the poll interval. - @param timeout The amount of time to poll in milliseconds while waiting - for a frame to arrive. */ - - static void kdpReceiveDispatcher(void * buffer, - UInt32 * length, - UInt32 timeout); - -/*! @function kdpTransmitDispatcher - @abstract The KDP transmit dispatch function. - @discussion Field KDP transmit requests, then dispatches the call to the - registered transmit handler. - @param buffer KDP transmit buffer. This buffer contains a KDP frame to - be sent on the network. - @param length The number of bytes in the transmit buffer. */ - - static void kdpTransmitDispatcher(void * buffer, UInt32 length); - -/*! @function free - @abstract Free the IOKernelDebugger instance. */ - - virtual void free(); - -/*! @function nullTxHandler - @abstract Null transmit handler. - @discussion This function is registered as the transmit handler when an - IOKernelDebugger object surrenders its status as the active debugger nub. - Until another IOKernelDebugger object gets promoted, this function will - handle polled transmit requests from KDP. This function does nothing - useful. */ - - static void nullTxHandler( IOService * target, - void * buffer, - UInt32 length ); - -/*! @function nullRxHandler - @abstract Null receive handler. - @discussion This function is registered as the receive handler when an - IOKernelDebugger object surrenders its status as the active debugger nub. - Until another IOKernelDebugger object gets promoted, this function will - handle polled receive requests from KDP. This function does nothing - except to log a warning message. */ - - static void nullRxHandler( IOService * target, - void * buffer, - UInt32 * length, - UInt32 timeout ); - -/*! @function registerHandler - @abstract Register the target and the handler functions. - @discussion This method is called by handleOpen() and handleClose() - to register or unregister the target and its handler functions. - @param target The target object. - @param txHandler The transmit handler function. The null handler is - registered if the argument is zero. - @param rxHandler The receive handler function. The null handler is - registered if the argument is zero. */ - - static void registerHandler( IOService * target, - IODebuggerTxHandler txHandler = 0, - IODebuggerRxHandler rxHandler = 0 ); - -/*! @function powerStateWillChangeTo - @abstract Handle notification that the network controller will change - power state. - @discussion If the controller is about to become unusable, then the - controller's handlers are unregistered, and the controller disabled. - @param flags Describe the capability of the controller in the new power - state. - @param stateNumber The number of the state in the state array that the - controller is switching to. - @param policyMaker The policy-maker that manages the controller's - power state. - @result The constant 3000000, to indicate a maximum of 3 seconds for the - preparation to complete, and an acknowledgement delivered to the - policy-maker. */ - - virtual IOReturn powerStateWillChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ); - -/*! @function powerStateDidChangeTo - @abstract Handle notification that the network controller did change - power state. - @discussion If the controller became usable, then the controller is - re-enabled, and the controller's handlers are re-registered. - @param flags Describe the capability of the controller in the new power - state. - @param stateNumber The number of the state in the state array that the - controller is switching to. - @param policyMaker The policy-maker that manages the controller's - power state. - @result The constant 3000000, to indicate a maximum of 3 seconds for the - preparation to complete, and an acknowledgement delivered to the - policy-maker. */ - - virtual IOReturn powerStateDidChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ); - -/*! @function handleOpen - @abstract Handle a client open. - @discussion This method is called by IOService::open() to handle an - open from a client (IOKDP) with the arbitration lock held. - @param forClient The client (IOKDP) requesting the open. - @param options Options passed to the open() call. Not used. - @param arg A family defined argument passed to the open() call. Not used. - @result true on success, false otherwise. */ - - virtual bool handleOpen( IOService * forClient, - IOOptionBits options, - void * arg ); - -/*! @function handleClose - @abstract Handle a client close. - @discussion This method is called by IOService::close() to handle a - close from a client with the arbitration lock held. - @param forClient The client (IOKDP) requesting the close. - @param options Options passed to the close() call. Not used. */ - - virtual void handleClose( IOService * forClient, - IOOptionBits options ); - -/*! @function handleIsOpen - @abstract Query whether a client has an open on this object. - @discussion This method is called by IOService::isOpen() with the - arbitration lock held. - @result true if the specified client, or any client if none (0) is - specified, presently has an open on this object. */ - - virtual bool handleIsOpen( const IOService * forClient ) const; - -public: - -/*! @function lock - @abstract Take the debugger lock conditionally. - @discussion Take the debugger lock if the object given matches the - target registered by registerHandler(). - @param target The target or provider of an IOKernelDebugger object. - @result kIODebuggerLockTaken if the lock was taken, or 0 otherwise. */ - - static IODebuggerLockState lock( IOService * target ); - -/*! @function unlock - @abstract Release the debugger lock. - @discussion Release the debugger lock if the kIODebuggerLockTaken flag is - set in the argument. */ - - static void unlock( IODebuggerLockState state ); - -/*! @function init - @abstract Initialize an IOKernelDebugger instance. - @param target The target object that implements the debugger handlers. - @param txHandler The target's transmit handler. A pointer to a 'C' function. - @param rxHandler The target's receive handler. A pointer to a 'C' function. - @result true if the instance initialized successfully, false otherwise. */ - - virtual bool init( IOService * target, - IODebuggerTxHandler txHandler, - IODebuggerRxHandler rxHandler ); - -/*! @function debugger - @abstract A factory method that performs allocation and initialization - of an IOKernelDebugger object. - @param target The target object that implements the debugger handlers. - @param txHandler The target's transmit handler. A pointer to a 'C' function. - @param rxHandler The target's receive handler. A pointer to a 'C' function. - @result An IOKernelDebugger instance on success, 0 otherwise. */ - - static IOKernelDebugger * debugger( IOService * target, - IODebuggerTxHandler txHandler, - IODebuggerRxHandler rxHandler ); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IOKernelDebugger, 0); - OSMetaClassDeclareReservedUnused( IOKernelDebugger, 1); - OSMetaClassDeclareReservedUnused( IOKernelDebugger, 2); - OSMetaClassDeclareReservedUnused( IOKernelDebugger, 3); -}; - -// Concise form of the lock()/unlock() static member functions. -// -#define IODebuggerLock IOKernelDebugger::lock -#define IODebuggerUnlock IOKernelDebugger::unlock - -#endif /* !_IOKERNELDEBUGGER_H */ diff --git a/iokit/IOKit/network/IOMbufMemoryCursor.h b/iokit/IOKit/network/IOMbufMemoryCursor.h deleted file mode 100644 index 6150c58bb..000000000 --- a/iokit/IOKit/network/IOMbufMemoryCursor.h +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOMbufMemoryCursor.h created by gvdl on 1999-1-20 - * - */ - -#ifndef _IOKIT_NETWORK_IOMBUFMEMORYCURSOR_H -#define _IOKIT_NETWORK_IOMBUFMEMORYCURSOR_H - -#include <IOKit/IOMemoryCursor.h> - -struct mbuf; - -/*! @class IOMbufMemoryCursor : public IOMemoryCursor - @abstract A mechanism to convert mbuf chains to physical addresses. - @discussion The IOMbufMemoryCursor defines the super class that all - specific mbuf cursors must inherit from, but a mbuf cursor can be created - without a specific formal subclass by just providing a segment function to - the initializers. This class performs the task of walking a given - mbuf chain and creating a physical scatter/gather list appropriate for - the target hardware. When necessary, this class may also coalesce - mbuf chains when the generated scatter/gather list exceeds the specified - hardware limit. However, this should be avoided since it exacts a - performance cost. - <br><br> - A driver is expected to create a mbuf cursor and configure it to match the - limitations of it's DMA hardware; for instance the mbuf cursor used by - an Ethernet controller driver may have a maximum physical segment size - of 1520, and allow for up to 6 physical segments. Thus it would create a - mbuf cursor with a maxSegmentSize of 1520 and a maxNumSegments of 6. - The driver may choose to supply an OutputSegmentFunc function to - format the output of each scatter/gather segment to match the - hardware descriptor format, or it may use a subclass of - IOMbufMemoryCursor to generate IOPhysicalSegment segments with - various byte orders. - <br><br> - A driver may also create more than one mbuf cursor, perhaps one - dedicated for the transmit thread, and the other for the receive thread. - This becomes a requirement when the driver is multi-threaded, since the - mbuf cursor maintains state and does not support reentrancy. */ - -class IOMbufMemoryCursor : public IOMemoryCursor -{ - OSDeclareAbstractStructors(IOMbufMemoryCursor) - -protected: - UInt32 maxNumSegments; - UInt32 coalesceCount; - UInt32 packetTooBigErrors; - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData *reserved; - - virtual bool initWithSpecification(OutputSegmentFunc outSeg, - UInt32 maxSegmentSize, - UInt32 maxTransferSize, - UInt32 align); - -public: -/*! @function initWithSpecification - @abstract Primary initializer for the IOMbufMemoryCursor class. - @param outSeg Function to call to output one physical segment. - @param maxSegmentSize Maximum allowable size for one segment. - @param maxNumSegments Maximum number of segments. - @result true if the inherited classes and this instance initialized - successfully. */ - - virtual bool initWithSpecification(OutputSegmentFunc outSeg, - UInt32 maxSegmentSize, - UInt32 maxNumSegments); - -/*! @function genPhysicalSegments - @abstract Generate a physical scatter/gather list given a mbuf packet. - @discussion Generates a list of physical segments from the given mbuf. - @param packet The mbuf packet. - @param vector Void pointer to base of output physical scatter/gather list. - Always passed directly onto the OutputSegmentFunc without interpretation - by the cursor. - @param maxSegs Maximum number of segments that can be written to segments - array. - @param doCoalesce Set to true to perform coalescing when the required - number of segments exceeds the specified limit, otherwise abort and - return 0. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - virtual UInt32 genPhysicalSegments(struct mbuf * packet, void * vector, - UInt32 maxSegs, bool doCoalesce); - -/*! @function getAndResetCoalesceCount - @abstract Returns a count of the total number of mbuf chains coalesced - by genPhysicalSegments(). The counter is then reset to 0. - @result The coalesce count. */ - - UInt32 getAndResetCoalesceCount(); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IOMbufMemoryCursor, 0); - OSMetaClassDeclareReservedUnused( IOMbufMemoryCursor, 1); - OSMetaClassDeclareReservedUnused( IOMbufMemoryCursor, 2); - OSMetaClassDeclareReservedUnused( IOMbufMemoryCursor, 3); -}; - - -/*! @class IOMbufNaturalMemoryCursor : public IOMbufMemoryCursor - @abstract A IOMbufMemoryCursor subclass that outputs a vector of - IOPhysicalSegments in the natural byte orientation for the cpu. - @discussion The IOMbufNaturalMemoryCursor would be used when it is too - difficult to implement an OutputSegmentFunc that is more appropriate for - your hardware. This cursor just outputs an array of IOPhysicalSegments. */ - -class IOMbufNaturalMemoryCursor : public IOMbufMemoryCursor -{ - OSDeclareDefaultStructors(IOMbufNaturalMemoryCursor) - -public: - -/*! @function withSpecification - @abstract Factory function to create and initialize an - IOMbufNaturalMemoryCursor in one operation, see - IOMbufMemoryCursor::initWithSpecification. - @param maxSegmentSize Maximum allowable size for one segment. - @param maxNumSegments Maximum number of segments. - @result A new mbuf cursor if successfully created and initialized, - 0 otherwise. */ - - static IOMbufNaturalMemoryCursor * withSpecification(UInt32 maxSegmentSize, - UInt32 maxNumSegments); - -/*! @function getPhysicalSegments - @abstract Generate a cpu natural physical scatter/gather list from a given - mbuf. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegments(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); - -/*! @function getPhysicalSegmentsWithCoalesce - @abstract Generate a cpu natural physical scatter/gather list from a given - mbuf. - @discussion Generate a cpu natural physical scatter/gather list from a - given mbuf. Coalesce mbuf chain when the number of segments in the - scatter/gather list exceeds numVectorSegments. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegmentsWithCoalesce(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); -}; - -//=========================================================================== -//=========================================================================== - -/*! @class IOMbufBigMemoryCursor : public IOMbufMemoryCursor - @abstract A IOMbufMemoryCursor subclass that outputs a vector of - IOPhysicalSegments in the big endian byte order. - @discussion The IOMbufBigMemoryCursor would be used when the DMA hardware - requires a big endian address and length pair. This cursor outputs an - array of IOPhysicalSegments that are encoded in big-endian format. */ - -class IOMbufBigMemoryCursor : public IOMbufMemoryCursor -{ - OSDeclareDefaultStructors(IOMbufBigMemoryCursor) - -public: - -/*! @function withSpecification - @abstract Factory function to create and initialize an - IOMbufBigMemoryCursor in one operation, see - IOMbufMemoryCursor::initWithSpecification. - @param maxSegmentSize Maximum allowable size for one segment. - @param maxNumSegments Maximum number of segments. - @result A new mbuf cursor if successfully created and initialized, - 0 otherwise. */ - - static IOMbufBigMemoryCursor * withSpecification(UInt32 maxSegmentSize, - UInt32 maxNumSegments); - -/*! @function getPhysicalSegments - @abstract Generate a big endian physical scatter/gather list from a given - mbuf. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegments(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); - -/*! @function getPhysicalSegmentsWithCoalesce - @abstract Generate a big endian physical scatter/gather list from a given - mbuf. - @discussion Generate a big endian physical scatter/gather list from a - given mbuf. Coalesce mbuf chain when the number of segments in the - scatter/gather list exceeds numVectorSegments. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegmentsWithCoalesce(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); -}; - -//=========================================================================== -//=========================================================================== - -/*! @class IOMbufLittleMemoryCursor : public IOMbufMemoryCursor - @abstract A IOMbufMemoryCursor subclass that outputs a vector of - IOPhysicalSegments in the little endian byte order. - @discussion The IOMbufLittleMemoryCursor would be used when the DMA - hardware requires a little endian address and length pair. This cursor - outputs an array of IOPhysicalSegments that are encoded in little endian - format. */ - -class IOMbufLittleMemoryCursor : public IOMbufMemoryCursor -{ - OSDeclareDefaultStructors(IOMbufLittleMemoryCursor) - -public: - -/*! @function withSpecification - @abstract Factory function to create and initialize an - IOMbufLittleMemoryCursor in one operation, see - IOMbufMemoryCursor::initWithSpecification. - @param maxSegmentSize Maximum allowable size for one segment. - @param maxNumSegments Maximum number of segments. - @result A new mbuf cursor if successfully created and initialized, - 0 otherwise. */ - - static IOMbufLittleMemoryCursor * withSpecification(UInt32 maxSegmentSize, - UInt32 maxNumSegments); - -/*! @function getPhysicalSegments - @abstract Generate a little endian physical scatter/gather list from a - given mbuf. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegments(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); - -/*! @function getPhysicalSegmentsWithCoalesce - @abstract Generate a little endian physical scatter/gather list from a - given mbuf. - @discussion Generate a little endian physical scatter/gather list from a - given mbuf. Coalesce mbuf chain when the number of segments in the - scatter/gather list exceeds numVectorSegments. - @param packet The mbuf packet. - @param vector Pointer to an array of IOPhysicalSegments for the output - physical scatter/gather list. - @param numVectorSegments Maximum number of IOPhysicalSegments accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegmentsWithCoalesce(struct mbuf * packet, - struct IOPhysicalSegment * vector, - UInt32 numVectorSegments = 0); -}; - -#ifdef __ppc__ - -struct IODBDMADescriptor; - -//=========================================================================== -//=========================================================================== - -/*! @class IOMbufDBDMAMemoryCursor : public IOMbufMemoryCursor - @abstract A IOMbufMemoryCursor subclass that outputs a vector of - IODBDMADescriptors. */ - -class IOMbufDBDMAMemoryCursor : public IOMbufMemoryCursor -{ - OSDeclareDefaultStructors(IOMbufDBDMAMemoryCursor) - -public: - -/*! @function withSpecification - @abstract Factory function to create and initialize an - IOMbufDBDMAMemoryCursor in one operation, see - IOMbufMemoryCursor::initWithSpecification. - @param maxSegmentSize Maximum allowable size for one segment. - @param maxNumSegments Maximum number of segments. - @result A new mbuf cursor if successfully created and initialized, - 0 otherwise. */ - - static IOMbufDBDMAMemoryCursor * withSpecification(UInt32 maxSegmentSize, - UInt32 maxNumSegments); - -/*! @function getPhysicalSegments - @abstract Generate a DBDMA descriptor list from a given mbuf. - @param packet The mbuf packet. - @param vector Pointer to an array of IODBDMADescriptor for the output list. - @param numVectorSegments Maximum number of IODBDMADescriptors accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegments(struct mbuf * packet, - struct IODBDMADescriptor *vector, - UInt32 numVectorSegments = 0); - -/*! @function getPhysicalSegmentsWithCoalesce - @abstract Generate a DBDMA descriptor list from a given mbuf. - @discussion Generate a DBDMA descriptor list from a given mbuf. - Coalesce mbuf chain when the number of elements in the list exceeds - numVectorSegments. - @param packet The mbuf packet. - @param vector Pointer to an array of IODBDMADescriptor for the output list. - @param numVectorSegments Maximum number of IODBDMADescriptors accepted. - @result The number of segments that were filled in is returned, or - 0 if an error occurred. */ - - UInt32 getPhysicalSegmentsWithCoalesce(struct mbuf * packet, - struct IODBDMADescriptor * vector, - UInt32 numVectorSegments = 0); -}; - -#endif /* __ppc__ */ - -inline UInt32 IOMbufMemoryCursor::getAndResetCoalesceCount() -{ - UInt32 cnt = coalesceCount; coalesceCount = 0; return cnt; -} - -inline UInt32 -IOMbufNaturalMemoryCursor::getPhysicalSegments(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, false); -} - -inline UInt32 -IOMbufNaturalMemoryCursor::getPhysicalSegmentsWithCoalesce(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, true); -} - -inline UInt32 -IOMbufBigMemoryCursor::getPhysicalSegments(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, false); -} - -inline UInt32 -IOMbufBigMemoryCursor::getPhysicalSegmentsWithCoalesce(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, true); -} - -inline UInt32 -IOMbufLittleMemoryCursor::getPhysicalSegments(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, false); -} - -inline UInt32 -IOMbufLittleMemoryCursor::getPhysicalSegmentsWithCoalesce(struct mbuf *packet, - struct IOPhysicalSegment *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, true); -} - -#ifdef __ppc__ -inline UInt32 -IOMbufDBDMAMemoryCursor::getPhysicalSegments(struct mbuf *packet, - struct IODBDMADescriptor *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, false); -} - -inline UInt32 -IOMbufDBDMAMemoryCursor::getPhysicalSegmentsWithCoalesce(struct mbuf *packet, - struct IODBDMADescriptor *vector, - UInt32 numVectorSegments = 0) -{ - return genPhysicalSegments(packet, vector, numVectorSegments, true); -} -#endif /* __ppc__ */ - -#endif /* !_IOKIT_NETWORK_IOMBUFMEMORYCURSOR_H */ - diff --git a/iokit/IOKit/network/IONetworkController.h b/iokit/IOKit/network/IONetworkController.h deleted file mode 100644 index e9ca383e6..000000000 --- a/iokit/IOKit/network/IONetworkController.h +++ /dev/null @@ -1,1375 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkController.h - * - * Network controller driver superclass. - * - * HISTORY - * 9-Dec-1998 Joe Liu (jliu) created. - * - */ - -#ifndef _IONETWORKCONTROLLER_H -#define _IONETWORKCONTROLLER_H - -/*! @defined kIONetworkControllerClass - @abstract kIONetworkControllerClass is the name of the - IONetworkController class. */ - -#define kIONetworkControllerClass "IONetworkController" - -/*! @defined kIOVendor - @abstract kIOVendor is a property of IONetworkController objects. - It has an OSString value. - @discussion The kIOVendor property is a string describing the - vendor of the network controller. */ - -#define kIOVendor "IOVendor" - -/*! @defined kIOModel - @abstract kIOModel is a property of IONetworkController objects. - It has an OSString value. - @discussion The kIOModel property is a string describing the - model of the network controller. */ - -#define kIOModel "IOModel" - -/*! @defined kIORevision - @abstract kIORevision is a property of IONetworkController objects. - It has an OSString value. - @discussion The kIORevision property is a string describing the - revision level of the network controller. */ - -#define kIORevision "IORevision" - -/*! @defined kIOFeatures - @abstract kIOFeatures is a property of IONetworkController objects. - It has an OSNumber value. - @discussion The kIOFeatures property describes generic features - defined by IONetworkController that are supported by the - network controller. */ - -#define kIOFeatures "IOFeatures" - -/*! @defined kIOMediumDictionary - @abstract kIOMediumDictionary is a property of IONetworkController - objects. It has an OSDictionary value. - @discussion The kIOMediumDictionary property is a container for the - collection of IONetworkMedium objects that represent the media - types supported by the network controller. - Each entry in the dictionary is a key/value pair consisting of - the medium name, and a dictionary value that contains the - properties for that medium entry. */ - -#define kIOMediumDictionary "IOMediumDictionary" - -/*! @defined kIODefaultMedium - @abstract kIODefaultMedium is a property of IONetworkController - objects. It has an OSString value. - @discussion The kIODefaultMedium property describes the name of the - default medium. This definition may change or disappear in the - future. */ - -#define kIODefaultMedium "IODefaultMedium" - -/*! @defined kIOSelectedMedium - @abstract kIOSelectedMedium is a property of IONetworkController - objects. It has an OSSymbol value. - @discussion The kIOSelectedMedium property describes the name of the - current selected medium. This name can be used as a key into the - medium dictionary to gather additional information about the - selected medium. */ - -#define kIOSelectedMedium "IOSelectedMedium" - -/*! @defined kIOActiveMedium - @abstract kIOActiveMedium is a property of IONetworkController - objects. It has an OSSymbol value. - @discussion The kIOActiveMedium property describes the name of the - active medium. This is the name of the medium where an active - link has been established. This name can be used as a key into - the medium dictionary to gather additional information about the - active medium. */ - -#define kIOActiveMedium "IOActiveMedium" - -/*! @defined kIOLinkSpeed - @abstract kIOLinkSpeed is a property of IONetworkController - objects. It has an OSNumber value. - @discussion The kIOLinkSpeed property describes the speed of the - link established over the active medium in bits per second. */ - -#define kIOLinkSpeed "IOLinkSpeed" - -/*! @defined kIOLinkStatus - @abstract kIOLinkStatus is a property of IONetworkController - objects. It has an OSNumber value. - @discussion The kIOLinkStatus property describes the current network - link status. See IONetworkMedium for the definition of the link - status bits. */ - -#define kIOLinkStatus "IOLinkStatus" - -/*! @defined kIOLinkData - @abstract kIOLinkData is a property of IONetworkController - objects. It has an OSData value. - @discussion The kIOLinkData property contains additional information, - that describes the active link that was established. - Its interpretation is not defined. */ - -#define kIOLinkData "IOLinkData" - -/*! @defined kIOPacketFilters - @abstract kIOPacketFilters is a property of IONetworkController - objects. It has an OSDictionary value. - @discussion The kIOPacketFilters property describes the entire - set of packet filters supported by the controller. Each entry - in the dictionary is a key/value pair consisting of the filter - group name, and an OSNumber describing the set of supported - filters for that group. */ - -#define kIOPacketFilters "IOPacketFilters" - -/*! @defined kIOMACAddress - @abstract kIOMACAddress is a property of IONetworkController - objects. It has an OSData value. - @discussion The kIOMACAddress property describes the hardware - MAC (media access controller) address, or station address, - of the network controller. */ - -#define kIOMACAddress "IOMACAddress" - -/*! @defined kIOMaxPacketSize - @abstract kIOMaxPacketSize is a property of IONetworkController - objects. It has an OSNumber value. - @discussion The kIOMaxPacketSize property describes the maximum - packet size supported by the controller. */ - -#define kIOMaxPacketSize "IOMaxPacketSize" - -/*! @defined kIOMinPacketSize - @abstract kIOMinPacketSize is a property of IONetworkController - objects. It has an OSNumber value. - @discussion The kIOMinPacketSize property describes the minimum - packet size supported by the controller. */ - -#define kIOMinPacketSize "IOMinPacketSize" - -/*! @defined kIONetworkFilterGroup - @abstract kIONetworkFilterGroup describes the name assigned to the - standard network filter group. */ - -#define kIONetworkFilterGroup "IONetworkFilterGroup" - -/*! @enum Enumeration of standard packet filters. - @discussion An enumeration of all standard packet filters. Each - filter will allow the reception of certain class of packets - depending on its destination MAC address. - @constant kIOPacketFilterUnicast Reception of unicast packets. - @constant kIOPacketFilterBroadcast Reception of broadcast packets. - @constant kIOPacketFilterMulticast Reception of multicast packets - addressed to a set of multicast addresses. - @constant kIOPacketFilterMulticastAll Reception of all multicast - packets. - @constant kIOPacketFilterPromiscuous Reception of all packets. - @constant kIOPacketFilterPromiscuousAll Reception of all packets, - including bad packets. */ - -enum { - kIOPacketFilterUnicast = 0x1, - kIOPacketFilterBroadcast = 0x2, - kIOPacketFilterMulticast = 0x10, - kIOPacketFilterMulticastAll = 0x20, - kIOPacketFilterPromiscuous = 0x100, - kIOPacketFilterPromiscuousAll = 0x200, -}; - -/*! @enum Feature flags returned by the getFeatures() method. - @constant kIONetworkFeatureNoBSDWait Set this bit in the value - returned by getFeatures() to disable the automatic wait for - "IOBSD" resource by the IONetworkController::start() method. */ - -enum { - kIONetworkFeatureNoBSDWait = 0x01, -}; - -/* - * Kernel - */ -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/IOService.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/network/IONetworkInterface.h> -#include <IOKit/network/IOKernelDebugger.h> - -struct mbuf; // forward declarations -class IOCommandGate; -class IOOutputQueue; -class IONetworkMedium; - -/*! @typedef IOPacketBufferConstraints - @discussion Constraint parameters, specified by a driver, - for the data buffer in a packet mbuf. This is observed by - allocatePacket() to satisfy the stated requirements. - @field alignStart Starting address byte alignment. - @field alignLength Buffer length byte alignment. */ - -typedef struct { - UInt32 alignStart; - UInt32 alignLength; - UInt32 reserved[6]; -} IOPacketBufferConstraints; - -// Some frequently used alignment constants. -// -enum { - kIOPacketBufferAlign1 = 1, - kIOPacketBufferAlign2 = 2, - kIOPacketBufferAlign4 = 4, - kIOPacketBufferAlign8 = 8, - kIOPacketBufferAlign16 = 16, - kIOPacketBufferAlign32 = 32, -}; - -/*! @defined gIONetworkFilterGroup - @discussion gIONetworkFilterGroup is an OSSymbol object that contains - the name of the standard network filter group as defined by - kIONetworkFilterGroup. */ - -extern const OSSymbol * gIONetworkFilterGroup; - -/*! @class IONetworkController : public IOService - @abstract IONetworkController implements the framework for a generic - network controller. A subclass of IONetworkController must provide - additional functionality specific for a particular networking type. - In addition, the driver must implement (override) a basic set of - hardware dependent methods to create a working driver. - - IONetworkController attaches itself to the data link layer (DLIL) via - an IONetworkInterface object. A controller object without a companion - interface is not accessible to the networking system. The controller - interacts with DLIL by calling methods defined by the interface object. - And conversely, DLIL will issue commands and packets to the controller - through the interface object. - - IONetworkController will create an IOCommandGate and attach this - event source to an IOWorkLoop object. All commands sent from the - interface object are handled through the IOCommandGate object, - which will serialize access to the controller. Outbound packets sent - from the interface to the controller have no implicit serialization. - Drivers must implement an output function that is thread safe, or use - an IOOutputQueue object which will provide a serialization model. - */ - -class IONetworkController : public IOService -{ - OSDeclareAbstractStructors( IONetworkController ) - -private: - - IOWorkLoop * _workLoop; - IOCommandGate * _cmdGate; - IOOutputQueue * _outputQueue; - OSSet * _clientSet; - OSCollectionIterator * _clientSetIter; - OSObject * _cmdClient; - UInt32 _alignStart; - UInt32 _alignLength; - UInt32 _alignPadding; - bool _propertiesPublished; - IOLock * _mediumLock; - IODebuggerLockState _debugLockState; - SInt32 _debugLockCount; - OSNumber * _linkStatus; - OSNumber * _linkSpeed; - const OSData * _lastLinkData; - const OSSymbol * _lastActiveMediumName; - const OSSymbol * _lastCurrentMediumName; - struct mbuf * _freeList; - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - - bool _broadcastEvent(UInt32 type, void * data = 0); - - static void debugRxHandler(IOService * handler, - void * buffer, - UInt32 * length, - UInt32 timeout); - - static void debugTxHandler(IOService * handler, - void * buffer, - UInt32 length); - - static IOReturn executeCommandAction(OSObject * owner, - void * arg0, - void * arg1, - void * arg2, - void * arg3); - - static IOReturn handleCommand(void * target, - void * param0, - void * param1, - void * param2, - void * param3); - -public: - -/*! @function initialize - @abstract IONetworkController class initializer. - @discussion Create frequently used OSSymbol objects that are used as keys. - This method is called explicitly by a line in IOStartIOKit.cpp and not - by the OSDefineMetaClassAndInit() mechanism, to ensure that this method - is called after the OSSymbol class (pool) is initialized. */ - - static void initialize(); - -/*! @function init - @abstract Initialize the IONetworkController object. - @discussion Instance variables are initialized, then super::init() - is called. - @param properties A dictionary object containing a property table - associated with this instance. - @result true on success, false otherwise. */ - - virtual bool init(OSDictionary * properties); - -/*! @function start - @abstract Start the network controller. - @discussion After the controller driver has successfully matched - to a provider, this method is called to start the network controller. - IONetworkController will allocate resources and gather controller - properties in its implementation. No I/O will be performed until - the subclass tries to attach a client object. A driver must override - this method, and call super::start() at the beginning of its own - implementation. Then check the return value to make sure that its - superclass was started successfully before proceeding. Tasks that - are usually performed by a driver's start method are; resource - allocation, hardware initialization, allocation of IOEventSources - and attaching them to a workloop, publishing a medium dictionary, - and finally, attaching an interface object when it is ready to - handle client requests. - @param provider The provider that the controller was matched - (and attached) to. - @result true on success, false otherwise. */ - - virtual bool start(IOService * provider); - -/*! @function stop - @abstract Stop the network controller. - @discussion The counterpart of start(). The controller has been - instructed to stop running. The stop() method should release - resources and undo actions performed by the start() method. - Subclasses must override this method and call super::stop() - at the end of its implementation. - @param provider The provider that the controller was matched - (and attached) to. */ - - virtual void stop(IOService * provider); - -/*! @typedef IONetworkController::Action - @discussion Definition of a C function that can be called - through executeCommand(). - @param target The first argument passed to action. - @param param0 Action parameter 0. - @param param1 Action parameter 1. - @param param2 Action parameter 2. - @param param3 Action parameter 3. */ - - typedef IOReturn (*Action)(void * target, void * param0, - void * param1, - void * param2, - void * param3); - -/*! @function executeCommand - @abstract Make a C function call through the command gate. - @discussion Make a call to a C function that will be synchronized - with the workloop thread, and any other threads that are called - with the workloop's gate closed. - @param client The client requesting the action. This parameter is not - passed to the function. - @param action Pointer to a C function to be executed. - @param target The first parameter in the action callout. - @param param0 Action parameter 0. - @param param1 Action parameter 1. - @param param2 Action parameter 2. - @param param3 Action parameter 3. - @result The value returned by the action. */ - - virtual IOReturn executeCommand(OSObject * client, - Action action, - void * target, - void * param0 = 0, - void * param1 = 0, - void * param2 = 0, - void * param3 = 0); - -/*! @function outputPacket - @abstract Transmit an output packet. - @discussion If an IOOutputQueue was created by createOutputQueue(), - then this method will be called by the output queue object. - Otherwise, an interface object will call this method directly when - it receives an output packet from the data link layer. - - There is no upper limit on the number of mbufs, hence the number of - memory fragments, in the mbuf chain provided. Drivers must be able to - handle cases when the mbuf count might exceed the limit supported by their - DMA engines, and perform coalescing to copy the various memory fragments - into a lesser number of fragments. This complexity can be hidden from - the driver when an IOMbufMemoryCursor is used, which is able to convert - a mbuf chain into a physical address scatter-gather list that will not - exceed a specified number of physically contiguous memory segments. - See IOMbufMemoryCursor. - - The implementation in IONetworkController performs no useful action - and will drop all packets. A driver must override this method and - process the output packet provided. The implementation in the driver - must not block, since this may cause the network stack to be reentered - from an unsafe point. - @param packet A mbuf chain containing the output packet to be sent on - the network. - @param param A parameter provided by the caller. - @result A return code defined by the caller. */ - - virtual UInt32 outputPacket(struct mbuf * packet, void * param); - -/*! @function getFeatures - @abstract Report generic features supported by the controller and/or - the driver. - @result This method will always return 0. Subclasses may override - this method and return a bit mask of all supported features. */ - - virtual UInt32 getFeatures() const; - -/*! @function newVendorString - @result Return a string describing the vendor of the network controller. - The caller is responsible for releasing the string object returned. */ - - virtual const OSString * newVendorString() const; - -/*! @function newModelString - @result Return a string describing the model of the network controller. - The caller is responsible for releasing the string object returned. */ - - virtual const OSString * newModelString() const; - -/*! @function newRevisionString - @result Return a string describing the hardware revision of the - network controller. The caller is responsible for releasing the - string object returned. */ - - virtual const OSString * newRevisionString() const; - -/*! @function getSelectedMedium - @abstract Get the current selected medium. - @discussion If the driver has previously called setSelectedMedium() - to indicate its current media selection, then this method will return - that medium object. Otherwise, the driver's property table is - consulted and a default medium property is examined, and the - corresponding entry in the medium dictionary is returned. - @result The current selected medium, the default medium, or 0. */ - - virtual const IONetworkMedium * getSelectedMedium() const; - inline const IONetworkMedium * getCurrentMedium() const; - -/*! @function getMediumDictionary - @abstract Returns the medium dictionary published by the driver. - @discussion Returns the medium dictionary published by the driver - through publishMediumDictionary(). Use copyMediumDictionary() to - create and get a copy of the medium dictionary. - @result The published medium dictionary, or 0 if the driver has not - yet published a medium dictionary through publishMediumDictionary(). */ - - virtual const OSDictionary * getMediumDictionary() const; - -/*! @function copyMediumDictionary - @abstract Returns a copy of the medium dictionary published by the - driver. - @discussion The caller is responsible for releasing the dictionary - object returned. Use getMediumDictionary() to get a reference to the - published medium dictionary instead of creating a copy. - @result A copy of the medium dictionary, or 0 if the driver has not - published a medium dictionary through publishMediumDictionary(). */ - - virtual OSDictionary * copyMediumDictionary() const; - -/*! @function getOutputHandler - @abstract Get the address of the method designated to handle output - packets for the network controller. - @result A pointer to the outputPacket() method is returned. */ - - virtual IOOutputAction getOutputHandler() const; - -/*! @function doEnable - @abstract Make a synchronized call to enable() through executeCommand(). - @discussion Do not use this method, it may be removed in the future. - See enable(). */ - - virtual IOReturn doEnable(IOService * client); - -/*! @function doDisable - @abstract Make a synchronized call to disable() through executeCommand(). - @discussion Do not use this method, it may be removed in the future. - See disable(). */ - - virtual IOReturn doDisable(IOService * client); - -/*! @function getCommandGate - @abstract Get the IOCommandGate object created by IONetworkController. - @discussion When IONetworkController is started, an IOCommandGate object - is instantiated and attached to the workloop returned by getWorkLoop(). - This IOCommandGate object is used internally to synchronize client - commands handled through executeCommand(). Subclasses that need an - IOCommandGate should try to reuse the object returned by this method, - rather than creating a new instance. See IOCommandGate documentation. - @result The IOCommandGate object created by IONetworkController. */ - - virtual IOCommandGate * getCommandGate() const; - -/*! @function getHardwareAddress - @abstract Get the network controller's permanent hardware/station - address. This method call is synchronized by the workloop's gate. - @param addr The buffer where the controller's hardware address should - be stored. - @param inOutAddrBytes The size of the address buffer provided by the - client, and replaced by this method with the actual size of - the hardware address in bytes. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn getHardwareAddress(void * addr, - UInt32 * inOutAddrBytes) = 0; - -/*! @function setHardwareAddress - @abstract Set or change the station address used by the network - controller. This method call is synchronized by the workloop's gate. - @param buffer The buffer containing the hardware address provided by - the client. - @param addrBytes The size of the address buffer provided by the - client in bytes. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn setHardwareAddress(const void * addr, - UInt32 addrBytes) = 0; - -/*! @function enable - @abstract An enable request from a client. - @discussion Handle an enable request from a client. A client will call - enable after it has opened the controller, and before it starts to use - the controller to send and to receive packets over the network. The - client object provided is typecasted using OSDynamicCast, and depending - on whether the client is an IOKernelDebugger or an IONetworkInterface, - then an overloaded enable method that takes a more specific argument - type is called. If the client matches neither type, then - kIOReturnBadArgument is returned. A driver has the option of overriding - this base enable method, or the overloaded form. This method call is - synchronized by the workloop's gate. - @param client The client object requesting the enable. - @result The return value from the overloaded enable() method, or - kIOReturnBadArgument if the client type is unknown. */ - - virtual IOReturn enable(IOService * client); - -/*! @function disable - @abstract A disable request from a client. - @discussion Handle a disable request from a client. A client will call - disable if it has previously enabled the controller, and it no longer - needs to transport packets or perform I/O using the controller. - The client object is typecasted using OSDynamicCast, and depending on - whether the client is an IOKernelDebugger or an IONetworkInterface, - then an overloaded disable method that takes a more specific argument - type is called. If the client matches neither type, then - kIOReturnBadArgument is returned. A driver has the option of overriding - this base disable method, or the overloaded form. This method call is - synchronized by the workloop's gate. - @param client The client object requesting the disable. - @result The return from the overloaded disable() method, or - kIOReturnBadArgument if the client type is unknown. */ - - virtual IOReturn disable(IOService * client); - -/*! @function setMaxPacketSize - @abstract A client request to change the maximum packet size. - @discussion This method call is synchronized by the workloop's gate. - @param maxSize The new maximum packet size. - @result kIOReturnUnsupported. Drivers may override this method - and return either kIOReturnSuccess to indicate that the new size - was accepted and is in effect, or an error code to indicate failure. */ - - virtual IOReturn setMaxPacketSize(UInt32 maxSize); - -/*! @function getMaxPacketSize - @abstract Get the maximum packet size supported by the controller. - @param maxSize Pointer to the return value. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn getMaxPacketSize(UInt32 * maxSize) const = 0; - -/*! @function getMinPacketSize - @abstract Get the minimum packet size supported by the controller. - @param minSize Pointer to the return value. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn getMinPacketSize(UInt32 * minSize) const = 0; - -/*! @function selectMedium - @abstract A client request to change the medium selection. - @discussion This method is called when a client issues a command - for the controller to change its current medium selection. - The implementation must call setSelectedMedium() after the change - has occurred. This method call is synchronized by the workloop's - gate. - @param medium An entry from the published medium dictionary that - represents the selection chosen by the client. - @result kIOReturnUnsupported. Drivers may override this method and - return kIOReturnSuccess if the selection was successful, - or an error code otherwise. */ - - virtual IOReturn selectMedium(const IONetworkMedium * medium); - -/*! @function selectMediumWithName - @abstract A client request to change the medium selection. - @discussion This method is called when a client issues a command - for the controller to change its current medium selection. - This implementation will look for an entry in the medium - dictionary published by the driver that is associated with the - key given. If a match is found, then selectMedium() is called to - perform the selection, otherwise an error is reported back to the - client. Subclasses should override selectMedium() and not this - method. This method call is synchronized by the workloop's gate. - @param mediumName An OSSymbol object that describes the name of the - new medium selected by the client. - @result The return from selectMedium() if a matching entry was found - from the medium dictionary. kIOReturnUnsupported if a medium - dictionary does not exist, or kIOReturnBadArgument if the name given - does not match any entry in the medium dictionary. */ - - virtual IOReturn selectMediumWithName(const OSSymbol * mediumName); - -/*! @function getPacketFilters - @abstract Get the set of packet filters supported by the network - controller for the given filter group. - @discussion A subclass must implement this method and report the - set of filters that are supported for the given filter group. - This method call is synchronized by the workloop's gate. - @param group The name of the filter group. - @param filters Pointer to the mask of supported filters returned by - this method. - @result kIOReturnSuccess on success, or an error to indicate a - failure to discover the set of supported filters. */ - - virtual IOReturn getPacketFilters(const OSSymbol * group, - UInt32 * filters) const = 0; - -/*! @function enablePacketFilter - @abstract Enable one of the supported packet filters from the - given filter group. - @discussion A client will call this method to enable a supported filter - from the filter group specified. If the client wishes to enable more - than one filter, it must call this method multiple times to enable the - desired set of filters. This method call is synchronized by the - workloop's gate. - @param group The name of the filter group containing the filter to be - enabled. - @param aFilter The filter to enable. - @param enabledFilters All filters currently enabled by the client. - @param options Optional flags for the enable request. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn enablePacketFilter(const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0) = 0; - -/*! @function disablePacketFilter - @abstract Disable a packet filter that is currently enabled from the - given filter group. - @discussion After a supported filter has been successfully enabled, - a client can call this method to disable that filter. This method call - is synchronized by the workloop's gate. - @param group The name of the filter group containing the filter to be - disabled. - @param aFilter The filter to disable. - @param enabledFilters All filters currently enabled by the client. - @param options Optional flags for the disable request. - @result kIOReturnSuccess on success, or an error otherwise. */ - - virtual IOReturn disablePacketFilter(const OSSymbol * group, - UInt32 aFilter, - UInt32 enabledFilters, - IOOptionBits options = 0) = 0; - -/*! @function getOutputQueue - @abstract Get the IOOutputQueue object created by createOutputQueue(). - @result Return a reference to the output queue object created by - createOutputQueue(). */ - - virtual IOOutputQueue * getOutputQueue() const; - -/*! @function getPacketBufferConstraints - @abstract Get the controller's packet buffer constraints. - @discussion Called by start() to obtain the constraints on the - memory buffer for each mbuf packet allocated through allocatePacket(). - Drivers can override this method to specify the buffer constraints - imposed by their bus master hardware. Note that outbound packets, - those that originate from the network stack, are not currently - subject to the constraints reported here. - @param constraints A pointer to an IOPacketBufferConstraints - structure that this method is expected to initialize. - See IOPacketBufferConstraints structure definition. */ - - virtual void getPacketBufferConstraints( - IOPacketBufferConstraints * constraints) const; - -/*! @function allocatePacket - @abstract Allocate a packet with a data buffer that is larger than - or equal to the size specified. - @discussion This method will always return a single mbuf unless the - size requested (plus the alignment padding) is greater than MCLBYTES. - The data buffer for the mbuf (or a mbuf chain) returned is aligned - according to the constraints reported by getPacketBufferConstraints(). - The length fields in each mbuf returned is set by this method, thus - allowing the mbuf to be passed directly to an IOMbufMemoryCursor object - in order to convert the mbuf to a physical address scatter-gather list. - @param size The minimum size of the data buffer for the mbuf - packet allocated. - @result A mbuf packet, or 0 if allocation failed. */ - - virtual struct mbuf * allocatePacket(UInt32 size); - -/*! @function copyPacket - @abstract Allocate a new packet, containing data copied from an - existing source packet. - @discussion The source packet is not modified by this method. - @param m The source packet. - @param size The number of bytes to copy. If set to 0, then the - entire data buffer from the source packet is copied. - @result A new packet containing the same data as the source packet. */ - - virtual struct mbuf * copyPacket(const struct mbuf * m, UInt32 size = 0); - -/*! @function replacePacket - @abstract Allocate a new packet to replace an existing packet, the - existing packet is then returned. - @param mp A handle to the existing packet. - @param size If size is 0, then the new packet shall have the same buffer - size as the original packet that is being replaced. Otherwise, the new - packet shall have the buffer size specified by this value. - @result If packet allocation was successful, then a replacement will - take place and the original packet will be returned. Otherwise, 0 - is returned, and the original packet will be left untouched. */ - - virtual struct mbuf * replacePacket(struct mbuf ** mp, UInt32 size = 0); - -/*! @function replaceOrCopyPacket - @abstract A helper method that combines the functionality of - copyPacket() and replacePacket() to process a packet containing - a received frame. - @discussion This method will either make a copy or replace the existing - packet, whichever is more time efficient. Packets containing small frames - are copied, otherwise they are replaced. If replaced, then the existing - packet is returned, and a new packet with the same buffer size is created - to take its place. If copied, the existing packet is left intact, while a - copy is returned that will hold a copy of the data from the source packet. - @param mp A handle to the existing packet that may be replaced. - @param length The number of bytes received held in the packet. - Must be greater than zero. - @param replaced Pointer to a return value that is set to true to indicate - that the existing packet was replaced, or false to indicate that the - existing packet was not replaced, and a copy was created. - @result A replacement or a copy of the existing packet, or 0 if packet - allocation failed. */ - - virtual struct mbuf * replaceOrCopyPacket(struct mbuf ** mp, - UInt32 length, - bool * replaced); - - enum { - kDelayFree = 0x01 - }; - -/*! @function freePacket - @abstract Release the packet given back to the free pool. - @param m The packet to be freed. - @param options When kDelayFree option is set, then the packet - provided to this function will be queued on the free packet queue. - A subsequent call to releaseFreePackets() will release all queued - packets by making a single BSD function call. Without the kDelayFree - option, the packet provided will be released immediately. */ - - virtual void freePacket(struct mbuf * m, IOOptionBits options = 0); - -/*! @function releaseFreePackets - @abstract Release all packets held in the free packet queue. - @discussion The free packet queue is not protected by a lock. This - function must be called in a single threaded manner with respect to - all calls to freePacket() with the kDelayFree option set. - @result The number of packets queued and released. */ - - virtual UInt32 releaseFreePackets(); - -/*! @enum An enumeration of TCP/IP checksums that may be supported by the - hardware. - @constant kChecksumFamilyTCPIP A value that describes the collection - of TCP/IP checksums. - @constant kChecksumIP An IP header checksum. - @constant kChecksumTCP A TCP checksum that covers the TCP header and TCP - data. - @constant kChecksumUDP An UDP checksum that covers the UDP header and UDP - data. - @constant kChecksumTCPNoPseudoHeader A TCP checksum that covers the TCP - header and the TCP data, but the pseudo header is not included in the - checksum computation. A partial 16-bit checksum value must be provided - to allow the protocol stacks to calculate and verify the final checksum. - This type of checksum is not currently supported on the output path. - @constant kChecksumUDPNoPseudoHeader An UDP checksum that covers the UDP - header and the UDP data, but the pseudo header is not included in the - checksum computation. A partial 16-bit checksum value must be provided - to allow the protocol stacks to calculate and verify the final checksum. - This type of checksum is not currently supported on the output path. - @constant kChecksumTCPSum16 The hardware has a simple checksum engine - that can perform a TCP style ones complement sum of 16-bit words over - a certain range of bytes in a packet. The hardware does not have the - ability to scan for IP or TCP headers, and the driver must pass/get - additional parameter(s) to or from the protocol stack to coordinate - the checksumming effort. */ - - enum { - kChecksumFamilyTCPIP = 0x00000001, - kChecksumIP = 0x0001, - kChecksumTCP = 0x0002, - kChecksumUDP = 0x0004, - kChecksumTCPNoPseudoHeader = 0x0100, - kChecksumUDPNoPseudoHeader = 0x0200, - kChecksumTCPSum16 = 0x0400, - }; - -/*! @function getChecksumSupport - @abstract Get checksums that are supported by the network controller for - the given checksum family. - @discussion A network controller that is capable of inserting and verifying - checksums on output and input packets, should override this method and - advertise its capability in order to assist or offload the software checksum - calculations performed by the protocol stacks. - @param checksumMask A pointer to the mask of supported checksums returned - by this method. - @param checksumFamily A value that specifies the checksum family. - @param isOutput Set to true to query the support for checksum insertion on - output packets, or false to query the support for checksum verification - on input packets. Controllers that have symmetric hardware checksum support - can return a fixed checksum mask value, and ignore this argument. - @result Default return is kIOReturnUnsupported. Controllers that override - this method must return kIOReturnSuccess. Any other return value will be - interpretated as a lack of checksum support, regardless of the value - returned through the first argument. */ - - virtual IOReturn getChecksumSupport( UInt32 * checksumMask, - UInt32 checksumFamily, - bool isOutput ); - -/*! @function setChecksumResult - @abstract Encode a received packet with the checksum result reported - by the hardware. - @discussion A network controller that can verify the checksum(s) for a - received packet, should call this method to encode the result on the - packet, before passing it up towards the protocol stacks. - @param packet A mbuf containing a packet that has been checksummed by - the hardware. - @param checksumFamily A value that specifies the checksum family. - @param resultMask A mask of all checksums that were checked or computed. - Setting a bit implies that the driver is able to report the result of - the checksum computation, by asserting the validity of the checksum, - or by returning a partial checksum value. - @param validMask A mask of all checksums are were computed and verified - by the hardware as valid. Certain types of checksum performed by the - hardware are inheritely incomplete, and therefore should never be marked - as valid. A checksum cannot be marked valid unless it has also been - checked. - @param param0 Optional parameter 0, defaults to 0. - @param param1 Optional parameter 1, defaults to 0. - @result true if the checksum family is valid and the packet has been - encoded with the checksum result provided, false otherwise. */ - - virtual bool setChecksumResult( struct mbuf * packet, - UInt32 checksumFamily, - UInt32 resultMask, - UInt32 validMask, - UInt32 param0 = 0, - UInt32 param1 = 0 ); - -/*! @function getChecksumDemand - @abstract Fetch the demand for hardware checksum computation and insertion - for the given packet before it is transmitted on the network. - @discussion A network controller that can insert a checksum for output - packets must call this method to obtain the set of checksums that it must - compute, and insert into the appropriate fields in the given output packet. - @param packet A mbuf containing a packet that may be missing one or more - checksums in the specified checksum family. - @param checksumFamily A value which specifies the checksum family. - @param demandMask A mask of all checksums that the hardware must compute - and insert into the appropriate checksum fields in the packet. - @param param0 Optional parameter 0, defaults to 0. - @param param1 Optional parameter 1, defaults to 0. */ - - virtual void getChecksumDemand( const struct mbuf * packet, - UInt32 checksumFamily, - UInt32 * demandMask, - void * param0 = 0, - void * param1 = 0 ); - -/*! @function publishMediumDictionary - @abstract Publish a dictionary of IONetworkMedium objects to - advertise the media selection supported by the network controller. - @discussion Called by drivers to publish their medium dictionary. - Each entry in the dictionary is an IONetworkMedium object that - represents a single medium that is supported by the controller. - This method will make a copy of the dictionary provided, then add - the copy to the driver's property table. The dictionary provided - can be released by the caller upon returning from this method. - It is permissible to call this method multiple times, which may be - necessary if the hardware's media capability changes dynamically. - However, if the capability is static, which is often the case, - then drivers will typically call this method only once from - its start() method. - - Several methods depend on the presence of a medium dictionary. - They should be called after the medium dictionary has been - published. Those methods are: - setSelectedMedium() - getSelectedMedium() - getMediumDictionary() - copyMediumDictionary() - - @param mediumDict A dictionary of IONetworkMedium objects. - @result true if the dictionary is valid, and was successfully - exported to the property table, false otherwise. */ - - virtual bool publishMediumDictionary(const OSDictionary * mediumDict); - -/*! @function setSelectedMedium - @abstract Designate an entry in the published medium dictionary as - the current selected medium. - @discussion After the driver has configured the hardware to select - one of its supported media types, it must call this method to inform - its parent about the change that has occurred. IONetworkController - will update a property in the registry to reflect the current selection. - @param medium A medium object representing the current selection. - @result true if the property table update was successful, - false if the update failed, or if the medium provided does not match - any entry from the published medium dictionary. */ - - virtual bool setSelectedMedium(const IONetworkMedium * medium); - inline bool setCurrentMedium(const IONetworkMedium * medium); - -/*! @function setLinkStatus - @abstract Report the link status and the active medium. - @discussion Drivers must call this method when a link change is - detected. IONetworkController will update the link status properties - in the registry, and generate an event to inform the upper layers - about the change. - @param status Link status bits. - See IONetworkMedium for the definition of the link status bits. - @param activeMedium An object in the published medium dictionary - that represents the active medium. This may not be the same as - the selected medium. Set this to 0 if the link is inactive. - @param speed Link speed in units of bits per second. If zero, then - the link speed is taken from the medium object provided. - @param data An OSData containing any additional link parameter that - the driver wishes to publish to the registry. - @result true if all link properties were successfully updated, - false otherwise. */ - - virtual bool setLinkStatus( - UInt32 status, - const IONetworkMedium * activeMedium = 0, - UInt64 speed = 0, - OSData * data = 0); - -protected: - -/*! @function free - @abstract Free the IONetworkController object. - @discussion Free the IONetworkController object by releasing all - allocated resources, followed by a call to super::free(). */ - - virtual void free(); - -/*! @function registerWithPolicyMaker - @abstract Implemented by controller drivers to register with - the power management policy-maker. - @discussion Drivers that are able to power manage their hardware - should override this method and register with the policy-maker - provided by calling IOService::registerPowerDriver(). - IONetworkController will call this method before the initial - attempt is made to attach a client. - @param policyMaker The policy-maker chosen to manage power for - this network controller. - @result kIOReturnSuccess on success, kIOReturnUnsupported if the - driver does not support power management, or an appropriate error - return code. The default return is kIOReturnUnsupported. */ - - virtual IOReturn registerWithPolicyMaker(IOService * policyMaker); - -/*! @function createWorkLoop - @abstract Method called by IONetworkController prior to the initial - getWorkLoop() call. - @discussion Before IONetworkController calls getWorkLoop() in its - start() method, it will call createWorkLoop() to make sure that a - subclass that wants to create a workloop, will do so before its - first use. - @result True to indicate success, false otherwise. Returning false - will fail IONetworkController::start(). */ - - virtual bool createWorkLoop(); - -/*! @function prepare - @abstract Prepare the controller before an IOService is created and - attached as a client. - @discussion This method is called by attachInterface() or - attachDebuggerClient() to prepare the controller before the new client - object is attached. This method will call publishProperties() to publish - controller capabilities and properties that may be used by client objects. - However, publishProperties() will be called only once, even if prepare() - is called multiple times. This method call is synchronized by the - workloop's gate. - @result kIOReturnSuccess on success, or an error code otherwise. - Returning an error will fail the client attach. */ - - virtual IOReturn prepare(); - -/*! @function publishProperties - @abstract Publish controller properties and capabilities. - @discussion Called by IONetworkController to discover controller - properties, and publish them to the property table in the I/O Kit - registry. This method is called once by prepare(). - @result true if all properties were discovered and published - successfully, false otherwise. Returning false will prevent client - objects from attaching to the controller, since a property that - a client relies upon may be missing. */ - - virtual bool publishProperties(); - -/*! @function getCommandClient - @abstract Get the command client object. - @discussion Methods called on the workloop context to service a - client request can call this method to get the client object which - initiated the command. - @result The command client. If the caller is not running on the - workloop thread, or if the thread does not have the workloop's gate - closed, then 0 is returned. */ - - virtual OSObject * getCommandClient() const; - -/*! @function handleOpen - @abstract Handle a client open. - @discussion Handle a client open on the controller object. IOService - calls this method with the arbitration lock held. Subclasses - should not override this method. - @param client The client that is attempting to open the controller. - @param options Not used. See IOService. - @param argument Not used. See IOService. - @result true to accept the client open, false to refuse it. */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * argument); - -/*! @function handleClose - @abstract Handle a client close. - @discussion Handle a close from one of the client objects. IOService - calls this method with the arbitration lock held. Subclasses - should not override this method. - @param client The client that is closing the controller. - @param options Not used. See IOService. */ - - virtual void handleClose(IOService * client, IOOptionBits options); - -/*! @function handleIsOpen - @abstract Query whether a client has an open on the controller. - @discussion This method is always called by IOService with the - arbitration lock held. Subclasses should not override this method. - @result true if the specified client, or any client if none (0) is - specified, presently has an open on this object. */ - - virtual bool handleIsOpen(const IOService * client) const; - -/*! @function enable - @abstract A request from an interface client to enable the controller. - @discussion Called by an interface client to enable the controller. - Upon receiving this command, the controller driver must bring up the - hardware and become ready to transmit and receive packets. A driver - should also delay the allocation of most runtime resources until this - method is called in order to conserve system resources. This method call - is synchronized by the workloop's gate. - @param interface The interface client object that requested the enable. - @result kIOReturnUnsupported. Drivers that override this method must - return kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn enable(IONetworkInterface * interface); - -/*! @function disable - @abstract A request from an interface client to disable the controller. - @discussion Called by an interface client to disable the controller. - This method should stop the hardware and disable hardware interrupt - sources. Any resources allocated by enable() should also be deallocated. - This method call is synchronized by the workloop's gate. - @param interface The interface object that requested the disable. - @result kIOReturnUnsupported. Drivers that override this method must - return kIOReturnSuccess on success, or an error code otherwise. */ - - virtual IOReturn disable(IONetworkInterface * interface); - -/*! @function attachInterface - @abstract Attach a new interface client object. - @discussion Create a new interface object and attach it to the - controller. The createInterface() method is called to perform - the interface allocation and initialization, followed by a call to - configureInterface() to configure it. Subclasses can override those - two methods to customize the interface client attached. Drivers will - usually call this method from start(), after they are ready to process - client requests. Since most drivers will have a single interface - client, this method will likely be called only once. - @param interface Upon success (return value is true), the - interface object will be written to the handle provided. - @param doRegister If true, then registerService() is called to register - the interface, which will trigger the matching process, and will ultimately - cause the interface to become registered with the data link layer. - Drivers that wish to delay the registration can set doRegister to false, - and call registerService() on the interface object when the controller - becomes ready. This allows the driver to attach an interface without - making its services available to the rest of the system. - @result true on success, false otherwise. */ - - virtual bool attachInterface(IONetworkInterface ** interface, - bool doRegister = true); - -/*! @function detachInterface - @abstract Detach an interface client object. - @discussion This method will verify that the object provided is indeed - an IONetworkInterface instance, and then call its terminate() method. - Note that an interface object will close and detach from its - controller after the data link layer has removed all references to - all data structures exposed by the interface. The interface object - should be released following this call. - @param interface An interface object to be detached and terminated. - @param sync If true, the interface is terminated synchronously. - This may cause this method to block for an indeterminate - amount of time. */ - - virtual void detachInterface(IONetworkInterface * interface, - bool sync = false); - -/*! @function createInterface - @abstract Create a new network interface object. - @discussion This method is called by attachInterface() to perform - allocation and initialization of a new interface object. A subclass of - IONetworkController must implement this method and return a matching - interface object. For example, IOEthernetController's implementation - will return an IOEthernetInterface object when createInterface() is - called. - @result A newly allocated and initialized interface object. */ - - virtual IONetworkInterface * createInterface() = 0; - -/*! @function configureInterface - @abstract Configure a newly created network interface object. - @discussion Configure an interface object that was created by - createInterface(). Subclasses can override this method to customize, - and examine the interface object that will be attached to the - controller as a client. - @param interface The interface object to be configured. - @result true if the operation was successful, false otherwise - (this will cause attachInterface() to fail and return 0). */ - - virtual bool configureInterface(IONetworkInterface * interface); - -/*! @function createOutputQueue - @abstract Create an IOOutputQueue to handle output packet queueing, - and also to resolve contention for the controller's transmitter from - multiple client threads. - @discussion Called by start() to create an IOOutputQueue object to - handle output packet queueing. The default implementation will always - return 0, hence no output queue will be created. A driver may override - this method and return a subclass of IOOutputQueue. IONetworkController - will keep a reference to the queue created, and will release this - object when IONetworkController is freed. Also see getOutputQueue(). - @result A newly allocated and initialized IOOutputQueue object. */ - - virtual IOOutputQueue * createOutputQueue(); - -/*! @function enable - @abstract An enable request from an IOKernelDebugger client. - @discussion Drivers that provide debugging support may either override - this method and setup the hardware to support the polled-mode send and - receive methods; receivePacket() and sendPacket(). Or override the base - enable() and disable() methods that take an IOService argument. - @param debugger The IOKernelDebugger client requesting the enable. - @result kIOReturnSuccess. Drivers must return kIOReturnSuccess - on success, or an error otherwise. */ - - virtual IOReturn enable(IOKernelDebugger * debugger); - -/*! @function disable - @abstract A disable request from an IOKernelDebugger client. - @discussion Drivers that provide debugging support may either override - this method to disable support for the polled-mode send and receive - methods. Or override the base enable() and disable() methods that - take an IOService argument. - @param debugger The IOKernelDebugger client requesting the disable. - @result kIOReturnSuccess. Drivers must return kIOReturnSuccess - on success, or an error otherwise. */ - - virtual IOReturn disable(IOKernelDebugger * debugger); - -/*! @function attachDebuggerClient - @abstract Attach a new IOKernelDebugger client object. - @discussion Allocate an IOKernelDebugger object and attach it as - a client. Having a debugger client implies that the controller - supports kernel debugging, and therefore must implement the two - polled-mode methods that are called by the debugger client. See - sendPacket() and receivePacket(). Only a single debugger client - should be attached to each controller. - @param debuggerP A handle that will return the new - IOKernelDebugger object created. - @result true on success, false otherwise. */ - - virtual bool attachDebuggerClient(IOKernelDebugger ** debuggerP); - -/*! @function detachDebuggerClient - @abstract Detach an IOKernelDebugger client object. - @discussion Detach and terminate the IOKernelDebugger client object - provided. A synchronous termination is issued, and this method will - return after the debugger client has been terminated. The debugger - client should be released following this call. - @param debugger The IOKernelDebugger object to be detached and - terminated. If the argument provided is NULL or is not an - IOKernelDebugger, this method will return immediately. */ - - virtual void detachDebuggerClient(IOKernelDebugger * debugger); - -/*! @function reserveDebuggerLock - @abstract Take the global debugger lock. - @discussion This method should not be used. Instead, call the - lock() method provided by IOKernelDebugger. */ - - void reserveDebuggerLock(); - -/*! @function releaseDebuggerLock - @abstract Release the global debugger lock. - @discussion This method should not be used. Instead, call the - unlock() method provided by IOKernelDebugger. */ - - void releaseDebuggerLock(); - -/*! @function receivePacket - @abstract Debugger polled-mode receive handler. - @discussion This method must be implemented by a driver that supports - kernel debugging. After a debugger client has been attached through - attachDebuggerClient(), this method will be called by the debugger - client to poll for a incoming packet when the kernel debugger is active. - This method may be called from the primary interrupt context, and the - implementation must avoid any memory allocation, and must never block. - The receivePacket() method in IONetworkController is used as a placeholder, - it performs no useful action, and should not be called. A driver that - attaches a debugger client must override this method. - @param pkt Address of a receive buffer where the received packet should - be stored. This buffer has room for 1518 bytes. - @param pktSize Address where the number of bytes received must be - recorded. Set this to zero if no packets were received during - the timeout interval. - @param timeout The maximum amount of time in milliseconds to poll for - a packet to arrive before this method must return. */ - - virtual void receivePacket(void * pkt, UInt32 * pktSize, UInt32 timeout); - -/*! @function sendPacket - @abstract Debugger polled-mode transmit handler. - @discussion This method must be implemented by a driver that supports - kernel debugging. After a debugger client has been attached through - attachDebuggerClient(), this method will be called by the debugger - to send an outbound packet only when the kernel debugger is active. - This method may be called from the primary interrupt context, and the - implementation must avoid any memory allocation, and must never block. - The sendPacket() method in IONetworkController is used as a placeholder, - it performs no useful action, and should not be called. A driver that - attaches a debugger client must override this method. - @param pkt Pointer to a transmit buffer containing the packet to be - sent on the network. - @param pktSize The size of the transmit buffer in bytes. */ - - virtual void sendPacket(void * pkt, UInt32 pktSize); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IONetworkController, 0); - OSMetaClassDeclareReservedUnused( IONetworkController, 1); - OSMetaClassDeclareReservedUnused( IONetworkController, 2); - OSMetaClassDeclareReservedUnused( IONetworkController, 3); - OSMetaClassDeclareReservedUnused( IONetworkController, 4); - OSMetaClassDeclareReservedUnused( IONetworkController, 5); - OSMetaClassDeclareReservedUnused( IONetworkController, 6); - OSMetaClassDeclareReservedUnused( IONetworkController, 7); - OSMetaClassDeclareReservedUnused( IONetworkController, 8); - OSMetaClassDeclareReservedUnused( IONetworkController, 9); - OSMetaClassDeclareReservedUnused( IONetworkController, 10); - OSMetaClassDeclareReservedUnused( IONetworkController, 11); - OSMetaClassDeclareReservedUnused( IONetworkController, 12); - OSMetaClassDeclareReservedUnused( IONetworkController, 13); - OSMetaClassDeclareReservedUnused( IONetworkController, 14); - OSMetaClassDeclareReservedUnused( IONetworkController, 15); - OSMetaClassDeclareReservedUnused( IONetworkController, 16); - OSMetaClassDeclareReservedUnused( IONetworkController, 17); - OSMetaClassDeclareReservedUnused( IONetworkController, 18); - OSMetaClassDeclareReservedUnused( IONetworkController, 19); - OSMetaClassDeclareReservedUnused( IONetworkController, 20); - OSMetaClassDeclareReservedUnused( IONetworkController, 21); - OSMetaClassDeclareReservedUnused( IONetworkController, 22); - OSMetaClassDeclareReservedUnused( IONetworkController, 23); - OSMetaClassDeclareReservedUnused( IONetworkController, 24); - OSMetaClassDeclareReservedUnused( IONetworkController, 25); - OSMetaClassDeclareReservedUnused( IONetworkController, 26); - OSMetaClassDeclareReservedUnused( IONetworkController, 27); - OSMetaClassDeclareReservedUnused( IONetworkController, 28); - OSMetaClassDeclareReservedUnused( IONetworkController, 29); - OSMetaClassDeclareReservedUnused( IONetworkController, 30); - OSMetaClassDeclareReservedUnused( IONetworkController, 31); -}; - -inline const IONetworkMedium * IONetworkController::getCurrentMedium() const -{ - return getSelectedMedium(); -} - -inline bool IONetworkController::setCurrentMedium(const IONetworkMedium * medium) -{ - return setSelectedMedium(medium); -} - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IONETWORKCONTROLLER_H */ - diff --git a/iokit/IOKit/network/IONetworkData.h b/iokit/IOKit/network/IONetworkData.h deleted file mode 100644 index 1c08caec0..000000000 --- a/iokit/IOKit/network/IONetworkData.h +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * IONetworkData.h - * - * HISTORY - * 21-Apr-1999 Joe Liu (jliu) created. - * - */ - -#ifndef _IONETWORKDATA_H -#define _IONETWORKDATA_H - -#define IONetworkParameter IONetworkData // FIXME - -/*! @enum An enumeration of constants that describe access types. - @constant kIONetworkDataAccessTypeRead Read access. - @constant kIONetworkDataAccessTypeWrite Write access. - @constant kIONetworkDataAccessTypeReset Reset access. - @constant kIONetworkDataAccessTypeSerialize Serialization access. */ - -enum { - kIONetworkDataAccessTypeRead = 0x01, - kIONetworkDataAccessTypeWrite = 0x02, - kIONetworkDataAccessTypeReset = 0x04, - kIONetworkDataAccessTypeSerialize = 0x08, - kIONetworkDataAccessTypeMask = 0xff, -}; - -/*! @define kIONetworkDataBasicAccessTypes - @discussion The default access types supported by an IONetworkData - object. Allow read() and serialize(). */ - -#define kIONetworkDataBasicAccessTypes \ - (kIONetworkDataAccessTypeRead | kIONetworkDataAccessTypeSerialize) - -/*! @enum An enumeration of the type of data buffers that can be - managed by an IONetworkData object. - @constant kIONetworkDataBufferTypeInternal An internal data buffer - allocated by the init() method. - @constant kIONetworkDataBufferTypeExternal An external (persistent) data - buffer. - @constant kIONetworkDataBufferTypeNone No data buffer. The only useful - action perfomed by an IONetworkData object with this buffer type - is to call the access notification handler. */ - -enum { - kIONetworkDataBufferTypeInternal = 0, - kIONetworkDataBufferTypeExternal, - kIONetworkDataBufferTypeNone, -}; - -/*! @defined kIONetworkDataBytes - @abstract kIONetworkDataBytes is a property of IONetworkData objects. - It has an OSData value. - @discussion The kIONetworkDataBytes property is an OSData that describes - the data buffer of an IONetworkData object. This property is present - only if kIONetworkDataAccessTypeSerialize access is supported. */ - -#define kIONetworkDataBytes "Data" - -/*! @defined kIONetworkDataAccessTypes - @abstract kIONetworkDataAccessTypes is a property of IONetworkData - objects. It has an OSNumber value. - @discussion The kIONetworkDataAccessTypes property is an OSNumber that - describes the supported access types of an IONetworkData object. */ - -#define kIONetworkDataAccessTypes "Access Types" - -/*! @defined kIONetworkDataSize - @abstract kIONetworkDataSize is a property of IONetworkData - objects. It has an OSNumber value. - @discussion The kIONetworkDataSize property is an OSNumber that - describes the size of the data buffer of an IONetworkData object. */ - -#define kIONetworkDataSize "Size" - -#ifdef KERNEL - -#include <libkern/c++/OSSymbol.h> -#include <libkern/c++/OSSerialize.h> - -/*! @class IONetworkData : public OSObject - An IONetworkData object manages a fixed-size named buffer. - This object provides external access methods that can be used to - access the contents of the data buffer. In addition, serialization - is supported, and therefore this object can be added to a property - table to publish the data object. An unique name must be assigned to - the object during initialization. An OSSymbol key will be created - based on the assigned name, and this key can be used when the object - is added to a dictionary. - - The level of access granted to the access methods can be restricted, - by specifying a set of supported access types when the object is - initialized, or modified later by calling setAccessTypes(). By default, - each IONetworkData object created will support serialization, and will - also allow its data buffer to be read through the read() access method. - - An access notification handler, in the form of a 'C' function, can - be registered to receive a call each time the data buffer is accessed - through an access method. Arguments provided to the handler will identify - the data object and the type of access that triggered the notification. - The handler can therefore perform lazy update of the data buffer until - an interested party tries to read or serialize the data. The notification - handler can also take over the default action performed by the access - methods when the buffer type is set to kIONetworkDataBufferTypeNone. - This will prevent the access methods from accessing the data buffer, - and allow the handler to override the access protocol. - - This object is primarily used by IONetworkInterface to export interface - properties to user space. */ - - -class IONetworkData : public OSObject -{ - OSDeclareDefaultStructors( IONetworkData ) - -public: - -/*! @typedef Action - Defines a C function that may be called by an IONetworkData object - when one of its access methods is called. - @param target The target of the notification. - @param param A parameter that was provided when the notification - handler was registered. - @param data The IONetworkData object being accessed, and the - sender of the notification. - @param accessType A bit will be set indicating the type of access - which triggered the notification. - @param buffer Pointer to the accessor's buffer. Only valid for - read() and write() accesses. - @param bufferSize Pointer to the size of the accessor's buffer. - @param offset An offset from the start of the data buffer to begin - reading or writing. */ - - typedef IOReturn (*Action)(void * target, - void * param, - IONetworkData * data, - UInt32 accessType, - void * buffer, - UInt32 * bufferSize, - UInt32 offset); - -protected: - const OSSymbol * _key; // key associated with this object. - UInt32 _access; // supported access types. - void * _buffer; // Data buffer. - UInt32 _bufType; // buffer type - UInt32 _size; // data buffer size. - void * _tapTarget; // target for access notification. - Action _tapAction; // the function to call. - void * _tapParam; // arbitrary notification param. - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - -/*! @function free - @abstract Free the IONetworkData object. */ - - virtual void free(); - -/*! @function writeBytes - @abstract Write to the data buffer with data from a source buffer - provided by the caller. - @param srcBuffer Pointer to a source buffer provided by the caller. - @param srcBufferSize The size of the source buffer. - @param writeOffset A byte offset from the start of the data buffer - to begin writting. - @result true if the operation was successful, false otherwise. */ - - virtual bool writeBytes(const void * srcBuffer, - UInt32 srcBufferSize, - UInt32 writeOffset = 0); - -/*! @function readBytes - @abstract Read from the data buffer and copy the data to a destination - buffer provided by the caller. - @param dstBuffer Pointer to the destination buffer. - @param dstBufferSize Pointer to an integer containing the size of the - destination buffer. And is overwritten by this method with the actual - number of bytes copied to the destination buffer. - @param readOffset A byte offset from the start of the data buffer - to begin reading. - @result true if the operation was successful, false otherwise. */ - - virtual bool readBytes(void * dstBuffer, - UInt32 * dstBufferSize, - UInt32 readOffset = 0) const; - -/*! @function clearBuffer - @abstract Clear the data buffer by filling it with zeroes. - @result true if the operation was successful, false otherwise. */ - - virtual bool clearBuffer(); - -public: - -/*! @function initialize - @abstract IONetworkData class initializer. */ - - static void initialize(); - -/*! @function withInternalBuffer - @abstract Factory method that will construct and initialize an - IONetworkData object with an internal data buffer. - @param name A name to assign to this object. - @param bufferSize The number of bytes to allocate for the internal data - buffer. - @param accessTypes The initial supported access types. - @param target The notification target. - @param action The notification action. - @param param A parameter to pass to the notification action. - @result An IONetworkData object on success, or 0 otherwise. */ - - static IONetworkData * - withInternalBuffer(const char * name, - UInt32 bufferSize, - UInt32 accessTypes = - kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0); - -/*! @function withExternalBuffer - @abstract Factory method that will construct and initialize an - IONetworkData object with an external data buffer. - @param name A name to assign to this object. - @param bufferSize The size of the external data buffer. - @param externalBuffer Pointer to the external data buffer. - @param accessTypes The initial supported access types. - @param target The notification target. - @param action The notification action. - @param param A parameter to pass to the notification action. - @result An IONetworkData object on success, or 0 otherwise. */ - - static IONetworkData * - withExternalBuffer(const char * name, - UInt32 bufferSize, - void * externalBuffer, - UInt32 accessTypes = - kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0); - -/*! @function withNoBuffer - @abstract Factory method that will construct and initialize an - IONetworkData object without a data buffer. The notification handler - must intervene when the IONetworkData is accessed. - @param name A name to assign to this object. - @param bufferSize The size of the phantom data buffer. - @param accessTypes The initial supported access types. - @param target The notification target. - @param action The notification action. - @param param A parameter to pass to the notification action. - @result An IONetworkData object on success, or 0 otherwise. */ - - static IONetworkData * withNoBuffer(const char * name, - UInt32 bufferSize, - UInt32 accessTypes, - void * target, - Action action, - void * param = 0); - -/*! @function init - @abstract Initialize an IONetworkData object. - @param name A name to assign to this object. - @param bufferType The type of buffer associated with this object. - @param bufferSize The size of the data buffer. - @param externalBuffer Pointer to an external data buffer. - @param accessTypes The initial supported access types. - Can be later modified by calling setAccessTypes(). - @param target The notification target. - @param action The notification action. - @param param A parameter to pass to the notification action. - @result true if initialized successfully, false otherwise. */ - - virtual bool init(const char * name, - UInt32 bufferType, - UInt32 bufferSize, - void * externalBuffer = 0, - UInt32 accessTypes = - kIONetworkDataBasicAccessTypes, - void * target = 0, - Action action = 0, - void * param = 0); - -/*! @function setAccessTypes - @abstract Set the types of access that are permitted on the data buffer. - @param types A mask of access types indicating the supported access - types. */ - - virtual void setAccessTypes(UInt32 types); - -/*! @function setNotificationTarget - @abstract Register a C function to handle access notifications sent - from this object. - @discussion A notification is sent by an IONetworkData object to the - registered notification handler, when an access method is called to - modify the contents of the data buffer. - @param target The first parameter passed to the notification handler. - @param action A pointer to a C function that will handle the notification. - If 0, then notification is disabled. - @param param An optional parameter passed to the notification handler. */ - - virtual void setNotificationTarget(void * target, - Action action, - void * param = 0); - -/*! @function getBuffer - @abstract Get a pointer to the data buffer. - @result A pointer to the data buffer. Returns 0 if the buffer type is - kIONetworkDataBufferTypeNone. */ - - virtual const void * getBuffer() const; - -/*! @function getBufferType - @abstract Get the type of data buffer managed by this object. - @result A constant that describes the type of the data buffer. */ - - virtual UInt32 getBufferType() const; - -/*! @function getAccessTypes - @abstract Get the types of data access supported by this object. - @result A mask of supported access types. */ - - virtual UInt32 getAccessTypes() const; - -/*! @function getNotificationTarget - @abstract Get the first parameter that will be passed to the access - notification handler. - @result The first parameter that will be passed to the access notification - handler. */ - - virtual void * getNotificationTarget() const; - -/*! @function getNotificationAction - @abstract Get the C function that was registered to handle access - notifications sent from this object. - @result A pointer to a C function, or 0 if notification is disabled. */ - - virtual Action getNotificationAction() const; - -/*! @function getNotificationParameter - @abstract Get the parameter that will be passed to the access - notification handler. - @result The parameter that will be passed to the access notification - handler. */ - - virtual void * getNotificationParameter() const; - -/*! @function getKey - @abstract Get an unique OSSymbol key associated with this object. - @discussion During initialization, IONetworkData will create an - OSSymbol key based on its assigned name. - @result An OSSymbol key that was generated from the name assigned to - this object. */ - - virtual const OSSymbol * getKey() const; - -/*! @function getSize - @abstract Get the size of the data buffer. - @result The size of the data buffer managed by this object in bytes. */ - - virtual UInt32 getSize() const; - -/*! @function reset - @abstract An access method to reset the data buffer. - @discussion Handle an external request to reset the data buffer. - If notication is enabled, then the notification handler is called - after the data buffer has been cleared. - @result kIOReturnSuccess on success, - kIOReturnNotWritable if reset access is not permitted, - or an error from the notification handler. */ - - virtual IOReturn reset(); - -/*! @function read - @abstract An access method to read from the data buffer. - @discussion Handle an external request to read from the data buffer - and copy it to the destination buffer provided by the accessor. - If notification is enabled, then the notification handler is called - before the data buffer is copied to the destination buffer. The - notification handler may use this opportunity to intervene and - to update the contents of the data buffer. - @param dstBuffer Pointer to the destination buffer. - @param dstBufferSize Pointer to an integer containing the size of the - destination buffer. And is overwritten by this method to the actual number - of bytes copied to the destination buffer. - @param readOffset An offset from the start of the source data buffer to - begin reading. - @result kIOReturnSuccess on success, - kIOReturnBadArgument if any of the arguments provided is invalid, - kIOReturnNotReadable if read access is not permitted, - or an error from the notification handler. */ - - virtual IOReturn read(void * dstBuffer, - UInt32 * dstBufferSize, - UInt32 readOffset = 0); - -/*! @function write - @abstract An access method to write to the data buffer. - @discussion Handle an external request to write to the data buffer - from a source buffer provided by the accessor. After checking that - the data object supports write accesses, the data buffer is updated - if it exists. Then the registered notification handler is called. - @param srcBuffer Pointer to the source buffer. - @param srcBufferSize The number of bytes to write to the data buffer. - @param writeOffset An offset from the start of the destination data buffer - to begin writing. - @result kIOReturnSuccess on success, - kIOReturnBadArgument if any of the arguments provided is invalid, - kIOReturnNotWritable if write access is not permitted, - or an error from the notification handler. */ - - virtual IOReturn write(void * srcBuffer, - UInt32 srcBufferSize, - UInt32 writeOffset = 0); - -/*! @function serialize - @abstract Serialize the IONetworkData object. - @discussion If notification is enabled, then the notification - handler is called just before the data buffer is serialized. - @param s An OSSerialize object. - @result true on success, false otherwise. */ - - virtual bool serialize(OSSerialize * s) const; - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IONetworkData, 0); - OSMetaClassDeclareReservedUnused( IONetworkData, 1); - OSMetaClassDeclareReservedUnused( IONetworkData, 2); - OSMetaClassDeclareReservedUnused( IONetworkData, 3); -}; - -#endif /* KERNEL */ - -#endif /* !_IONETWORKDATA_H */ diff --git a/iokit/IOKit/network/IONetworkInterface.h b/iokit/IOKit/network/IONetworkInterface.h deleted file mode 100644 index 85f16fb45..000000000 --- a/iokit/IOKit/network/IONetworkInterface.h +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkInterface.h - * - * HISTORY - * 8-Jan-1999 Joe Liu (jliu) created. - */ - -#ifndef _IONETWORKINTERFACE_H -#define _IONETWORKINTERFACE_H - -/*! @defined kIONetworkInterfaceClass - @abstract kIONetworkInterfaceClass is the name of the - IONetworkInterface class. */ - -#define kIONetworkInterfaceClass "IONetworkInterface" - -/*! @defined kIONetworkData - @abstract kIONetworkData is a property of IONetworkInterface - objects. It has an OSDictionary value. - @discussion The kIONetworkData property is a container for the - set of IONetworkData objects managed by the interface. - Each entry in the dictionary is a key/value pair consisting of - the network data name, and an OSDictionary describing the - contents of the network data. */ - -#define kIONetworkData "IONetworkData" - -/*! @defined kIOInterfaceType - @abstract kIOInterfaceType is a property of IONetworkInterface objects. - It has an OSNumber value. - @discussion The kIOInterfaceType property specifies the type of - network interface that this interface represents. The type - constants are defined in bsd/net/if_types.h. */ - -#define kIOInterfaceType "IOInterfaceType" - -/*! @defined kIOMaxTransferUnit - @abstract kIOMaxTransferUnit is a property of IONetworkInterface objects. - It has an OSNumber value. - @discussion The kIOMaxTransferUnit property specifies the maximum - transfer unit for the interface in bytes. */ - -#define kIOMaxTransferUnit "IOMaxTransferUnit" - -/*! @defined kIOMediaAddressLength - @abstract kIOMediaAddressLength is a property of IONetworkInterface objects. - It has an OSNumber value. - @discussion The kIOMediaAddressLength property specifies the size of the - media address in bytes. */ - -#define kIOMediaAddressLength "IOMediaAddressLength" - -/*! @defined kIOMediaHeaderLength - @abstract kIOMediaHeaderLength is a property of IONetworkInterface objects. - It has an OSNumber value. - @discussion The kIOMediaHeaderLength property specifies the size of the - media header in bytes. */ - -#define kIOMediaHeaderLength "IOMediaHeaderLength" - -/*! @defined kIOInterfaceFlags - @abstract kIOInterfaceFlags is a property of IONetworkInterface objects. - It has an OSNumber value. - @discussion The kIOInterfaceFlags property specifies the current value - of the interface flags. The flag constants are defined in - bsd/net/if.h. */ - -#define kIOInterfaceFlags "IOInterfaceFlags" - -/*! @defined kIOInterfaceExtraFlags - @abstract kIOInterfaceExtraFlags is a property of IONetworkInterface - objects. It has an OSNumber value. - @discussion The kIOInterfaceExtraFlags property specifies the current - value of the interface extra flags. The extra flag constants are - defined in bsd/net/if.h. */ - -#define kIOInterfaceExtraFlags "IOInterfaceExtraFlags" - -/*! @defined kIOInterfaceUnit - @abstract kIOInterfaceUnit is a property of IONetworkInterface - objects. It has an OSNumber value. - @discussion The kIOInterfaceUnit property describes the unit number - assigned to the interface object. */ - -#define kIOInterfaceUnit "IOInterfaceUnit" - -/*! @defined kIOInterfaceState - @abstract kIOInterfaceState is a property of IONetworkInterface - objects. It has an OSNumber value. - @discussion The kIOInterfaceState property describes the current state - of the interface object. This property is not exported to BSD via - the ifnet structure. */ - -#define kIOInterfaceState "IOInterfaceState" - -/*! @defined kIOInterfaceNamePrefix - @abstract kIOInterfaceNamePrefix is a property of IONetworkInterface - objects. It has an OSString value. - @discussion The kIOInterfaceNamePrefix property describes the string - prefix for the BSD name assigned to the interface. */ - -#define kIOInterfaceNamePrefix "IOInterfaceNamePrefix" - -/*! @defined kIOPrimaryInterface - @abstract kIOPrimaryInterface is a property of IONetworkInterface - objects. It has an OSBoolean value. - @discussion The kIOInterfaceNamePrefix property describes whether the - interface is the primary or the built-in network interface. */ - -#define kIOPrimaryInterface "IOPrimaryInterface" - -/*! @enum Interface state flags. - @discussion An enumeration of the constants that are used to encode the - state of the interface object. - @constant kIONetworkInterfaceRegisteredState The interface object has - registered with the data link layer. - @constant kIONetworkInterfaceOpenedState One or more clients have an - open on the interface object. - @constant kIONetworkInterfaceDisabledState The interface is temporarily - unable to service its clients. This will occur when the network - controller that is servicing the interface has entered a low power - state that renders it unusable. */ - -enum { - kIONetworkInterfaceRegisteredState = 0x1, - kIONetworkInterfaceOpenedState = 0x2, - kIONetworkInterfaceDisabledState = 0x4 -}; - -/* - * Kernel - */ -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/IOService.h> -#include <IOKit/network/IONetworkData.h> -#include <IOKit/network/IONetworkStats.h> -#include <IOKit/network/IONetworkMedium.h> - -struct mbuf; // forward declarations. -struct ifnet; -class IONetworkController; -class IONetworkStack; -class IOCommandGate; - -/*! @typedef IOOutputAction - @discussion Prototype for an output packet handler that will process - all outbound packets sent to the interface from the data link layer. - An output handler is registered with the interface by calling - registerOutputHandler(). - @param m A packet mbuf. - @param param A parameter for the output request. */ - -typedef UInt32 (OSObject::*IOOutputAction)(struct mbuf * m, void * param); - -/*! @typedef BPF_FUNC - @discussion Prototype for the BPF tap handler. This will disappear - when the correct DLIL header file is included. */ - -typedef int (*BPF_FUNC)(struct ifnet *, struct mbuf *); - -// Network event types recognized by inputEvent(). -// -enum { - /* DLIL defined event, argument must be a pointer to a - kern_event_msg structure. */ - kIONetworkEventTypeDLIL = 0xff000001, - - /* Link up event, no argument */ - kIONetworkEventTypeLinkUp = 0xff000002, - - /* Link down event, no argument */ - kIONetworkEventTypeLinkDown = 0xff000003 -}; - -/*! @class IONetworkInterface : public IOService - @abstract An IONetworkInterface object manages the connection between - an IONetworkController and the data link interface layer (DLIL). - All interactions between the controller and DLIL must go through an - interface object. Any data structures that are required by DLIL for a - particular interface type shall be allocated and mantained by the - interface object. IONetworkInterface is an abstract class that must be - extended by a concrete subclass to specialize for a particular network - type. - - Although most drivers will allocate a single interface object. - It is possible for multiple interfaces to be attached to a single - controller. This controller driver will be responsible for arbitrating - access among its multiple interface clients. - - IONetworkInterface also maintains a dictionary of IONetworkData - objects containing statistics structures. Controller drivers can - ask for a particular data object by name and update the - statistics counters within directly. This dictionary is added to - the interface's property table and is visible outside of the kernel. */ - -class IONetworkInterface : public IOService -{ - OSDeclareAbstractStructors( IONetworkInterface ) - - friend class IONetworkStack; - -private: - IONetworkController * _controller; - struct ifnet * _ifp; - IORecursiveLock * _ifLock; - OSSet * _clientSet; - OSNumber * _stateBits; - BPF_FUNC _inputFilterFunc; - BPF_FUNC _outputFilterFunc; - OSObject * _outTarget; - IOOutputAction _outAction; - UInt32 _clientVar[4]; - OSDictionary * _dataDict; - struct mbuf * _inputQHead; - struct mbuf * _inputQTail; - UInt32 _inputQCount; - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData * _reserved; - - bool _syncNetworkDataDict(); - bool _setInterfaceProperty(UInt32 value, - UInt32 mask, - UInt32 bytes, - void * addr, - char * name); - - SInt32 syncSIOCSIFMEDIA(IONetworkController * ctlr, struct ifreq * ifr); - SInt32 syncSIOCGIFMEDIA(IONetworkController * ctlr, struct ifreq * ifr); - SInt32 syncSIOCSIFMTU(IONetworkController * ctlr, struct ifreq * ifr); - - static int performGatedCommand(void *, void *, void *, void *, void *); - static int ioctl_shim(struct ifnet * ifp, u_long cmd, caddr_t data); - static int set_bpf_tap_shim(struct ifnet * ifp, int mode, BPF_FUNC func); - static int free_shim(struct ifnet * ifp); - static int output_shim(struct ifnet * ifp, struct mbuf *m); - static void null_shim(struct ifnet * ifp); - - static IOReturn sControllerWillChangePowerState( IONetworkInterface *, - void *, void *, - void *, void *); - - static IOReturn sControllerDidChangePowerState( IONetworkInterface *, - void *, void *, - void *, void *); - -public: - -/*! @function isPrimaryInterface - @abstract Query whether the interface object provided represents - the "primary" network interface for the system. - @result true if the interface provided is the primary inteface, - false otherwise. */ - - virtual bool isPrimaryInterface() const; - -/*! @function init - @abstract Initialize an IONetworkInterface object. - @discussion Initialize instance variables, and allocate resources. - Call getIfnet() to get the ifnet structure allocated by a concrete - subclass, then call initIfnet() to initialize this ifnet structure. - @param controller A network controller object that will service - the interface object being initialized. - @result true on success, false otherwise. */ - - virtual bool init( IONetworkController * controller ); - -/*! @function isRegistered - @abstract Returns true if the interface has been registered with - the data link layer. - @discussion Once registered, the interface will be assigned a - BSD name (such as en0), and a kIOBSDNameKey property is added to the - property table containing this name. Calling this method performs - the same function as checking for the kIONetworkInterfaceRegisteredState - bit in the value returned by getInterfaceState(). - @result True if interface is registered. False if the data link layer - has no references to this network interface, which implies that either the - interface has yet to attach to the data link layer, or the interface has - been detached. */ - - virtual bool isRegistered() const; - -/*! @function getInterfaceState - @abstract Report the current state of the interface object by returning - the interface state flags. - @result Returns the interface state flags. */ - - virtual UInt32 getInterfaceState() const; - -/*! @function matchPropertyTable - @abstract Override the implementation in IOService in order to - implement family specific matching. - @discussion When the gIOLocationMatchKey property is present in the - dictionary provided, then fail the match unless the kIOBSDNameKey property - is found. This is to prevent a premature match when hunting for a root - device for BSD. The presence of the kIOBSDNameKey property indicates that - the interface has registered with BSD, and is a valid candidate for - matching against the gIOLocationMatchKey property. If the - gIOLocationMatchKey property is absent, then this method will always - return true. - @param table The dictionary of properties to match against. - @param score Pointer to the current driver's probe score, not used. - @result Returns true for a positive match, false otherwise. */ - - virtual bool matchPropertyTable( OSDictionary * table, - SInt32 * score ); - -/*! @function getController - @abstract Return the provider, an IONetworkController object, that - is servicing this interface object. - @discussion This is the same controller object that was supplied as - an argument to the init() method. - @result The IONetworkController object that is providing service to - this interface object. */ - - virtual IONetworkController * getController() const; - -/*! @function inputPacket - @abstract Called by the network controller to submit a single packet - received from the network to the data link layer. - @discussion The packet received by this method may be added to an input - queue on the interface object, which the controller can use to postpone - the packet handoff to the upper layers, until all received packets have - been transferred to the input queue. A subsequent call to flushInputQueue(), - will transfer the entire contents of the queue to the data link layer, - by making a single call to dlil_input(). Other methods that can be used - to manage the input queue are flushInputQueue() and clearInputQueue(). - This input queue is not protected by a lock. Access to the queue by the - controller must be serialized, otherwise its use must be avoided. - @param m The mbuf containing the received packet. - @param length Specify the size of the received packet in the mbuf. - The mbuf length fields are updated with this value. If zero, - then the mbuf length fields are not updated. - @param options Options defined by inputPacket() that the caller - can use to specify this method call. - @param param A parameter provided by the caller. Not used by - IONetworkInterface. - @result The number of packets that were submitted to the data link layer, - or 0 if the packet was queued. */ - - virtual UInt32 inputPacket(struct mbuf * m, - UInt32 length = 0, - IOOptionBits options = 0, - void * param = 0); - -/*! @enum Options for the inputPacket() method. - @discussion An enumeration of the option bits that can be specified - in the options argument when calling inputPacket(). - @constant kInputOptionQueuePacket Keep the packet provided in the - input packet queue. No packets are sent to the data link layers, - and the caller's thread will not venture outside the interface - object. Calls to inputPacket() must be serialized. */ - - enum { - kInputOptionQueuePacket = 0x1 - }; - -/*! @function flushInputQueue - @abstract Send all packets held in the input queue to the data - link layer. - @discussion Remove all packets from the input queue and - send them to the data link layer by calling dlil_input(). This - method should be used in connection with the inputPacket() method, - to flush the input queue after inputPacket() was used to queue up - some number of received packets. See inputPacket() and clearInputQueue(). - @result The number of packets that were submitted to the data link layer. - May be zero if the queue was empty. */ - - virtual UInt32 flushInputQueue(); - -/*! @function clearInputQueue - @abstract Remove and discard all packets in the input queue. - @discussion Remove all packets from the input queue and - release them back to the free mbuf pool. Also see flushInputQueue(). - @result The number of packets freed. */ - - virtual UInt32 clearInputQueue(); - -/*! @function inputEvent - @abstract Send an event to the data link layer. - @discussion This method can be used by the network controller to - send an event to the data link layer. - @param type A constant describing the event type. - @param data Data associated with the event. - @result true if the event was delivered, false if the event type - specified is invalid, or if the event delivery was unsuccesful. */ - - virtual bool inputEvent(UInt32 type, void * data); - -/*! @function registerOutputHandler - @abstract Register a target/action to handle output packets. - @discussion The interface object will forward all output packets, - received from the data link layer, to the output handler registered - through this method. The default target and action are set by the init() - method to the controller, and the handler returned by the controller's - getOutputHandler() method. Once the interface becomes registered with - the data link layer, this method will return false and will reject any - further changes. - @param target Target object that implements the output handler. - @param action The function that will process output packets. - @result true if the target/action provided was accepted, - false otherwise. */ - - virtual bool registerOutputHandler(OSObject * target, - IOOutputAction action); - -/*! @function getNamePrefix - @abstract Return a string containing the prefix to use when - creating a BSD name for this interface. - @discussion The BSD name for each interface object is generated by - concatenating a string returned by this method, with an unique - unit number assigned by IONetworkStack. - A concrete subclass of IONetworkInterface must implement this method - and enforce a consistent name for all of its instances. - @result A pointer to a constant C string. */ - - virtual const char * getNamePrefix() const = 0; - -/*! @function getInterfaceType - @abstract Get the interface type. - @discussion Return the value in the if_type field in the ifnet structure. - @result A constant defined in bsd/net/if_types.h header file - that describes the interface type. */ - - virtual UInt8 getInterfaceType() const; - -/*! @function getMaxTransferUnit - @abstract Get the maximum transfer unit for this interface. - @discussion Return the value in the if_mtu field in the ifnet structure. - @result The interface MTU size in bytes. */ - - virtual UInt32 getMaxTransferUnit() const; - -/*! @function getFlags - @abstract Get the value of the interface flags. - @discussion Return the value in the if_flags field in the ifnet structure. - @result The value of the interface flags. */ - - virtual UInt16 getFlags() const; - -/*! @function getExtraFlags - @abstract Get the value of the interface extra flags. - @discussion Return the value in the if_eflags field in the ifnet structure. - @result The value of the interface extra flags. */ - - virtual UInt32 getExtraFlags() const; - -/*! @function getMediaAddressLength - @abstract Get the size of the media (MAC-layer) address. - @discussion Return the value in the if_addrlen field in the ifnet structure. - @result The size of the media address in bytes. */ - - virtual UInt8 getMediaAddressLength() const; - -/*! @function getMediaHeaderLength - @abstract Get the size of the media header. - @discussion Return the value in the if_hdrlen field in the ifnet structure. - @result The size of the media header in bytes. */ - - virtual UInt8 getMediaHeaderLength() const; - -/*! @function getUnitNumber - @abstract Get the unit number assigned to this interface object. - @discussion Return the value in the if_unit field in the ifnet structure. - @result The assigned interface unit number. */ - - virtual UInt16 getUnitNumber() const; - -/*! @function addNetworkData - @abstract Add an IONetworkData object to a dictionary managed by - the interface. - @param aData An IONetworkData object to be added to a dictionary - managed by the interface. This object is retained by the dictionary. - @result true if the operation was successful, false otherwise. */ - - virtual bool addNetworkData(IONetworkData * aData); - -/*! @function removeNetworkData - @abstract Remove an entry from the IONetworkData dictionary - managed by the interface. The removed object is released. - @param aKey A unique OSSymbol identifying the IONetworkData object - to be removed from the dictionary. - @result true if the operation was successful, false otherwise. */ - - virtual bool removeNetworkData(const OSSymbol * aKey); - -/*! @function removeNetworkData - @abstract Remove an entry from the IONetworkData dictionary - managed by the interface. The removed object is released. - @param aKey A unique string identifying the IONetworkData object - to be removed from the dictionary. - @result true if the operation was successful, false otherwise. */ - - virtual bool removeNetworkData(const char * aKey); - -/*! @function getNetworkData - @abstract Get an IONetworkData object from the interface that is - associated with the given key. - @param aKey The unique string identifying the IONetworkData object to be - returned to caller. - @result Returns a reference to the matching IONetworkData object, - or 0 if no match was found. */ - - virtual IONetworkData * getNetworkData(const char * aKey) const; - -/*! @function getNetworkData - @abstract Get an IONetworkData object from the interface that is - associated with the given key. - @param aKey The unique OSSymbol identifying the IONetworkData object to be - returned to caller. - @result Returns a reference to the matching IONetworkData object, - or 0 if no match was found. */ - - virtual IONetworkData * getNetworkData(const OSSymbol * aKey) const; - - // FIXME - Compatibility methods (to be removed) - inline IONetworkData * getParameter(const char * aKey) const - { return getNetworkData(aKey); } - - inline bool setExtendedFlags(UInt32 flags, UInt32 clear = 0) - { return true; } - -protected: - -/*! @function setInterfaceType - @abstract Set the interface type. - @discussion Both the if_type field in the ifnet structure, and the - kIOInterfaceType property are updated with the value provided. - @param type A constant defined in bsd/net/if_types.h header file - that describes the interface type. - @result true if the update was successful, false otherwise. */ - - virtual bool setInterfaceType(UInt8 type); - -/*! @function setMaxTransferUnit - @abstract Set the maximum transfer unit for this interface. - @discussion Both the if_mtu field in the ifnet structure, and the - kIOMaxTransferUnit property are updated with the value provided. - @param mtu The interface MTU size in bytes. - @result true if the update was successful, false otherwise. */ - - virtual bool setMaxTransferUnit(UInt32 mtu); - -/*! @function setFlags - @abstract Perform a read-modify-write operation on the current - interface flags value. - @discussion See bsd/net/if.h header file for the definition of the - flag constants. Both the if_flags field in the ifnet structure, and - the kIOInterfaceFlags property are updated with the value provided. - @param flags The bits that should be set. - @param clear The bits that should be cleared. If 0, then non - of the flags are cleared and the result is formed by OR'ing the - original flags value with the new flags. - @result true if the update was successful, false otherwise. */ - - virtual bool setFlags(UInt16 flags, UInt16 clear = 0); - -/*! @function setExtraFlags - @abstract Perform a read-modify-write operation on the current - interface extra flags value. - @discussion See bsd/net/if.h header file for the definition of the - extra flag constants. Both the if_eflags field in the ifnet structure, - and the kIOInterfaceExtraFlags property are updated with the value - provided. - @param flags The bits that should be set. - @param flags The bits that should be set. - @param clear The bits that should be cleared. If 0, then non - of the flags are cleared and the result is formed by OR'ing the - original flags with the new flags. - @result true if the update was successful, false otherwise. */ - - virtual bool setExtraFlags(UInt32 flags, UInt32 clear = 0); - -/*! @function setMediaAddressLength - @abstract Set the size of the media (MAC-layer) address. - @discussion Both the if_addrlen field in the ifnet structure, and the - kIOMediaAddressLength property are updated with the value provided. - @param length The size of the media address in bytes. - @result true if the update was successful, false otherwise. */ - - virtual bool setMediaAddressLength(UInt8 length); - -/*! @function setMediaHeaderLength - @abstract Set the size of the media header. - @discussion Both the if_hdrlen field in the ifnet structure, and the - kIOMediaHeaderLength property are updated with the value provided. - @param length The size of the media header in bytes. - @result true if the update was successful, false otherwise. */ - - virtual bool setMediaHeaderLength(UInt8 length); - -/*! @function setUnitNumber - @abstract Assign an unique unit number to this interface. - @discussion This method is called by IONetworkStack before the - interface is registered with the data link layer, to assign an - unique unit number to the interface object. Both the if_unit field - in the ifnet structure, and the kIOInterfaceUnit property are updated - with the value provided. - @param unit The unit number assigned to this interface object. - @result true if the update was successful, false otherwise. */ - - virtual bool setUnitNumber(UInt16 unit); - -/*! @function free - @abstract Free the IONetworkInterface object. - @discussion Resource allocated by init() are released, and - clearInputQueue() is called to ensure that the input queue is empty. */ - - virtual void free(); - -/*! @function handleOpen - @abstract Handle a client open on the interface. - @discussion This method is called by IOService::open() with the - arbitration lock held, and must return true to accept the client open. - This method will in turn call handleClientOpen() to qualify the client - requesting the open. Since the controller is opened by the interface - in a lazy fashion, the interface may also perform an open on the - controller before this method returns. If the controller was opened, - then controllerDidOpen() is called to notify interested subclasses. - Subclasses should not override this method. - @param client The client object that requested the open. - @param options Options passed to IOService::open(). - @param argument Argument passed to IOService::open(). - @result true to accept the client open, false otherwise. */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * argument); - -/*! @function handleClose - @abstract Handle a client close on the interface. - @discussion This method is called by IOService::close() with the - arbitration lock held. This method will in turn call handleClientClose() - to notify interested subclasses about the client close. If this represents - the last close, then the interface will also close the controller before - this method returns. The controllerWillClose() method will be called before - closing the controller. Subclasses should not override this method. - @param client The client object that requested the close. - @param options Options passed to IOService::close(). */ - - virtual void handleClose(IOService * client, IOOptionBits options); - -/*! @function handleIsOpen - @abstract Query whether a client has an open on the interface. - @discussion This method is always called by IOService with the - arbitration lock held. Subclasses should not override this method. - @result true if the specified client, or any client if none (0) is - specified, presently has an open on this object. */ - - virtual bool handleIsOpen(const IOService * client) const; - -/*! @function lock - @abstract Take the network interface lock. - @discussion Take the recursive lock that protects the interface - state. All updates to the interface state and to the ifnet structure - must be performed while holding this lock. This call must be balanced - by a subsequent call to unlock(). */ - - virtual void lock(); - -/*! @function unlock - @abstract Release the network interface lock. - @discussion Release the recursive lock that protects the interface - state to balance a previous lock() call. */ - - virtual void unlock(); - -/*! @function controllerDidOpen - @abstract A notification that the interface has opened the network - controller. - @discussion Called by handleOpen() to notify subclasses that the - controller has been opened. The open on the controller is done when - the interface receives the initial open request from a client. - Subclasses can override this method and inspect the controller before - allowing the client open. The implementation in the subclass must first - call the method in super and check the return value. This method is - called with our arbitration lock held, hence issuing I/O to the - controller must be avoided to eliminate the possibility of a - deadlock. - @param controller The controller that was opened. - @result Must return true in order for handleOpen() to accept - the client open. If the return is false, then the controller will be - closed and the client open will be refused. */ - - virtual bool controllerDidOpen(IONetworkController * controller); - -/*! @function controllerWillClose - @abstract A notification that the interface will close the network - controller. - @discussion Called by handleClose() after receiving a close from the - last client, and just before the controller is closed. Subclasses - can override this method to perform any cleanup action before the - controller is closed. This method is called with our arbitration lock - held, hence issuing I/O to the controller must be avoided to eliminate - the possibility of a deadlock. - @param controller The controller that is about to be closed. */ - - virtual void controllerWillClose(IONetworkController * controller); - -/*! @function performCommand - @abstract Handle an ioctl command sent to the network interface. - @discussion This method handles socket ioctl commands sent to the - network interface from DLIL. - IONetworkInterface handles commands that are common for all network - interface types. A subclass of IONetworkInterface may override this - method to override the command handling in IONetworkInterface, or - to extend the command processing to handle additional commands, - and then call super for any commands not handled in the subclass. - The ioctl commands handled by IONetworkInterface are - SIOCGIFMTU (Get interface MTU size), - SIOCSIFMTU (Set interface MTU size), - SIOCSIFMEDIA (Set media), and - SIOCGIFMEDIA (Get media and link status). - @param controller The controller object. - @param cmd The ioctl command code. - @param arg0 Command argument 0. Generally a pointer to an ifnet structure - associated with the interface. - @param arg1 Command argument 1. - @result A BSD return value defined in bsd/sys/errno.h. */ - - virtual SInt32 performCommand(IONetworkController * controller, - UInt32 cmd, - void * arg0, - void * arg1); - -/*! @function getIfnet - @abstract Get the ifnet structure allocated by the interface object. - @discussion Request an interface to reveal its ifnet structure. - A concrete subclass must allocate an ifnet structure when the - object is initialized, and return a pointer to the ifnet structure - when this method is called. - @result Pointer to an ifnet structure allocated by a concrete - interface subclass. */ - - virtual struct ifnet * getIfnet() const = 0; - -/*! @function initIfnet - @abstract Initialize the ifnet structure given. - @discussion A concrete subclass must override this method and initialize - the ifnet structure given. The implementation in the subclass must call - super before it returns, to allow IONetworkInterface to complete the - initialization, and to insert the BSD shim functions implemented in - IONetworkInterface to the appropriate function pointer fields in the - ifnet structure. IONetworkInterface will call this method during its - init() method. Subclasses are encouraged to use the ifnet accessor - methods to update the ifnet structure when possible, since this will - ensure that properties in the registry will also be updated to reflect - any changes made. - @param ifp Pointer to an ifnet structure obtained earlier through - the getIfnet() method call. - @result true on success, false otherwise. */ - - virtual bool initIfnet(struct ifnet * ifp); - -/*! @function handleClientOpen - @abstract Handle a client open on the interface. - @discussion Called by handleOpen() to handle an open from a client object. - Unlike handleOpen(), subclasses may override this method to catch an open - request from a client. This method is called with the arbitration lock held. - @param client The client object requesting the open. - @param options Options passed to IONetworkInterface::handleOpen(). - @param argument Argument passed to IONetworkInterface::handleOpen(). - @result true to accept the client open, false to refuse it. */ - - virtual bool handleClientOpen(IOService * client, - IOOptionBits options, - void * argument); - -/*! @function handleClientClose - @abstract Handle a client close on the interface. - @discussion Called by handleClose() to handle a close from a client object. - Unlike handleClose(), subclasses may override this method to catch a close - reuqest from a client. This method is called with the arbitration lock held. - @param client The client object requesting the close. - @param options Options passed to IONetworkInterface::handleClose(). */ - - virtual void handleClientClose(IOService * client, - IOOptionBits options); - -/*! @function newUserClient - @abstract A request to create a connection for a non kernel client. - @discussion Create a new IOUserClient to service a connection to a - non kernel client. - @param owningTask The mach task requesting the connection. - @param security_id A token representing the access level for the task. - @param type A constant specifying the type of connection to be created. - An IONetworkUserClient object is created if the type specified is - kIONetworkUserClientTypeID. - @param handler The IOUserClient object returned. - @result kIOReturnSuccess if an IONetworkUserClient was created, - kIOReturnNoMemory for a memory allocation error, or - kIOReturnBadArgument if the type specified is unknown. */ - - virtual IOReturn newUserClient(task_t owningTask, - void * security_id, - UInt32 type, - IOUserClient ** handler); - -/*! @function setInterfaceState - @abstract Update the interface object state flags. - @discussion The kIOInterfaceState property is updated with the value - provided. - @param flags The bits that should be set. - @param clear The bits that should be cleared. - @result The resulting interface state flags following any changes - made by this method. */ - - virtual UInt32 setInterfaceState( UInt32 set, UInt32 clear = 0 ); - -/*! @function powerStateWillChangeTo - @abstract Handle a notification that the network controller which is servicing - this interface object is about to transition to a new power state. - @discussion This method will call the controllerWillChangePowerState() method - on the controller's work loop context to prepare for the power state change. - Subclasses should not override this method. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller is switching to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return will always be IOPMAckImplied to indicate that the - preparation for the power change has already completed when this method - returns. */ - - virtual IOReturn powerStateWillChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ); - -/*! @function powerStateDidChangeTo - @abstract Handle a notification that the network controller which is servicing - this interface object has transitioned to a new power state. - @discussion This method will call the controllerDidChangePowerState() method - on the controller's work loop context to prepare for the power state change. - Subclasses should not override this method. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller has switched to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return will always be IOPMAckImplied to indicate that the - preparation for the power change has already completed when this method - returns. */ - - virtual IOReturn powerStateDidChangeTo( IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker ); - -/*! @function controllerWillChangePowerState - @abstract Handle a notification that the network controller which is servicing - this interface object is about to transition to a new power state. - @param controller The network controller object. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller is switching to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return value is always kIOReturnSuccess. */ - - virtual IOReturn controllerWillChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker); - -/*! @function controllerDidChangePowerState - @abstract Handle a notification that the network controller which is servicing - this interface object has transitioned to a new power state. - @param controller The network controller object. - @param flags Flags that describe the capability of the controller in the new - power state. - @param stateNumber An index to a state in the network controller's - power state array that the controller has switched to. - @param policyMaker A reference to the network controller's policy-maker, - and is also the originator of this notification. - @result The return value is always kIOReturnSuccess. */ - - virtual IOReturn controllerDidChangePowerState( - IONetworkController * controller, - IOPMPowerFlags flags, - UInt32 stateNumber, - IOService * policyMaker); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IONetworkInterface, 0); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 1); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 2); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 3); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 4); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 5); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 6); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 7); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 8); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 9); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 10); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 11); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 12); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 13); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 14); - OSMetaClassDeclareReservedUnused( IONetworkInterface, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IONETWORKINTERFACE_H */ diff --git a/iokit/IOKit/network/IONetworkLib.h b/iokit/IOKit/network/IONetworkLib.h deleted file mode 100644 index 375c5693c..000000000 --- a/iokit/IOKit/network/IONetworkLib.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - -#ifndef _IONETWORKLIB_H -#define _IONETWORKLIB_H - -#include <IOKit/IOKitLib.h> -#include <IOKit/network/IONetworkData.h> -#include <IOKit/network/IONetworkMedium.h> -#include <IOKit/network/IONetworkStats.h> -#include <IOKit/network/IOEthernetStats.h> -#include <IOKit/network/IONetworkUserClient.h> - -typedef UInt32 IONDHandle; - -#ifdef __cplusplus -extern "C" { -#endif - -/*! @function IONetworkOpen - @abstract Open a connection to an IONetworkInterface object. - An IONetworkUserClient object is created to manage the connection. */ - - IOReturn IONetworkOpen(io_object_t obj, io_connect_t * con); - -/*! @function IONetworkClose - @abstract Close the connection to an IONetworkInterface object. */ - - IOReturn IONetworkClose(io_connect_t con); - -/*! @function IONetworkWriteData - @abstract Write to the buffer of a network data object. - @param conObject The connection object. - @param dataHandle The handle of a network data object. - @param srcBuf The data to write is taken from this buffer. - @param inSize The size of the source buffer. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - IOReturn IONetworkWriteData(io_connect_t conObj, - IONDHandle dataHandle, - UInt8 * srcBuf, - UInt32 inSize); - -/*! @function IONetworkReadData - @abstract Read the buffer of a network data object. - @param conObject The connection object. - @param dataHandle The handle of a network data object. - @param destBuf The buffer where the data read shall be written to. - @param inOutSizeP Pointer to an integer that the caller must initialize - to contain the size of the buffer. This function will overwrite - it with the actual number of bytes written to the buffer. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - IOReturn IONetworkReadData(io_connect_t conObj, - IONDHandle dataHandle, - UInt8 * destBuf, - UInt32 * inOutSizeP); - -/*! @function IONetworkResetData - @abstract Fill the buffer of a network data object with zeroes. - @param conObject The connection object. - @param dataHandle The handle of a network data object. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - IOReturn IONetworkResetData(io_connect_t conObject, IONDHandle dataHandle); - -/*! @function IONetworkGetDataCapacity - @abstract Get the capacity (in bytes) of a network data object. - @param con The connection object. - @param dataHandle The handle of a network data object. - @param capacityP Upon success, the capacity is written to this address. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - IOReturn IONetworkGetDataCapacity(io_connect_t conObject, - IONDHandle dataHandle, - UInt32 * capacityP); - -/*! @function IONetworkGetDataHandle - @abstract Get the handle of a network data object with the given name. - @param con The connection object. - @param dataName The name of the network data object. - @param dataHandleP Upon success, the handle is written to this address. - @result kIOReturnSuccess on success, or an error code otherwise. */ - - IOReturn IONetworkGetDataHandle(io_connect_t conObject, - const char * dataName, - IONDHandle * dataHandleP); - -#ifdef __cplusplus -} -#endif - -#endif /* !_IONETWORKLIB_H */ diff --git a/iokit/IOKit/network/IONetworkMedium.h b/iokit/IOKit/network/IONetworkMedium.h deleted file mode 100644 index fd948c279..000000000 --- a/iokit/IOKit/network/IONetworkMedium.h +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkMedium.h - * - * HISTORY - * - */ - -#ifndef _IONETWORKMEDIUM_H -#define _IONETWORKMEDIUM_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <net/if_media.h> - -/*! @typedef IOMediumType - @discussion A 32-bit value divided into fields which describes - a single medium type. */ - -typedef UInt32 IOMediumType; - -/*! @defined kIOMediumType - @abstract kIOMediumType is a property of IONetworkMedium objects. - It is an OSNumber object. - @discussion The kIOMediumType property describes the type of - medium that this object represents. */ - -#define kIOMediumType "Type" - -/*! @defined kIOMediumFlags - @abstract kIOMediumFlags is a property of IONetworkMedium objects. - It is an OSNumber object. - @discussion The kIOMediumFlags property describes a set of - attributes assigned to the medium. */ - -#define kIOMediumFlags "Flags" - -/*! @defined kIOMediumSpeed - @abstract kIOMediumSpeed is a property of IONetworkMedium objects. - It is an OSNumber object. - @discussion The kIOMediumSpeed property describes the maximum link - speed supported by the medium in bits per second. */ - -#define kIOMediumSpeed "Speed" - -/*! @defined kIOMediumIndex - @abstract kIOMediumIndex is a property of IONetworkMedium objects. - It is an OSNumber object. - @discussion The kIOMediumIndex property describes an index assigned - by the owner of the medium object. Its interpretation is driver - specific. */ - -#define kIOMediumIndex "Index" - -//=========================================================================== -// Medium Type (IOMediumType). -// -// The medium type is encoded by a 32-bit value. The definitions of -// the fields and the encoding for each field is adapted from FreeBSD. -// -// Bits Definition -// ------------------- -// 4-0 medium subtype -// 7-5 network type -// 15-8 network specific options -// 19-16 reserved -// 27-20 common options -// 31-28 instance number - -// Ethernet. -// -enum { - kIOMediumEthernet = IFM_ETHER, - kIOMediumEthernetAuto = ( IFM_AUTO | IFM_ETHER ), - kIOMediumEthernetManual = ( IFM_MANUAL | IFM_ETHER ), - kIOMediumEthernetNone = ( IFM_NONE | IFM_ETHER ), - kIOMediumEthernet10BaseT = ( IFM_10_T | IFM_ETHER ), - kIOMediumEthernet10Base2 = ( IFM_10_2 | IFM_ETHER ), - kIOMediumEthernet10Base5 = ( IFM_10_5 | IFM_ETHER ), - kIOMediumEthernet100BaseTX = ( IFM_100_TX | IFM_ETHER ), - kIOMediumEthernet100BaseFX = ( IFM_100_FX | IFM_ETHER ), - kIOMediumEthernet100BaseT4 = ( IFM_100_T4 | IFM_ETHER ), - kIOMediumEthernet100BaseVG = ( IFM_100_VG | IFM_ETHER ), - kIOMediumEthernet100BaseT2 = ( IFM_100_T2 | IFM_ETHER ), - kIOMediumEthernet1000BaseSX = ( IFM_1000_SX | IFM_ETHER ), - kIOMediumEthernet10BaseSTP = ( IFM_10_STP | IFM_ETHER ), - kIOMediumEthernet10BaseFL = ( IFM_10_FL | IFM_ETHER ), - kIOMediumEthernet1000BaseLX = ( IFM_1000_LX | IFM_ETHER ), - kIOMediumEthernet1000BaseCX = ( IFM_1000_CX | IFM_ETHER ), - kIOMediumEthernet1000BaseTX = ( IFM_1000_TX | IFM_ETHER ), - kIOMediumEthernetHomePNA1 = ( IFM_HPNA_1 | IFM_ETHER ), -}; - -// IEEE 802.11 Wireless. -// -enum { - kIOMediumIEEE80211 = IFM_IEEE80211, - kIOMediumIEEE80211Auto = ( IFM_AUTO | IFM_IEEE80211 ), - kIOMediumIEEE80211Manual = ( IFM_MANUAL | IFM_IEEE80211 ), - kIOMediumIEEE80211None = ( IFM_NONE | IFM_IEEE80211 ), - kIOMediumIEEE80211FH1 = ( IFM_IEEE80211_FH1 | IFM_IEEE80211 ), - kIOMediumIEEE80211FH2 = ( IFM_IEEE80211_FH2 | IFM_IEEE80211 ), - kIOMediumIEEE80211DS2 = ( IFM_IEEE80211_DS2 | IFM_IEEE80211 ), - kIOMediumIEEE80211DS5 = ( IFM_IEEE80211_DS5 | IFM_IEEE80211 ), - kIOMediumIEEE80211DS11 = ( IFM_IEEE80211_DS11 | IFM_IEEE80211 ), - kIOMediumIEEE80211DS1 = ( IFM_IEEE80211_DS1 | IFM_IEEE80211 ), - kIOMediumIEEE80211OptionAdhoc = IFM_IEEE80211_ADHOC, -}; - -// Common options. -// -enum { - kIOMediumOptionFullDuplex = IFM_FDX, - kIOMediumOptionHalfDuplex = IFM_HDX, - kIOMediumOptionFlowControl = IFM_FLOW, - kIOMediumOptionFlag0 = IFM_FLAG0, - kIOMediumOptionFlag1 = IFM_FLAG1, - kIOMediumOptionFlag2 = IFM_FLAG2, - kIOMediumOptionLoopback = IFM_LOOP, -}; - -// Medium type masks. -// -#define kIOMediumSubTypeMask IFM_TMASK -#define kIOMediumNetworkTypeMask IFM_NMASK -#define kIOMediumOptionsMask IFM_OMASK -#define kIOMediumCommonOptionsMask IFM_GMASK -#define kIOMediumInstanceShift IFM_ISHIFT -#define kIOMediumInstanceMask IFM_IMASK - -// Medium type field accessors. -// -#define IOMediumGetSubType(x) ((x) & kIOMediumSubTypeMask) -#define IOMediumGetNetworkType(x) ((x) & kIOMediumNetworkMask) -#define IOMediumGetInstance(x) (((x) & kIOMediumInstanceMask) >> \ - kIOMediumInstanceShift) - -//=========================================================================== -// Medium flags. - - -//=========================================================================== -// Link status bits. -// -enum { - kIONetworkLinkValid = IFM_AVALID, // link status is valid - kIONetworkLinkActive = IFM_ACTIVE, // link is up/active. -}; - -#ifdef __cplusplus -} -#endif - -//=========================================================================== -// IONetworkMedium class. - -#ifdef KERNEL - -#include <libkern/c++/OSObject.h> -#include <libkern/c++/OSSymbol.h> - -/*! @class IONetworkMedium - @abstract An object that encapsulates information about a network - medium (i.e. 10Base-T, or 100Base-T Full Duplex). The main purpose of - this object is for network drivers to advertise its media capability, - through a collection of IONetworkMedium objects stored in a dictionary - in its property table. IONetworkMedium supports serialization, and will - encode its properties in the form of a dictionary to the serialization - stream when instructed. This will allow a user-space application to - browse the set of media types supported by the controller. */ - -class IONetworkMedium : public OSObject -{ - OSDeclareDefaultStructors( IONetworkMedium ) - -protected: - IOMediumType _type; - UInt32 _flags; - UInt64 _speed; - UInt32 _index; - const OSSymbol * _name; - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData *_reserved; - - -/*! @function free - @abstract Free the IONetworkMedium object. */ - - virtual void free(); - -public: - -/*! @function nameForType - @abstract Create a name that describes a medium type. - @discussion Given a medium type, create an OSymbol object that - describes the medium type. There is a 1-to-1 mapping between the - medium type, and the medium name created by this method. The caller - is responsible for releasing the OSSymbol object returned. - @param type A medium type. See IONetworkMedium.h for type encoding. - @result An OSSymbol object is created based on the type provided. */ - - static const OSSymbol * nameForType(IOMediumType type); - -/*! @function addMedium - @abstract Add an IONetworkMedium object to a dictionary. - @discussion A helper function to add an IONetworkMedium object to a - given dictionary. The name of the medium is used as the key for the - new dictionary entry. - @param dict An OSDictionary object where the medium object should be - added as a new entry. - @param medium The IONetworkMedium object to add to the dictionary. - @result true on success, false otherwise. */ - - static bool addMedium(OSDictionary * dict, - const IONetworkMedium * medium); - -/*! @function removeMedium - @abstract Remove an IONetworkMedium object from a dictionary. - @discussion A helper function to remove an entry in a dictionary. - @param dict The OSDictionary object where the medium object should be - removed from. - @param medium The name of this medium object is used as the key. */ - - static void removeMedium(OSDictionary * dict, - const IONetworkMedium * medium); - -/*! @function getMediumWithType - @abstract Find a medium object from a dictionary with a given type. - @discussion Iterate through a dictionary and return an IONetworkMedium - entry with the given type. An optional mask supplies the don't care bits. - @param dict The dictionary to look for a matching entry. - @param type Search for an entry with this type. - @param mask The don't care bits in IOMediumType. Defaults to 0, which - implies that a perfect match is desired. - @result The first matching IONetworkMedium entry found, - or 0 if no match was found. */ - - static IONetworkMedium * getMediumWithType(const OSDictionary * dict, - IOMediumType type, - IOMediumType mask = 0); - -/*! @function getMediumWithIndex - @abstract Find a medium object from a dictionary with a given index. - @discussion Iterate through a dictionary and return an IONetworkMedium - entry with the given index. An optional mask supplies the don't care bits. - @param dict The dictionary to look for a matching entry. - @param index Search for an entry with the given index. - @param mask The don't care bits in index. Defaults to 0, which - implies that a perfect match is desired. - @result The first matching IONetworkMedium entry found, - or 0 if no match was found. */ - - static IONetworkMedium * getMediumWithIndex(const OSDictionary * dict, - UInt32 index, - UInt32 mask = 0); - -/*! @function init - @abstract Initialize an IONetworkMedium object. - @param type The medium type, this value is encoded with bits defined in - IONetworkMedium.h. - @param speed The maximum (or the only) link speed supported over this - medium in units of bits per second. - @param flags An optional flag for the medium object. - See IONetworkMedium.h for defined flags. - @param index An optional index number assigned by the owner. - Drivers can use this to store an index to a media table in - the driver, or it may map to a driver defined media type. - @param name An optional name assigned to this medium object. If 0, - then a name will be created based on the medium type by - calling IONetworkMedium::nameForType(). Since the name of - the medium is used as a key when inserted into a dictionary, - the name chosen must be unique within the scope of the owner. - @result true on success, false otherwise. */ - - virtual bool init(IOMediumType type, - UInt64 speed, - UInt32 flags = 0, - UInt32 index = 0, - const char * name = 0); - -/*! @function medium - @abstract Factory method which performs allocation and initialization - of an IONetworkMedium object. - @param type The medium type, this value is encoded with bits defined in - IONetworkMedium.h. - @param speed The maximum (or the only) link speed supported over this - medium in units of bits per second. - @param flags An optional flag for the medium object. - See IONetworkMedium.h for defined flags. - @param index An optional index number assigned by the owner. - Drivers can use this to store an index to a media table in - the driver, or it may map to a driver defined media type. - @param name An optional name assigned to this medium object. If 0, - then a name will be created based on the medium type by - calling IONetworkMedium::nameForType(). Since the name of - the medium is used as a key when inserted into a dictionary, - the name chosen must be unique within the scope of the owner. - @result An IONetworkMedium instance on success, or 0 otherwise. */ - - static IONetworkMedium * medium(IOMediumType type, - UInt64 speed, - UInt32 flags = 0, - UInt32 index = 0, - const char * name = 0); - -/*! @function getType - @result The medium type assigned to this medium object. */ - - virtual IOMediumType getType() const; - -/*! @function getSpeed - @result The maximum link speed supported by this medium. */ - - virtual UInt64 getSpeed() const; - -/*! @function getFlags - @result The medium flags. */ - - virtual UInt32 getFlags() const; - -/*! @function getIndex - @result The assigned medium index. */ - - virtual UInt32 getIndex() const; - -/*! @function getName - @result The name assigned to this medium object. */ - - virtual const OSSymbol * getName() const; - -/*! @function getKey - @result The key to use for this medium object. This key should be - used when this object is added to a dictionary. Same as getName(). */ - - virtual const OSSymbol * getKey() const; - -/*! @function isEqualTo - @abstract Test for equality between two IONetworkMedium objects. - @discussion Two IONetworkMedium objects are considered equal if - they have similar properties assigned to them during initialization. - @param medium An IONetworkMedium to test against the IONetworkMedium - object being called. - @result true if equal, false otherwise. */ - - virtual bool isEqualTo(const IONetworkMedium * medium) const; - -/*! @function isEqualTo - @abstract Test for equality between a IONetworkMedium object and an - OSObject. - @discussion The OSObject is considered equal to the IONetworkMedium - object if the OSObject is an IONetworkMedium, and they have - similar properties assigned to them during initialization. - @param obj An OSObject to test against an IONetworkMedium object. - @result true if equal, false otherwise. */ - - virtual bool isEqualTo(const OSMetaClassBase * obj) const; - -/*! @function serialize - @abstract Serialize the IONetworkMedium object. - @discussion A dictionary is created containing the properties - assigned to this medium object, and this dictionary is then - serialized using the OSSerialize object provided. - @param s An OSSerialize object. - @result true on success, false otherwise. */ - - virtual bool serialize(OSSerialize * s) const; - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IONetworkMedium, 0); - OSMetaClassDeclareReservedUnused( IONetworkMedium, 1); - OSMetaClassDeclareReservedUnused( IONetworkMedium, 2); - OSMetaClassDeclareReservedUnused( IONetworkMedium, 3); -}; - -// Translate getKey() to getName(). -// -inline const OSSymbol * IONetworkMedium::getKey() const -{ - return getName(); -} - -#endif /* KERNEL */ - -#endif /* !_IONETWORKMEDIUM_H */ diff --git a/iokit/IOKit/network/IONetworkStack.h b/iokit/IOKit/network/IONetworkStack.h deleted file mode 100644 index b2d97c810..000000000 --- a/iokit/IOKit/network/IONetworkStack.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkStack.h - An IOKit proxy for the BSD network stack. - * - * HISTORY - * - */ - -#ifndef _IONETWORKSTACK_H -#define _IONETWORKSTACK_H - -// User-client keys -// -#define kIONetworkStackUserCommand "IONetworkStackUserCommand" -enum { - kIORegisterOne = 1, - kIORegisterAll -}; - -#ifdef KERNEL - -class IONetworkInterface; - -class IONetworkStack : public IOService -{ - OSDeclareDefaultStructors( IONetworkStack ) - -protected: - OSOrderedSet * _ifSet; - OSDictionary * _ifDict; - IONotifier * _interfaceNotifier; - bool _registerPrimaryInterface; - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData *_reserved; - - - static bool interfacePublished( void * target, - void * param, - IOService * service ); - - static void unregisterBSDInterface( IONetworkInterface * netif ); - - static void registerBSDInterface( IONetworkInterface * netif ); - - static SInt32 orderRegisteredInterfaces( const OSMetaClassBase * obj1, - const OSMetaClassBase * obj2, - void * ref ); - - static void completeRegistrationUsingArray( OSArray * array ); - - static void completeRegistration( OSArray * array, bool isSync ); - - virtual void free(); - - virtual bool addInterface( IONetworkInterface * netif ); - - virtual void removeInterface( IONetworkInterface * netif ); - - virtual IONetworkInterface * getInterface( UInt32 index ); - - virtual bool containsInterface( IONetworkInterface * netif ); - - virtual bool addRegisteredInterface( IONetworkInterface * netif ); - - virtual void removeRegisteredInterface( IONetworkInterface * netif ); - - virtual IONetworkInterface * getRegisteredInterface( const char * name, - UInt32 unit ); - - virtual IONetworkInterface * getLastRegisteredInterface(const char * name); - - virtual UInt32 getNextAvailableUnitNumber( const char * name, - UInt32 startingUnit = 0 ); - - virtual bool preRegisterInterface( IONetworkInterface * netif, - const char * name, - UInt32 unit, - OSArray * array ); - -public: - static IONetworkStack * getNetworkStack(); - - static int bsdInterfaceWasUnregistered( struct ifnet * ifp ); - - virtual bool init( OSDictionary * properties ); - - virtual bool start( IOService * provider ); - - virtual void stop( IOService * provider ); - - virtual IOReturn registerAllInterfaces(); - - virtual IOReturn registerPrimaryInterface( bool enable ); - - virtual IOReturn registerInterface( IONetworkInterface * netif, - const char * name, - UInt32 unit = 0, - bool isSync = true ); - - virtual IOReturn message( UInt32 type, - IOService * provider, - void * argument = 0 ); - - virtual IOReturn newUserClient( task_t owningTask, - void * security_id, - UInt32 type, - IOUserClient ** handler ); - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IONetworkStack, 0); - OSMetaClassDeclareReservedUnused( IONetworkStack, 1); - OSMetaClassDeclareReservedUnused( IONetworkStack, 2); - OSMetaClassDeclareReservedUnused( IONetworkStack, 3); - -}; - -#endif /* KERNEL */ - -#endif /* !_IONETWORKSTACK_H */ diff --git a/iokit/IOKit/network/IONetworkStats.h b/iokit/IOKit/network/IONetworkStats.h deleted file mode 100644 index 03496c214..000000000 --- a/iokit/IOKit/network/IONetworkStats.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IONetworkStats.h - * - * HISTORY - */ - -#ifndef _IONETWORKSTATS_H -#define _IONETWORKSTATS_H - -/*! @header IONetworkStats.h - @discussion Generic network statistics. */ - -//------------------------------------------------------------------------ -// Generic network statistics. Common to all network interfaces. -// -// WARNING: This structure must match the statistics field in -// ifnet->if_data. This structure will overlay a portion of ifnet. - -/*! @typedef IONetworkStats - @discussion Generic network statistics structure. - @field inputPackets count input packets. - @field inputErrors count input errors. - @field outputPackets count output packets. - @field outputErrors count output errors. - @field collisions count collisions on CDMA networks. */ - -typedef struct { - UInt32 inputPackets; - UInt32 inputErrors; - UInt32 outputPackets; - UInt32 outputErrors; - UInt32 collisions; -} IONetworkStats; - -/*! @defined kIONetworkStatsKey - @discussion Defines the name of an IONetworkData that contains - an IONetworkStats. */ - -#define kIONetworkStatsKey "IONetworkStatsKey" - -//------------------------------------------------------------------------ -// Output queue statistics. - -/*! @typedef IOOutputQueueStats - @discussion Statistics recorded by IOOutputQueue objects. - @field capacity queue capacity. - @field size current size of the queue. - @field peakSize peak size of the queue. - @field dropCount number of packets dropped. - @field outputCount number of output packets. - @field retryCount number of retries. - @field stallCount number of queue stalls. */ - -typedef struct { - UInt32 capacity; - UInt32 size; - UInt32 peakSize; - UInt32 dropCount; - UInt32 outputCount; - UInt32 retryCount; - UInt32 stallCount; - UInt32 reserved[4]; -} IOOutputQueueStats; - -/*! @defined kIOOutputQueueStatsKey - @discussion Defines the name of an IONetworkData that contains - an IOOutputQueueStats. */ - -#define kIOOutputQueueStatsKey "IOOutputQueueStatsKey" - -#endif /* !_IONETWORKSTATS_H */ diff --git a/iokit/IOKit/network/IONetworkUserClient.h b/iokit/IOKit/network/IONetworkUserClient.h deleted file mode 100644 index 9bbfab393..000000000 --- a/iokit/IOKit/network/IONetworkUserClient.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * HISTORY - * - */ - -#ifndef _IONETWORKUSERCLIENT_H -#define _IONETWORKUSERCLIENT_H - -// IONetworkUserClient type ID. -// -#define kIONetworkUserClientTypeID 0xff000001 -#define kIONUCType 0xff000001 // FIXME - -// IONetworkUserClient call structure definitions. -// -enum { - kIONUCResetNetworkDataIndex = 0, -#define kIONUCResetNetworkDataInputs 1 -#define kIONUCResetNetworkDataOutputs 0 -#define kIONUCResetNetworkDataFlags kIOUCScalarIScalarO - - kIONUCWriteNetworkDataIndex = 1, -#define kIONUCWriteNetworkDataInput0 0xffffffff -#define kIONUCWriteNetworkDataInput1 0xffffffff -#define kIONUCWriteNetworkDataFlags kIOUCScalarIStructI - - kIONUCReadNetworkDataIndex = 2, -#define kIONUCReadNetworkDataInputs 1 -#define kIONUCReadNetworkDataOutputs 0xffffffff -#define kIONUCReadNetworkDataFlags kIOUCScalarIStructO - - kIONUCGetNetworkDataCapacityIndex = 3, -#define kIONUCGetNetworkDataCapacityInputs 1 -#define kIONUCGetNetworkDataCapacityOutputs 1 -#define kIONUCGetNetworkDataCapacityFlags kIOUCScalarIScalarO - - kIONUCGetNetworkDataHandleIndex = 4, -#define kIONUCGetNetworkDataHandleInputs 0xffffffff -#define kIONUCGetNetworkDataHandleOutputs 0xffffffff -#define kIONUCGetNetworkDataHandleFlags kIOUCStructIStructO - - kIONUCLastIndex -}; - -#ifdef KERNEL - -#include <IOKit/IOUserClient.h> - -class IONetworkInterface; - -/*! @class IONetworkUserClient - @abstract An IOUserClient created by an IONetworkInterface to - manage user space requests. */ - -class IONetworkUserClient : public IOUserClient -{ - OSDeclareDefaultStructors( IONetworkUserClient ) - -protected: - IONetworkInterface * _owner; - task_t _task; - IOExternalMethod _methods[kIONUCLastIndex]; - -/*! @function - @abstract Free the IONetworkUserClient object. */ - - virtual void free(); - -public: - -/*! @function withTask - @abstract Factory method that performs allocation and initialization - of an IONetworkUserClient object. - @param owningTask See IOUserClient. - @result An IONetworkUserClient on success, 0 otherwise. */ - - static IONetworkUserClient * withTask(task_t owningTask); - -/*! @function start - @abstract Start the IONetworkUserClient. - @discussion Open the provider, must be an IONetworkInterface object, - and initialize the IOExternalMethod array. - @result true on success, false otherwise. */ - - virtual bool start(IOService * provider); - -/*! @function clientClose - @abstract Handle a client close. - @discussion Close and detach from our owner (provider). - @result kIOReturnSuccess. */ - - virtual IOReturn clientClose(); - -/*! @function clientDied - @abstract Handle client death. - @discussion Close and detach from our owner (provider). - @result kIOReturnSuccess. */ - - virtual IOReturn clientDied(); - -/*! @function getExternalMethodForIndex - @abstract Look up a method entry from the method array. - @discussion Called by IOUserClient to fetch the method entry, - described by an IOExternalMethod structure, that correspond to - the index provided. - @param index The method index. - @result A pointer to an IOExternalMethod structure containing the - method definition for the given index. */ - - virtual IOExternalMethod * getExternalMethodForIndex(UInt32 index); - -protected: - -/*! @function resetNetworkData - @abstract Fill the data buffer in an IONetworkData object with zeroes. - @param key An OSSymbol key associated with an IONetworkData object. - @result kIOReturnSuccess on success, kIOReturnBadArgument if an - argument is invalid, or an error from IONetworkData::reset(). */ - - virtual IOReturn resetNetworkData(OSSymbol * key); - -/*! @function writeNetworkData - @abstract Write to the data buffer in an IONetworkData object with - data from a source buffer provided by the caller. - @param key The OSSymbol key associated with an IONetworkData object. - @param srcBuffer The source buffer provided by the caller. - @param srcBufferSize The size of the source buffer. - @result kIOReturnSuccess on success, kIOReturnBadArgument if an - argument is invalid, or an error from IONetworkData::write(). */ - - virtual IOReturn writeNetworkData(OSSymbol * key, - void * srcBuffer, - IOByteCount srcBufferSize); - -/*! @function readNetworkData - @abstract Read the data buffer in an IONetworkData object and copy - this data to a destination buffer provided by the caller. - @param key The OSSymbol key associated with an IONetworkData object. - @param dstBuffer The destination buffer provided by the caller. - @param dstBufferSize Pointer to an integer that the caller must - initialize to hold the size of the destination buffer. This method - will overwrite it with the actual number of bytes written. - @result kIOReturnSuccess on success, kIOReturnBadArgument if an - argument is invalid, or an error from IONetworkData::read(). */ - - virtual IOReturn readNetworkData(OSSymbol * key, - void * dstBuffer, - IOByteCount * dstBufferSize); - -/*! @function getNetworkDataCapacity - @abstract Get the capacity of an IONetworkData object, described - by the size of its data buffer. - @param key The OSSymbol key of an IONetworkData object. - @param capacity A pointer to the capacity value returned by this - method. - @result kIOReturnSuccess on success, kIOReturnBadArgument if an - argument is invalid. */ - - virtual IOReturn getNetworkDataCapacity(OSSymbol * key, - UInt32 * capacity); - -/*! @function getNetworkDataHandle - @abstract Return an opaque handle to a provider's IONetworkData object. - @discussion Called to obtain an unique handle that maps to an IONetworkData - object. This handle can be later passed to other methods defined in this - class to refer to the same object. - @param name A C string with the name of the IONetworkData object. - @param handle If an IONetworkData object with the given name is found, - then its associated OSSymbol object is written to this address. - @param nameSize The size of the name string, including the final - terminating null character. - @param handleSizeP The size of the buffer allocated by the caller - to store the handle. This should be 4 bytes. - @result kIOReturnSuccess on success, kIOReturnBadArgument if an - argument is invalid, or kIOReturnNoMemory if unable to allocate memory. */ - - virtual IOReturn getNetworkDataHandle(char * name, - OSSymbol ** handle, - IOByteCount nameSize, - IOByteCount * handleSizeP); -}; - -#endif /* KERNEL */ - -#endif /* !_IONETWORKUSERCLIENT_H */ diff --git a/iokit/IOKit/network/IOOutputQueue.h b/iokit/IOKit/network/IOOutputQueue.h deleted file mode 100644 index 3c685f3e0..000000000 --- a/iokit/IOKit/network/IOOutputQueue.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOOutputQueue.h - * - * HISTORY - * 2-Feb-1999 Joe Liu (jliu) created. - * - */ - -#ifndef _IOOUTPUTQUEUE_H -#define _IOOUTPUTQUEUE_H - -#include <IOKit/network/IONetworkInterface.h> - -// Forward declarations. -// -struct mbuf; -class IONetworkData; - -// FIXME - We do not want the enqueue/dequeue macros defined in queue.h. -// -#undef enqueue(queue,elt) -#undef dequeue(queue) - -// FIXME - Belongs in IOBasicOutputQueue.h -// -/*! @enum The status of the packet sent to the target. - @constant kIOOutputStatusMask Define the status field in the return code. - @constant kIOOutputStatusAccept Packet was accepted by the target. - @constant kIOOutputStatusDropped Packet accepted, but was also dropped. - @constant kIOOutputStatusRetry Target ran out of resources, and is unable - to accept the packet. The ownership of the packet reverts back to the - queue. */ - -enum { - kIOOutputStatusMask = 0x00ff, - kIOOutputStatusAccepted = 0x0000, - kIOOutputStatusDropped = 0x0001, - kIOOutputStatusRetry = 0x0002 -}; - -/*! @enum A command requested by the target. - @constant kIOOutputCommandMask Define the command field in the return code. - @constant kIOOutputCommandNone No command. - @constant kIOOutputCommandStall A command to stall the queue. */ - -enum { - kIOOutputCommandMask = 0xff00, - kIOOutputCommandNone = 0x0000, - kIOOutputCommandStall = 0x0100 -}; - -/*! @enum Definition of common return codes returned by the target's - output handler. - @constant kIOReturnOutputSuccess Packet was accepted. - @constant kIOReturnOutputDropped Packet was dropped. - @constant kIOReturnOutputStall Stall the queue and retry the same packet - when the queue is restarted. */ - -enum { - kIOReturnOutputSuccess = (kIOOutputStatusAccepted | kIOOutputCommandNone), - kIOReturnOutputDropped = (kIOOutputStatusDropped | kIOOutputCommandNone), - kIOReturnOutputStall = (kIOOutputStatusRetry | kIOOutputCommandStall) -}; - -/*! @class IOOutputQueue : public OSObject - @abstract A packet queue that supports multiple producers, and a single - consumer. Each producer, or a client thread, will deliver a chain of packets - to the queue. A single consumer will remove packets from the queue one at a - time and forward it to the registered target/action. This object may be used - by an IONetworkController on the output (transmit) side to handle the output - packet flow downstream from an IONetworkInterface, and then call the driver's - output function. IOOutputQueue is an abstract class that provides an interface - for its subclasses. Concrete subclasses will complete the implementation, and - specify the context that the target is called for packets removed from - the queue. */ - -class IOOutputQueue : public OSObject -{ - OSDeclareAbstractStructors( IOOutputQueue ) - -private: - - static void runServiceThread(thread_call_param_t, thread_call_param_t); - -protected: - - thread_call_t _callEntry; // callout entry structure. - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData *_reserved; - - -/*! @function init - @abstract Initialize an IOOutputQueue object. - @result true if initialized successfully, false otherwise. */ - - virtual bool init(); - -/*! @function free - @abstract Free the IOOutputQueue object. - @discussion Release allocated resources, then call super::free(). */ - - virtual void free(); - -/*! @function scheduleServiceThread - @abstract Schedule a service thread callout. - @discussion This method can be called by service() to schedule - a thread that will call serviceThread() when it starts running. - @param param A parameter to pass to the serviceThread() method. - @result true if a thread callout was scheduled, false otherwise. */ - - virtual bool scheduleServiceThread(void * param); - -/*! @function cancelServiceThread - @abstract Cancel any pending service thread callout. - @result true if a previously scheduled thread callout was canceled, - false otherwise. */ - - virtual bool cancelServiceThread(); - -/*! @function serviceThread - @abstract Method called by the scheduled service thread when it - starts to run. - @discussion Must be implemented by a subclass that calls - scheduleServiceThread(). The default implementation does nothing. - @param param A parameter that was given to scheduleServiceThread() - when the service thread was scheduled. */ - - virtual void serviceThread(void * param); - -public: - -/*! @function start - @abstract Start up the queue. - @discussion Called by the target to start the queue. This will allow - packets to be removed from the queue, then delivered to the target. - @result true if the queue was started successfully, false otherwise. */ - - virtual bool start() = 0; - -/*! @function stop - @abstract Stop the queue. - @discussion Stop the queue and prevent it from sending packets to its - target. - @result Returns the previous running state of the queue, - true if the queue was running, false if the queue was already stopped. */ - - virtual bool stop() = 0; - -/*! @function service - @abstract Service the queue. - @discussion Manage the queue after it has been started. - @param options Options for the service request. - @result A return value to indicate the service result. */ - - virtual bool service(IOOptionBits options = 0) = 0; - -/*! @function flush - @abstract Drop and free all packets currently held by the queue. - @result The number of packets that were dropped and freed. */ - - virtual UInt32 flush() = 0; - -/*! @function setCapacity - @abstract Change the number of packets that the queue can hold - before it begins to drop excess packets. - @param capacity The new desired capacity. - @result true if the new capacity was accepted, false otherwise. */ - - virtual bool setCapacity(UInt32 capacity) = 0; - -/*! @function getCapacity - @abstract Get the number of packets that the queue can hold. - @discussion The queue will begin to drop incoming packets when the - size of queue reaches its capacity. - @result The current queue capacity. */ - - virtual UInt32 getCapacity() const = 0; - -/*! @function getSize - @abstract Get the number of packets currently held in the queue. - @result The size of the queue. */ - - virtual UInt32 getSize() const = 0; - -/*! @function enqueue - @abstract Called by a client to add a packet, or a chain of packets, - to the queue. - @discussion A packet is described by a mbuf chain, while a chain - of packets is constructed by linking multiple mbuf chains via the - m_nextpkt field. - @param m A single packet, or a chain of packets. - @param param A parameter provided by the caller. - @result A return code. */ - - virtual UInt32 enqueue(struct mbuf * m, void * param) = 0; - -/*! @function getOutputHandler - @abstract Return the address of a function that is designated to handle - incoming packets sent to the queue object. - @result The address of the enqueue() method is returned. */ - - virtual IOOutputAction getOutputHandler() const; - -/*! @function getStatisticsData - @abstract Return an IONetworkData object containing statistics counters - updated by the queue. - @result An IONetworkData object. This implementation will always return - 0. */ - - virtual IONetworkData * getStatisticsData() const; - - // Virtual function padding - OSMetaClassDeclareReservedUnused( IOOutputQueue, 0); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 1); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 2); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 3); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 4); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 5); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 6); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 7); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 8); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 9); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 10); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 11); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 12); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 13); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 14); - OSMetaClassDeclareReservedUnused( IOOutputQueue, 15); -}; - -#endif /* !_IOOUTPUTQUEUE_H */ diff --git a/iokit/IOKit/network/IOPacketQueue.h b/iokit/IOKit/network/IOPacketQueue.h deleted file mode 100644 index d77df981f..000000000 --- a/iokit/IOKit/network/IOPacketQueue.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. - * - * IOPacketQueue.h - * - * HISTORY - * 9-Dec-1998 Joe Liu (jliu) created. - * - */ - -#ifndef _IOPACKETQUEUE_H -#define _IOPACKETQUEUE_H - -#include <libkern/c++/OSObject.h> -#include <IOKit/IOLocks.h> - -// Forward declarations. -// -struct mbuf; -struct IOMbufQueue; - -// We do not want the enqueue/dequeue macros defined in queue.h. -// -// #warning queue.h should not be included -#undef enqueue(queue,elt) -#undef dequeue(queue) - -/*! @class IOPacketQueue : public OSObject - @abstract Implements a bounded FIFO queue of mbuf packets. Packets are - removed from the head of the queue (dequeue), and new packets are added - to the tail of the queue (enqueue). A spinlock is used to synchronize - access to the queue between methods that have a "lock" prefix. */ - -class IOPacketQueue : public OSObject -{ - OSDeclareDefaultStructors( IOPacketQueue ) - -protected: - IOMbufQueue * _queue; // mbuf queue - IOSimpleLock * _lock; // spinlock for synchronized methods - - struct ExpansionData { }; - /*! @var reserved - Reserved for future use. (Internal use only) */ - ExpansionData *_reserved; - -/*! @function free - @abstract Free the IOPacketQueue object. - @discussion All packets held by the queue are released back to the free - pool, resource are deallocated, then super::free() is called. */ - - virtual void free(); - -/*! @var IOPacketQueueDefaultCapacity Describes the default capacity of the - queue object. The capacity is only observed by the enqueue() method. - Therefore, it is possible for the size of the queue to exceed its - capacity when other methods, such as prepend(), are used to add packets - to the queue. */ - - static const UInt32 IOPacketQueueDefaultCapacity = 100; - -public: - -/*! @function withCapacity - @abstract Factory method that will construct and initialize an - IOPacketQueue object. - @param capacity The initial capacity of the queue object. Can be - later changed by calling the setCapacity() method. - @result An IOPacketQueue instance on success, or 0 otherwise. */ - - static IOPacketQueue * withCapacity(UInt32 capacity = - IOPacketQueueDefaultCapacity); - -/*! @function initWithCapacity - @abstract Initialize an IOPacketQueue object. - @discussion Initialize an IOPacketQueue object with the given capacity. - @param capacity The initial capacity of the queue. Can be later changed - by calling the setCapacity() method. - @result true if initialized successfully, false otherwise. */ - - virtual bool initWithCapacity(UInt32 capacity = - IOPacketQueueDefaultCapacity); - -/*! @function getSize - @abstract Get the size of the queue. - @result The number of packets currently held by the queue. */ - - virtual UInt32 getSize() const; - -/*! @function setCapacity - @abstract Change the capacity of the queue. - @param capacity The new capacity. - @result true if the new capacity was accepted, false otherwise. */ - - virtual bool setCapacity(UInt32 capacity); - -/*! @function getCapacity - @abstract Get the current capacity of the queue. - @result The current queue capacity. */ - - virtual UInt32 getCapacity() const; - -/*! @function peek - @abstract Examine the packet at the head of the queue without - removing it from the queue. - @discussion A following call to peek() or dequeue() will return - the same packet. The caller must never modify the mbuf packet returned. - @result The packet at the head of the queue. */ - - virtual const struct mbuf * peek() const; - -/*! @function prepend - @abstract Add a chain of packets to the head of the queue. - @param m A chain of packets to add to the head of the queue. */ - - virtual void prepend(struct mbuf * m); - -/*! @function prepend - @abstract Remove all packets from the specified queue, and add them - to the head of this queue. - @param queue The source IOPacketQueue object containing the packets to - be transferred. */ - - virtual void prepend(IOPacketQueue * queue); - -/*! @function lockPrepend - @abstract Add a chain of packets to the head of a synchronized queue. - @discussion A spinlock is used to synchronize access to the queue. - @param m A chain of packets to add to the head of the queue. - @result Will always return true. */ - - virtual void lockPrepend(struct mbuf * m); - -/*! @function enqueue - @abstract Add a chain of packets to the tail of the queue. - @discussion Packets are not added if the size of the queue has reached - its capacity. - @param m A chain of packets to add to the tail of the queue. - @result true on success, or false to indicate over-capacity and refusal - to accept the packet chain provided. */ - - virtual bool enqueue(struct mbuf * m); - -/*! @function enqueue - @abstract Remove all packets from the specified queue, and add them - to the tail of this queue. - @param queue The source IOPacketQueue object containing the packets to - be transferred. - @result Always return true. */ - - virtual bool enqueue(IOPacketQueue * queue); - -/*! @function enqueueWithDrop - @abstract Add a chain of packets to the tail of the queue. Packets are - dropped if the size of the queue has reached its capacity. - @param m A chain of packets to add to the tail of the queue. - @result The number of packets dropped and freed by the queue. */ - - virtual UInt32 enqueueWithDrop(struct mbuf * m); - -/*! @function lockEnqueue - @abstract Add a chain of packets to the tail of a synchronized queue. - @discussion Packets are not added if the size of the queue has reached - its capacity. A spinlock is used to synchronize access to the queue. - @param m A chain of packets to add to the tail of the queue. - @result true on success, or false to indicate over-capacity and refusal - to accept the packet chain provided. */ - - virtual bool lockEnqueue(struct mbuf * m); - -/*! @function lockEnqueueWithDrop - @abstract Add a chain of packets to the tail of a synchronized queue. - Packets are dropped if the size of the queue has reached its capacity. - @discussion A spinlock is used to synchronize access to the queue. - @param m A chain of packets to add to the tail of the queue. - @result The number of packets dropped and freed by the queue. */ - - virtual UInt32 lockEnqueueWithDrop(struct mbuf * m); - -/*! @function dequeue - @abstract Remove a single packet from the head of the queue. - @result A packet removed from the head of the queue, or NULL if the - queue was empty. */ - - virtual struct mbuf * dequeue(); - -/*! @function lockDequeue - @abstract Remove a single packet from the head of a synchronized queue. - @discussion A spinlock is used to synchronize access to the queue. - @result A packet removed from the head of the queue, or NULL if the - queue was empty. */ - - virtual struct mbuf * lockDequeue(); - -/*! @function dequeueAll - @abstract Remove all packets from the queue and return the head of the - packet chain. - @discussion The size of the queue is cleared to zero. - @result The head of a packet chain linking all packets that were held - in the queue, or NULL if the queue was empty. */ - - virtual struct mbuf * dequeueAll(); - -/*! @function lockDequeueAll - @abstract Remove all packets from a synchronized queue and return the - head of the packet chain. - @discussion The size of the queue is cleared to zero. A spinlock is used - to synchronize access to the queue. - @result The head of a packet chain linking all packets that were held - in the queue, or NULL if the queue was empty. */ - - virtual struct mbuf * lockDequeueAll(); - -/*! @function flush - @abstract Free all packets currently held in the queue and release them - back to the free mbuf pool. - @discussion The size of the queue is cleared to zero. - @result The number of packets freed. */ - - virtual UInt32 flush(); - -/*! @function lockFlush - @abstract Free all packets currently held in a synchronized queue and - release them back to the free mbuf pool. - @discussion The size of the queue is cleared to zero. A spinlock is used - to synchronize access to the queue. - @result The number of packets freed. */ - - virtual UInt32 lockFlush(); - - // Virtual Pad functions - OSMetaClassDeclareReservedUnused( IOPacketQueue, 0); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 1); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 2); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 3); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 4); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 5); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 6); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 7); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 8); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 9); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 10); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 11); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 12); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 13); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 14); - OSMetaClassDeclareReservedUnused( IOPacketQueue, 15); -}; - -#endif /* !_IOPACKETQUEUE_H */ diff --git a/iokit/IOKit/network/Makefile b/iokit/IOKit/network/Makefile deleted file mode 100644 index 030f9d775..000000000 --- a/iokit/IOKit/network/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = network -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = \ - IONetworkMedium.h \ - IONetworkData.h \ - IONetworkStats.h \ - IOEthernetStats.h \ - IONetworkUserClient.h \ - IONetworkStack.h \ - IONetworkController.h \ - IONetworkInterface.h \ - IOEthernetController.h \ - IOEthernetInterface.h -INSTALL_MI_LCL_LIST = "" -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/pci/IOAGPDevice.h b/iokit/IOKit/pci/IOAGPDevice.h index fe06914b0..06c58dd5f 100644 --- a/iokit/IOKit/pci/IOAGPDevice.h +++ b/iokit/IOKit/pci/IOAGPDevice.h @@ -45,6 +45,7 @@ enum { kIOAGPSideBandAddresssing = 0x00000200, kIOAGPEnable = 0x00000100, kIOAGP4GbAddressing = 0x00000020, + kIOAGPFastWrite = 0x00000010, kIOAGP4xDataRate = 0x00000004, kIOAGP2xDataRate = 0x00000002, kIOAGP1xDataRate = 0x00000001 diff --git a/iokit/IOKit/pci/IOPCIBridge.h b/iokit/IOKit/pci/IOPCIBridge.h index 0349d35c7..d6e1f7a1e 100644 --- a/iokit/IOKit/pci/IOPCIBridge.h +++ b/iokit/IOKit/pci/IOPCIBridge.h @@ -133,7 +133,7 @@ public: UInt8 capabilityID, UInt8 * offset = 0 ); virtual IOReturn setDevicePowerState( IOPCIDevice * device, - unsigned long powerState ); + unsigned long whatToDo ); virtual IOReturn saveDeviceState( IOPCIDevice * device, IOOptionBits options = 0 ); virtual IOReturn restoreDeviceState( IOPCIDevice * device, diff --git a/iokit/IOKit/pci/IOPCIDevice.h b/iokit/IOKit/pci/IOPCIDevice.h index 43c4fbead..523d6db11 100644 --- a/iokit/IOKit/pci/IOPCIDevice.h +++ b/iokit/IOKit/pci/IOPCIDevice.h @@ -149,6 +149,14 @@ struct IOPCIPhysicalAddress { #define kIOPCISecondaryMatchKey "IOPCISecondaryMatch" #define kIOPCIClassMatchKey "IOPCIClassMatch" +// property to control PCI default config space save on sleep +#define kIOPMPCIConfigSpaceVolatileKey "IOPMPCIConfigSpaceVolatile" + +enum { + kIOPCIDevicePowerStateCount = 3, + kIOPCIDeviceOffState = 0, + kIOPCIDeviceOnState = 2 +}; /*! @class IOPCIDevice : public IOService @abstract An IOService class representing a PCI device. @@ -241,9 +249,7 @@ public: /* IOService/IORegistryEntry methods */ virtual bool attach( IOService * provider ); - virtual unsigned long maxCapabilityForDomainState( IOPMPowerFlags ); - virtual unsigned long initialPowerStateForDomainState( IOPMPowerFlags ); - virtual unsigned long powerStateForDomainState( IOPMPowerFlags ); + virtual void detach( IOService * provider ); virtual IOReturn setPowerState( unsigned long, IOService * ); virtual IOReturn addPowerChild ( IOService * theChild ); virtual void joinPMtree( IOService * driver ); diff --git a/iokit/IOKit/ppc/IOSharedLockImp.h b/iokit/IOKit/ppc/IOSharedLockImp.h index 030fd4913..3bff4b078 100644 --- a/iokit/IOKit/ppc/IOSharedLockImp.h +++ b/iokit/IOKit/ppc/IOSharedLockImp.h @@ -49,35 +49,14 @@ #define _IOKIT_IOSHAREDLOCKIMP_H #include <architecture/ppc/asm_help.h> -#ifdef KERNEL -#undef END -#include <mach/ppc/asm.h> -#endif +// 'Till we're building in kernel .macro DISABLE_PREEMPTION #ifdef KERNEL - stwu r1,-(FM_SIZE)(r1) - mflr r0 - stw r3,FM_ARG0(r1) - stw r0,(FM_SIZE+FM_LR_SAVE)(r1) - bl EXT(_disable_preemption) - lwz r3,FM_ARG0(r1) - lwz r1,0(r1) - lwz r0,FM_LR_SAVE(r1) - mtlr r0 #endif .endmacro .macro ENABLE_PREEMPTION #ifdef KERNEL - stwu r1,-(FM_SIZE)(r1) - mflr r0 - stw r3,FM_ARG0(r1) - stw r0,(FM_SIZE+FM_LR_SAVE)(r1) - bl EXT(_enable_preemption) - lwz r3,FM_ARG0(r1) - lwz r1,0(r1) - lwz r0,FM_LR_SAVE(r1) - mtlr r0 #endif .endmacro @@ -93,20 +72,34 @@ #ifndef KERNEL LEAF(_ev_lock) -LEAF(_IOSpinLock) - li a6,1 // lock value - lwarx a7,0,a0 // CEMV10 + li a6,1 // lock value + lwarx a7,0,a0 // CEMV10 9: sync - lwarx a7,0,a0 // read the lock - cmpwi cr0,a7,0 // is it busy? - bne- 9b // yes, spin + lwarx a7,0,a0 // read the lock + cmpwi cr0,a7,0 // is it busy? + bne- 9b // yes, spin sync - stwcx. a6,0,a0 // try to get the lock - bne- 9b // failed, try again + stwcx. a6,0,a0 // try to get the lock + bne- 9b // failed, try again isync - blr // got it, return + blr // got it, return END(_ev_lock) + +LEAF(_IOSpinLock) + li a6,1 // lock value + lwarx a7,0,a0 // CEMV10 +9: + sync + lwarx a7,0,a0 // read the lock + cmpwi cr0,a7,0 // is it busy? + bne- 9b // yes, spin + sync + stwcx. a6,0,a0 // try to get the lock + bne- 9b // failed, try again + isync + blr // got it, return +END(_IOSpinLock) #endif /* @@ -118,7 +111,6 @@ END(_ev_lock) */ LEAF(_ev_unlock) -LEAF(_IOSpinUnlock) sync li a7,0 stw a7,0(a0) @@ -126,6 +118,14 @@ LEAF(_IOSpinUnlock) blr END(_ev_unlock) +LEAF(_IOSpinUnlock) + sync + li a7,0 + stw a7,0(a0) + ENABLE_PREEMPTION() + blr +END(_IOSpinUnlock) + /* * ev_try_lock(p) @@ -135,25 +135,45 @@ END(_ev_unlock) */ LEAF(_ev_try_lock) -LEAF(_IOTrySpinLock) - li a6,1 // lock value + li a6,1 // lock value DISABLE_PREEMPTION() - lwarx a7,0,a0 // CEMV10 + lwarx a7,0,a0 // CEMV10 8: sync - lwarx a7,0,a0 // read the lock - cmpwi cr0,a7,0 // is it busy? - bne- 9f // yes, give up + lwarx a7,0,a0 // read the lock + cmpwi cr0,a7,0 // is it busy? + bne- 9f // yes, give up sync - stwcx. a6,0,a0 // try to get the lock - bne- 8b // failed, try again - li a0,1 // return TRUE + stwcx. a6,0,a0 // try to get the lock + bne- 8b // failed, try again + li a0,1 // return TRUE isync blr 9: ENABLE_PREEMPTION() - li a0,0 // return FALSE + li a0,0 // return FALSE blr END(_ev_try_lock) +LEAF(_IOTrySpinLock) + li a6,1 // lock value + DISABLE_PREEMPTION() + lwarx a7,0,a0 // CEMV10 +8: + sync + lwarx a7,0,a0 // read the lock + cmpwi cr0,a7,0 // is it busy? + bne- 9f // yes, give up + sync + stwcx. a6,0,a0 // try to get the lock + bne- 8b // failed, try again + li a0,1 // return TRUE + isync + blr +9: + ENABLE_PREEMPTION() + li a0,0 // return FALSE + blr +END(_IOTrySpinLock) + #endif /* ! _IOKIT_IOSHAREDLOCKIMP_H */ diff --git a/iokit/IOKit/ps2/ApplePS2Device.h b/iokit/IOKit/ps2/ApplePS2Device.h deleted file mode 100644 index 88540b3eb..000000000 --- a/iokit/IOKit/ps2/ApplePS2Device.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2DEVICE_H -#define _APPLEPS2DEVICE_H - -#include <IOKit/IOService.h> - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Definitions -// -// Data Port (0x60) Commands. These commands are all transmitted directly to -// the physical keyboard and/or mouse, so expect an acknowledge for each byte -// that you send through this port. -// - -#define kDP_SetMouseScaling1To1 0xE6 // (mouse) -#define kDP_SetMouseScaling2To1 0xE7 // (mouse) -#define kDP_SetMouseResolution 0xE8 // (mouse) -#define kDP_GetMouseInformation 0xE9 // (mouse) -#define kDP_SetMouseStreamMode 0xEA // (mouse) -#define kDP_SetKeyboardLEDs 0xED // (keyboard) -#define kDP_TestKeyboardEcho 0xEE // (keyboard) -#define kDP_GetSetKeyboardASCs 0xF0 // (keyboard) -#define kDP_GetId 0xF2 // (keyboard+mouse) -#define kDP_SetKeyboardTypematic 0xF3 // (keyboard) -#define kDP_SetMouseSampleRate 0xF3 // (mouse) -#define kDP_Enable 0xF4 // (keyboard+mouse) -#define kDP_SetDefaultsAndDisable 0xF5 // (keyboard+mouse) -#define kDP_SetDefaults 0xF6 // (keyboard+mouse) -#define kDP_SetAllTypematic 0xF7 // (keyboard) -#define kDP_SetAllMakeRelease 0xF8 // (keyboard) -#define kDP_SetAllMakeOnly 0xF9 // (keyboard) -#define kDP_SetAllTypematicMakeRelease 0xFA // (keyboard) -#define kDP_SetKeyMakeRelease 0xFB // (keyboard) -#define kDP_SetKeyMakeOnly 0xFC // (keyboard) -#define kDP_Reset 0xFF // (keyboard+mouse) - -// -// Command Port (0x64) Commands. These commands all access registers local -// to the motherboard, ie. nothing is transmitted, thus these commands and -// any associated data passed thru the Data Port do not return acknowledges. -// - -#define kCP_GetCommandByte 0x20 // (keyboard+mouse) -#define kCP_ReadControllerRAMBase 0x21 // -#define kCP_SetCommandByte 0x60 // (keyboard+mouse) -#define kCP_WriteControllerRAMBase 0x61 // -#define kCP_TestPassword 0xA4 // -#define kCP_GetPassword 0xA5 // -#define kCP_VerifyPassword 0xA6 // -#define kCP_DisableMouseClock 0xA7 // (mouse) -#define kCP_EnableMouseClock 0xA8 // (mouse) -#define kCP_TestMousePort 0xA9 // -#define kCP_TestController 0xAA // -#define kCP_TestKeyboardPort 0xAB // -#define kCP_GetControllerDiagnostic 0xAC // -#define kCP_DisableKeyboardClock 0xAD // (keyboard) -#define kCP_EnableKeyboardClock 0xAE // (keyboard) -#define kCP_ReadInputPort 0xC0 // -#define kCP_PollInputPortLow 0xC1 // -#define kCP_PollInputPortHigh 0xC2 // -#define kCP_ReadOutputPort 0xD0 // -#define kCP_WriteOutputPort 0xD1 // -#define kCP_WriteKeyboardOutputBuffer 0xD2 // (keyboard) -#define kCP_WriteMouseOutputBuffer 0xD3 // (mouse) -#define kCP_TransmitToMouse 0xD4 // (mouse) -#define kCP_ReadTestInputs 0xE0 // -#define kCP_PulseOutputBitBase 0xF0 // - -// -// Bit definitions for the 8-bit "Command Byte" register, which is accessed -// through the Command Port (0x64). -// - -#define kCB_EnableKeyboardIRQ 0x01 // Enable Keyboard IRQ -#define kCB_EnableMouseIRQ 0x02 // Enable Mouse IRQ -#define kCB_SystemFlag 0x04 // Set System Flag -#define kCB_InhibitOverride 0x08 // Inhibit Override -#define kCB_DisableKeyboardClock 0x10 // Disable Keyboard Clock -#define kCB_DisableMouseClock 0x20 // Disable Mouse Clock -#define kCB_TranslateMode 0x40 // Keyboard Translate Mode - -// -// Bit definitions for the 8-bit "LED" register, which is accessed through -// the Data Port (0x64). Undefined bit positions must be zero. -// - -#define kLED_ScrollLock 0x01 // Scroll Lock -#define kLED_NumLock 0x02 // Num Lock -#define kLED_CapsLock 0x04 // Caps Lock - -// -// Scan Codes used for special purposes on the keyboard and/or mouse receive -// port. These values would be received from your interrupt handler or from -// a ReadDataPort command primitive. These values do not represent actual -// keys, but indicate some sort of status. -// - -#define kSC_Acknowledge 0xFA // ack for transmitted commands -#define kSC_Extend 0xE0 // marker for "extended" sequence -#define kSC_Pause 0xE1 // marker for pause key sequence -#define kSC_Resend 0xFE // request to resend keybd cmd -#define kSC_Reset 0xAA // the keyboard/mouse has reset -#define kSC_UpBit 0x80 // OR'd in if key below is released - -// -// Scan Codes for some modifier keys. -// - -#define kSC_Alt 0x38 // (extended = right key) -#define kSC_Ctrl 0x1D // (extended = right key) -#define kSC_ShiftLeft 0x2A -#define kSC_ShiftRight 0x36 -#define kSC_WindowsLeft 0x5B // extended -#define kSC_WindowsRight 0x5C // extended - -// -// Scan Codes for some keys. -// - -#define kSC_Delete 0x53 // (extended = gray key) -#define kSC_NumLock 0x45 - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// PS/2 Command Primitives -// -// o kPS2C_ReadDataPort: -// o Description: Reads the next available byte off the data port (60h). -// o Out Field: Holds byte that was read. -// -// o kPS2C_ReadDataAndCompare: -// o Description: Reads the next available byte off the data port (60h), -// and compares it with the byte in the In Field. If the -// comparison fails, the request is aborted (refer to the -// commandsCount field in the request structure). -// o In Field: Holds byte that comparison should be made to. -// -// o kPS2C_WriteDataPort: -// o Description: Writes the byte in the In Field to the data port (60h). -// o In Field: Holds byte that should be written. -// -// o kPS2C_WriteCommandPort: -// o Description: Writes the byte in the In Field to the command port (64h). -// o In Field: Holds byte that should be written. -// - -enum PS2CommandEnum -{ - kPS2C_ReadDataPort, - kPS2C_ReadDataPortAndCompare, - kPS2C_WriteDataPort, - kPS2C_WriteCommandPort -}; -typedef enum PS2CommandEnum PS2CommandEnum; - -struct PS2Command -{ - PS2CommandEnum command; - UInt8 inOrOut; -}; -typedef struct PS2Command PS2Command; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// PS/2 Request Structure -// -// o General Notes: -// o allocateRequest allocates the request structure -- use it always. -// o freeRequest deallocates the request structure -- use it always. -// o It is the driver's responsibility to free the request structure: -// o after a submitRequestAndBlock call returns, or -// o in the completion routine for each submitRequest issued. -// o It is not the driver's resposiblity to free the request structure: -// o when no completion routine is specified in a request issued via -// submitRequest, in which case the request is freed automatically -// by the controller. This case is called "fire-and-forget". -// o On completion, the requester can see how far the processing got by -// looking at the commandsCount field. If it is equal to the original -// number of commands, then the request was successful. If isn't, the -// value represents the zero-based index of the command that failed. -// -// o General Notes For Inquisitive Minds: -// o Requests are executed atomically with respect to all other requests, -// that is, if a keyboard request is currently being processed, then a -// request submitted by the mouse driver or one submitted by a separate -// thread of control in the keyboard driver will get queued until the -// controller is available again. -// o Request processing can be preempted to service interrupts on other -// PS/2 devices, should other-device data arrive unexpectedly on the -// input stream while processing a request. -// o The request processor knows when to read the mouse input stream -// over the keyboard input stream for a given command sequence. It -// does not depend on which driver it came from, rest assurred. If -// the mouse driver so chose, it could send keyboard commands. -// -// o commands: -// o Description: Holds list of commands that controller should execute. -// o Comments: Refer to PS2Command structure. -// -// o commandsCount: -// o Description: Holds the number of commands in the command list. -// o Comments: Number of commands should never exceed kMaxCommands. -// -// o completionRoutineTarget, Action, and Param: -// o Description: Object and method of the completion routine, which is -// called when the request has finished. The Param field -// may be filled with anything you want; it is passed to -// completion routine when it is called. These fields -// are optional. If left null, the request structure -// will be deallocated automatically by the controller -// on completion of the request. -// o Prototype: void completionRoutine(void * target, void * param); -// o Comments: Never issue submitRequestAndBlock or otherwise BLOCK on -// any request sent down to your device from the completion -// routine. Obey, or deadlock. -// - -#define kMaxCommands 20 - -typedef void (*PS2CompletionAction)(void * target, void * param); - -struct PS2Request -{ - UInt8 commandsCount; - PS2Command commands[kMaxCommands]; - void * completionTarget; - PS2CompletionAction completionAction; - void * completionParam; -}; -typedef struct PS2Request PS2Request; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// ApplePS2KeyboardDevice and ApplePS2MouseDevice Class Descriptions -// -// -// o General Notes: -// o When the probe method is invoked on the client driver, the controller -// guarantees that the keyboard clock is enabled and the keyboard itself -// is disabled. This implies the client driver can send commands to the -// keyboard without a problem, and the keyboard itself will not send any -// asynchronous key data that may mess up the responses expected by the -// commands sent to it. -// -// o installInterruptAction: -// o Description: Ask the device to deliver asynchronous data to driver. -// o In Fields: Target/action of completion routine. -// -// o installInterruptAction Interrupt Routine: -// o Description: Delivers a newly read byte from the input data stream. -// o Prototype: void interruptOccurred(void * target, UInt8 byte); -// o In Fields: Byte that was read. -// o Comments: Never issue submitRequestAndBlock or otherwise BLOCK on -// any request sent down to your device from the interrupt -// routine. Obey, or deadlock. -// -// o uninstallInterruptHandler: -// o Description: Ask the device to stop delivering asynchronous data. -// -// o allocateRequest: -// o Description: Allocate a request structure, blocks until successful. -// o Result: Request structure pointer. -// o Comments: Request structure is guaranteed to be zeroed. -// -// o freeRequest: -// o Description: Deallocate a request structure. -// o In Fields: Request structure pointer. -// -// o submitRequest: -// o Description: Submit the request to the controller for processing. -// o In Fields: Request structure pointer. -// o Result: kern_return_t queueing status. -// -// o submitRequestAndBlock: -// o Description: Submit the request to the controller for processing, then -// block the calling thread until the request completes. -// o In Fields: Request structure pointer. -// - -typedef void (*PS2InterruptAction)(void * target, UInt8 data); - -#endif /* !_APPLEPS2DEVICE_H */ diff --git a/iokit/IOKit/ps2/ApplePS2KeyboardDevice.h b/iokit/IOKit/ps2/ApplePS2KeyboardDevice.h deleted file mode 100644 index 5ef738b03..000000000 --- a/iokit/IOKit/ps2/ApplePS2KeyboardDevice.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2KEYBOARDDEVICE_H -#define _APPLEPS2KEYBOARDDEVICE_H - -#include <IOKit/ps2/ApplePS2Device.h> - -class ApplePS2Controller; - -class ApplePS2KeyboardDevice : public IOService -{ - OSDeclareDefaultStructors(ApplePS2KeyboardDevice); - -private: - ApplePS2Controller * _controller; - -public: - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - // Interrupt Handling Routines - - virtual void installInterruptAction(OSObject *, PS2InterruptAction); - virtual void uninstallInterruptAction(); - - // Request Submission Routines - - virtual PS2Request * allocateRequest(); - virtual void freeRequest(PS2Request * request); - virtual bool submitRequest(PS2Request * request); - virtual void submitRequestAndBlock(PS2Request * request); -}; - -#endif /* !_APPLEPS2KEYBOARDDEVICE_H */ diff --git a/iokit/IOKit/ps2/ApplePS2MouseDevice.h b/iokit/IOKit/ps2/ApplePS2MouseDevice.h deleted file mode 100644 index f46cf9c86..000000000 --- a/iokit/IOKit/ps2/ApplePS2MouseDevice.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _APPLEPS2MOUSEDEVICE_H -#define _APPLEPS2MOUSEDEVICE_H - -#include <IOKit/ps2/ApplePS2Device.h> - -class ApplePS2Controller; - -class ApplePS2MouseDevice : public IOService -{ - OSDeclareDefaultStructors(ApplePS2MouseDevice); - -private: - ApplePS2Controller * _controller; - -public: - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - // Interrupt Handling Routines - - virtual void installInterruptAction(OSObject *, PS2InterruptAction); - virtual void uninstallInterruptAction(); - - // Request Submission Routines - - virtual PS2Request * allocateRequest(); - virtual void freeRequest(PS2Request * request); - virtual bool submitRequest(PS2Request * request); - virtual void submitRequestAndBlock(PS2Request * request); -}; - -#endif /* !_APPLEPS2MOUSEDEVICE_H */ diff --git a/iokit/IOKit/ps2/Makefile b/iokit/IOKit/ps2/Makefile deleted file mode 100644 index 57243bc95..000000000 --- a/iokit/IOKit/ps2/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MD_DIR = ps2 -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MD_LIST = -INSTALL_MD_LCL_LIST = "" -INSTALL_MD_DIR = $(MD_DIR) - -EXPORT_MD_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MD_DIR = IOKit/$(MD_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/pwr_mgt/IOPM.h b/iokit/IOKit/pwr_mgt/IOPM.h index 6809d125b..891643d7c 100644 --- a/iokit/IOKit/pwr_mgt/IOPM.h +++ b/iokit/IOKit/pwr_mgt/IOPM.h @@ -25,35 +25,79 @@ #define IOPMMaxPowerStates 10 typedef unsigned long IOPMPowerFlags; +enum { + // following bits are used in the input and output power fields + kIOPMClockNormal = 0x0004, + kIOPMClockRunning = 0x0008, + kIOPMAuxPowerOn = 0x0020, // used only between root and root parent + kIOPMPagingAvailable = 0x0020, // used only between paging plexus and its children + kIOPMPassThrough = 0x0100, + kIOPMDoze = 0x0400, + kIOPMSoftSleep = 0x0400, // old usage, replaced by kIOPMDoze + kIOPMSleep = 0x0001, + kIOPMRestart = 0x0080, + // following bits are used in the capabilites field and the power fields + kIOPMPowerOn = 0x0002, + kIOPMPreventSystemSleep = 0x0010, + kIOPMPreventIdleSleep = 0x0040, + // following bits are used in the capabilites field + kIOPMNotAttainable = 0x0001, // used between a driver and its policy-maker + kIOPMChildClamp = 0x0080, // used internally in a power domain parent + kIOPMChildClamp2 = 0x0200, // used internally in a power domain parent + kIOPMDeviceUsable = 0x8000, + kIOPMMaxPerformance = 0x4000, + kIOPMContextRetained = 0x2000, + kIOPMConfigRetained = 0x1000, + kIOPMSleepCapability = 0x0004, + kIOPMRestartCapability = 0x0080, + kIOPMNotPowerManaged = 0x0800, // this is an error return rather than a bit + kIOPMStaticPowerValid = 0x0800, // therefore this bit safely overloads it + + kIOPMCapabilitiesMask = kIOPMPowerOn | kIOPMDeviceUsable | kIOPMMaxPerformance | + kIOPMContextRetained | kIOPMConfigRetained | kIOPMSleepCapability | + kIOPMRestartCapability +}; + + +enum { + IOPMNotAttainable = kIOPMNotAttainable, + IOPMPowerOn = kIOPMPowerOn, + IOPMClockNormal = kIOPMClockNormal, + IOPMClockRunning = kIOPMClockRunning, + IOPMAuxPowerOn = kIOPMAuxPowerOn, + IOPMDeviceUsable = kIOPMDeviceUsable, + IOPMMaxPerformance = kIOPMMaxPerformance, + IOPMContextRetained = kIOPMContextRetained, + IOPMConfigRetained = kIOPMConfigRetained, + IOPMNotPowerManaged = kIOPMNotPowerManaged, + IOPMPagingAvailable = kIOPMPagingAvailable, + IOPMSoftSleep = kIOPMSoftSleep +}; + + +enum { + kIOPMNextHigherState = 1, + kIOPMHighestState = 2, + kIOPMNextLowerState = 3, + kIOPMLowestState = 4 +}; + +enum { + IOPMNextHigherState = kIOPMNextHigherState, + IOPMHighestState = kIOPMHighestState, + IOPMNextLowerState = kIOPMNextLowerState, + IOPMLowestState = kIOPMLowestState +}; -#define IOPMNotAttainable 0x0001 -#define IOPMPowerOn 0x0002 -#define IOPMClockNormal 0x0004 -#define IOPMClockRunning 0x0008 -#define IOPMWakeupEnabled 0x0010 -#define IOPMAuxPowerOn 0x0020 - // following "capabilites" exist for the convenience - // of the "interested drivers" -#define IOPMDeviceUsable 0x8000 -#define IOPMMaxPerformance 0x4000 -#define IOPMContextRetained 0x2000 -#define IOPMConfigRetained 0x1000 -#define IOPMNotPowerManaged 0x0800 -#define IOPMSoftSleep 0x0400 - -#define IOPMNextHigherState 1 -#define IOPMHighestState 2 -#define IOPMNextLowerState 3 -#define IOPMLowestState 4 enum { // commands on power managment command queue - kPMbroadcastAggressiveness = 1, - kPMunIdleDevice, - kPMsleepDemand, - kPMwakeSignal, - kPMallowSleep, - kPMcancelSleep + kIOPMBroadcastAggressiveness = 1, + kIOPMUnidleDevice +}; + +enum { // special value means "power consumption unknown" + kIOPMUnknown = 0xFFFF }; // Power events @@ -73,7 +117,8 @@ enum { kIOPMPowerButton = (1<<3), // power button was pressed kIOPMClamshellClosed = (1<<4), // clamshell was closed kIOPMPowerEmergency = (1<<5), // battery dangerously low - kIOPMIgnoreClamshell = (1<<6) // take no action on clamshell closure + kIOPMDisableClamshell = (1<<6), // do not sleep on clamshell closure + kIOPMEnableClamshell = (1<<7) // sleep on clamshell closure }; // Return codes @@ -219,9 +264,10 @@ enum { kPMGeneralAggressiveness = 0, kPMMinutesToDim, kPMMinutesToSpinDown, - kPMMinutesToSleep + kPMMinutesToSleep, + kPMEthernetWakeOnLANSettings, }; -#define kMaxType kPMMinutesToSleep +#define kMaxType kPMEthernetWakeOnLANSettings #define kIOBatteryInfoKey "IOBatteryInfo" @@ -256,11 +302,14 @@ struct stateChangeNote{ }; typedef struct stateChangeNote stateChangeNote; -struct sleepWakeNote{ +struct IOPowerStateChangeNotification { void * powerRef; unsigned long returnValue; + unsigned long stateNumber; + IOPMPowerFlags stateFlags; }; -typedef struct sleepWakeNote sleepWakeNote; +typedef struct IOPowerStateChangeNotification IOPowerStateChangeNotification; +typedef IOPowerStateChangeNotification sleepWakeNote; extern void IOPMRegisterDevice(const char *, IOService *); #endif /* KERNEL && __cplusplus */ diff --git a/iokit/IOKit/pwr_mgt/IOPMLibDefs.h b/iokit/IOKit/pwr_mgt/IOPMLibDefs.h index 752c829a4..a1546528c 100644 --- a/iokit/IOKit/pwr_mgt/IOPMLibDefs.h +++ b/iokit/IOKit/pwr_mgt/IOPMLibDefs.h @@ -26,5 +26,7 @@ #define kPMSleepSystem 2 #define kPMAllowPowerChange 3 #define kPMCancelPowerChange 4 +#define kPMShutdownSystem 5 +#define kPMRestartSystem 6 -#define kNumPMMethods 5 +#define kNumPMMethods 7 diff --git a/iokit/IOKit/graphics/IOGraphicsDevice.h b/iokit/IOKit/pwr_mgt/IOPMPagingPlexus.h similarity index 61% rename from iokit/IOKit/graphics/IOGraphicsDevice.h rename to iokit/IOKit/pwr_mgt/IOPMPagingPlexus.h index a16e0c114..0840c4c3a 100644 --- a/iokit/IOKit/graphics/IOGraphicsDevice.h +++ b/iokit/IOKit/pwr_mgt/IOPMPagingPlexus.h @@ -27,27 +27,40 @@ */ -#ifndef _IOKIT_IOGRAPHICSDEVICE_H -#define _IOKIT_IOGRAPHICSDEVICE_H +#ifndef _IOKIT_IOPMPAGINGPLEXUS_H +#define _IOKIT_IOPMPAGINGPLEXUS_H #include <IOKit/IOService.h> -#include <IOKit/graphics/IOGraphicsTypes.h> -class IOGraphicsDevice : public IOService + +/*! @class IOPMPagingPlexus : public IOService + @abstract + @discussion +*/ + +class IOPMPagingPlexus : public IOService { - OSDeclareAbstractStructors(IOGraphicsDevice) + OSDeclareDefaultStructors(IOPMPagingPlexus) + + +protected: + bool systemBooting; // true until preferences received. Then we act. + IOLock * ourLock; + public: - virtual void hideCursor( void ) = 0; - virtual void showCursor( Point * cursorLoc, int frame ) = 0; - virtual void moveCursor( Point * cursorLoc, int frame ) = 0; + virtual bool start ( IOService * ); + virtual IOReturn setAggressiveness ( unsigned long, unsigned long ); + +protected: - virtual void getVBLTime( AbsoluteTime * time, AbsoluteTime * delta ) = 0; + virtual IOService * findProvider ( IOService * ); + virtual void processSiblings ( IOService * ); + virtual void processChildren ( void ); - virtual void getBoundingRect ( Bounds ** bounds ) = 0; }; -#endif /* ! _IOKIT_IOGRAPHICSDEVICE_H */ +#endif /* ! _IOKIT_IOPMPAGINGPLEXUS_H */ diff --git a/iokit/IOKit/pwr_mgt/IOPMchangeNoteList.h b/iokit/IOKit/pwr_mgt/IOPMchangeNoteList.h index aaf484e9c..ce8b9090e 100644 --- a/iokit/IOKit/pwr_mgt/IOPMchangeNoteList.h +++ b/iokit/IOKit/pwr_mgt/IOPMchangeNoteList.h @@ -60,7 +60,8 @@ unsigned long newStateNumber; IOPMPowerFlags outputPowerCharacter; IOPMPowerFlags inputPowerRequirement; IOPMPowerFlags domainState; -IOPowerConnection * parent; +IOPowerConnection * parent; +IOPMPowerFlags singleParentState; IOPMPowerFlags capabilityFlags; }; diff --git a/iokit/IOKit/pwr_mgt/IOPMpowerState.h b/iokit/IOKit/pwr_mgt/IOPMpowerState.h index 095b653fd..ff0c89e97 100644 --- a/iokit/IOKit/pwr_mgt/IOPMpowerState.h +++ b/iokit/IOKit/pwr_mgt/IOPMpowerState.h @@ -39,3 +39,6 @@ unsigned long powerDomainBudget; // power in mw a domain in this state can deliv typedef struct IOPMPowerState IOPMPowerState; +enum { + kIOPMPowerStateVersion1 = 1 +}; diff --git a/iokit/IOKit/pwr_mgt/IOPowerConnection.h b/iokit/IOKit/pwr_mgt/IOPowerConnection.h index 03adf0aa4..c24469971 100644 --- a/iokit/IOKit/pwr_mgt/IOPowerConnection.h +++ b/iokit/IOKit/pwr_mgt/IOPowerConnection.h @@ -48,6 +48,21 @@ protected: used by parent */ unsigned long desiredDomainState; + /*! @field requestFlag set to true when desiredDomainState is set */ + bool requestFlag; + + /*! @field preventIdleSleepFlag true if child has this bit set in its desired state + used by parent */ + unsigned long preventIdleSleepFlag; + + /*! @field preventSystemSleepFlag true if child has this bit set in its desired state + used by parent */ + unsigned long preventSystemSleepFlag; + + /*! @field awaitingAck true if child has not yet acked our notification + used by parent */ + bool awaitingAck; + public: /*! @function setParentKnowsState @abstract Sets the stateKnown variable. @@ -69,13 +84,55 @@ public: /*! @function setDesiredDomainState @abstract Sets the desiredDomainState variable. - @discussion Called by the child. */ + @discussion Called by the parent. */ void setDesiredDomainState (unsigned long ); /*! @function getDesiredDomainState @abstract Returns the desiredDomainState variable. - @discussion Called by the child. */ + @discussion Called by the parent. */ unsigned long getDesiredDomainState ( void ); + + /*! @function setChildHasRequestedPower + @abstract Set the flag that says that the child has called requestPowerDomainState. + @discussion Called by the parent. */ + void setChildHasRequestedPower ( void ); + + + /*! @function childHasRequestedPower + @abstract Return the flag that says whether the child has called requestPowerDomainState. + @discussion Called by the PCI Aux Power Supply Driver to see if a device driver + is power managed. */ + bool childHasRequestedPower ( void ); + + /*! @function setPreventIdleSleepFlag + @abstract Sets the preventIdleSleepFlag variable. + @discussion Called by the parent. */ + void setPreventIdleSleepFlag (unsigned long ); + + /*! @function getPreventIdleSleepFlag + @abstract Returns the preventIdleSleepFlag variable. + @discussion Called by the parent. */ + bool getPreventIdleSleepFlag ( void ); + + /*! @function setPreventSystemSleepFlag + @abstract Sets the preventSystemSleepFlag variable. + @discussion Called by the parent. */ + void setPreventSystemSleepFlag (unsigned long ); + + /*! @function getPreventSystemSleepFlag + @abstract Returns the preventSystemSleepFlag variable. + @discussion Called by the parent. */ + bool getPreventSystemSleepFlag ( void ); + + /*! @function setAwaitingAck + @abstract Sets the awaitingAck variable. + @discussion Called by the parent. */ + void setAwaitingAck ( bool ); + + /*! @function getAwaitingAck + @abstract Returns the awaitingAck variable. + @discussion Called by the parent. */ + bool getAwaitingAck ( void ); }; #endif /* ! _IOKIT_IOPOWERCONNECTION_H */ diff --git a/iokit/IOKit/pwr_mgt/RootDomain.h b/iokit/IOKit/pwr_mgt/RootDomain.h index 91a798947..28d95a059 100644 --- a/iokit/IOKit/pwr_mgt/RootDomain.h +++ b/iokit/IOKit/pwr_mgt/RootDomain.h @@ -30,13 +30,18 @@ class RootDomainUserClient; enum { kRootDomainSleepNotSupported = 0x00000000, kRootDomainSleepSupported = 0x00000001, - kFrameBufferDeepSleepSupported = 0x00000002 + kFrameBufferDeepSleepSupported = 0x00000002, + kPCICantSleep = 0x00000004 }; extern "C" { IONotifier * registerSleepWakeInterest(IOServiceInterestHandler, void *, void * = 0); + IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref = 0); IOReturn acknowledgeSleepWakeNotification(void * ); + IOReturn vetoSleepWakeNotification(void * PMrefcon); + IOReturn rootDomainRestart ( void ); + IOReturn rootDomainShutdown ( void ); } @@ -46,20 +51,30 @@ OSDeclareDefaultStructors(IOPMrootDomain) public: - virtual bool start( IOService * provider ); + class IOService * wrangler; // we tickle the wrangler on button presses, etc + + static IOPMrootDomain * construct( void ); + virtual bool start( IOService * provider ); virtual IOReturn newUserClient ( task_t, void *, UInt32, IOUserClient ** ); virtual IOReturn setAggressiveness ( unsigned long, unsigned long ); virtual IOReturn youAreRoot ( void ); virtual IOReturn sleepSystem ( void ); + IOReturn shutdownSystem ( void ); + IOReturn restartSystem ( void ); virtual IOReturn receivePowerNotification (UInt32 msg); virtual void setSleepSupported( IOOptionBits flags ); virtual IOOptionBits getSleepSupported(); - virtual bool activityTickle ( unsigned long, unsigned long x=0 ); + virtual IOReturn requestPowerDomainState ( IOPMPowerFlags, IOPowerConnection *, unsigned long ); + virtual void handleSleepTimerExpiration ( void ); + void wakeFromDoze( void ); private: - class IORootParent * patriarch; // points to our parent - unsigned long idlePeriod; // idle timer period + class IORootParent * patriarch; // points to our parent + long sleepSlider; // pref: idle time before idle sleep + long longestNonSleepSlider; // pref: longest of other idle times + long extraSleepDelay; // sleepSlider - longestNonSleepSlider + thread_call_t extraSleepTimer; // used to wait between say display idle and system idle virtual void powerChangeDone ( unsigned long ); virtual void command_received ( void *, void * , void * , void *); @@ -67,23 +82,52 @@ private: virtual bool askChangeDown ( unsigned long stateNum); virtual void tellChangeUp ( unsigned long ); virtual void tellNoChangeDown ( unsigned long ); + void reportUserInput ( void ); + static IOReturn sysPowerDownHandler( void * target, void * refCon, + UInt32 messageType, IOService * service, + void * messageArgument, vm_size_t argSize ); + + static IOReturn displayWranglerNotification( void * target, void * refCon, + UInt32 messageType, IOService * service, + void * messageArgument, vm_size_t argSize ); + + static bool displayWranglerPublished( void * target, void * refCon, + IOService * newService); + + void setQuickSpinDownTimeout ( void ); + void adjustPowerState( void ); + void restoreUserSpinDownTimeout ( void ); - bool systemBooting; - bool ignoringClamshell; - bool allowSleep; - bool sleepIsSupported; + unsigned int user_spindown; // User's selected disk spindown value + + unsigned int systemBooting:1; + unsigned int ignoringClamshell:1; + unsigned int allowSleep:1; + unsigned int sleepIsSupported:1; + unsigned int canSleep:1; + unsigned int idleSleepPending:1; + unsigned int sleepASAP:1; + unsigned int reservedA:1; + unsigned int reservedB[2]; + thread_call_t diskSyncCalloutEntry; IOOptionBits platformSleepSupport; }; class IORootParent: public IOService { OSDeclareDefaultStructors(IORootParent) + +private: + unsigned long mostRecentChange; public: bool start ( IOService * nub ); void shutDownSystem ( void ); + void restartSystem ( void ); void sleepSystem ( void ); + void dozeSystem ( void ); + void sleepToDoze ( void ); void wakeSystem ( void ); }; diff --git a/iokit/IOKit/storage/IOApplePartitionScheme.h b/iokit/IOKit/storage/IOApplePartitionScheme.h deleted file mode 100644 index 46140bddf..000000000 --- a/iokit/IOKit/storage/IOApplePartitionScheme.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOAPPLEPARTITIONSCHEME_H -#define _IOAPPLEPARTITIONSCHEME_H - -#include <IOKit/IOTypes.h> - -/* - * Apple Partition Map Definitions - */ - -#pragma pack(2) /* (enable 16-bit struct packing for dpme, DDMap, Block0) */ - -/* Structure constants. */ - -#define DPISTRLEN 32 - -/* Partition map entry, as found in blocks 1 to dpme_map_entries of the disk. */ - -typedef struct dpme -{ - UInt16 dpme_signature; /* (unique value for partition entry, 'PM') */ - UInt16 dpme_reserved_1; /* (reserved for future use) */ - UInt32 dpme_map_entries; /* (number of partition entries) */ - UInt32 dpme_pblock_start; /* (physical block start of partition) */ - UInt32 dpme_pblocks; /* (physical block count of partition) */ - char dpme_name[DPISTRLEN]; /* (name of partition) */ - char dpme_type[DPISTRLEN]; /* (type of partition, eg. Apple_HFS) */ - UInt32 dpme_lblock_start; /* (logical block start of partition) */ - UInt32 dpme_lblocks; /* (logical block count of partition) */ - UInt32 dpme_flags; /* (partition flags, see defines below) */ - UInt32 dpme_boot_block; /* (logical block start of boot code) */ - UInt32 dpme_boot_bytes; /* (byte count of boot code) */ - UInt8 * dpme_load_addr; /* (load address in memory of boot code) */ - UInt8 * dpme_load_addr_2; /* (reserved for future use) */ - UInt8 * dpme_goto_addr; /* (jump address in memory of boot code) */ - UInt8 * dpme_goto_addr_2; /* (reserved for future use) */ - UInt32 dpme_checksum; /* (checksum of boot code) */ - UInt8 dpme_process_id[16]; /* (processor type) */ - UInt32 dpme_reserved_2[32]; /* (reserved for future use) */ - UInt32 dpme_reserved_3[62]; /* (reserved for future use) */ -} DPME; - -/* Driver descriptor map entry. */ - -typedef struct DDMap -{ - UInt32 ddBlock; /* (driver's block start, sbBlkSize-blocks) */ - UInt16 ddSize; /* (driver's block count, 512-blocks) */ - UInt16 ddType; /* (driver's system type) */ -} DDMap; - -/* Driver descriptor map, as found in block zero of the disk. */ - -typedef struct Block0 -{ - UInt16 sbSig; /* (unique value for block zero, 'ER') */ - UInt16 sbBlkSize; /* (block size for this device) */ - UInt32 sbBlkCount; /* (block count for this device) */ - UInt16 sbDevType; /* (device type) */ - UInt16 sbDevId; /* (device id) */ - UInt32 sbDrvrData; /* (driver data) */ - UInt16 sbDrvrCount; /* (driver descriptor count) */ - DDMap sbDrvrMap[8]; /* (driver descriptor table) */ - UInt8 sbReserved[430]; /* (reserved for future use) */ -} Block0; - -/* Partition map signature (sbSig). */ - -#define BLOCK0_SIGNATURE 0x4552 - -/* Partition map entry signature (dpme_signature). */ - -#define DPME_SIGNATURE 0x504D - -/* Partition map entry flags (dpme_flags). */ - -#define DPME_FLAGS_VALID 0x00000001 /* (bit 0) */ -#define DPME_FLAGS_ALLOCATED 0x00000002 /* (bit 1) */ -#define DPME_FLAGS_IN_USE 0x00000004 /* (bit 2) */ -#define DPME_FLAGS_BOOTABLE 0x00000008 /* (bit 3) */ -#define DPME_FLAGS_READABLE 0x00000010 /* (bit 4) */ -#define DPME_FLAGS_WRITABLE 0x00000020 /* (bit 5) */ -#define DPME_FLAGS_OS_PIC_CODE 0x00000040 /* (bit 6) */ -#define DPME_FLAGS_OS_SPECIFIC_2 0x00000080 /* (bit 7) */ -#define DPME_FLAGS_OS_SPECIFIC_1 0x00000100 /* (bit 8) */ -#define DPME_FLAGS_RESERVED_2 0xFFFFFE00 /* (bit 9..31) */ - -#pragma options align=reset /* (reset to default struct packing) */ - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOPartitionScheme.h> - -/* - * Class - */ - -class IOApplePartitionScheme : public IOPartitionScheme -{ - OSDeclareDefaultStructors(IOApplePartitionScheme); - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - OSSet * _partitions; /* (set of media objects representing partitions) */ - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(void); - - /* - * Scan the provider media for an Apple partition map. Returns the set - * of media objects representing each of the partitions (the retain for - * the set is passed to the caller), or null should no partition map be - * found. The default probe score can be adjusted up or down, based on - * the confidence of the scan. - */ - - virtual OSSet * scan(SInt32 * score); - - /* - * Ask whether the given partition appears to be corrupt. A partition that - * is corrupt will cause the failure of the Apple partition map recognition - * altogether. - */ - - virtual bool isPartitionCorrupt( dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ); - - /* - * Ask whether the given partition appears to be invalid. A partition that - * is invalid will cause it to be skipped in the scan, but will not cause a - * failure of the Apple partition map recognition. - */ - - virtual bool isPartitionInvalid( dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ); - - /* - * Instantiate a new media object to represent the given partition. - */ - - virtual IOMedia * instantiateMediaObject( dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ); - - /* - * Allocate a new media object (called from instantiateMediaObject). - */ - - virtual IOMedia * instantiateDesiredMediaObject( - dpme * partition, - UInt32 partitionID, - UInt32 partitionBlockSize ); - - /* - * Attach the given media object to the device tree plane. - */ - - virtual bool attachMediaObjectToDeviceTree(IOMedia * media); - - /* - * Detach the given media object from the device tree plane. - */ - - virtual void detachMediaObjectFromDeviceTree(IOMedia * media); - -public: - - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * Determine whether the provider media contains an Apple partition map. - */ - - virtual IOService * probe(IOService * provider, SInt32 * score); - - /* - * Publish the new media objects which represent our partitions. - */ - - virtual bool start(IOService * provider); - - /* - * Clean up after the media objects we published before terminating. - */ - - virtual void stop(IOService * provider); - - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 0); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 1); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 2); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 3); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 4); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 5); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 6); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 7); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 8); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 9); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 10); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 11); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 12); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 13); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 14); - OSMetaClassDeclareReservedUnused(IOApplePartitionScheme, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOAPPLEPARTITIONSCHEME_H */ diff --git a/iokit/IOKit/storage/IOBlockStorageDevice.h b/iokit/IOKit/storage/IOBlockStorageDevice.h deleted file mode 100644 index 0d7fc0c86..000000000 --- a/iokit/IOKit/storage/IOBlockStorageDevice.h +++ /dev/null @@ -1,411 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOBlockStorageDevice.h - * - * This class is the protocol for generic block storage functionality, independent - * of the physical connection protocol (e.g. SCSI, ATA, USB). - * - * A subclass implements relay methods that translate our requests into - * calls to a protocol- and device-specific provider. - */ - -/*! @language embedded-c++ */ - -#ifndef _IOBLOCKSTORAGEDEVICE_H -#define _IOBLOCKSTORAGEDEVICE_H - -#include <IOKit/IOMessage.h> -#include <IOKit/IOTypes.h> -#include <IOKit/IOService.h> -#include <IOKit/storage/IOMedia.h> - -/*! - * @defined kIOMessageMediaStateHasChanged - * The message ID which indicates that the media state has changed. The message - * is passed to all clients of the IOBlockStorageDevice via the message() method. - * The argument that is passed along with this message is an IOMediaState value. - * - * Devices that aren't capable of detecting media state changes indicate this in - * the reportPollRequirements() method. - */ -#define kIOMessageMediaStateHasChanged iokit_family_msg(sub_iokit_block_storage, 1) - -/* Property used for matching, so the generic driver gets the nub it wants. */ -/*! - * @defined kIOBlockStorageDeviceTypeKey - * The name of the property tested for nub type matching by the generic block - * storage driver. - */ -#define kIOBlockStorageDeviceTypeKey "device-type" -/*! - * @defined kIOBlockStorageDeviceTypeGeneric - * A character string used for nub matching. - */ -#define kIOBlockStorageDeviceTypeGeneric "Generic" - -class IOMemoryDescriptor; - -/*! - * @class - * IOBlockStorageDevice : public IOService - * @abstract - * "Impedance-matcher" class to connect Generic device driver to Transport Driver. - * @discussion - * The IOBlockStorageDevice class exports the generic block storage protocol, - * forwarding all requests to its provider (the Transport Driver). - * Though the nub does no actual processing of requests, it is necessary - * in a C++ environment. The Transport Driver can be of any type, as - * long as it inherits from IOService. Because Transport Drivers needn't - * derive from a type known to IOBlockStorageDriver, it isn't possible for - * IOBlockStorageDriver to include the appropriate header file to allow direct - * communication with the Transport Driver. Thus we achieve polymorphism by - * having the Transport Driver instantiate a subclass of IOBlockStorageDevice. - * A typical implementation for a concrete subclass of IOBlockStorageDevice - * simply relays all methods to its provider (the Transport Driver). - * - * All pure-virtual functions must be implemented by the Transport Driver, which - * is responsible for instantiating the Nub. - */ - -class IOBlockStorageDevice : public IOService { - - OSDeclareAbstractStructors(IOBlockStorageDevice) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - - /* Overrides from IORegistryEntry */ - - /*! - * @function init - * @discussion - * This function is overridden so that IOBlockStorageDevice can set a - * property, used by IOBlockStorageDriver for matching. Since the concrete - * subclass of IOBlockStorageDevice can be of any class type, the property - * is used for matching. - * - * This function is usually not overridden by developers. - */ - virtual bool init(OSDictionary * properties); - - /* --- A subclass must implement the the following methods: --- */ - - /*! - * @function doAsyncReadWrite - * @abstract - * Start an asynchronous read or write operation. - * @param buffer - * An IOMemoryDescriptor describing the data-transfer buffer. The data direction - * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor - * rests with the caller. - * @param block - * The starting block number of the data transfer. - * @param nblks - * The integral number of blocks to be transferred. - * @param completion - * The completion routine to call once the data transfer is complete. - */ - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion) = 0; - - /*! - * @function doSyncReadWrite - * @abstract - * Perform a synchronous read or write operation. - * @param buffer - * An IOMemoryDescriptor describing the data-transfer buffer. The data direction - * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor - * rests with the caller. - * @param block - * The starting block number of the data transfer. - * @param nblks - * The integral number of blocks to be transferred. - */ - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks) = 0; - - /*! - * @function doEjectMedia - * @abstract - * Eject the media. - */ - virtual IOReturn doEjectMedia(void) = 0; - - /*! - * @function doFormatMedia - * @abstract - * Format the media to the specified byte capacity. - * @discussion - * The specified byte capacity must be one supported by the device. - * Supported capacities can be obtained by calling doGetFormatCapacities. - * @param byteCapacity - * The byte capacity to which the device is to be formatted, if possible. - */ - virtual IOReturn doFormatMedia(UInt64 byteCapacity) = 0; - - /*! - * @function doGetFormatCapacities - * @abstract - * Return the allowable formatting byte capacities. - * @discussion - * This function returns the supported byte capacities for the device. - * @param capacities - * Pointer for returning the list of capacities. - * @param capacitiesMaxCount - * The number of capacity values returned in "capacities." - */ - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const = 0; - - /*! - * @function doLockUnlockMedia - * @abstract - * Lock or unlock the (removable) media in the drive. - * @discussion - * This method should only be called if the media is known to be removable. - * @param doLock - * True to lock the media, False to unlock. - */ - virtual IOReturn doLockUnlockMedia(bool doLock) = 0; - - /*! - * @function doSynchronizeCache - * @abstract - * Force data blocks in the hardware's buffer to be flushed to the media. - * @discussion - * This method should only be called if the media is writable. - */ - virtual IOReturn doSynchronizeCache(void) = 0; - - /*! - * @function getVendorString - * @abstract - * Return Vendor Name string for the device. - * @result - * A pointer to a static character string. - */ - virtual char * getVendorString(void) = 0; - - /*! - * @function getProductString - * @abstract - * Return Product Name string for the device. - * @result - * A pointer to a static character string. - */ - virtual char * getProductString(void) = 0; - - /*! - * @function getRevisionString - * @abstract - * Return Product Revision string for the device. - * @result - * A pointer to a static character string. - */ - virtual char * getRevisionString(void) = 0; - - /*! - * @function getAdditionalDeviceInfoString - * @abstract - * Return additional informational string for the device. - * @result - * A pointer to a static character string. - */ - virtual char * getAdditionalDeviceInfoString(void) = 0; - - /*! - * @function reportBlockSize - * @abstract - * Report the block size for the device, in bytes. - * @param blockSize - * Pointer to returned block size value. - */ - virtual IOReturn reportBlockSize(UInt64 *blockSize) = 0; - - /*! - * @function reportEjectability - * @abstract - * Report if the media is ejectable under software control. - * @discussion - * This method should only be called if the media is known to be removable. - * @param isEjectable - * Pointer to returned result. True indicates the media is ejectable, False indicates - * the media cannot be ejected under software control. - */ - virtual IOReturn reportEjectability(bool *isEjectable) = 0; - - /*! - * @function reportLockability - * @abstract - * Report if the media is lockable under software control. - * @discussion - * This method should only be called if the media is known to be removable. - * @param isLockable - * Pointer to returned result. True indicates the media can be locked in place; False - * indicates the media cannot be locked by software. - */ - virtual IOReturn reportLockability(bool *isLockable) = 0; - - /*! - * @function reportMaxReadTransfer - * @abstract - * Report the maximum allowed byte transfer for read operations. - * @discussion - * Some devices impose a maximum data transfer size. Because this limit - * may be determined by the size of a block-count field in a command, the limit may - * depend on the block size of the transfer. - * @param blockSize - * The block size desired for the transfer. - * @param max - * Pointer to returned result. - */ - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize,UInt64 *max) = 0; - - /*! - * @function reportMaxWriteTransfer - * @abstract - * Report the maximum allowed byte transfer for write operations. - * @discussion - * Some devices impose a maximum data transfer size. Because this limit - * may be determined by the size of a block-count field in a command, the limit may - * depend on the block size of the transfer. - * @param blockSize - * The block size desired for the transfer. - * @param max - * Pointer to returned result. - */ - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max) = 0; - - /*! - * @function reportMaxValidBlock - * @abstract - * Report the highest valid block for the device. - * @param maxBlock - * Pointer to returned result - */ - virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock) = 0; - - /*! - * @function reportMediaState - * @abstract - * Report the device's media state. - * @discussion - * This method reports whether we have media in the drive or not, and - * whether the state has changed from the previously reported state. - * - * A result of kIOReturnSuccess is always returned if the test for media is successful, - * regardless of media presence. The mediaPresent result should be used to determine - * whether media is present or not. A return other than kIOReturnSuccess indicates that - * the Transport Driver was unable to interrogate the device. In this error case, the - * outputs mediaState and changedState will *not* be stored. - * @param mediaPresent Pointer to returned media state. True indicates media is present - * in the device; False indicates no media is present. - * @param changedState Pointer to returned result. True indicates a change of state since - * prior calls, False indicates that the state has not changed. - */ - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changedState) = 0; - - /*! - * @function reportPollRequirements - * @abstract - * Report if it's necessary to poll for media insertion, and if polling is expensive. - * @discussion - * This method reports whether the device must be polled to detect media - * insertion, and whether a poll is expensive to perform. - * - * The term "expensive" typically implies a device that must be spun-up to detect media, - * as on a PC floppy. Most devices can detect media inexpensively. - * @param pollRequired - * Pointer to returned result. True indicates that polling is required; False indicates - * that polling is not required to detect media. - * @param pollIsExpensive - * Pointer to returned result. True indicates that the polling operation is expensive; - * False indicates that the polling operation is cheap. - */ - virtual IOReturn reportPollRequirements(bool *pollRequired, - bool *pollIsExpensive) = 0; - - /*! - * @function reportRemovability - * @abstract - * Report whether the media is removable or not. - * @discussion - * This method reports whether the media is removable, but it does not - * provide detailed information regarding software eject or lock/unlock capability. - * @param isRemovable - * Pointer to returned result. True indicates that the media is removable; False - * indicates the media is not removable. - */ - virtual IOReturn reportRemovability(bool *isRemovable) = 0; - - /*! - * @function reportWriteProtection - * @abstract - * Report whether the media is write-protected or not. - * @param isWriteProtected - * Pointer to returned result. True indicates that the media is write-protected (it - * cannot be written); False indicates that the media is not write-protected (it - * is permissible to write). - */ - virtual IOReturn reportWriteProtection(bool *isWriteProtected) = 0; - - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 0); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 1); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 2); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 3); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 4); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 5); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 6); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 7); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 8); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 9); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 10); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 11); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 12); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 13); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 14); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 15); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 16); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 17); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 18); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 19); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 20); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 21); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 22); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 23); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 24); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 25); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 26); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 27); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 28); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 29); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 30); - OSMetaClassDeclareReservedUnused(IOBlockStorageDevice, 31); -}; -#endif diff --git a/iokit/IOKit/storage/IOBlockStorageDriver.h b/iokit/IOKit/storage/IOBlockStorageDriver.h deleted file mode 100644 index f02dc1d96..000000000 --- a/iokit/IOKit/storage/IOBlockStorageDriver.h +++ /dev/null @@ -1,1320 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOBlockStorageDriver - * @abstract - * This header contains the IOBlockStorageDriver class definition. - */ - -#ifndef _IOBLOCKSTORAGEDRIVER_H -#define _IOBLOCKSTORAGEDRIVER_H - -/*! - * @defined kIOBlockStorageDriverClass - * @abstract - * kIOBlockStorageDriverClass is the name of the IOBlockStorageDriver class. - * @discussion - * kIOBlockStorageDriverClass is the name of the IOBlockStorageDriver class. - */ - -#define kIOBlockStorageDriverClass "IOBlockStorageDriver" - -/*! - * @defined kIOBlockStorageDriverStatisticsKey - * @abstract - * This property holds a table of numeric values describing the driver's - * operating statistics. - * @discussion - * This property holds a table of numeric values describing the driver's - * operating statistics. The table is an OSDictionary, where each entry - * describes one given statistic. - */ - -#define kIOBlockStorageDriverStatisticsKey "Statistics" - -/*! - * @defined kIOBlockStorageDriverStatisticsBytesReadKey - * @abstract - * This property describes the number of bytes read since the block storage - * driver was instantiated. It is one of the statistic entries listed under - * the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of bytes read since the block storage - * driver was instantiated. It is one of the statistic entries listed under - * the top-level kIOBlockStorageDriverStatisticsKey property table. It has - * an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsBytesReadKey "Bytes (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsBytesWrittenKey - * @abstract - * This property describes the number of bytes written since the block storage - * driver was instantiated. It is one of the statistic entries listed under the - * top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of bytes written since the block storage - * driver was instantiated. It is one of the statistic entries listed under the - * top-level kIOBlockStorageDriverStatisticsKey property table. It has an - * OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsBytesWrittenKey "Bytes (Write)" - -/*! - * @defined kIOBlockStorageDriverStatisticsReadErrorsKey - * @abstract - * This property describes the number of read errors encountered since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of read errors encountered since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. It - * has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsReadErrorsKey "Errors (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsWriteErrorsKey - * @abstract - * This property describes the number of write errors encountered since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of write errors encountered since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsWriteErrorsKey "Errors (Write)" - -/*! - * @defined kIOBlockStorageDriverStatisticsLatentReadTimeKey - * @abstract - * This property describes the number of nanoseconds of latency during reads - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. - * @discussion - * This property describes the number of nanoseconds of latency during reads - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsLatentReadTimeKey "Latency Time (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsLatentWriteTimeKey - * @abstract - * This property describes the number of nanoseconds of latency during writes - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. - * @discussion - * This property describes the number of nanoseconds of latency during writes - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsLatentWriteTimeKey "Latency Time (Write)" - -/*! - * @defined kIOBlockStorageDriverStatisticsReadsKey - * @abstract - * This property describes the number of read operations processed since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of read operations processed since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsReadsKey "Operations (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsWritesKey - * @abstract - * This property describes the number of write operations processed since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of write operations processed since the - * block storage driver was instantiated. It is one of the statistic entries - * listed under the top-level kIOBlockStorageDriverStatisticsKey property table. - * It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsWritesKey "Operations (Write)" - -/*! - * @defined kIOBlockStorageDriverStatisticsReadRetriesKey - * @abstract - * This property describes the number of read retries required since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. - * @discussion - * This property describes the number of read retries required since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. It - * has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsReadRetriesKey "Retries (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsWriteRetriesKey - * @abstract - * This property describes the number of write retries required since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. It - * has an OSNumber value. - * @discussion - * This property describes the number of write retries required since the block - * storage driver was instantiated. It is one of the statistic entries listed - * under the top-level kIOBlockStorageDriverStatisticsKey property table. It - * has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsWriteRetriesKey "Retries (Write)" - -/*! - * @defined kIOBlockStorageDriverStatisticsTotalReadTimeKey - * @abstract - * This property describes the number of nanoseconds spent performing reads - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. - * @discussion - * This property describes the number of nanoseconds spent performing reads - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsTotalReadTimeKey "Total Time (Read)" - -/*! - * @defined kIOBlockStorageDriverStatisticsTotalWriteTimeKey - * @abstract - * This property describes the number of nanoseconds spent performing writes - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. - * @discussion - * This property describes the number of nanoseconds spent performing writes - * since the block storage driver was instantiated. It is one of the statistic - * entries listed under the top-level kIOBlockStorageDriverStatisticsKey - * property table. It has an OSNumber value. - */ - -#define kIOBlockStorageDriverStatisticsTotalWriteTimeKey "Total Time (Write)" - -/*! - * @enum IOMediaState - * @discussion - * The different states that getMediaState() can report. - * @constant kIOMediaStateOffline - * Media is not available. - * @constant kIOMediaStateOnline - * Media is available and ready for operations. - * @constant kIOMediaStateBusy - * Media is available, but not ready for operations. - */ - -typedef UInt32 IOMediaState; - -#define kIOMediaStateOffline 0 -#define kIOMediaStateOnline 1 -#define kIOMediaStateBusy 2 - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOBlockStorageDevice.h> -#include <IOKit/storage/IOMedia.h> -#include <IOKit/storage/IOStorage.h> -#include <kern/thread_call.h> - -/*! - * @class IOBlockStorageDriver - * @abstract - * The IOBlockStorageDriver class is the common base class for generic block - * storage drivers. It matches and communicates via an IOBlockStorageDevice - * interface, and connects to the remainder of the storage framework via the - * IOStorage protocol. - * @discussion - * The IOBlockStorageDriver class is the common base class for generic block - * storage drivers. It matches and communicates via an IOBlockStorageDevice - * interface, and connects to the remainder of the storage framework via the - * IOStorage protocol. It extends the IOStorage protocol by implementing the - * appropriate open and close semantics, deblocking for unaligned transfers, - * polling for ejectable media, locking and ejection policies, media object - * creation and teardown, and statistics gathering and reporting. - * - * Block storage drivers are split into two parts: the generic driver handles - * all generic device issues, independent of the lower-level transport - * mechanism (e.g. SCSI, ATA, USB, FireWire). All storage operations - * at the generic driver level are translated into a series of generic - * device operations. These operations are passed via the IOBlockStorageDevice - * nub to a transport driver, which implements the appropriate - * transport-dependent protocol to execute these operations. - * - * To determine the write-protect state of a device (or media), for - * example, the generic driver would issue a call to the - * Transport Driver's reportWriteProtection method. If this were a SCSI - * device, its transport driver would issue a Mode Sense command to - * extract the write-protection status bit. The transport driver then - * reports true or false to the generic driver. - * - * The generic driver therefore has no knowledge of, or involvement - * with, the actual commands and mechanisms used to communicate with - * the device. It is expected that the generic driver will rarely, if - * ever, need to be subclassed to handle device idiosyncrasies; rather, - * the transport driver should be changed via overrides. - * - * A generic driver could be subclassed to create a different type of - * generic device. The generic driver IOCDBlockStorageDriver class is - * a subclass of IOBlockStorageDriver, adding CD functions. - */ - -class IOBlockStorageDriver : public IOStorage -{ - OSDeclareDefaultStructors(IOBlockStorageDriver); - -public: - - /*! - * @enum Statistics - * @discussion - * Indices for the different statistics that getStatistics() can report. - * @constant kStatisticsReads - * Number of read operations thus far. - * @constant kStatisticsBytesRead - * Number of bytes read thus far. - * @constant kStatisticsTotalReadTime - * Nanoseconds spent performing reads thus far. - * @constant kStatisticsLatentReadTime - * Nanoseconds of latency during reads thus far. - * @constant kStatisticsReadRetries - * Number of read retries thus far. - * @constant kStatisticsReadErrors - * Number of read errors thus far. - * @constant kStatisticsWrites - * Number of write operations thus far. - * @constant kStatisticsSingleBlockWrites - * Number of write operations for a single block thus far. - * @constant kStatisticsBytesWritten - * Number of bytes written thus far. - * @constant kStatisticsTotalWriteTime - * Nanoseconds spent performing writes thus far. - * @constant kStatisticsLatentWriteTime - * Nanoseconds of latency during writes thus far. - * @constant kStatisticsWriteRetries - * Number of write retries thus far. - * @constant kStatisticsWriteErrors - * Number of write errors thus far. - */ - - enum Statistics - { - kStatisticsReads, - kStatisticsBytesRead, - kStatisticsTotalReadTime, - kStatisticsLatentReadTime, - kStatisticsReadRetries, - kStatisticsReadErrors, - - kStatisticsWrites, - kStatisticsSingleBlockWrites, - kStatisticsBytesWritten, - kStatisticsTotalWriteTime, - kStatisticsLatentWriteTime, - kStatisticsWriteRetries, - kStatisticsWriteErrors - }; - - static const UInt32 kStatisticsCount = kStatisticsWriteErrors + 1; - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - OSSet * _openClients; - OSNumber * _statistics[kStatisticsCount]; - - /* - * @struct Context - * @discussion - * Context structure for a read/write operation. It describes the block size, - * and where applicable, a block type and block sub-type, for a data transfer, - * as well as the completion information for the original request. Note that - * the block type field is unused in the IOBlockStorageDriver class. - * @field block.size - * Block size for the operation. - * @field block.type - * Block type for the operation. Unused in IOBlockStorageDriver. The default - * value for this field is IOBlockStorageDriver::kBlockTypeStandard. - * @field block.typeSub - * Block sub-type for the operation. It's definition depends on block.type. - * Unused in IOBlockStorageDriver. - * @field original.byteStart - * Starting byte offset for the data transfer. - * @param original.buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param original.completion - * Completion routine to call once the data transfer is complete. - */ - - struct Context - { - struct - { - UInt32 size; - UInt8 type; - UInt8 typeSub[3]; - } block; - - struct - { - UInt64 byteStart; - IOMemoryDescriptor * buffer; - IOStorageCompletion completion; - } original; - - UInt32 reserved[8]; - }; - - static const UInt8 kBlockTypeStandard = 0x00; - - /* - * Free all of this object's outstanding resources. - * - * This method's implementation is not typically overidden. - */ - - void free(); - - /*! - * @function handleOpen - * @discussion - * The handleOpen method grants or denies permission to access this object - * to an interested client. The argument is an IOStorageAccess value that - * specifies the level of access desired -- reader or reader-writer. - * - * This method can be invoked to upgrade or downgrade the access level for - * an existing client as well. The previous access level will prevail for - * upgrades that fail, of course. A downgrade should never fail. If the - * new access level should be the same as the old for a given client, this - * method will do nothing and return success. In all cases, one, singular - * close-per-client is expected for all opens-per-client received. - * - * This implementation replaces the IOService definition of handleIsOpen(). - * @param client - * Client requesting the open. - * @param options - * Options for the open. Set to zero. - * @param access - * Access level for the open. Set to kIOStorageAccessReader or - * kIOStorageAccessReaderWriter. - * @result - * Returns true if the open was successful, false otherwise. - */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * access); - - /*! - * @function handleIsOpen - * @discussion - * The handleIsOpen method determines whether the specified client, or any - * client if none is specificed, presently has an open on this object. - * - * This implementation replaces the IOService definition of handleIsOpen(). - * @param client - * Client to check the open state of. Set to zero to check the open state - * of all clients. - * @result - * Returns true if the client was (or clients were) open, false otherwise. - */ - - virtual bool handleIsOpen(const IOService * client) const; - - /*! - * @function handleClose - * @discussion - * The handleClose method closes the client's access to this object. - * - * This implementation replaces the IOService definition of handleIsOpen(). - * @param client - * Client requesting the close. - * @param options - * Options for the close. Set to zero. - */ - - virtual void handleClose(IOService * client, IOOptionBits options); - - /*! - * @function addToBytesTransferred - * @discussion - * Update the total number of bytes transferred, the total transfer time, - * and the total latency time -- used for statistics. - * - * This method's implementation is not typically overidden. - * @param bytesTransferred - * Number of bytes transferred in this operation. - * @param totalTime - * Nanoseconds spent performing this operation. - * @param latentTime - * Nanoseconds of latency during this operation. - * @param isWrite - * Indicates whether this operation was a write, otherwise is was a read. - */ - - virtual void addToBytesTransferred(UInt64 bytesTransferred, - UInt64 totalTime, - UInt64 latentTime, - bool isWrite); - - /*! - * @function incrementErrors - * @discussion - * Update the total error count -- used for statistics. - * - * This method's implementation is not typically overidden. - * @param isWrite - * Indicates whether this operation was a write, otherwise is was a read. - */ - - virtual void incrementErrors(bool isWrite); - - /*! - * @function incrementRetries - * @discussion - * Update the total retry count -- used for statistics. - * - * This method's implementation is not typically overidden. - * @param isWrite - * Indicates whether this operation was a write, otherwise is was a read. - */ - - virtual void incrementRetries(bool isWrite); - - /*! - * @function allocateContext - * @discussion - * Allocate a context structure for a read/write operation. - * @result - * Context structure. - */ - - virtual Context * allocateContext(); - - /*! - * @function deleteContext - * @discussion - * Delete a context structure from a read/write operation. - * @param context - * Context structure to be deleted. - */ - - virtual void deleteContext(Context * context); - - /*! - * @function prepareRequest - * @discussion - * The prepareRequest method allocates and prepares state for the transfer. - * - * This method is part of a sequence of methods invoked for each read/write - * request. The first is prepareRequest, which allocates and prepares some - * context for the transfer; the second is deblockRequest, which aligns the - * transfer at the media block boundaries; and the third is executeRequest, - * which implements the actual transfer from the block storage device. - * - * This method's implementation is not typically overidden. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void prepareRequest(UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /*! - * @function deblockRequest - * @discussion - * The deblockRequest method checks to see if the incoming request rests - * on the media's block boundaries, and if not, deblocks it. Deblocking - * involves rounding out the request to the nearest block boundaries and - * transferring the excess bytes into a scratch buffer. - * - * This method is part of a sequence of methods invoked for each read/write - * request. The first is prepareRequest, which allocates and prepares some - * context for the transfer; the second is deblockRequest, which aligns the - * transfer at the media block boundaries; and the third is executeRequest, - * which implements the actual transfer from the block storage device. - * - * This method's implementation is not typically overidden. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - * @param context - * Additional context information for the data transfer (eg. block size). - */ - - virtual void deblockRequest(UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion, - Context * context); - - /*! - * @function executeRequest - * @discussion - * Execute an asynchrnous storage request. The request is guaranteed to be - * block-aligned. - * - * This method is part of a sequence of methods invoked for each read/write - * request. The first is prepareRequest, which allocates and prepares some - * context for the transfer; the second is deblockRequest, which aligns the - * transfer at the media block boundaries; and the third is executeRequest, - * which implements the actual transfer from the block storage device. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - * @param context - * Additional context information for the data transfer (eg. block size). - */ - - virtual void executeRequest(UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion, - Context * context); - - /*! - * @function handleStart - * @discussion - * Prepare the block storage driver for operation. - * - * This is where a media object needs to be created for fixed media, and - * optionally for removable media. - * - * Note that this method is called from within the start() routine; - * if this method returns successfully, it should be prepared to accept - * any of IOBlockStorageDriver's APIs. - * @param provider - * This object's provider. - * @result - * Returns true on success, false otherwise. - */ - - virtual bool handleStart(IOService * provider); - - /*! - * @function handleYield - * @discussion - * Stop the block storage driver. - * - * This method is called as a result of the kIOMessageServiceIsTerminated - * or kIOMessageServiceIsRequestingClose provider messages. The argument - * is passed in as-is from the message. The kIOServiceRequired option is - * set for the kIOMessageServiceIsTerminated message to indicate that the - * yield must succeed. - * - * This is where the driver should clean up its state in preparation for - * removal from the system. This implementation issues a synchronize cache - * operation, if the media is writable, and then ejects the media. - * - * Note that this method is called from within the yield() routine. - * - * This method is called with the arbitration lock held. - * @param provider - * This object's provider. - */ - - virtual bool handleYield(IOService * provider, - IOOptionBits options = 0, - void * argument = 0); - - - /*! - * @function getMediaBlockSize - * @discussion - * Ask the driver about the media's natural block size. - * @result - * Natural block size, in bytes. - */ - - virtual UInt64 getMediaBlockSize() const; - -public: - -///m:2333367:workaround:commented:start -// using read; -// using write; -///m:2333367:workaround:commented:stop - - /* - * Initialize this object's minimal state. - * - * This method's implementation is not typically overidden. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * This method is called once we have been attached to the provider object. - * - * This method's implementation is not typically overidden. - */ - - virtual bool start(IOService * provider); - - /* - * This method is called as a result of the kIOMessageServiceIsTerminated - * or kIOMessageServiceIsRequestingClose provider messages. The argument - * is passed in as-is from the message. The kIOServiceRequired option is - * set for the kIOMessageServiceIsTerminated message to indicate that the - * yield must succeed. - * - * This method is called with the arbitration lock held. - * - * This method's implementation is not typically overidden. - */ - - virtual bool yield(IOService * provider, - IOOptionBits options = 0, - void * argument = 0); - - /*! - * @function read - * @discussion - * The read method is the receiving end for all read requests from the - * storage framework (through the media object created by this driver). - * - * This method kicks off a sequence of three methods for each read or write - * request. The first is prepareRequest, which allocates and prepares some - * context for the transfer; the second is deblockRequest, which aligns the - * transfer at the media block boundaries; and the third is executeRequest, - * which implements the actual transfer from the block storage device. - * - * This method's implementation is not typically overidden. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /*! - * @function write - * @discussion - * The write method is the receiving end for all write requests from the - * storage framework (through the media object created by this driver). - * - * This method kicks off a sequence of three methods for each read or write - * request. The first is prepareRequest, which allocates and prepares some - * context for the transfer; the second is deblockRequest, which aligns the - * transfer at the media block boundaries; and the third is executeRequest, - * which implements the actual transfer from the block storage device. - * - * This method's implementation is not typically overidden. - * @param client - * Client requesting the write. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - virtual IOReturn synchronizeCache(IOService * client); - - /*! - * @function ejectMedia - * @discussion - * Eject the media from the device. The driver is responsible for tearing - * down the media object it created before proceeding with the eject. If - * the teardown fails, an error should be returned. - * @result - * An IOReturn code. - */ - - virtual IOReturn ejectMedia(); - - /*! - * @function formatMedia - * @discussion - * Format the media with the specified byte capacity. The driver is - * responsible for tearing down the media object and recreating it. - * @param byteCapacity - * Number of bytes to format media to. - * @result - * An IOReturn code. - */ - - virtual IOReturn formatMedia(UInt64 byteCapacity); - - /*! - * @function lockMedia - * @discussion - * Lock or unlock the ejectable media in the device, that is, prevent - * it from manual ejection or allow its manual ejection. - * @param lock - * Pass true to lock the media, otherwise pass false to unlock the media. - * @result - * An IOReturn code. - */ - - virtual IOReturn lockMedia(bool lock); - - /*! - * @function pollMedia - * @discussion - * Poll for the presence of media in the device. The driver is responsible - * for tearing down the media object it created should the media have been - * removed since the last poll, and vice-versa, creating the media object - * should new media have arrived since the last poll. - * @result - * An IOReturn code. - */ - - virtual IOReturn pollMedia(); - - /*! - * @function isMediaEjectable - * @discussion - * Ask the driver whether the media is ejectable. - * @result - * Returns true if the media is ejectable, false otherwise. - */ - - virtual bool isMediaEjectable() const; - - /*! - * @function isMediaPollExpensive - * @discussion - * Ask the driver whether a pollMedia() would be an expensive operation, - * that is, one that requires the device to spin up or delay for a while. - * @result - * Returns true if polling the media is expensive, false otherwise. - */ - - virtual bool isMediaPollExpensive() const; - - /*! - * @function isMediaPollRequired - * @discussion - * Ask the driver whether the block storage device requires polling, which is - * typically required for devices without the ability to asynchronously detect - * the arrival or departure of the media. - * @result - * Returns true if polling the media is required, false otherwise. - */ - - virtual bool isMediaPollRequired() const; - - virtual bool isMediaWritable() const; - - /*! - * @function getMediaState - * @discussion - * Ask the driver about the media's current state. - * @result - * An IOMediaState value. - */ - - virtual IOMediaState getMediaState() const; - - /*! - * @function getFormatCapacities - * @discussion - * Ask the driver to report the feasible formatting capacities for the - * inserted media (in bytes). This routine fills the caller's buffer, - * up to the maximum count specified if the real number of capacities - * would overflow the buffer. The return value indicates the actual - * number of capacities copied to the buffer. - * - * If the capacities buffer is not supplied or if the maximum count is - * zero, the routine returns the proposed count of capacities instead. - * @param capacities - * Buffer that will receive the UInt64 capacity values. - * @param capacitiesMaxCount - * Maximum number of capacity values that can be held in the buffer. - * @result - * Actual number of capacity values copied to the buffer, or if no buffer - * is given, the total number of capacity values available. - */ - - virtual UInt32 getFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - - /*! - * @function getStatistics - * @discussion - * Ask the driver to report its operating statistics. - * - * The statistics are each indexed by IOBlockStorageDriver::Statistics - * indices. This routine fills the caller's buffer, up to the maximum - * count specified if the real number of statistics would overflow the - * buffer. The return value indicates the actual number of statistics - * copied to the buffer. - * - * If the statistics buffer is not supplied or if the maximum count is - * zero, the routine returns the proposed count of statistics instead. - * @param statistics - * Buffer that will receive the UInt64 statistic values. - * @param statisticsMaxCount - * Maximum number of statistic values that can be held in the buffer. - * @result - * Actual number of statistic values copied to the buffer, or if no buffer - * is given, the total number of statistic values available. - */ - - virtual UInt32 getStatistics(UInt64 * statistics, - UInt32 statisticsMaxCount) const; - - /*! - * @function getStatistic - * @discussion - * Ask the driver to report one of its operating statistics. - * @param statistic - * Statistic index (an IOBlockStorageDriver::Statistics index). - * @result - * Statistic value. - */ - - virtual UInt64 getStatistic(Statistics statistic) const; - - /* - * Generic entry point for calls from the provider. A return value of - * kIOReturnSuccess indicates that the message was received, and where - * applicable, that it was successful. - */ - - virtual IOReturn message(UInt32 type, IOService * provider, void * argument); - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IOBlockStorageDevice. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IOBlockStorageDevice * getProvider() const; - -protected: - - IOLock * _deblockRequestWriteLock; - thread_call_t _pollerCall; - - /* - * This is the completion routine for the aligned deblocker subrequests. - * It verifies the success of the just-completed stage, transitions to - * the next stage, then builds and issues a transfer for the next stage. - */ - - static void deblockRequestCompletion(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount); - - /* - * This is the completion routine for the prepared request. It updates - * the driver's statistics, performs some clean up work, then calls the - * original request's completion routine. - */ - - static void prepareRequestCompletion(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount); - - /* - * Schedule the poller mechanism. - */ - - virtual void schedulePoller(); - - /* - * Unschedule the poller mechanism. - */ - - virtual void unschedulePoller(); - - /* - * This method is the timeout handler for the poller mechanism. It polls - * for media and reschedules another timeout if there are still no opens. - */ - - static void poller(void *, void *); - -protected: - - /* Device info: */ - - /*! - * @var _removable - * True if the media is removable; False if it is fixed (not removable). - */ - bool _removable; - - /*! - * @var _ejectable - * True if the media is ejectable under software control. - */ - bool _ejectable; /* software-ejectable */ - - /*! - * @var _lockable - * True if the media can be locked in the device under software control. - */ - bool _lockable; /* software lockable in device */ - /*! - * @var _pollIsRequired - * True if we must poll to detect media insertion or removal. - */ - bool _pollIsRequired; - /*! - * @var _pollIsExpensive - * True if polling is expensive; False if not. - */ - bool _pollIsExpensive; - - /* Media info and states: */ - - /*! - * @var _mediaObject - * A pointer to the media object we have instantiated (if any). - */ - IOMedia * _mediaObject; - /*! - * @var _mediaType - * Type of the media (can be used to differentiate between the - * different types of CD media, DVD media, etc). - */ - UInt32 _mediaType; - /*! - * @var _mediaPresent - * True if media is present in the device; False if not. - */ - bool _mediaPresent; /* media is present and ready */ - /*! - * @var _writeProtected - * True if the media is write-protected; False if not. - */ - bool _writeProtected; - -private: - - /*! - * @var _mediaStateLock - * A lock used to protect during media checks. - */ - IOLock * _mediaStateLock; - -protected: - - /*! - * @var _mediaBlockSize - * The block size of the media, in bytes. - */ - UInt64 _mediaBlockSize; - /*! - * @var _maxBlockNumber - * The maximum allowable block number for the media, zero-based. - */ - UInt64 _maxBlockNumber; - - /*! - * @var _maxReadByteTransfer - * The maximum byte transfer allowed for read operations. - */ - UInt64 _maxReadByteTransfer; - - /*! - * @var _maxWriteByteTransfer - * The maximum byte transfer allowed for write operations. - */ - UInt64 _maxWriteByteTransfer; - - /*! - * @function acceptNewMedia - * @abstract - * React to new media insertion. - * @discussion - * This method logs the media block size and block count, then calls - * instantiateMediaObject to get a media object instantiated. The - * media object is then attached above us and registered. - * - * This method can be overridden to control what happens when new media - * is inserted. The default implementation deals with one IOMedia object. - */ - virtual IOReturn acceptNewMedia(void); - - /*! - * @function constrainByteCount - * @abstract - * Constrain the byte count for this IO to device limits. - * @discussion - * This function should be called prior to each read or write operation, so that - * the driver can constrain the requested byte count, as necessary, to meet - * current device limits. Such limits could be imposed by the device depending - * on operating modes, media types, or transport prototol (e.g. ATA, SCSI). - * - * At present, this method is not used. - * @param requestedCount - * The requested byte count for the next read or write operation. - * @param isWrite - * True if the operation will be a write; False if the operation will be a read. - */ - virtual UInt64 constrainByteCount(UInt64 requestedCount,bool isWrite); - - /*! - * @function decommissionMedia - * @abstract - * Decommission an existing piece of media that has gone away. - * @discussion - * This method wraps a call to terminate, to tear down the stack and - * the IOMedia object for the media. If "forcible" is true, the media - * object will be forgotten, and initMediaState will be called. A - * forcible decommission would occur when an unrecoverable error - * happens during teardown (e.g. perhaps a client is still open), but - * we must still forget about the media. - * @param forcible - * True to force forgetting of the media object even if terminate reports - * that there was an active client. - */ - virtual IOReturn decommissionMedia(bool forcible); - - /*! - * @function instantiateDesiredMediaObject - * @abstract - * Create an IOMedia object for media. - * @discussion - * This method creates the exact type of IOMedia object desired. It is called by - * instantiateMediaObject. A subclass may override this one-line method to change - * the type of media object actually instantiated. - */ - virtual IOMedia * instantiateDesiredMediaObject(void); - - /*! - * @function instantiateMediaObject - * @abstract - * Create an IOMedia object for media. - * @discussion - * This method creates an IOMedia object from the supplied parameters. It is a - * convenience method to wrap the handful of steps to do the job. - * @param base - * Byte number of beginning of active data area of the media. Usually zero. - * @param byteSize - * Size of the data area of the media, in bytes. - * @param blockSize - * Block size of the media, in bytes. - * @param mediaName - * Name of the IOMedia object. - * @result - * A pointer to the created IOMedia object, or a null on error. - */ - virtual IOMedia * instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName); - - /*! - * @function recordMediaParameters - * @abstract - * Obtain media-related parameters on media insertion. - * @discussion - * This method obtains media-related parameters via calls to the - * Transport Driver's reportBlockSize, reportMaxValidBlock, - * reportMaxReadTransfer, reportMaxWriteTransfer, and reportWriteProtection - * methods. - */ - virtual IOReturn recordMediaParameters(void); - - /*! - * @function rejectMedia - * @abstract - * Reject new media. - * @discussion - * This method will be called if validateNewMedia returns False (thus rejecting - * the new media. A vendor may choose to override this method to control behavior - * when media is rejected. - * - * The default implementation simply calls ejectMedia. - */ - virtual void rejectMedia(void); /* default ejects */ - - /*! - * @function validateNewMedia - * @abstract - * Verify that new media is acceptable. - * @discussion - * This method will be called whenever new media is detected. Return true to accept - * the media, or false to reject it (andcall rejectMedia). Vendors might override - * this method to handle password-protection for new media. - * - * The default implementation always returns True, indicating media is accepted. - */ - virtual bool validateNewMedia(void); - - /* --- Internally used methods. --- */ - - /* - * @group - * Internally Used Methods - * @discussion - * These methods are used internally, and will not generally be modified. - */ - - /*! - * @function checkForMedia - * @abstract - * Check if media has newly arrived or disappeared. - * @discussion - * This method does most of the work in polling for media, first - * calling the block storage device's reportMediaState method. If - * reportMediaState reports no change in the media state, kIOReturnSuccess - * is returned. If the media state has indeed changed, a call is made to - * mediaStateHasChanged to act on the event. - */ - virtual IOReturn checkForMedia(void); - - /*! - * @function getDeviceTypeName - * @abstract - * Return the desired device name. - * @discussion - * This method returns a string, used to compare the - * kIOBlockStorageDeviceTypeKey of our provider. This method is called from - * probe. - * - * The default implementation of this method returns - * kIOBlockStorageDeviceTypeGeneric. - */ - virtual const char * getDeviceTypeName(void); - - /*! - * @function initMediaState - * @abstract - * Initialize media-related instance variables. - * @discussion - * Called when media is not present, this method marks the device state - * as not having media present, not spun up, and write-enabled. - */ - virtual void initMediaState(void); - - /*! - * @function mediaStateHasChanged - * @abstract - * React to a new media insertion or a media removal. - * @discussion - * This method is called on a media state change, that is, an arrival - * or removal. If media has just become available, calls are made to - * recordMediaParameters and acceptNewMedia. If media has just gone - * away, a call is made to decommissionMedia, with the forcible - * parameter set to true. The forcible teardown is needed to enforce - * the disappearance of media, regardless of interested clients. - */ - virtual IOReturn mediaStateHasChanged(IOMediaState state); - - /* - * @endgroup - */ - - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 0); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 1); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 2); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 3); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 4); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 5); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 6); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 7); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 8); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 9); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 10); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 11); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 12); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 13); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 14); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 15); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 16); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 17); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 18); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 19); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 20); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 21); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 22); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 23); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 24); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 25); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 26); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 27); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 28); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 29); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 30); - OSMetaClassDeclareReservedUnused(IOBlockStorageDriver, 31); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOBLOCKSTORAGEDRIVER_H */ diff --git a/iokit/IOKit/storage/IOCDAudioControl.h b/iokit/IOKit/storage/IOCDAudioControl.h deleted file mode 100644 index 7a1a99969..000000000 --- a/iokit/IOKit/storage/IOCDAudioControl.h +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOCDAudioControl - * @abstract - * This header contains the IOCDAudioControl class definition. - */ - -#ifndef _IOCDAUDIOCONTROL_H -#define _IOCDAUDIOCONTROL_H - -/*! - * @defined kIOCDAudioControlClass - * @abstract - * kIOCDAudioControlClass is the name of the IOCDAudioControl class. - * @discussion - * kIOCDAudioControlClass is the name of the IOCDAudioControl class. - */ - -#define kIOCDAudioControlClass "IOCDAudioControl" - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOCDBlockStorageDriver.h> - -/*! - * @class IOCDAudioControl - * @discussion - * This class is the protocol for CD audio control functionality, independent of - * the physical connection protocol (eg. SCSI, ATA, USB). Any methods that deal - * with audio play and/or volume are here. - */ - -class IOCDAudioControl : public IOService -{ - OSDeclareDefaultStructors(IOCDAudioControl) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - /* - * Create a new IOCDAudioControlUserClient. - */ - - virtual IOReturn newUserClient( task_t task, - void * security, - UInt32 type, - IOUserClient ** object ); - -public: - - /*! - * @function getStatus - * @abstract - * Get the current audio play status information. - * @param status - * The buffer for the returned information. - */ - - virtual IOReturn getStatus(CDAudioStatus * status); - - /*! - * @function getTOC - * @abstract - * Get the full Table Of Contents. - * @result - * Returns a pointer to the TOC buffer (do not deallocate). - */ - - virtual CDTOC * getTOC(void); - - /*! - * @function getVolume - * @abstract - * Get the current audio volume. - * @param left - * A pointer to the returned left-channel volume. - * @param right - * A pointer to the returned right-channel volume. - */ - - virtual IOReturn getVolume(UInt8 * left, UInt8 * right); - - /*! - * @function setVolume - * @abstract - * Set the current audio volume. - * @param left - * The desired left-channel volume. - * @param right - * The desired right-channel volume. - */ - - virtual IOReturn setVolume(UInt8 left, UInt8 right); - - /*! - * @function pause - * @abstract - * Pause or resume the audio playback. - * @param pause - * True to pause playback; False to resume. - */ - - virtual IOReturn pause(bool pause); - - /*! - * @function play - * @abstract - * Play audio. - * @param timeStart - * The M:S:F address from which to begin. - * @param timeStop - * The M:S:F address at which to stop. - */ - - virtual IOReturn play(CDMSF timeStart, CDMSF timeStop); - - /*! - * @function scan - * @abstract - * Perform a fast-forward or fast-backward operation. - * @param timeStart - * The M:S:F address from which to begin. - * @param reverse - * True to go backward; False to go forward. - */ - - virtual IOReturn scan(CDMSF timeStart, bool reverse); - - /*! - * @function stop - * @abstract - * Stop the audio playback (or audio scan). - */ - - virtual IOReturn stop(); - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IOCDBlockStorageDriver. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IOCDBlockStorageDriver * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 0); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 1); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 2); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 3); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 4); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 5); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 6); - OSMetaClassDeclareReservedUnused(IOCDAudioControl, 7); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOCDAUDIOCONTROL_H */ diff --git a/iokit/IOKit/storage/IOCDAudioControlUserClient.h b/iokit/IOKit/storage/IOCDAudioControlUserClient.h deleted file mode 100644 index f6b4c688b..000000000 --- a/iokit/IOKit/storage/IOCDAudioControlUserClient.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOCDAUDIOCONTROLUSERCLIENT_H -#define _IOCDAUDIOCONTROLUSERCLIENT_H - -#include <IOKit/storage/IOCDTypes.h> - -/* - * Audio Control User Client Methods - */ - -enum -{ - kIOCDAudioControlMethodGetStatus, // IOCDAudioControlUserClient::getStatus() - kIOCDAudioControlMethodGetTOC, // IOCDAudioControlUserClient::getTOC() - kIOCDAudioControlMethodGetVolume, // IOCDAudioControlUserClient::getVolume() - kIOCDAudioControlMethodSetVolume, // IOCDAudioControlUserClient::setVolume() - kIOCDAudioControlMethodPause, // IOCDAudioControlUserClient::pause() - kIOCDAudioControlMethodPlay, // IOCDAudioControlUserClient::play() - kIOCDAudioControlMethodScan, // IOCDAudioControlUserClient::scan() - kIOCDAudioControlMethodStop, // IOCDAudioControlUserClient::stop() - kIOCDAudioControlMethodCount // (total number of methods supported) -}; - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/IOUserClient.h> -#include <IOKit/storage/IOCDAudioControl.h> - -class IOCDAudioControlUserClient : public IOUserClient -{ - OSDeclareDefaultStructors(IOCDAudioControlUserClient) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - IOExternalMethod _methods[kIOCDAudioControlMethodCount]; - - /* - * Get the current audio play status information. - */ - - virtual IOReturn getStatus(CDAudioStatus * status, UInt32 * statusSize); - - /* - * Get the full Table Of Contents. - */ - - virtual IOReturn getTOC(CDTOC * toc, UInt32 * tocMaxSize); - - /* - * Get the current audio volume. - */ - - virtual IOReturn getVolume(UInt32 * left, UInt32 * right); - - /* - * Set the current audio volume. - */ - - virtual IOReturn setVolume(UInt32 left, UInt32 right); - - /* - * Pause or resume the audio playback. - */ - - virtual IOReturn pause(UInt32 pause); - - /* - * Play audio. - */ - - virtual IOReturn play(UInt32 msfStart, UInt32 msfStop); - - /* - * Perform a fast-forward or fast-backward operation. - */ - - virtual IOReturn scan(UInt32 msfStart, UInt32 reverse); - - /* - * Stop the audio playback (or audio scan). - */ - - virtual IOReturn stop(); - -public: - - /* - * Create a new IOCDAudioControlUserClient. - */ - - static IOCDAudioControlUserClient * withTask(task_t task); - - /* - * Prepare the user client for usage. - */ - - virtual bool start(IOService * provider); - - /* - * Relinquish the user client. - */ - - virtual IOReturn clientClose(); - - /* - * Obtain the method definition given a method index. - */ - - virtual IOExternalMethod * getExternalMethodForIndex(UInt32 index); - - /* - * Obtain this object's provider. We override the superclass's method - * to return a more specific subclass of IOService -- IOCDAudioControl. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IOCDAudioControl * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 0); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 1); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 2); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 3); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 4); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 5); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 6); - OSMetaClassDeclareReservedUnused(IOCDAudioControlUserClient, 7); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* _IOCDAUDIOCONTROLUSERCLIENT_H */ diff --git a/iokit/IOKit/storage/IOCDBlockStorageDevice.h b/iokit/IOKit/storage/IOCDBlockStorageDevice.h deleted file mode 100644 index cb2d31273..000000000 --- a/iokit/IOKit/storage/IOCDBlockStorageDevice.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOCDBlockStorageDevice.h - * - * This class is the protocol for generic CDROM functionality, independent of - * the physical connection protocol (e.g. SCSI, ATA, USB). - * - * The APIs are the union of CDROM (block storage) data APIs and all - * necessary low-level CD APIs. - * - * A subclass implements relay methods that translate our requests into - * calls to a protocol- and device-specific provider. - */ - -#ifndef _IOCDBLOCKSTORAGEDEVICE_H -#define _IOCDBLOCKSTORAGEDEVICE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDTypes.h> -#include <IOKit/storage/IOBlockStorageDevice.h> - -/* Property used for matching, so the generic driver gets the nub it wants. */ -#define kIOBlockStorageDeviceTypeCDROM "CDROM" - -class IOMemoryDescriptor; - -class IOCDBlockStorageDevice : public IOBlockStorageDevice { - - OSDeclareAbstractStructors(IOCDBlockStorageDevice) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - - /* Overrides from IORegistryEntry */ - - virtual bool init(OSDictionary * properties); - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion) = 0; - virtual UInt32 getMediaType(void) = 0; - virtual IOReturn readISRC(UInt8 track,CDISRC isrc) = 0; - virtual IOReturn readMCN(CDMCN mcn) = 0; - virtual IOReturn readTOC(IOMemoryDescriptor * buffer) = 0; - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - virtual IOReturn audioPause(bool pause) = 0; - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop) = 0; - virtual IOReturn audioScan(CDMSF timeStart,bool reverse) = 0; - virtual IOReturn audioStop() = 0; - virtual IOReturn getAudioStatus(CDAudioStatus *status) = 0; - virtual IOReturn getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) = 0; - virtual IOReturn setAudioVolume(UInt8 leftVolume,UInt8 rightVolume) = 0; - - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 0); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 1); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 2); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 3); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 4); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 5); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 6); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 7); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 8); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 9); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 10); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 11); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 12); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 13); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 14); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDevice, 15); -}; -#endif diff --git a/iokit/IOKit/storage/IOCDBlockStorageDriver.h b/iokit/IOKit/storage/IOCDBlockStorageDriver.h deleted file mode 100644 index de98e7489..000000000 --- a/iokit/IOKit/storage/IOCDBlockStorageDriver.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOCDBlockStorageDriver.h - * - * This class implements CD functionality, independent of - * the physical connection protocol (e.g. SCSI, ATA, USB). - * - * A protocol-specific provider implements the functionality using an appropriate - * protocol and commands. - */ - -#ifndef _IOCDBLOCKSTORAGEDRIVER_H -#define _IOCDBLOCKSTORAGEDRIVER_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDBlockStorageDevice.h> -#include <IOKit/storage/IOCDTypes.h> -#include <IOKit/storage/IOBlockStorageDriver.h> - -/*! - * @defined kIOCDBlockStorageDriverClass - * @abstract - * kIOCDBlockStorageDriverClass is the name of the IOCDBlockStorageDriver class. - * @discussion - * kIOCDBlockStorageDriverClass is the name of the IOCDBlockStorageDriver class. - */ - -#define kIOCDBlockStorageDriverClass "IOCDBlockStorageDriver" - -class IOCDAudioControl; -class IOCDMedia; -class IOCDBlockStorageDevice; - -class IOCDBlockStorageDriver : public IOBlockStorageDriver { - - OSDeclareDefaultStructors(IOCDBlockStorageDriver) - -public: - - static const UInt64 kBlockSizeCD = 2352; - static const UInt8 kBlockTypeCD = 0x01; - - /* Overrides of IORegistryEntry */ - - virtual bool init(OSDictionary * properties); - - /* Overrides of IOBlockStorageDriver: */ - - virtual IOReturn ejectMedia(void); - virtual void executeRequest(UInt64 byteStart, - IOMemoryDescriptor *buffer, - IOStorageCompletion completion, - Context *context); - virtual const char * getDeviceTypeName(void); - virtual IOMedia * instantiateDesiredMediaObject(void); - virtual IOMedia * instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName); - - /* End of IOBlockStorageDriver overrides. */ - - /* - * @function getMediaType - * @abstract - * Get the current type of media inserted in the CD drive. - * @discussion - * Certain I/O operations may not be allowed depending on the type of - * media currently inserted. For example, one cannot issue write operations - * if CD-ROM media is inserted. - * @result - * See the kCDMediaType constants in IOCDTypes.h. - */ - virtual UInt32 getMediaType(void); - - /* -------------------------------------------------*/ - /* APIs implemented here, exported by IOCDMedia: */ - /* -------------------------------------------------*/ - - virtual CDTOC * getTOC(void); - virtual void readCD(IOService *client, - UInt64 byteStart, - IOMemoryDescriptor *buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - virtual IOReturn readISRC(UInt8 track,CDISRC isrc); - virtual IOReturn readMCN(CDMCN mcn); - - /* end of IOCDMedia APIs */ - - /* --------------------------------------------------------*/ - /* APIs implemented here, exported by IOCDAudioControl: */ - /* --------------------------------------------------------*/ - - virtual IOReturn audioPause(bool pause); - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop); - virtual IOReturn audioScan(CDMSF timeStart,bool reverse); - virtual IOReturn audioStop(); - virtual IOReturn getAudioStatus(CDAudioStatus *status); - virtual IOReturn getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume); - virtual IOReturn setAudioVolume(UInt8 leftVolume,UInt8 rightVolume); - - /* end of IOCDAudioControl APIs */ - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IOCDBlockStorageDevice. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IOCDBlockStorageDevice * getProvider() const; - -protected: - - /* Overrides of IOBlockStorageDriver behavior. */ - - /* When CD media is inserted, we want to create multiple nubs for the data and - * audio tracks, for sessions, and the entire media. We override the methods - * that manage nubs. - */ - virtual IOReturn acceptNewMedia(void); - virtual IOReturn decommissionMedia(bool forcible); - - /* End of IOBlockStorageDriver overrides. */ - - /* Internally used methods: */ - - virtual IOReturn cacheTocInfo(void); - virtual UInt64 getMediaBlockSize(CDSectorArea area,CDSectorType type); - virtual void prepareRequest(UInt64 byteStart, - IOMemoryDescriptor *buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - - /* ------- */ - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - IOCDAudioControl * _acNub; - - /* We keep the TOC here because we'll always need it, so what the heck. - * - * There are possible "point" track entries for 0xa0..a2, 0xb0..b4, and 0xc0..0xc1. - * Tracks need not start at 1, as long as they're between 1 and 99, and have contiguous - * numbers. - */ - - CDTOC * _toc; - UInt32 _tocSize; - - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 0); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 1); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 2); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 3); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 4); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 5); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 6); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 7); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 8); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 9); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 10); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 11); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 12); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 13); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 14); - OSMetaClassDeclareReservedUnused(IOCDBlockStorageDriver, 15); -}; -#endif diff --git a/iokit/IOKit/storage/IOCDMedia.h b/iokit/IOKit/storage/IOCDMedia.h deleted file mode 100644 index 05315c9fb..000000000 --- a/iokit/IOKit/storage/IOCDMedia.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOCDMedia - * @abstract - * This header contains the IOCDMedia class definition. - */ - -#ifndef _IOCDMEDIA_H -#define _IOCDMEDIA_H - -/*! - * @defined kIOCDMediaClass - * @abstract - * kIOCDMediaClass is the name of the IOCDMedia class. - * @discussion - * kIOCDMediaClass is the name of the IOCDMedia class. - */ - -#define kIOCDMediaClass "IOCDMedia" - -/*! - * @defined kIOCDMediaTOCKey - * @abstract - * kIOCDMediaTOCKey is a property of IOCDMedia objects. It has an OSData value - * and a CDTOC structure. - * @discussion - * The kIOCDMediaTOCKey property contains the CD's full table of contents, - * formatted as a CDTOC structure. The CDTOC structure is same as what is - * returned by a READ TOC command, format 0x02, but with BCD numbers converted - * to binary-encoded numbers, and the multi-byte fields converted to - * host-endianess. - */ - -#define kIOCDMediaTOCKey "TOC" -#define kIOCDMediaTOC "TOC" ///d:deprecated - -/*! - * @defined kIOCDMediaTypeKey - * @abstract - * kIOCDMediaTypeKey is a property of IOCDMedia objects. It has an OSString - * value. - * @discussion - * The kIOCDMediaTypeKey property identifies the CD media type (CD-ROM, CD-R, - * CD-RW, etc). See the kIOCDMediaType contants for possible values. - */ - -#define kIOCDMediaTypeKey "Type" - -/*! - * @defined kIOCDMediaTypeROM - * The kIOCDMediaTypeKey constant for CD-ROM media (inclusive of the CD-I, - * CD-ROM XA, and CD Audio standards, and mixed mode combinations thereof). - */ - -#define kIOCDMediaTypeROM "CD-ROM" - -/*! - * @defined kIOCDMediaTypeR - * The kIOCDMediaTypeKey constant for CD Recordable (CD-R) media. - */ - -#define kIOCDMediaTypeR "CD-R" - -/*! - * @defined kIOCDMediaTypeRW - * The kIOCDMediaTypeKey constant for CD ReWritable (CD-RW) media. - */ - -#define kIOCDMediaTypeRW "CD-RW" - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOCDBlockStorageDriver.h> -#include <IOKit/storage/IOMedia.h> - -/*! - * @class IOCDMedia - * @abstract - * The IOCDMedia class is a random-access disk device abstraction for CDs. - * @discussion - * The IOCDMedia class is a random-access disk device abstraction for CDs. It - * extends the IOMedia class by implementing special CD APIs, such as readCD, - * and publishing the TOC as a property of the IOCDMedia object. - */ - -class IOCDMedia : public IOMedia -{ - OSDeclareDefaultStructors(IOCDMedia) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - -///m:2333367:workaround:commented:start -// using read; -///m:2333367:workaround:commented:stop - - /*! - * @function read - * @discussion - * Read data from the storage object at the specified byte offset into the - * specified buffer, asynchronously. When the read completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the read. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /*! - * @function readCD - * @discussion - * Read data from the CD media object at the specified byte offset into the - * specified buffer, asynchronously. Special areas of the CD sector can be - * read via this method, such as the header and subchannel data. When the - * read completes, the caller will be notified via the specified completion - * action. - * - * The buffer will be retained for the duration of the read. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer (see withAreas parameter). - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param sectorArea - * Sector area(s) to read. The sum of each area's size defines the "natural - * block size" of the media for the call, which should be taken into account - * when computing the address of byteStart. See IOCDTypes.h. - * @param sectorType - * Sector type that is expected. The data transfer is terminated as soon as - * data is encountered that does not match the expected type. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void readCD(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - - /*! - * @function readCD - * @discussion - * Read data from the CD media object at the specified byte offset into the - * specified buffer, synchronously. Special areas of the CD sector can be - * read via this method, such as the header and subchannel data. When the - * read completes, this method will return to the caller. The actual byte - * count field is optional. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param sectorArea - * Sector area(s) to read. The sum of each area's size defines the "natural - * block size" of the media for the call, which should be taken into account - * when computing the address of byteStart. See IOCDTypes.h. - * @param sectorType - * Sector type that is expected. The data transfer is terminated as soon as - * data is encountered that does not match the expected type. - * @param actualByteCount - * Returns the actual number of bytes transferred in the data transfer. - * @result - * Returns the status of the data transfer. - */ - - virtual IOReturn readCD(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - CDSectorArea sectorArea, - CDSectorType sectorType, - UInt64 * actualByteCount = 0); - - /*! - * @function readISRC - * @abstract - * Read the International Standard Recording Code for the specified track. - * @param track - * The track number from which to read the ISRC. - * @param isrc - * The buffer for the ISRC data. Buffer contents will be zero-terminated. - */ - - virtual IOReturn readISRC(UInt8 track, CDISRC isrc); - - /*! - * @function readMCN - * @abstract - * Read the Media Catalog Number (also known as the Universal Product Code). - * @param mcn - * The buffer for the MCN data. Buffer contents will be zero-terminated. - */ - - virtual IOReturn readMCN(CDMCN mcn); - - /* - * @function getTOC - * @discussion - * Get the full Table Of Contents. - * - * All CDTOC fields passed across I/O Kit APIs are guaranteed to be - * binary-encoded numbers (not BCD) and converted to host-endianess. - * @result - * Returns a pointer to the TOC buffer (do not deallocate). - */ - - virtual CDTOC * getTOC(); - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IOCDBlockStorageDriver. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IOCDBlockStorageDriver * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOCDMedia, 0); - OSMetaClassDeclareReservedUnused(IOCDMedia, 1); - OSMetaClassDeclareReservedUnused(IOCDMedia, 2); - OSMetaClassDeclareReservedUnused(IOCDMedia, 3); - OSMetaClassDeclareReservedUnused(IOCDMedia, 4); - OSMetaClassDeclareReservedUnused(IOCDMedia, 5); - OSMetaClassDeclareReservedUnused(IOCDMedia, 6); - OSMetaClassDeclareReservedUnused(IOCDMedia, 7); - OSMetaClassDeclareReservedUnused(IOCDMedia, 8); - OSMetaClassDeclareReservedUnused(IOCDMedia, 9); - OSMetaClassDeclareReservedUnused(IOCDMedia, 10); - OSMetaClassDeclareReservedUnused(IOCDMedia, 11); - OSMetaClassDeclareReservedUnused(IOCDMedia, 12); - OSMetaClassDeclareReservedUnused(IOCDMedia, 13); - OSMetaClassDeclareReservedUnused(IOCDMedia, 14); - OSMetaClassDeclareReservedUnused(IOCDMedia, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOCDMEDIA_H */ diff --git a/iokit/IOKit/storage/IOCDPartitionScheme.h b/iokit/IOKit/storage/IOCDPartitionScheme.h deleted file mode 100644 index 4161d157c..000000000 --- a/iokit/IOKit/storage/IOCDPartitionScheme.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOCDPartitionScheme - * @abstract - * This header contains the IOCDPartitionScheme class definition. - */ - -#ifndef _IOCDPARTITIONSCHEME_H -#define _IOCDPARTITIONSCHEME_H - -#include <IOKit/storage/IOCDTypes.h> - -/*! - * @defined kIOMediaSessionIDKey - * @abstract - * kIOMediaSessionIDKey is property of IOMedia objects. It has an OSNumber - * value. - * @discussion - * The kIOMediaSessionIDKey property is placed into each IOMedia instance - * created by the CD partition scheme. It identifies the session number - * the track was recorded on. - */ - -#define kIOMediaSessionIDKey "Session ID" - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOCDMedia.h> -#include <IOKit/storage/IOPartitionScheme.h> - -/* - * Class - */ - -class IOCDPartitionScheme : public IOPartitionScheme -{ - OSDeclareDefaultStructors(IOCDPartitionScheme); - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - OSSet * _partitions; /* (set of media objects representing partitions) */ - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(void); - - /* - * Scan the provider media for CD partitions (in TOC). Returns the set - * of media objects representing each of the partitions (the retain for - * the set is passed to the caller), or null should no CD partitions be - * found. The default probe score can be adjusted up or down, based on - * the confidence of the scan. - */ - - virtual OSSet * scan(SInt32 * score); - - /* - * Ask whether the given partition appears to be corrupt. A partition that - * is corrupt will cause the failure of the CD partition scheme altogether. - */ - - virtual bool isPartitionCorrupt( CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ); - - /* - * Ask whether the given partition appears to be invalid. A partition that - * is invalid will cause it to be skipped in the scan, but will not cause a - * failure of the CD partition scheme. - */ - - virtual bool isPartitionInvalid( CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ); - - /* - * Instantiate a new media object to represent the given partition. - */ - - virtual IOMedia * instantiateMediaObject( - CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ); - - /* - * Allocate a new media object (called from instantiateMediaObject). - */ - - virtual IOMedia * instantiateDesiredMediaObject( - CDTOCDescriptor * partition, - UInt64 partitionSize, - UInt32 partitionBlockSize, - CDSectorType partitionBlockType, - CDTOC * toc ); - -public: - - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * Scan the provider media for CD partitions. - */ - - virtual IOService * probe(IOService * provider, SInt32 * score); - - /* - * Determine whether the provider media contains CD partitions. - */ - - virtual bool start(IOService * provider); - - /* - * Read data from the storage object at the specified byte offset into the - * specified buffer, asynchronously. When the read completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the read. - * - * For the CD partition scheme, we convert the read from a partition - * object into the appropriate readCD command to our provider media. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /* - * Obtain this object's provider. We override the superclass's method - * to return a more specific subclass of OSObject -- IOCDMedia. This - * method serves simply as a convenience to subclass developers. - */ - - virtual IOCDMedia * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 0); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 1); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 2); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 3); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 4); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 5); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 6); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 7); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 8); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 9); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 10); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 11); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 12); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 13); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 14); - OSMetaClassDeclareReservedUnused(IOCDPartitionScheme, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOCDPARTITIONSCHEME_H */ diff --git a/iokit/IOKit/storage/IOCDTypes.h b/iokit/IOKit/storage/IOCDTypes.h deleted file mode 100644 index 92b5bd456..000000000 --- a/iokit/IOKit/storage/IOCDTypes.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOCDTYPES_H -#define _IOCDTYPES_H - -#include <IOKit/IOTypes.h> - -/* - * Minutes, Seconds, Frames (M:S:F) - * - * All M:S:F values passed across I/O Kit APIs are guaranteed to be - * binary-encoded numbers (no BCD-encoded numbers are ever passed). - */ - -typedef struct -{ - UInt8 minute; - UInt8 second; - UInt8 frame; -} CDMSF; - -/* - * Media Catalogue Numbers (MCN), International Standard Recording Codes (ISRC) - * - * All MCN and ISRC values passed across I/O Kit APIs are guaranteed - * to have a zero-terminating byte, for convenient use as C strings. - */ - -#define kCDMCNMaxLength 13 -#define kCDISRCMaxLength 12 - -typedef char CDMCN [kCDMCNMaxLength + 1]; -typedef char CDISRC[kCDISRCMaxLength + 1]; - -/* - * Audio Status - * - * All CDAudioStatus fields passed across I/O Kit APIs are guaranteed to - * be binary-encoded numbers (no BCD-encoded numbers are ever passed). - */ - -#define kCDAudioStatusUnsupported 0x00 -#define kCDAudioStatusActive 0x11 -#define kCDAudioStatusPaused 0x12 -#define kCDAudioStatusSuccess 0x13 -#define kCDAudioStatusFailure 0x14 -#define kCDAudioStatusNone 0x15 - -typedef struct -{ - UInt8 status; - struct - { - CDMSF time; - struct { - UInt8 index; - UInt8 number; - CDMSF time; - } track; - } position; -} CDAudioStatus; - -/* - * Table Of Contents - * - * All CDTOC fields passed across I/O Kit APIs are guaranteed to be - * binary-encoded numbers (not BCD) and converted to host-endianess. - */ - -typedef struct -{ - UInt8 session; -#if defined(__LITTLE_ENDIAN__) - UInt8 control:4, adr:4; -#else /* !defined(__LITTLE_ENDIAN__) */ - UInt8 adr:4, control:4; -#endif /* !defined(__LITTLE_ENDIAN__) */ - UInt8 tno; - UInt8 point; - CDMSF address; - UInt8 zero; - CDMSF p; -} CDTOCDescriptor; - -typedef struct -{ - UInt16 length; - UInt8 sessionFirst; - UInt8 sessionLast; - CDTOCDescriptor descriptors[0]; -} CDTOC; - -/* - * M:S:F To LBA Convenience Function - */ - -static UInt32 __inline CDConvertMSFToLBA(CDMSF msf) -{ - return (((msf.minute * 60UL) + msf.second) * 75UL) + msf.frame - 150; -} - -/* - * LBA To M:S:F Convenience Function - */ - -static CDMSF __inline CDConvertLBAToMSF(UInt32 lba) -{ - CDMSF msf; - - lba += 150; - msf.minute = (lba / (75 * 60)); - msf.second = (lba % (75 * 60)) / 75; - msf.frame = (lba % (75 )); - - return msf; -} - -/* - * Track Number To M:S:F Convenience Function - * - * The CDTOC structure is assumed to be complete, that is, none of - * the descriptors are missing or clipped due to an insufficiently - * sized buffer holding the CDTOC contents. - */ - -static CDMSF __inline CDConvertTrackNumberToMSF(UInt8 track, CDTOC * toc) -{ - UInt32 count = (toc->length - sizeof(UInt16)) / sizeof(CDTOCDescriptor); - UInt32 i; - CDMSF msf = { 0xFF, 0xFF, 0xFF }; - - for (i = 0; i < count; i++) - { - if (toc->descriptors[i].point == track && toc->descriptors[i].adr == 1) - { - msf = toc->descriptors[i].p; - break; - } - } - - return msf; -} - -/* - * Sector Areas, Sector Types - * - * Bytes Per Type CDDA Mode1 Mode2 Mode2Form1 Mode2Form2 - * Per Area +----------+----------+----------+----------+----------+ - * Sync | 0 | 12 | 12 | 12 | 12 | - * Header | 0 | 4 | 4 | 4 | 4 | - * SubHeader | 0 | 0 | 0 | 8 | 8 | - * User | 2352 | 2048 | 2336 | 2048 | 2328 | - * Auxiliary | 0 | 288 | 0 | 280 | 0 | - * ErrorFlags | 294 | 294 | 294 | 294 | 294 | - * SubChannel | 96 | 96 | 96 | 96 | 96 | - * +----------+----------+----------+----------+----------+ - */ - -typedef enum -{ - kCDSectorAreaSync = 0x80, - kCDSectorAreaHeader = 0x20, - kCDSectorAreaSubHeader = 0x40, - kCDSectorAreaUser = 0x10, - kCDSectorAreaAuxiliary = 0x08, - kCDSectorAreaErrorFlags = 0x02, - kCDSectorAreaSubChannel = 0x01 -} CDSectorArea; - -typedef enum -{ - kCDSectorTypeUnknown = 0x00, - kCDSectorTypeCDDA = 0x01, - kCDSectorTypeMode1 = 0x02, - kCDSectorTypeMode2 = 0x03, - kCDSectorTypeMode2Form1 = 0x04, - kCDSectorTypeMode2Form2 = 0x05, - kCDSectorTypeCount = 0x06 -} CDSectorType; - -typedef enum -{ - kCDSectorSizeCDDA = 2352, - kCDSectorSizeMode1 = 2048, - kCDSectorSizeMode2 = 2336, - kCDSectorSizeMode2Form1 = 2048, - kCDSectorSizeMode2Form2 = 2328, - kCDSectorSizeWhole = 2352 -} CDSectorSize; - -/* - * Media Types - */ - -typedef enum -{ - kCDMediaTypeUnknown = 0x0100, - kCDMediaTypeROM = 0x0102, /* CD-ROM */ - kCDMediaTypeR = 0x0104, /* CD-R */ - kCDMediaTypeRW = 0x0105, /* CD-RW */ - - kCDMediaTypeMin = 0x0100, - kCDMediaTypeMax = 0x01FF -} CDMediaType; - -#endif /* _IOCDTYPES_H */ diff --git a/iokit/IOKit/storage/IODVDBlockStorageDevice.h b/iokit/IOKit/storage/IODVDBlockStorageDevice.h deleted file mode 100644 index 9f51aed87..000000000 --- a/iokit/IOKit/storage/IODVDBlockStorageDevice.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - /* This class is the protocol for generic DVD functionality, independent of - * the physical connection protocol (e.g. SCSI, ATA, USB). - * - * The APIs are the union of CDRO APIs and all - * necessary new low-level DVD APIs. - * - * A subclass implements relay methods that translate our requests into - * calls to a protocol- and device-specific provider. - */ - -#ifndef _IODVDBLOCKSTORAGEDEVICE_H -#define _IODVDBLOCKSTORAGEDEVICE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDBlockStorageDevice.h> -#include <IOKit/storage/IODVDTypes.h> - -/* Property used for matching, so the generic driver gets the nub it wants. */ -#define kIOBlockStorageDeviceTypeDVD "DVD" - -class IOMemoryDescriptor; - -class IODVDBlockStorageDevice : public IOCDBlockStorageDevice { - - OSDeclareAbstractStructors(IODVDBlockStorageDevice) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - - /* Overrides from IORegistryEntry */ - - virtual bool init(OSDictionary * properties); - - /* New APIs for DVD */ - - virtual IOReturn reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat) = 0; - virtual IOReturn sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat) = 0; - - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 0); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 1); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 2); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 3); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 4); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 5); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 6); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 7); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 8); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 9); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 10); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 11); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 12); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 13); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 14); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 15); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 16); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 17); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 18); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 19); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 20); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 21); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 22); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 23); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 24); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 25); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 26); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 27); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 28); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 29); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 30); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDevice, 31); -}; -#endif diff --git a/iokit/IOKit/storage/IODVDBlockStorageDriver.h b/iokit/IOKit/storage/IODVDBlockStorageDriver.h deleted file mode 100644 index d1cb02bc7..000000000 --- a/iokit/IOKit/storage/IODVDBlockStorageDriver.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IODVDBlockStorageDriver.h - * - * This class implements DVD functionality, independent of - * the physical connection protocol (e.g. SCSI, ATA, USB). - * - * A protocol-specific provider implements the functionality using an appropriate - * protocol and commands. - */ - -#ifndef _IODVDBLOCKSTORAGEDRIVER_H -#define _IODVDBLOCKSTORAGEDRIVER_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDBlockStorageDriver.h> -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/IODVDTypes.h> - -/*! - * @defined kIODVDBlockStorageDriverClass - * @abstract - * kIODVDBlockStorageDriverClass is the name of the IODVDBlockStorageDriver class. - * @discussion - * kIODVDBlockStorageDriverClass is the name of the IODVDBlockStorageDriver class. - */ - -#define kIODVDBlockStorageDriverClass "IODVDBlockStorageDriver" - -class IODVDBlockStorageDevice; - -/*! - * @class - * IODVDBlockStorageDriver : public IOCDBlockStorageDriver - * @abstract - * Generic DVD Driver. - * @discussion - * Storage drivers are split into two parts: the Generic Driver handles - * all generic device issues, independent of the lower-level transport - * mechanism (e.g. SCSI, ATA, USB, FireWire). All storage operations - * at the Generic Driver level are translated into a series of generic - * device operations. These operations are passed via the Device Nub - * to a Transport Driver, which implements the appropriate - * transport-dependent protocol to execute these operations. - * - * To determine the write-protect state of a device (or media), for - * example, the generic driver would issue a call to the - * Transport Driver's reportWriteProtection method. If this were a SCSI - * device, its Transport Driver would issue a Mode Sense command to - * extract the write-protection status bit. The Transport Driver then - * reports true or false to the generic driver. - * - * The generic driver therefore has no knowledge of, or involvement - * with, the actual commands and mechanisms used to communicate with - * the device. It is expected that the generic driver will rarely, if - * ever, need to be subclassed to handle device idiosyncrasies; rather, - * the Transport Driver should be changed via overrides. - * - * A generic driver could be subclassed to create a different type of - * generic device. The generic driver IODVDBlockStorageDriver class is a subclass - * of IOCDBlockStorageDriver, adding DVD functions. Similarly, the Transport Driver - * IODVDBlockStorageDevice is a subclass of IOCDBlockStorageDevice, adding DVD - * functions. -*/ - -class IODVDBlockStorageDriver : public IOCDBlockStorageDriver { - - OSDeclareDefaultStructors(IODVDBlockStorageDriver) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - - /* Overrides of IOCDBlockStorageDriver: */ - - virtual const char * getDeviceTypeName(void); - virtual IOMedia * instantiateDesiredMediaObject(void); - virtual IOMedia * instantiateMediaObject(UInt64 base,UInt64 byteSize, - UInt32 blockSize,char *mediaName); - - /* End of IOCDBlockStorageDriver overrides. */ - - /*! - * @function reportKey - * @abstract - * Get key info from the DVD drive. - * @discussion - * This function handles the getting of key- and encryption-related data for the drive. - * @param buffer - * A buffer containing information, as documented in the specification - * "MtFuji Commands For Multimedia Devices." - * @param keyClass - * As documented by MtFuji. See DVDKeyClass. - * @param agid - * An AGID, as documented by MtFuji. - * @param keyFormat - * As documented by MtFuji. See DVDKeyFormat. - */ - virtual IOReturn reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat); - - /*! - * @function sendKey - * @abstract - * Send key info to the DVD drive. - * @discussion - * This function handles the setting of key- and encryption-related data for the drive. - * @param buffer - * A buffer containing information, as documented in the specification - * "MtFuji Commands For Multimedia Devices." - * @param keyClass - * As documented by MtFuji. See DVDKeyClass. - * @param agid - * As documented by MtFuji. - * @param keyFormat - * As documented by MtFuji. See DVDKeyFormat. - */ - virtual IOReturn sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat); - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IODVDBlockStorageDevice. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IODVDBlockStorageDevice * getProvider() const; - -protected: - - /* Overrides of IOCDBlockStorageDriver behavior. */ - - virtual IOReturn acceptNewMedia(void); - - /* End of IOCDBlockStorageDriver overrides. */ - - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 0); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 1); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 2); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 3); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 4); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 5); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 6); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 7); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 8); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 9); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 10); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 11); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 12); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 13); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 14); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 15); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 16); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 17); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 18); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 19); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 20); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 21); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 22); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 23); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 24); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 25); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 26); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 27); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 28); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 29); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 30); - OSMetaClassDeclareReservedUnused(IODVDBlockStorageDriver, 31); -}; -#endif diff --git a/iokit/IOKit/storage/IODVDMedia.h b/iokit/IOKit/storage/IODVDMedia.h deleted file mode 100644 index 24472829e..000000000 --- a/iokit/IOKit/storage/IODVDMedia.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IODVDMedia - * @abstract - * This header contains the IODVDMedia class definition. - */ - -#ifndef _IODVDMEDIA_H -#define _IODVDMEDIA_H - -/*! - * @defined kIODVDMediaClass - * @abstract - * kIODVDMediaClass is the name of the IODVDMedia class. - * @discussion - * kIODVDMediaClass is the name of the IODVDMedia class. - */ - -#define kIODVDMediaClass "IODVDMedia" - -/*! - * @defined kIODVDMediaTypeKey - * @abstract - * kIODVDMediaTypeKey is a property of IODVDMedia objects. It has an OSString - * value. - * @discussion - * The kIODVDMediaTypeKey property identifies the DVD media type (DVD-ROM, - * DVD-R, DVD-RW, DVD+RW, DVD-RAM, etc). See the kIODVDMediaType contants - * for possible values. - */ - -#define kIODVDMediaTypeKey "Type" - -/*! - * @defined kIODVDMediaTypeROM - * The kIODVDMediaTypeKey constant for DVD-ROM media. - */ - -#define kIODVDMediaTypeROM "DVD-ROM" - -/*! - * @defined kIODVDMediaTypeR - * The kIODVDMediaTypeKey constant for DVD Recordable (DVD-R) media. - */ - -#define kIODVDMediaTypeR "DVD-R" - -/*! - * @defined kIODVDMediaTypeRW - * The kIODVDMediaTypeKey constant for DVD ReWritable (DVD-RW) media. - */ - -#define kIODVDMediaTypeRW "DVD-RW" - -/*! - * @defined kIODVDMediaTypePlusRW - * The kIODVDMediaTypeKey constant for DVD "Plus" ReWritable (DVD+RW) media. - */ - -#define kIODVDMediaTypePlusRW "DVD+RW" - -/*! - * @defined kIODVDMediaTypeRAM - * The kIODVDMediaTypeKey constant for DVD-RAM media. - */ - -#define kIODVDMediaTypeRAM "DVD-RAM" - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IODVDBlockStorageDriver.h> -#include <IOKit/storage/IOMedia.h> - -/*! - * @class IODVDMedia - * @abstract - * The IODVDMedia class is a random-access disk device abstraction for DVDs. - * @discussion - * The IODVDMedia class is a random-access disk device abstraction for DVDs. - */ - -class IODVDMedia : public IOMedia -{ - OSDeclareDefaultStructors(IODVDMedia) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - -public: - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of IOService -- IODVDBlockStorageDriver. - * This method serves simply as a convenience to subclass developers. - */ - - virtual IODVDBlockStorageDriver * getProvider() const; - - OSMetaClassDeclareReservedUnused(IODVDMedia, 0); - OSMetaClassDeclareReservedUnused(IODVDMedia, 1); - OSMetaClassDeclareReservedUnused(IODVDMedia, 2); - OSMetaClassDeclareReservedUnused(IODVDMedia, 3); - OSMetaClassDeclareReservedUnused(IODVDMedia, 4); - OSMetaClassDeclareReservedUnused(IODVDMedia, 5); - OSMetaClassDeclareReservedUnused(IODVDMedia, 6); - OSMetaClassDeclareReservedUnused(IODVDMedia, 7); - OSMetaClassDeclareReservedUnused(IODVDMedia, 8); - OSMetaClassDeclareReservedUnused(IODVDMedia, 9); - OSMetaClassDeclareReservedUnused(IODVDMedia, 10); - OSMetaClassDeclareReservedUnused(IODVDMedia, 11); - OSMetaClassDeclareReservedUnused(IODVDMedia, 12); - OSMetaClassDeclareReservedUnused(IODVDMedia, 13); - OSMetaClassDeclareReservedUnused(IODVDMedia, 14); - OSMetaClassDeclareReservedUnused(IODVDMedia, 15); - OSMetaClassDeclareReservedUnused(IODVDMedia, 16); - OSMetaClassDeclareReservedUnused(IODVDMedia, 17); - OSMetaClassDeclareReservedUnused(IODVDMedia, 18); - OSMetaClassDeclareReservedUnused(IODVDMedia, 19); - OSMetaClassDeclareReservedUnused(IODVDMedia, 20); - OSMetaClassDeclareReservedUnused(IODVDMedia, 21); - OSMetaClassDeclareReservedUnused(IODVDMedia, 22); - OSMetaClassDeclareReservedUnused(IODVDMedia, 23); - OSMetaClassDeclareReservedUnused(IODVDMedia, 24); - OSMetaClassDeclareReservedUnused(IODVDMedia, 25); - OSMetaClassDeclareReservedUnused(IODVDMedia, 26); - OSMetaClassDeclareReservedUnused(IODVDMedia, 27); - OSMetaClassDeclareReservedUnused(IODVDMedia, 28); - OSMetaClassDeclareReservedUnused(IODVDMedia, 29); - OSMetaClassDeclareReservedUnused(IODVDMedia, 30); - OSMetaClassDeclareReservedUnused(IODVDMedia, 31); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IODVDMEDIA_H */ diff --git a/iokit/IOKit/storage/IODVDTypes.h b/iokit/IOKit/storage/IODVDTypes.h deleted file mode 100644 index 4b13111ea..000000000 --- a/iokit/IOKit/storage/IODVDTypes.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IODVDTYPES_H -#define _IODVDTYPES_H - -#include <IOKit/IOTypes.h> - - enum DVDKeyFormat { - kCSSAGID = 0x00, - kChallengeKey = 0x01, - kKey1 = 0x02, - kKey2 = 0x03, - kTitleKey = 0x04, - kASF = 0x05, - kSetRegion = 0x06, - kRPCState = 0x08, - kCSS2AGID = 0x10, - kCPRMAGID = 0x11, - kInvalidateAGID = 0x3f - }; - - enum DVDKeyClass { - kCSS_CSS2_CPRM = 0x00, - kRSSA = 0x01 - }; - - enum DVDMediaType { - kDVDMediaTypeUnknown = 0x0200, - kDVDMediaTypeROM = 0x0202, /* DVD-ROM */ - kDVDMediaTypeRAM = 0x0203, /* DVD-RAM */ - kDVDMediaTypeR = 0x0204, /* DVD-R */ - kDVDMediaTypeRW = 0x0205, /* DVD-RW */ - kDVDMediaTypePlusRW = 0x0206, /* DVD+RW */ - - kDVDMediaTypeMin = 0x0200, - kDVDMediaTypeMax = 0x02FF - }; - -#endif diff --git a/iokit/IOKit/storage/IOFDiskPartitionScheme.h b/iokit/IOKit/storage/IOFDiskPartitionScheme.h deleted file mode 100644 index b26ebdbd0..000000000 --- a/iokit/IOKit/storage/IOFDiskPartitionScheme.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOFDISKPARTITIONSCHEME_H -#define _IOFDISKPARTITIONSCHEME_H - -#include <IOKit/IOTypes.h> - -/* - * FDisk Partition Map Definitions - */ - -#pragma pack(2) /* (enable 16-bit struct packing for fdisk_part, disk_blk0) */ - -/* Structure constants. */ - -#define DISK_BLK0SZ sizeof(struct disk_blk0) /* (size of partition map) */ -#define DISK_BOOTSZ 446 /* (size of boot code in map) */ -#define DISK_NPART 4 /* (number of entries in map) */ - -/* Partition map entry. */ - -struct fdisk_part -{ - UInt8 bootid; /* (is active boot partition?) */ - UInt8 beghead; /* (beginning head) */ - UInt8 begsect; /* (beginning sector; beginning cylinder, high 2 bits) */ - UInt8 begcyl; /* (beginning cylinder, low 8 bits) */ - UInt8 systid; /* (type) */ - UInt8 endhead; /* (ending head) */ - UInt8 endsect; /* (ending sector; ending cylinder, high 2 bits) */ - UInt8 endcyl; /* (ending cylinder, low 8 bits) */ - UInt32 relsect; /* (block start) */ - UInt32 numsect; /* (block count) */ -}; - -/* Partition map, as found in block zero of the disk (or extended partition). */ - -struct disk_blk0 -{ - UInt8 bootcode[DISK_BOOTSZ]; /* (boot code) */ - struct fdisk_part parts[DISK_NPART]; /* (partition entries) */ - UInt16 signature; /* (unique signature for map) */ -}; - -/* Partition map signature (signature). */ - -#define DISK_SIGNATURE 0xAA55 - -/* Partition map entry types (systid). */ - -#define FDISK_PARTITION_TYPE_01 "DOS_FAT_12" -#define FDISK_PARTITION_TYPE_04 "DOS_FAT_16_S" -#define FDISK_PARTITION_TYPE_05 "DOS_Extended" -#define FDISK_PARTITION_TYPE_06 "DOS_FAT_16" -#define FDISK_PARTITION_TYPE_07 "Windows_NTFS" -#define FDISK_PARTITION_TYPE_0A "Boot_Manager" -#define FDISK_PARTITION_TYPE_0B "DOS_FAT_32" -#define FDISK_PARTITION_TYPE_0C "Windows_FAT_32" -#define FDISK_PARTITION_TYPE_0E "Windows_FAT_16" -#define FDISK_PARTITION_TYPE_0F "Windows_Extended" -#define FDISK_PARTITION_TYPE_11 "DOS_FAT_12_Hidden" -#define FDISK_PARTITION_TYPE_14 "DOS_FAT_16_S_Hidden" -#define FDISK_PARTITION_TYPE_16 "DOS_FAT_16_Hidden" -#define FDISK_PARTITION_TYPE_17 "Windows_NTFS_Hidden" -#define FDISK_PARTITION_TYPE_1B "DOS_FAT_32_Hidden" -#define FDISK_PARTITION_TYPE_1C "Windows_FAT_32_Hidden" -#define FDISK_PARTITION_TYPE_1E "Windows_FAT_16_Hidden" -#define FDISK_PARTITION_TYPE_63 "UNIX" -#define FDISK_PARTITION_TYPE_82 "Linux_Swap" -#define FDISK_PARTITION_TYPE_83 "Linux_Ext2FS" -#define FDISK_PARTITION_TYPE_84 "Hibernation" -#define FDISK_PARTITION_TYPE_85 "Linux_Extended" -#define FDISK_PARTITION_TYPE_86 "Windows_FAT_16_FT" -#define FDISK_PARTITION_TYPE_87 "Windows_NTFS_FT" -#define FDISK_PARTITION_TYPE_A5 "FreeBSD" -#define FDISK_PARTITION_TYPE_A6 "OpenBSD" -#define FDISK_PARTITION_TYPE_A7 "Apple_Rhapsody_UFS" -#define FDISK_PARTITION_TYPE_A8 "Apple_UFS" -#define FDISK_PARTITION_TYPE_A9 "NetBSD" -#define FDISK_PARTITION_TYPE_AB "Apple_Boot" -#define FDISK_PARTITION_TYPE_AF "Apple_HFS" -#define FDISK_PARTITION_TYPE_B7 "BSDI" -#define FDISK_PARTITION_TYPE_B8 "BSDI_Swap" -#define FDISK_PARTITION_TYPE_C6 "Windows_FAT_16_FT_Corrupt" -#define FDISK_PARTITION_TYPE_C7 "Windows_NTFS_FT_Corrupt" -#define FDISK_PARTITION_TYPE_EB "BeOS" -#define FDISK_PARTITION_TYPE_F2 "DOS_Secondary" -#define FDISK_PARTITION_TYPE_FD "Linux_RAID" - -#pragma options align=reset /* (reset to default struct packing) */ - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOPartitionScheme.h> - -/* - * Class - */ - -class IOFDiskPartitionScheme : public IOPartitionScheme -{ - OSDeclareDefaultStructors(IOFDiskPartitionScheme); - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - OSSet * _partitions; /* (set of media objects representing partitions) */ - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(void); - - /* - * Scan the provider media for an FDisk partition map. Returns the set - * of media objects representing each of the partitions (the retain for - * the set is passed to the caller), or null should no partition map be - * found. The default probe score can be adjusted up or down, based on - * the confidence of the scan. - */ - - virtual OSSet * scan(SInt32 * score); - - /* - * Ask whether the given partition is extended. - */ - - virtual bool isPartitionExtended(fdisk_part * partition); - - /* - * Ask whether the given partition is used. - */ - - virtual bool isPartitionUsed(fdisk_part * partition); - - /* - * Ask whether the given partition appears to be corrupt. A partition that - * is corrupt will cause the failure of the FDisk partition map recognition - * altogether. - */ - - virtual bool isPartitionCorrupt( fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ); - - /* - * Ask whether the given partition appears to be invalid. A partition that - * is invalid will cause it to be skipped in the scan, but will not cause a - * failure of the FDisk partition map recognition. - */ - - virtual bool isPartitionInvalid( fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ); - - /* - * Instantiate a new media object to represent the given partition. - */ - - virtual IOMedia * instantiateMediaObject( fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ); - - /* - * Allocate a new media object (called from instantiateMediaObject). - */ - - virtual IOMedia * instantiateDesiredMediaObject( fdisk_part * partition, - UInt32 partitionID, - UInt32 fdiskBlock ); - -public: - - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * Determine whether the provider media contains an FDisk partition map. - */ - - virtual IOService * probe(IOService * provider, SInt32 * score); - - /* - * Publish the new media objects which represent our partitions. - */ - - virtual bool start(IOService * provider); - - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 0); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 1); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 2); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 3); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 4); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 5); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 6); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 7); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 8); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 9); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 10); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 11); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 12); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 13); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 14); - OSMetaClassDeclareReservedUnused(IOFDiskPartitionScheme, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOFDISKPARTITIONSCHEME_H */ diff --git a/iokit/IOKit/storage/IOMedia.h b/iokit/IOKit/storage/IOMedia.h deleted file mode 100644 index 709f8f16c..000000000 --- a/iokit/IOKit/storage/IOMedia.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOMedia - * @abstract - * This header contains the IOMedia class definition. - */ - -#ifndef _IOMEDIA_H -#define _IOMEDIA_H - -/*! - * @defined kIOMediaClass - * @abstract - * kIOMediaClass is the name of the IOMedia class. - * @discussion - * kIOMediaClass is the name of the IOMedia class. - */ - -#define kIOMediaClass "IOMedia" - -/*! - * @defined kIOMediaContentKey - * @abstract - * kIOMediaContentKey is a property of IOMedia objects. It has an OSString - * value. - * @discussion - * The kIOMediaContentKey property contains a description of the media's - * contents. The description is the same as the hint at the time of the object's - * creation, but it is possible that the description be overrided by a client - * (which has probed the media and identified the content correctly) of the media - * object. It is more accurate than the hint for this reason. The string is - * formed in the likeness of Apple's "Apple_HFS" strings. - */ - -#define kIOMediaContentKey "Content" -#define kIOMediaContent "Content" ///d:deprecated - -/*! - * @defined kIOMediaContentHintKey - * @abstract - * kIOMediaContentHintKey is a property of IOMedia objects. It has an OSString - * value. - * @discussion - * The kIOMediaContentHintKey property contains a hint of the media's contents. - * The hint is set at the time of the object's creation, should the creator have - * a clue as to what it may contain. The hint string does not change for the - * lifetime of the object and is formed in the likeness of Apple's "Apple_HFS" - * strings. - */ - -#define kIOMediaContentHintKey "Content Hint" - -/*! - * @defined kIOMediaEjectableKey - * @abstract - * kIOMediaEjectableKey is a property of IOMedia objects. It has an OSBoolean - * value. - * @discussion - * The kIOMediaEjectableKey property describes whether the media is ejectable. - */ - -#define kIOMediaEjectableKey "Ejectable" -#define kIOMediaEjectable "Ejectable" ///d:deprecated - -/*! - * @defined kIOMediaLeafKey - * @abstract - * kIOMediaLeafKey is a property of IOMedia objects. It has an OSBoolean value. - * @discussion - * The kIOMediaLeafKey property describes whether the media is a leaf, that is, - * it is the deepest media object in this branch of the I/O Kit registry. - */ - -#define kIOMediaLeafKey "Leaf" -#define kIOMediaLeaf "Leaf" ///d:deprecated - -/*! - * @defined kIOMediaPreferredBlockSizeKey - * @abstract - * kIOMediaPreferredBlockSizeKey is a property of IOMedia objects. It has an - * OSNumber value. - * @discussion - * The kIOMediaPreferredBlockSizeKey property describes the media's natural block - * size in bytes. This information is useful to clients that want to optimize - * access to the media. - */ - -#define kIOMediaPreferredBlockSizeKey "Preferred Block Size" - -/*! - * @defined kIOMediaSizeKey - * @abstract - * kIOMediaSizeKey is a property of IOMedia objects. It has an OSNumber value. - * @discussion - * The kIOMediaSizeKey property describes the total length of the media in bytes. - */ - -#define kIOMediaSizeKey "Size" -#define kIOMediaSize "Size" ///d:deprecated - -/*! - * @defined kIOMediaWholeKey - * @abstract - * kIOMediaWholeKey is a property of IOMedia objects. It has an OSBoolean value. - * @discussion - * The kIOMediaWholeKey property describes whether the media is whole, that is, - * it represents the whole disk (the physical disk, or a virtual replica - * thereof). - */ - -#define kIOMediaWholeKey "Whole" - -/*! - * @defined kIOMediaWritableKey - * @abstract - * kIOMediaWritableKey is a property of IOMedia objects. It has an OSBoolean - * value. - * @discussion - * The kIOMediaWritableKey property describes whether the media is writable. - */ - -#define kIOMediaWritableKey "Writable" -#define kIOMediaWritable "Writable" ///d:deprecated - -/*! - * @defined kIOMediaContentMaskKey - * @abstract - * kIOMediaContentMaskKey is a property of IOMedia clients. It has an OSString - * value. - * @discussion - * The kIOMediaContentMaskKey property must exist in all IOMedia clients that - * drive new content (that is, produce new media objects). When the client - * matches against the provider media, the value of the client's - * kIOMediaContentMaskKey property is used to replace the provider's - * kIOMediaContentKey property. - */ - -#define kIOMediaContentMaskKey "Content Mask" - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOStorage.h> - -/*! - * @class IOMedia - * @abstract - * The IOMedia class is a random-access disk device abstraction. - * @discussion - * The IOMedia class is a random-access disk device abstraction. It provides a - * consistent interface for both real and virtual disk devices, for subdivisions - * of disks such as partitions, for supersets of disks such as RAID volumes, and - * so on. It extends the IOStorage class by implementing the appropriate open, - * close, read, write, and matching semantics for media objects. The properties - * it has reflect the properties of real disk devices, such as ejectability and - * writability. - * - * The read and write interfaces support byte-level access to the storage space, - * with the appropriate deblocking handled by the block storage driver, however, - * a typical client will want to get the natural block size in order to optimize - * access to the real disk device. A read or write is accepted so long as the - * client's access is valid, the media is formatted and the transfer is within - * the bounds of the media. An optional non-zero base (offset) is then applied - * before the read or write is passed to provider object. - * - * An open is accepted so long as no more than one writer is active at any time. - */ - -class IOMedia : public IOStorage -{ - OSDeclareDefaultStructors(IOMedia) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - bool _isEjectable; - bool _isWhole; - bool _isWritable; - - UInt64 _mediaBase; /* (relative to the storage object below us) */ - UInt64 _mediaSize; - - IOStorageAccess _openLevel; - OSSet * _openReaders; - IOService * _openReaderWriter; - - UInt64 _preferredBlockSize; - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(); - - /*! - * @function handleOpen - * @discussion - * The handleOpen method grants or denies permission to access this object - * to an interested client. The argument is an IOStorageAccess value that - * specifies the level of access desired -- reader or reader-writer. - * - * This method can be invoked to upgrade or downgrade the access level for - * an existing client as well. The previous access level will prevail for - * upgrades that fail, of course. A downgrade should never fail. If the - * new access level should be the same as the old for a given client, this - * method will do nothing and return success. In all cases, one, singular - * close-per-client is expected for all opens-per-client received. - * - * This implementation replaces the IOService definition of handleOpen(). - * @param client - * Client requesting the open. - * @param options - * Options for the open. Set to zero. - * @param access - * Access level for the open. Set to kIOStorageAccessReader or - * kIOStorageAccessReaderWriter. - * @result - * Returns true if the open was successful, false otherwise. - */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * access); - - /*! - * @function handleIsOpen - * @discussion - * The handleIsOpen method determines whether the specified client, or any - * client if none is specificed, presently has an open on this object. - * - * This implementation replaces the IOService definition of handleIsOpen(). - * @param client - * Client to check the open state of. Set to zero to check the open state - * of all clients. - * @result - * Returns true if the client was (or clients were) open, false otherwise. - */ - - virtual bool handleIsOpen(const IOService * client) const; - - /*! - * @function handleClose - * @discussion - * The handleClose method closes the client's access to this object. - * - * This implementation replaces the IOService definition of handleClose(). - * @param client - * Client requesting the close. - * @param options - * Options for the close. Set to zero. - */ - - virtual void handleClose(IOService * client, IOOptionBits options); - -public: - -///m:2333367:workaround:commented:start -// using read; -// using write; -///m:2333367:workaround:commented:stop - - /*! - * @function init - * @discussion - * Initialize this object's minimal state. - * @param base - * Media offset, in bytes. - * @param size - * Media size, in bytes. - * @param preferredBlockSize - * Natural block size, in bytes. - * @param isEjectable - * Indicates whether the media is ejectable. - * @param isWhole - * Indicated whether the media represents the whole disk. - * @param isWritable - * Indicates whether the media is writable. - * @param contentHint - * Hint of media's contents (optional). See getContentHint(). - * @param properties - * Substitute property table for this object (optional). - * @result - * Returns true on success, false otherwise. - */ - - virtual bool init(UInt64 base, - UInt64 size, - UInt64 preferredBlockSize, - bool isEjectable, - bool isWhole, - bool isWritable, - const char * contentHint = 0, - OSDictionary * properties = 0); - - /* - * This method is called for each client interested in the services we - * provide. The superclass links us as a parent to this client in the - * I/O Kit registry on success. - */ - - virtual bool attachToChild(IORegistryEntry * client, - const IORegistryPlane * plane); - - /* - * This method is called for each client that loses interest in the - * services we provide. The superclass unlinks us from this client - * in the I/O Kit registry on success. - */ - - virtual void detachFromChild(IORegistryEntry * client, - const IORegistryPlane * plane); - - /* - * Compare the properties in the supplied table to this object's properties. - */ - - virtual bool matchPropertyTable(OSDictionary * table, SInt32 * score); - - /*! - * @function read - * @discussion - * Read data from the storage object at the specified byte offset into the - * specified buffer, asynchronously. When the read completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the read. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /*! - * @function write - * @discussion - * Write data into the storage object at the specified byte offset from the - * specified buffer, asynchronously. When the write completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the write. - * @param client - * Client requesting the write. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - virtual IOReturn synchronizeCache(IOService * client); - - /*! - * @function getPreferredBlockSize - * @discussion - * Ask the media object for its natural block size. This information - * is useful to clients that want to optimize access to the media. - * @result - * Natural block size, in bytes. - */ - - virtual UInt64 getPreferredBlockSize() const; - - /*! - * @function getSize - * @discussion - * Ask the media object for its total length in bytes. - * @result - * Media size, in bytes. - */ - - virtual UInt64 getSize() const; - - /*! - * @function getBase - * @discussion - * Ask the media object for its byte offset relative to its provider media - * object below it in the storage hierarchy. - * Media offset, in bytes. - */ - - virtual UInt64 getBase() const; - - /*! - * @function isEjectable - * @discussion - * Ask the media object whether it is ejectable. - * @result - * Returns true if the media is ejectable, false otherwise. - */ - - virtual bool isEjectable() const; - - /*! - * @function isFormatted - * @discussion - * Ask the media object whether it is formatted. - * @result - * Returns true if the media is formatted, false otherwise. - */ - - virtual bool isFormatted() const; - - /*! - * @function isWhole - * @discussion - * Ask the media object whether it represents the whole disk. - * @result - * Returns true if the media represents the whole disk, false otherwise. - */ - - virtual bool isWhole() const; - - /*! - * @function isWritable - * @discussion - * Ask the media object whether it is writable. - * @result - * Returns true if the media is writable, false otherwise. - */ - - virtual bool isWritable() const; - - /*! - * @function getContent - * @discussion - * Ask the media object for a description of its contents. The description - * is the same as the hint at the time of the object's creation, but it is - * possible that the description be overrided by a client (which has probed - * the media and identified the content correctly) of the media object. It - * is more accurate than the hint for this reason. The string is formed in - * the likeness of Apple's "Apple_HFS" strings. - * - * The content description can be overrided by any client that matches onto - * this media object with a match category of kIOStorageCategory. The media - * object checks for a kIOMediaContentMaskKey property in the client, and if - * it finds one, it copies it into kIOMediaContentKey property. - * @result - * Description of media's contents. - */ - - virtual const char * getContent() const; - - /*! - * @function getContentHint - * @discussion - * Ask the media object for a hint of its contents. The hint is set at the - * time of the object's creation, should the creator have a clue as to what - * it may contain. The hint string does not change for the lifetime of the - * object and is also formed in the likeness of Apple's "Apple_HFS" strings. - * @result - * Hint of media's contents. - */ - - virtual const char * getContentHint() const; - - /* - * Obtain this object's provider. We override the superclass's method to - * return a more specific subclass of OSObject -- IOStorage. This method - * serves simply as a convenience to subclass developers. - */ - - virtual IOStorage * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOMedia, 0); - OSMetaClassDeclareReservedUnused(IOMedia, 1); - OSMetaClassDeclareReservedUnused(IOMedia, 2); - OSMetaClassDeclareReservedUnused(IOMedia, 3); - OSMetaClassDeclareReservedUnused(IOMedia, 4); - OSMetaClassDeclareReservedUnused(IOMedia, 5); - OSMetaClassDeclareReservedUnused(IOMedia, 6); - OSMetaClassDeclareReservedUnused(IOMedia, 7); - OSMetaClassDeclareReservedUnused(IOMedia, 8); - OSMetaClassDeclareReservedUnused(IOMedia, 9); - OSMetaClassDeclareReservedUnused(IOMedia, 10); - OSMetaClassDeclareReservedUnused(IOMedia, 11); - OSMetaClassDeclareReservedUnused(IOMedia, 12); - OSMetaClassDeclareReservedUnused(IOMedia, 13); - OSMetaClassDeclareReservedUnused(IOMedia, 14); - OSMetaClassDeclareReservedUnused(IOMedia, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOMEDIA_H */ diff --git a/iokit/IOKit/storage/IOMediaBSDClient.h b/iokit/IOKit/storage/IOMediaBSDClient.h deleted file mode 100644 index 599fdb344..000000000 --- a/iokit/IOKit/storage/IOMediaBSDClient.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOMEDIABSDCLIENT_H -#define _IOMEDIABSDCLIENT_H - -#include <IOKit/IOService.h> - -/* - * Definitions - */ - -class AnchorTable; -class MinorTable; -struct MinorSlot; - -/* - * Class - */ - -class IOMediaBSDClient : public IOService -{ - OSDeclareDefaultStructors(IOMediaBSDClient) - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - AnchorTable * _anchors; /* (table of anchors) */ - bool _bdevswInstalled; /* (are bdevsw functions installed?) */ - bool _cdevswInstalled; /* (are cdevsw functions installed?) */ - MinorTable * _minors; /* (table of minors) */ - IONotifier * _notifier; /* (media arrival notification) */ - - /* - * Notification handler for media arrivals. - */ - - static bool mediaHasArrived(void *, void *, IOService * service); - - /* - * Find the whole media that roots this media tree. - */ - - virtual IOMedia * getWholeMedia( IOMedia * media, - UInt32 * slicePathSize = 0, - char * slicePath = 0 ); - - /* - * Create bdevsw and cdevsw nodes for the given media object. - */ - - virtual bool createNodes(IOMedia * media); - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(); - -public: - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * This method is called once we have been attached to the provider object. - */ - - virtual bool start(IOService * provider); - - /* - * This method is called before we are detached from the provider object. - */ - - virtual void stop(IOService * provider); - - /* - * Obtain the table of anchors. - */ - - virtual AnchorTable * getAnchors(); - - /* - * Obtain the table of minors. - */ - - virtual MinorTable * getMinors(); - - /* - * Obtain information for the specified minor ID. - */ - - virtual MinorSlot * getMinor(UInt32 minorID); - - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 0); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 1); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 2); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 3); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 4); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 5); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 6); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 7); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 8); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 9); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 10); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 11); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 12); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 13); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 14); - OSMetaClassDeclareReservedUnused(IOMediaBSDClient, 15); -}; - -#endif /* !_IOMEDIABSDCLIENT_H */ diff --git a/iokit/IOKit/storage/IONeXTPartitionScheme.h b/iokit/IOKit/storage/IONeXTPartitionScheme.h deleted file mode 100644 index 3172c6bd0..000000000 --- a/iokit/IOKit/storage/IONeXTPartitionScheme.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IONEXTPARTITIONSCHEME_H -#define _IONEXTPARTITIONSCHEME_H - -#include <IOKit/IOTypes.h> - -/* - * NeXT Partition Map Definitions - */ - -#pragma pack(2) /* (enable 16-bit struct packing for dl_un, disk[tab,_label]) */ - -#include <sys/disktab.h> - -/* Structure constants. */ - -#define MAXLBLLEN 24 /* (length of disk name) */ -#define NBAD 1670 /* (size of bad sector table in map) */ -#define NLABELS 4 /* (number of partition maps on disk) */ - -/* Structure aliases, for disktab and dl_un fields. */ - -#define dl_name dl_dt.d_name -#define dl_type dl_dt.d_type -#define dl_part dl_dt.d_partitions -#define dl_front dl_dt.d_front -#define dl_back dl_dt.d_back -#define dl_ngroups dl_dt.d_ngroups -#define dl_ag_size dl_dt.d_ag_size -#define dl_ag_alts dl_dt.d_ag_alts -#define dl_ag_off dl_dt.d_ag_off -#define dl_secsize dl_dt.d_secsize -#define dl_ncyl dl_dt.d_ncylinders -#define dl_nsect dl_dt.d_nsectors -#define dl_ntrack dl_dt.d_ntracks -#define dl_rpm dl_dt.d_rpm -#define dl_bootfile dl_dt.d_bootfile -#define dl_boot0_blkno dl_dt.d_boot0_blkno -#define dl_hostname dl_dt.d_hostname -#define dl_rootpartition dl_dt.d_rootpartition -#define dl_rwpartition dl_dt.d_rwpartition -#define dl_v3_checksum dl_un.DL_v3_checksum -#define dl_bad dl_un.DL_bad - -/* Partition map, as found in block zero (or a redundant block) of the disk. */ - -typedef union -{ - UInt16 DL_v3_checksum; /* (V3: ones complement checksum) */ - SInt32 DL_bad[NBAD]; /* (V1-V2: bad sector table) */ -} dl_un_t; - -typedef struct disk_label -{ - SInt32 dl_version; /* (unique signature for map) */ - SInt32 dl_label_blkno; /* (block on which this map resides) */ - SInt32 dl_size; /* (device block count) */ - char dl_label[MAXLBLLEN]; /* (device name) */ - UInt32 dl_flags; /* (device flags) */ - UInt32 dl_tag; /* (device tag) */ - struct disktab dl_dt; /* (device info, partition entries) */ - dl_un_t dl_un; - UInt16 dl_checksum; /* (V1-V2: ones complement checksum) */ - - /* (add things here so dl_checksum stays in a fixed place) */ -} disk_label_t; - -/* Partition map signature (dl_version). */ - -#define DL_V1 0x4e655854 /* (version 1: "NeXT") */ -#define DL_V2 0x646c5632 /* (version 2: "dlV2") */ -#define DL_V3 0x646c5633 /* (version 3: "dlV3") */ -#define DL_VERSION DL_V3 /* (default version) */ - -/* Partition map flags (dl_flags). */ - -#define DL_UNINIT 0x80000000 /* (is uninitialized?) */ - -#pragma options align=reset /* (reset to default struct packing) */ - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOPartitionScheme.h> - -/* - * Class - */ - -class IONeXTPartitionScheme : public IOPartitionScheme -{ - OSDeclareDefaultStructors(IONeXTPartitionScheme); - -private: - - /* - * Compute a 16-bit (big-endian) checksum over the specified data range. - */ - - UInt16 checksum16(void * data, UInt32 bytes) const; - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - OSSet * _partitions; /* (set of media objects representing partitions) */ - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(void); - - /* - * Scan the provider media for a NeXT partition map. Returns the set - * of media objects representing each of the partitions (the retain for - * the set is passed to the caller), or null should no partition map be - * found. The default probe score can be adjusted up or down, based on - * the confidence of the scan. - */ - - virtual OSSet * scan(SInt32 * score); - - /* - * Ask whether the given partition is used. - */ - - virtual bool isPartitionUsed(partition_t * partition); - - /* - * Ask whether the given partition appears to be corrupt. A partition that - * is corrupt will cause the failure of the NeXT partition map recognition - * altogether. - */ - - virtual bool isPartitionCorrupt( partition_t * partition, - UInt32 partitionID, - UInt64 nextBase, - disk_label_t * nextMap ); - - /* - * Ask whether the given partition appears to be invalid. A partition that - * is invalid will cause it to be skipped in the scan, but will not cause a - * failure of the NeXT partition map recognition. - */ - - virtual bool isPartitionInvalid( partition_t * partition, - UInt32 partitionID, - UInt64 nextBase, - disk_label_t * nextMap ); - - /* - * Instantiate a new media object to represent the given partition. - */ - - virtual IOMedia * instantiateMediaObject( partition_t * partition, - UInt32 partitionID, - UInt64 nextBase, - disk_label_t * nextMap ); - - /* - * Allocate a new media object (called from instantiateMediaObject). - */ - - virtual IOMedia * instantiateDesiredMediaObject( partition_t * partition, - UInt32 partitionID, - UInt64 nextBase, - disk_label_t * nextMap ); - -public: - - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /* - * Determine whether the provider media contains a NeXT partition map. - */ - - virtual IOService * probe(IOService * provider, SInt32 * score); - - /* - * Publish the new media objects which represent our partitions. - */ - - virtual bool start(IOService * provider); - - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 0); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 1); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 2); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 3); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 4); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 5); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 6); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 7); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 8); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 9); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 10); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 11); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 12); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 13); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 14); - OSMetaClassDeclareReservedUnused(IONeXTPartitionScheme, 15); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IONEXTPARTITIONSCHEME_H */ diff --git a/iokit/IOKit/storage/IOPartitionScheme.h b/iokit/IOKit/storage/IOPartitionScheme.h deleted file mode 100644 index 3babae091..000000000 --- a/iokit/IOKit/storage/IOPartitionScheme.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOPartitionScheme - * @abstract - * This header contains the IOPartitionScheme class definition. - */ - -#ifndef _IOPARTITIONSCHEME_H -#define _IOPARTITIONSCHEME_H - -/*! - * @defined kIOPartitionSchemeClass - * @abstract - * kIOPartitionSchemeClass is the name of the IOPartitionScheme class. - * @discussion - * kIOPartitionSchemeClass is the name of the IOPartitionScheme class. - */ - -#define kIOPartitionSchemeClass "IOPartitionScheme" - -/*! - * @defined kIOMediaPartitionIDKey - * @abstract - * kIOMediaPartitionIDKey is property of IOMedia objects. It has an OSNumber - * value. - * @discussion - * The kIOMediaPartitionIDKey property is placed into each IOMedia instance - * created via the partition scheme. It is an ID that differentiates one - * partition from the other (within a given scheme). It is typically an index - * into the on-disk partition table. - */ - -#define kIOMediaPartitionIDKey "Partition ID" -#define kIOMediaPartitionID "Partition ID" ///d:deprecated - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/storage/IOMedia.h> -#include <IOKit/storage/IOStorage.h> - -/*! - * @class IOPartitionScheme - * @abstract - * The IOPartitionScheme class is the common base class for all partition scheme - * objects. - * @discussion - * The IOPartitionScheme class is the common base class for all partition scheme - * objects. It extends the IOStorage class by implementing the appropriate open - * and close semantics for partition objects (standard semantics are to act as a - * multiplexor for incoming opens, producing one outgoing open with the correct - * access). It also implements the default read and write semantics, which pass - * all reads and writes through to the provider media unprocessed. For simple - * schemes, the default behavior is sufficient. More complex partition schemes - * such as RAID will want to do extra processing for reads and writes. - */ - -class IOPartitionScheme : public IOStorage -{ - OSDeclareDefaultStructors(IOPartitionScheme); - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - IOStorageAccess _openLevel; - OSSet * _openReaders; - OSSet * _openReaderWriters; - - /* - * Free all of this object's outstanding resources. - */ - - virtual void free(); - - /*! - * @function handleOpen - * @discussion - * The handleOpen method grants or denies permission to access this object - * to an interested client. The argument is an IOStorageAccess value that - * specifies the level of access desired -- reader or reader-writer. - * - * This method can be invoked to upgrade or downgrade the access level for - * an existing client as well. The previous access level will prevail for - * upgrades that fail, of course. A downgrade should never fail. If the - * new access level should be the same as the old for a given client, this - * method will do nothing and return success. In all cases, one, singular - * close-per-client is expected for all opens-per-client received. - * - * This implementation replaces the IOService definition of handleOpen(). - * @param client - * Client requesting the open. - * @param options - * Options for the open. Set to zero. - * @param access - * Access level for the open. Set to kIOStorageAccessReader or - * kIOStorageAccessReaderWriter. - * @result - * Returns true if the open was successful, false otherwise. - */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * access); - - /*! - * @function handleIsOpen - * @discussion - * The handleIsOpen method determines whether the specified client, or any - * client if none is specificed, presently has an open on this object. - * - * This implementation replaces the IOService definition of handleIsOpen(). - * @param client - * Client to check the open state of. Set to zero to check the open state - * of all clients. - * @result - * Returns true if the client was (or clients were) open, false otherwise. - */ - - virtual bool handleIsOpen(const IOService * client) const; - - /*! - * @function handleClose - * @discussion - * The handleClose method closes the client's access to this object. - * - * This implementation replaces the IOService definition of handleClose(). - * @param client - * Client requesting the close. - * @param options - * Options for the close. Set to zero. - */ - - virtual void handleClose(IOService * client, IOOptionBits options); - -public: - -///m:2333367:workaround:commented:start -// using read; -// using write; -///m:2333367:workaround:commented:stop - - /* - * Initialize this object's minimal state. - */ - - virtual bool init(OSDictionary * properties = 0); - - /*! - * @function read - * @discussion - * Read data from the storage object at the specified byte offset into the - * specified buffer, asynchronously. When the read completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the read. - * - * For simple partition schemes, the default behavior is to simply pass the - * read through to the provider media. More complex partition schemes such - * as RAID will need to do extra processing here. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - /*! - * @function write - * @discussion - * Write data into the storage object at the specified byte offset from the - * specified buffer, asynchronously. When the write completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the write. - * - * For simple partition schemes, the default behavior is to simply pass the - * write through to the provider media. More complex partition schemes such - * as RAID will need to do extra processing here. - * @param client - * Client requesting the write. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion); - - virtual IOReturn synchronizeCache(IOService * client); - - /* - * Obtain this object's provider. We override the superclass's method - * to return a more specific subclass of OSObject -- an IOMedia. This - * method serves simply as a convenience to subclass developers. - */ - - virtual IOMedia * getProvider() const; - - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 0); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 1); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 2); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 3); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 4); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 5); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 6); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 7); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 8); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 9); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 10); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 11); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 12); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 13); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 14); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 15); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 16); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 17); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 18); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 19); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 20); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 21); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 22); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 23); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 24); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 25); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 26); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 27); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 28); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 29); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 30); - OSMetaClassDeclareReservedUnused(IOPartitionScheme, 31); -}; - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOPARTITIONSCHEME_H */ diff --git a/iokit/IOKit/storage/IOStorage.h b/iokit/IOKit/storage/IOStorage.h deleted file mode 100644 index e2247581f..000000000 --- a/iokit/IOKit/storage/IOStorage.h +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/*! - * @header IOStorage - * @abstract - * This header contains the IOStorage class definition. - */ - -#ifndef _IOSTORAGE_H -#define _IOSTORAGE_H - -#include <IOKit/IOTypes.h> - -/*! - * @defined kIOStorageClass - * @abstract - * kIOStorageClass is the name of the IOStorage class. - * @discussion - * kIOStorageClass is the name of the IOStorage class. - */ - -#define kIOStorageClass "IOStorage" - -/*! - * @enum IOStorageAccess - * @discussion - * The IOStorageAccess enumeration describes the possible access levels for open - * requests. - * @constant kIOStorageAccessNone - * No access is requested; should not be passed to open(). - * @constant kIOStorageAccessReader - * Read-only access is requested. - * @constant kIOStorageAccessReaderWriter - * Read and write access is requested. - */ - -typedef UInt32 IOStorageAccess; - -#define kIOStorageAccessNone 0x00 -#define kIOStorageAccessReader 0x01 -#define kIOStorageAccessReaderWriter 0x03 - -/*! - * @defined kIOStorageCategory - * @abstract - * kIOStorageCategory is a value for IOService's kIOMatchCategoryKey property. - * @discussion - * The kIOStorageCategory value is the standard value for the IOService property - * kIOMatchCategoryKey ("IOMatchCategory") for all storage drivers. All storage - * objects that expect to drive new content (that is, produce new media objects) - * are expected to compete within the kIOStorageCategory namespace. - * - * See the IOService documentation for more information on match categories. - */ - -#define kIOStorageCategory "IOStorage" /* (as IOMatchCategory) */ - -/* - * Kernel - */ - -#if defined(KERNEL) && defined(__cplusplus) - -#include <IOKit/assert.h> -#include <IOKit/IOMemoryDescriptor.h> -#include <IOKit/IOService.h> - -/*! - * @typedef IOStorageCompletionAction - * @discussion - * The IOStorageCompletionAction declaration describes the C (or C++) completion - * routine that is called once an asynchronous storage operation completes. - * @param target - * Opaque client-supplied pointer (or an instance pointer for a C++ callback). - * @param parameter - * Opaque client-supplied pointer. - * @param status - * Status of the data transfer. - * @param actualByteCount - * Actual number of bytes transferred in the data transfer. - */ - -typedef void (*IOStorageCompletionAction)(void * target, - void * parameter, - IOReturn status, - UInt64 actualByteCount); - -/*! - * @struct IOStorageCompletion - * @discussion - * The IOStorageCompletion structure describes the C (or C++) completion routine - * that is called once an asynchronous storage operation completes. The values - * passed for the target and parameter fields will be passed to the routine when - * it is called. - * @field target - * Opaque client-supplied pointer (or an instance pointer for a C++ callback). - * @field action - * Completion routine to call on completion of the data transfer. - * @field parameter - * Opaque client-supplied pointer. - */ - -struct IOStorageCompletion -{ - void * target; - IOStorageCompletionAction action; - void * parameter; -}; - -/*! - * @class IOStorage - * @abstract - * The IOStorage class is the common base class for mass storage objects. - * @discussion - * The IOStorage class is the common base class for mass storage objects. It is - * an abstract class that defines the open/close/read/write APIs that need to be - * implemented in a given subclass. Synchronous versions of the read/write APIs - * are provided here -- they are coded in such a way as to wrap the asynchronous - * versions implmeneted in the subclass. - */ - -class IOStorage : public IOService -{ - OSDeclareAbstractStructors(IOStorage); - -protected: - - struct ExpansionData { /* */ }; - ExpansionData * _expansionData; - - /*! - * @function handleOpen - * @discussion - * The handleOpen method grants or denies permission to access this object - * to an interested client. The argument is an IOStorageAccess value that - * specifies the level of access desired -- reader or reader-writer. - * - * This method can be invoked to upgrade or downgrade the access level for - * an existing client as well. The previous access level will prevail for - * upgrades that fail, of course. A downgrade should never fail. If the - * new access level should be the same as the old for a given client, this - * method will do nothing and return success. In all cases, one, singular - * close-per-client is expected for all opens-per-client received. - * @param client - * Client requesting the open. - * @param options - * Options for the open. Set to zero. - * @param access - * Access level for the open. Set to kIOStorageAccessReader or - * kIOStorageAccessReaderWriter. - * @result - * Returns true if the open was successful, false otherwise. - */ - - virtual bool handleOpen(IOService * client, - IOOptionBits options, - void * access) = 0; - - /*! - * @function handleIsOpen - * @discussion - * The handleIsOpen method determines whether the specified client, or any - * client if none is specificed, presently has an open on this object. - * @param client - * Client to check the open state of. Set to zero to check the open state - * of all clients. - * @result - * Returns true if the client was (or clients were) open, false otherwise. - */ - - virtual bool handleIsOpen(const IOService * client) const = 0; - - /*! - * @function handleClose - * @discussion - * The handleClose method closes the client's access to this object. - * @param client - * Client requesting the close. - * @param options - * Options for the close. Set to zero. - */ - - virtual void handleClose(IOService * client, IOOptionBits options) = 0; - -public: - -///m:2333367:workaround:commented:start -// using open; -///m:2333367:workaround:commented:stop - - /*! - * @function open - * @discussion - * Ask the storage object for permission to access its contents; the method - * is equivalent to IOService::open(), but with the correct parameter types. - * - * This method may also be invoked to upgrade or downgrade the access of an - * existing open (if it fails, the existing open prevails). - * @param client - * Client requesting the open. - * @param options - * Options for the open. Set to zero. - * @param access - * Access level for the open. Set to kIOStorageAccessReader or - * kIOStorageAccessReaderWriter. - * @result - * Returns true if the open was successful, false otherwise. - */ - - virtual bool open(IOService * client, - IOOptionBits options, - IOStorageAccess access); - - /*! - * @function read - * @discussion - * Read data from the storage object at the specified byte offset into the - * specified buffer, asynchronously. When the read completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the read. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) = 0; - - /*! - * @function write - * @discussion - * Write data into the storage object at the specified byte offset from the - * specified buffer, asynchronously. When the write completes, the caller - * will be notified via the specified completion action. - * - * The buffer will be retained for the duration of the write. - * @param client - * Client requesting the write. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param completion - * Completion routine to call once the data transfer is complete. - */ - - virtual void write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - IOStorageCompletion completion) = 0; - - /*! - * @function read - * @discussion - * Read data from the storage object at the specified byte offset into the - * specified buffer, synchronously. When the read completes, this method - * will return to the caller. The actual byte count field is optional. - * @param client - * Client requesting the read. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param actualByteCount - * Returns the actual number of bytes transferred in the data transfer. - * @result - * Returns the status of the data transfer. - */ - - virtual IOReturn read(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - UInt64 * actualByteCount = 0); - - /*! - * @function write - * @discussion - * Write data into the storage object at the specified byte offset from the - * specified buffer, synchronously. When the write completes, this method - * will return to the caller. The actual byte count field is optional. - * @param client - * Client requesting the write. - * @param byteStart - * Starting byte offset for the data transfer. - * @param buffer - * Buffer for the data transfer. The size of the buffer implies the size of - * the data transfer. - * @param actualByteCount - * Returns the actual number of bytes transferred in the data transfer. - * @result - * Returns the status of the data transfer. - */ - - virtual IOReturn write(IOService * client, - UInt64 byteStart, - IOMemoryDescriptor * buffer, - UInt64 * actualByteCount = 0); - - virtual IOReturn synchronizeCache(IOService * client) = 0; - - /*! - * @function complete - * @discussion - * Invokes the specified completion action of the read/write request. If - * the completion action is unspecified, no action is taken. This method - * serves simply as a convenience to storage subclass developers. - * @param completion - * Completion information for the data transfer. - * @param status - * Status of the data transfer. - * @param actualByteCount - * Actual number of bytes transferred in the data transfer. - */ - - static inline void complete(IOStorageCompletion completion, - IOReturn status, - UInt64 actualByteCount = 0); - - OSMetaClassDeclareReservedUnused(IOStorage, 0); - OSMetaClassDeclareReservedUnused(IOStorage, 1); - OSMetaClassDeclareReservedUnused(IOStorage, 2); - OSMetaClassDeclareReservedUnused(IOStorage, 3); - OSMetaClassDeclareReservedUnused(IOStorage, 4); - OSMetaClassDeclareReservedUnused(IOStorage, 5); - OSMetaClassDeclareReservedUnused(IOStorage, 6); - OSMetaClassDeclareReservedUnused(IOStorage, 7); - OSMetaClassDeclareReservedUnused(IOStorage, 8); - OSMetaClassDeclareReservedUnused(IOStorage, 9); - OSMetaClassDeclareReservedUnused(IOStorage, 10); - OSMetaClassDeclareReservedUnused(IOStorage, 11); - OSMetaClassDeclareReservedUnused(IOStorage, 12); - OSMetaClassDeclareReservedUnused(IOStorage, 13); - OSMetaClassDeclareReservedUnused(IOStorage, 14); - OSMetaClassDeclareReservedUnused(IOStorage, 15); -}; - -/* - * Inline Functions - */ - -inline void IOStorage::complete(IOStorageCompletion completion, - IOReturn status, - UInt64 actualByteCount) -{ - /* - * Invokes the specified completion action of the read/write request. If - * the completion action is unspecified, no action is taken. This method - * serves simply as a convenience to storage subclass developers. - */ - - if (completion.action) (*completion.action)(completion.target, - completion.parameter, - status, - actualByteCount); -} - -#endif /* defined(KERNEL) && defined(__cplusplus) */ - -#endif /* !_IOSTORAGE_H */ diff --git a/iokit/IOKit/storage/Makefile b/iokit/IOKit/storage/Makefile deleted file mode 100644 index 3b567c9c7..000000000 --- a/iokit/IOKit/storage/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = storage -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = \ - scsi - -INSTINC_SUBDIRS_PPC = - -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = \ - IOApplePartitionScheme.h \ - IOBlockStorageDriver.h \ - IOCDAudioControlUserClient.h \ - IOCDMedia.h \ - IOCDPartitionScheme.h \ - IOCDTypes.h \ - IODVDMedia.h \ - IOFDiskPartitionScheme.h \ - IOMedia.h \ - IONeXTPartitionScheme.h \ - IOPartitionScheme.h \ - IOStorage.h -INSTALL_MI_LCL_LIST = "" -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/storage/ata/IOATAHDDrive.h b/iokit/IOKit/storage/ata/IOATAHDDrive.h deleted file mode 100644 index e70e6ae75..000000000 --- a/iokit/IOKit/storage/ata/IOATAHDDrive.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAHDDrive.h - * - * HISTORY - * Aug 27, 1999 jliu - Ported from AppleATADrive. - */ - -#ifndef _IOATAHDDRIVE_H -#define _IOATAHDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/ata/IOATADeviceInterface.h> -#include <IOKit/IOCommandGate.h> -#include <IOKit/IOWorkLoop.h> -#include <IOKit/storage/IOStorage.h> - -class IOSyncer; - -// ATA parameters. -// -#define kIOATASectorSize 512 -#define kIOATAMaxBlocksPerXfer 256 - -// ATA commands. -// -enum { - kIOATACommandReadPIO = 0x20, - kIOATACommandWritePIO = 0x30, - kIOATACommandReadDMA = 0xc8, - kIOATACommandWriteDMA = 0xca, - kIOATACommandReadDMAQueued = 0xc7, - kIOATACommandWriteDMAQueued = 0xcc, - kIOATACommandStandbyImmediate = 0xe0, - kIOATACommandSleep = 0xe6, - kIOATACommandFlushCache = 0xe7, - kIOATACommandSetFeatures = 0xef, -}; - -// ATA power states, from lowest to highest power usage. -// -typedef enum { - kIOATAPowerStateSleep = 0, - kIOATAPowerStateStandby, - kIOATAPowerStateIdle, - kIOATAPowerStateActive -} IOATAPowerState; - -// ATA supported features. -// -enum { - kIOATAFeaturePowerManagement = 0x01, - kIOATAFeatureWriteCache = 0x02 -}; - -// Stages to transition into each power state. -// -enum { - kIOATAStandbyStage0, /* hold the queue */ - kIOATAStandbyStage1, /* flush disk write cache */ - kIOATAStandbyStage2, /* issue ATA STANDBY IMMEDIATE command */ - kIOATAStandbyStage3 /* finalize state transition */ -}; - -enum { - kIOATAActiveStage0, /* issue a software reset */ - kIOATAActiveStage1, /* spin up the drive */ - kIOATAActiveStage2, /* release the queue */ - kIOATAActiveStage3 /* finalize state transition */ -}; - -// Property table keys. -// -#define kIOATASupportedFeaturesKey "ATA Features" -#define kIOATAEnableWriteCacheKey "Enable Write Cache" - -//=========================================================================== -// IOATAClientData - This structure is stored on the IOATACommand's -// driver private area. -//=========================================================================== - -struct IOATAClientData -{ - IOATACommand * command; // back pointer to command object. - IOMemoryDescriptor * buffer; // transfer buffer descriptor. - union { - IOStorageCompletion async; // completion target/action/param. - IOSyncer * syncLock; // used by sync commands. - } completion; - bool isSync; // command is synchronous. - SInt32 maxRetries; // max retry attempts (0 = no retry). - IOReturn returnCode; // sync command return code. -}; - -// Get driver private data (IOATAClientData) from an IOATACommand object. -// -#define ATA_CLIENT_DATA(x) ((IOATAClientData *)((x)->getClientData())) - -//=========================================================================== -// IOATAHDDrive -//=========================================================================== - -class IOATAHDDrive : public IOService -{ - OSDeclareDefaultStructors(IOATAHDDrive) - -protected: - IOATADevice * _ataDevice; - IOCommandGate * _cmdGate; - UInt _unit; - ATATimingProtocol _timingProtocol; - ATAProtocol _ataProtocol; - UInt8 _ataReadCmd; - UInt8 _ataWriteCmd; - char _revision[9]; - char _model[41]; - bool _powerStateChanging; - bool _setPowerAckPending; - bool _logSelectedTimingProtocol; - IOOptionBits _supportedFeatures; - IOATAPowerState _currentATAPowerState; - IOATAPowerState _proposedATAPowerState; - void * _configThreadCall; - bool _pmReady; - - //----------------------------------------------------------------------- - // Default timeout (in milliseconds) for async and sync commands. - - static const UInt kATADefaultTimeout = 30000; // 30 seconds - - //----------------------------------------------------------------------- - // Default retry count for async and sync commands. - - static const UInt kATADefaultRetries = 4; - static const UInt kATAZeroRetry = 0; - - //----------------------------------------------------------------------- - // Static member functions called by IOCommandGate, or registered - // as completion routines. - - static void sHandleCommandCompletion(IOATAHDDrive * self, - IOATACommand * cmd); - - static void sHandleSetPowerState(IOATAHDDrive * self, - UInt32 powerStateOrdinal, - IOService * whatDevice, - IOReturn * handlerReturn); - - static void sHandleSleepStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred); - - static void sHandleActiveStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred); - - static void sHandleIdleStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred); - - static void sHandleStandbyStateTransition(IOATAHDDrive * self, - void * stage, - IOReturn status, - UInt64 bytesTransferred); - - static void sHandleInitialPowerStateForDomainState( - IOATAHDDrive * self, - IOPMPowerFlags domainState, - UInt32 * state); - - static void sHandleConfigureDevice(IOATAHDDrive * self); - - //----------------------------------------------------------------------- - // Release all allocated resource before calling super::free(). - - virtual void free(); - - //----------------------------------------------------------------------- - // Select the device timing protocol. - - virtual bool selectTimingProtocol(); - - //----------------------------------------------------------------------- - // Select the ATA protocol. - - virtual bool selectCommandProtocol(bool isDMA); - - //----------------------------------------------------------------------- - // Setup an ATATaskFile from the parameters given, and write the taskfile - // to the ATATaskfile structure pointer provided. - - virtual void setupReadWriteTaskFile(ATATaskfile * taskfile, - ATAProtocol protocol, - UInt8 command, - UInt32 block, - UInt32 nblks); - - //----------------------------------------------------------------------- - // Return an IOATACommand initialized to perform a read/write operation. - - virtual IOATACommand * ataCommandReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - //----------------------------------------------------------------------- - // Return a ATA Set Features command. - - virtual IOATACommand * ataCommandSetFeatures(UInt8 features, - UInt8 SectorCount = 0, - UInt8 SectorNumber = 0, - UInt8 CylinderLow = 0, - UInt8 CyclinderHigh = 0); - - //----------------------------------------------------------------------- - // Return a ATA Flush Cache command. - - virtual IOATACommand * ataCommandFlushCache(); - - //----------------------------------------------------------------------- - // Return a ATA Standby Immediate command. - - virtual IOATACommand * ataCommandStandby(); - - //----------------------------------------------------------------------- - // Issue a synchronous ATA command. - - virtual IOReturn syncExecute(IOATACommand * cmd, - UInt32 timeout = kATADefaultTimeout, - UInt retries = kATADefaultRetries, - IOMemoryDescriptor * senseData = 0); - - //----------------------------------------------------------------------- - // Issue an asynchronous ATA command. - - virtual IOReturn asyncExecute( - IOATACommand * cmd, - IOStorageCompletion completion, - UInt32 timeout = kATADefaultTimeout, - UInt retries = kATADefaultRetries); - - //----------------------------------------------------------------------- - // Allocate an IOATACommand object. - - virtual IOATACommand * allocateCommand(); - - //----------------------------------------------------------------------- - // Inspect the ATA device. - - virtual bool inspectDevice(IOATADevice * device); - - //----------------------------------------------------------------------- - // Configure the ATA device. - - virtual bool configureDevice(IOATADevice * device); - - //----------------------------------------------------------------------- - // Returns an IOATAHDDriveNub instance. - - virtual IOService * instantiateNub(); - - //----------------------------------------------------------------------- - // Calls instantiateNub() then initialize, attach, and register the - // drive nub. - - virtual bool createNub(IOService * provider); - - //----------------------------------------------------------------------- - // Power management support. Subclasses can override these functions - // to replace/enhance the default power management support. - - virtual void initForPM(); - - virtual UInt32 handleInitialPowerStateForDomainState( - IOPMPowerFlags domainState); - - virtual IOReturn handleSetPowerState(UInt32 powerStateOrdinal, - IOService * whatDevice); - - virtual IOATAPowerState getATAPowerStateForStateOrdinal( - UInt32 stateOrdinal); - - virtual void startATAPowerStateTransition(IOATAPowerState ataPowerState); - - virtual void endATAPowerStateTransition(IOATAPowerState ataPowerState); - - virtual void abortATAPowerStateTransition(); - - virtual void handleSleepStateTransition(UInt32 stage, IOReturn status); - - virtual void handleActiveStateTransition(UInt32 stage, IOReturn status); - - virtual void handleIdleStateTransition(UInt32 stage, IOReturn status); - - virtual void handleStandbyStateTransition( UInt32 stage, IOReturn status); - - virtual IOReturn readSector(IOStorageCompletion completion, - UInt32 sector = 0); - - static void acknowledgeATAPowerStateTransition(void *castMeToIOATAHDDrive, void*); - -public: - /* - * Overrides from IOService. - */ - virtual bool init(OSDictionary * properties); - virtual IOService * probe(IOService * provider, SInt32 * score); - virtual bool start(IOService * provider); - virtual void stop(IOService * provider); - - //----------------------------------------------------------------------- - // Report the type of ATA device (ATA vs. ATAPI). - - virtual ATADeviceType reportATADeviceType() const; - - //----------------------------------------------------------------------- - // Handles read/write requests. - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - //----------------------------------------------------------------------- - // Eject the media in the drive. - - virtual IOReturn doEjectMedia(); - - //----------------------------------------------------------------------- - // Format the media in the drive. - - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - - //----------------------------------------------------------------------- - // Returns disk capacity in bytes. - - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - - //----------------------------------------------------------------------- - // Lock the media and prevent a user-initiated eject. - - virtual IOReturn doLockUnlockMedia(bool doLock); - - //----------------------------------------------------------------------- - // Flush the write-cache to the physical media. - - virtual IOReturn doSynchronizeCache(); - - //----------------------------------------------------------------------- - // Start/stop the drive. - - virtual IOReturn doStart(); - virtual IOReturn doStop(); - - //----------------------------------------------------------------------- - // Return device identification strings - - virtual char * getAdditionalDeviceInfoString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getVendorString(); - - //----------------------------------------------------------------------- - // Report the device block size in bytes. - - virtual IOReturn reportBlockSize(UInt64 * blockSize); - - //----------------------------------------------------------------------- - // Report whether the media in the ATA device is ejectable. - - virtual IOReturn reportEjectability(bool * isEjectable); - - //----------------------------------------------------------------------- - // Report whether the media can be locked. - - virtual IOReturn reportLockability(bool * isLockable); - - //----------------------------------------------------------------------- - // Report the polling requirements for a removable media. - - virtual IOReturn reportPollRequirements(bool * pollRequired, - bool * pollIsExpensive); - - //----------------------------------------------------------------------- - // Report the max number of bytes transferred for an ATA read command. - - virtual IOReturn reportMaxReadTransfer(UInt64 blocksize, - UInt64 * max); - - //----------------------------------------------------------------------- - // Report the max number of bytes transferred for an ATA write command. - - virtual IOReturn reportMaxWriteTransfer(UInt64 blocksize, - UInt64 * max); - - //----------------------------------------------------------------------- - // Returns the maximum addressable sector number. - - virtual IOReturn reportMaxValidBlock(UInt64 * maxBlock); - - //----------------------------------------------------------------------- - // Report whether the media is currently present, and whether a media - // change has been registered since the last reporting. - - virtual IOReturn reportMediaState(bool * mediaPresent, - bool * changed); - - //----------------------------------------------------------------------- - // Report whether the media is removable. - - virtual IOReturn reportRemovability(bool * isRemovable); - - //----------------------------------------------------------------------- - // Report if the media is write-protected. - - virtual IOReturn reportWriteProtection(bool * isWriteProtected); - - //----------------------------------------------------------------------- - // Handles messages (notifications) from our provider. - - virtual IOReturn message(UInt32 type, - IOService * provider, - void * argument); - - //----------------------------------------------------------------------- - // Returns the device type. - - virtual const char * getDeviceTypeName(); - - //----------------------------------------------------------------------- - // Power management support. Functions inherited from IOService. - - virtual IOReturn setAggressiveness(UInt32 type, UInt32 minutes); - - virtual UInt32 initialPowerStateForDomainState(IOPMPowerFlags domainState); - - virtual IOReturn setPowerState(UInt32 powerStateOrdinal, - IOService * whatDevice); -}; - -#endif /* !_IOATAHDDRIVE_H */ diff --git a/iokit/IOKit/storage/ata/IOATAHDDriveNub.h b/iokit/IOKit/storage/ata/IOATAHDDriveNub.h deleted file mode 100644 index cbf7749eb..000000000 --- a/iokit/IOKit/storage/ata/IOATAHDDriveNub.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAHDDriveNub.h - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * Aug 27, 1999 jliu - Created. - */ - -#ifndef _IOATAHDDRIVENUB_H -#define _IOATAHDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOBlockStorageDevice.h> - -class IOATAHDDrive; - -class IOATAHDDriveNub : public IOBlockStorageDevice -{ - OSDeclareDefaultStructors(IOATAHDDriveNub) - -protected: - IOATAHDDrive * _provider; - -public: - /* - * Overrides from IOService. - */ - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - /* - * Mandatory overrides from IOBlockStorageDevice. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - virtual IOReturn doEjectMedia(); - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual IOReturn doSynchronizeCache(); - virtual char * getVendorString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getAdditionalDeviceInfoString(); - virtual IOReturn reportBlockSize(UInt64 * blockSize); - virtual IOReturn reportEjectability(bool * isEjectable); - virtual IOReturn reportLockability(bool * isLockable); - virtual IOReturn reportMediaState(bool * mediaPresent, bool * changed); - virtual IOReturn reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive); - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize,UInt64 * max); - virtual IOReturn reportMaxValidBlock(UInt64 * maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 * max); - virtual IOReturn reportRemovability(bool * isRemovable); - virtual IOReturn reportWriteProtection(bool * isWriteProtected); -}; - -#endif /* !_IOATAHDDRIVENUB_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPICDDrive.h b/iokit/IOKit/storage/ata/IOATAPICDDrive.h deleted file mode 100644 index aa5e65683..000000000 --- a/iokit/IOKit/storage/ata/IOATAPICDDrive.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPICDDrive.h - Generic ATAPI CD-ROM driver. - * - * HISTORY - * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. - */ - -#ifndef _IOATAPICDDRIVE_H -#define _IOATAPICDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/ata/IOATAPIHDDrive.h> -#include <IOKit/storage/IOCDTypes.h> - -// ATAPI (inquiry) device type. -// -enum -{ - kIOATAPIDeviceTypeCDROM = 0x05 -}; - -// ATAPI packet commands. -// -enum -{ - kIOATAPICommandReadSubChannel = 0x42, - kIOATAPICommandReadTOC = 0x43, - kIOATAPICommandPlayAudioMSF = 0x47, - kIOATAPICommandPauseResume = 0x4b, - kIOATAPICommandStopPlay = 0x4e, - kIOATAPICommandScan = 0xba, - kIOATAPICommandReadCD = 0xbe -}; - -//=========================================================================== -// IOATAPICDDrive -//=========================================================================== - -class IOATAPICDDrive : public IOATAPIHDDrive -{ - OSDeclareDefaultStructors(IOATAPICDDrive) - -protected: - //----------------------------------------------------------------------- - // Given the device type from the ATAPI Inquiry data, returns true if - // the device type is supported by this driver. - - virtual bool matchATAPIDeviceType(UInt8 type, SInt32 * score); - - //---------------------------------------------------------------------- - // ATAPI Read Subchannel command (42). - - virtual IOATACommand * atapiCommandReadSubChannel( - IOMemoryDescriptor * buffer, - UInt8 dataFormat, - UInt8 trackNumber); - - //----------------------------------------------------------------------- - // ATAPI Read TOC command (43). - - virtual IOATACommand * atapiCommandReadTOC( - IOMemoryDescriptor * buffer, - bool msf, - UInt8 format, - UInt8 startTrackSession); - - //---------------------------------------------------------------------- - // ATAPI Play Audio command (47). - - virtual IOATACommand * atapiCommandPlayAudioMSF( - CDMSF timeStart, - CDMSF timeStop); - - //---------------------------------------------------------------------- - // ATAPI Pause/Resume command (4b). - - virtual IOATACommand * atapiCommandPauseResume( - bool resume); - - - //---------------------------------------------------------------------- - // ATAPI STOP PLAY/SCAN command (4e). - - virtual IOATACommand * atapiCommandStopPlay(); - - //---------------------------------------------------------------------- - // ATAPI Read CD command (b9). - - virtual IOATACommand * atapiCommandReadCD( - IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType); - - //---------------------------------------------------------------------- - // ATAPI Scan command (ba). - - virtual IOATACommand * atapiCommandScan( - CDMSF timeStart, - bool reverse); - - //----------------------------------------------------------------------- - // Overrides the method in IOATAPIHDDrive and returns an - // IOATAPICDDriveNub instance. - - virtual IOService * instantiateNub(); - -public: - //----------------------------------------------------------------------- - // Handles read CD requests. - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - - //----------------------------------------------------------------------- - // IOATAHDDrive override. Returns the device type. - - virtual const char * getDeviceTypeName(); - - //----------------------------------------------------------------------- - // IOATAPIHDDrive override. Reports whether media is write protected. - - virtual IOReturn reportWriteProtection(bool * isWriteProtected); - - //----------------------------------------------------------------------- - // Read the Table of Contents. - - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - //----------------------------------------------------------------------- - // Play audio - - virtual IOReturn audioPause(bool pause); - - virtual IOReturn audioPlay(CDMSF timeStart, CDMSF timeStop); - - virtual IOReturn audioScan(CDMSF timeStart, bool reverse); - - virtual IOReturn audioStop(); - - virtual IOReturn getAudioStatus(CDAudioStatus *status); - - virtual IOReturn getAudioVolume(UInt8 * leftVolume, - UInt8 * rightVolume); - - virtual IOReturn setAudioVolume(UInt8 leftVolume, - UInt8 rightVolume); - - virtual IOReturn readModeSense(UInt8 * buffer, - UInt32 length, UInt8 pageCode, - UInt8 pageControl = 0); - - virtual IOReturn writeModeSelect(UInt8 * buffer, - UInt32 length); - - virtual IOReturn readSubChannel(UInt8 * buffer, - UInt32 length, - UInt8 dataFormat, - UInt8 trackNumber); - - virtual IOReturn readMCN(CDMCN mcn); - - virtual IOReturn readISRC(UInt8 track, CDISRC isrc); -}; - -#endif /* !_IOATAPICDDRIVE_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPICDDriveNub.h b/iokit/IOKit/storage/ata/IOATAPICDDriveNub.h deleted file mode 100644 index 6a0465f93..000000000 --- a/iokit/IOKit/storage/ata/IOATAPICDDriveNub.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPICDDriveNub.h - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * 2-Sep-1999 Joe Liu (jliu) created. - */ - -#ifndef _IOATAPICDDRIVENUB_H -#define _IOATAPICDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDBlockStorageDevice.h> - -class IOATAPICDDrive; - -class IOATAPICDDriveNub : public IOCDBlockStorageDevice -{ - OSDeclareDefaultStructors(IOATAPICDDriveNub) - -protected: - IOATAPICDDrive * _provider; - -public: - /* - * Overrides from IOService. - */ - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - /* - * Mandatory overrides from IOBlockStorageDevice. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doSynchronizeCache(); - virtual IOReturn doEjectMedia(); - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual char * getVendorString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getAdditionalDeviceInfoString(); - virtual IOReturn reportBlockSize(UInt64 * blockSize); - virtual IOReturn reportEjectability(bool * isEjectable); - virtual IOReturn reportLockability(bool * isLockable); - virtual IOReturn reportMediaState(bool * mediaPresent, bool * changed); - virtual IOReturn reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive); - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize, UInt64 * max); - virtual IOReturn reportMaxValidBlock(UInt64 * maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize, UInt64 * max); - virtual IOReturn reportRemovability(bool * isRemovable); - virtual IOReturn reportWriteProtection(bool * isWriteProtected); - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - virtual UInt32 getMediaType(); - virtual IOReturn readISRC(UInt8 track, CDISRC isrc); - virtual IOReturn readMCN(CDMCN mcn); - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - virtual IOReturn audioPause(bool pause); - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop); - virtual IOReturn audioScan(CDMSF timeStart,bool reverse); - virtual IOReturn audioStop(); - virtual IOReturn getAudioStatus(CDAudioStatus * status); - virtual IOReturn getAudioVolume(UInt8 * leftVolume, - UInt8 * rightVolume); - virtual IOReturn setAudioVolume(UInt8 leftVolume, UInt8 rightVolume); -}; - -#endif /* !_IOATAPICDDRIVENUB_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPIDVDDrive.h b/iokit/IOKit/storage/ata/IOATAPIDVDDrive.h deleted file mode 100644 index 23525e6e8..000000000 --- a/iokit/IOKit/storage/ata/IOATAPIDVDDrive.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _IOATAPIDVDDRIVE_H -#define _IOATAPIDVDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/ata/IOATAPICDDrive.h> -#include <IOKit/storage/IODVDTypes.h> - -enum { - kIOATAPIFeatureProfileList = 0x0000, - kIOATAPIFeatureCore = 0x0001, - kIOATAPIFeatureMorphing = 0x0002, - kIOATAPIFeatureRemovableMedium = 0x0003, - kIOATAPIFeatureRandomReadable = 0x0010, - kIOATAPIFeatureMultiRead = 0x001d, - kIOATAPIFeatureCDRead = 0x001e, - kIOATAPIFeatureDVDRead = 0x001f, - kIOATAPIFeatureRandomWrite = 0x0020, - kIOATAPIFeatureIncrStreamWrite = 0x0021, - kIOATAPIFeatureSectorErasable = 0x0022, - kIOATAPIFeatureFormattable = 0x0023, - kIOATAPIFeatureDefectManagement = 0x0024, - kIOATAPIFeatureWriteOnce = 0x0025, - kIOATAPIFeatureRestrictedOverwrite = 0x0026, - kIOATAPIFeatureDVDRWRestrictedOverwrite = 0x002c, - kIOATAPIFeatureCDTrackAtOnce = 0x002d, - kIOATAPIFeatureCDMastering = 0x002e, - kIOATAPIFeatureDVDR_RWWrite = 0x002f, - kIOATAPIFeaturePowerManagement = 0x0100, - kIOATAPIFeatureSMART = 0x0101, - kIOATAPIFeatureEmbeddedChanger = 0x0102, - kIOATAPIFeatureCDAudioAnalogPlay = 0x0103, - kIOATAPIFeatureMicrocodeUpgrade = 0x0104, - kIOATAPIFeatureTimeout = 0x0105, - kIOATAPIFeatureDVDCSS = 0x0106, - kIOATAPIFeatureRealTimeStreaming = 0x0107, - kIOATAPIFeatureLUNSerialNumber = 0x0108, - kIOATAPIFeatureDiskControlBlocks = 0x010a, - kIOATAPIFeatureDVDCPRM = 0x010b -}; - -// DVD specific command codes. - -enum { - kIOATAPICommandGetConfiguration = 0x46, - kIOATAPICommandSendKey = 0xa3, - kIOATAPICommandReportKey = 0xa4, - kIOATAPICommandReadDVDStructure = 0xad -}; - -// Format code definitions for READ DVD STRUCTURE command. - -enum { - kIODVDReadStructurePhysical = 0x00, - kIODVDReadStructureCopyright = 0x01, - kIODVDReadStructureWriteProtection = 0xC0 -}; - -#define IODVDGetDataLength16(ptr) OSReadBigInt16((void *) ptr, 0) -#define IODVDGetDataLength32(ptr) OSReadBigInt32((void *) ptr, 0) - -#if defined(__BIG_ENDIAN__) - -// Big Endian DVD structure definitions. - -struct IODVDStructurePhysical -{ - UInt8 length[2]; - UInt8 rsvd1[2]; - - UInt8 bookType : 4, - partVersion : 4; - -#define kIODVDBookTypeDVDROM 0 -#define kIODVDBookTypeDVDRAM 1 -#define kIODVDBookTypeDVDR 2 -#define kIODVDBookTypeDVDRW 3 -#define kIODVDBookTypeDVDPlusRW 9 - - UInt8 diskSize : 4, - maximumRate : 4; - - UInt8 rsvd2 : 1, - layers : 2, - trackPath : 1, - layerType : 4; - - UInt8 linearDensity : 4, - trackDensity : 4; - - UInt8 zero1; - UInt8 dataAreaPSNStart[3]; - UInt8 zero2; - UInt8 dataAreaPSNEnd[3]; - UInt8 zero3; - UInt8 layerZeroEndSectorNumber; - - UInt8 bcaFlag : 1, - rsvd3 : 7; -}; - -struct IODVDStructureWriteProtection -{ - UInt8 length[2]; - UInt8 rsvd1[2]; - - UInt8 rsvd2 : 4, - mswi : 1, - cwp : 1, - pwp : 1, - swpp : 1; - - UInt8 rsvd3[3]; -}; - -#elif defined(__LITTLE_ENDIAN__) - -// Little Endian DVD structure definitions. - -struct IODVDStructurePhysical -{ - UInt8 length[2]; - UInt8 rsvd1[2]; - - UInt8 partVersion : 4, - bookType : 4; - -#define kIODVDBookTypeDVDROM 0 -#define kIODVDBookTypeDVDRAM 1 -#define kIODVDBookTypeDVDR 2 -#define kIODVDBookTypeDVDRW 3 -#define kIODVDBookTypeDVDPlusRW 9 - - UInt8 maximumRate : 4, - diskSize : 4; - - UInt8 layerType : 4, - trackPath : 1, - layers : 2, - rsvd2 : 1; - - UInt8 trackDensity : 4, - linearDensity : 4; - - UInt8 zero1; - UInt8 dataAreaPSNStart[3]; - UInt8 zero2; - UInt8 dataAreaPSNEnd[3]; - UInt8 zero3; - UInt8 layerZeroEndSectorNumber; - - UInt8 rsvd3 : 7, - bcaFlag : 1; -}; - -struct IODVDStructureWriteProtectionStatus -{ - UInt8 length[2]; - UInt8 rsvd1[2]; - - UInt8 swpp : 1, - pwp : 1, - cwp : 1, - mswi : 1, - rsvd2 : 4; - - UInt8 rsvd3[3]; -}; - -#else -#error Unknown endianess. -#endif - -//=========================================================================== -// IOATAPIDVDDrive -//=========================================================================== - -class IOATAPIDVDDrive : public IOATAPICDDrive -{ - OSDeclareDefaultStructors(IOATAPIDVDDrive) - -protected: - virtual IOReturn determineMediaType(UInt32 * mediaType); - - virtual IOReturn getConfiguration(UInt8 * buffer, - UInt32 length, - UInt32 * actualLength, - bool current); - - virtual IOReturn classifyDrive(bool * isDVDDrive); - - virtual bool matchATAPIDeviceType(UInt8 type, SInt32 * score); - - virtual IOService * instantiateNub(); - - virtual IOATACommand * atapiCommandGetConfiguration( - IOMemoryDescriptor * buffer, - UInt8 rt, - UInt16 sfn = 0); - - virtual IOATACommand * atapiCommandSendKey( - IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat); - - virtual IOATACommand * atapiCommandReportKey( - IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat); - - virtual IOATACommand * atapiCommandReadDVDStructure( - IOMemoryDescriptor * buffer, - UInt8 format, - UInt32 address = 0, - UInt8 layer = 0, - UInt8 agid = 0); - -public: - virtual bool init(OSDictionary * properties); - - virtual const char * getDeviceTypeName(); - - virtual UInt32 getMediaType(); - - virtual IOReturn reportWriteProtection(bool * isWriteProtected); - - virtual IOReturn reportMediaState(bool * mediaPresent, bool * changed); - - virtual IOReturn reportKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat); - - virtual IOReturn sendKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat); -}; - -#endif /* ! _IOATAPIDVDDRIVE_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPIDVDDriveNub.h b/iokit/IOKit/storage/ata/IOATAPIDVDDriveNub.h deleted file mode 100644 index 1f7bddcf5..000000000 --- a/iokit/IOKit/storage/ata/IOATAPIDVDDriveNub.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIDVDDriveNub.h - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * 2-Sep-1999 Joe Liu (jliu) created. - */ - -#ifndef _IOATAPIDVDDRIVENUB_H -#define _IOATAPIDVDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/IODVDTypes.h> - -class IOATAPIDVDDrive; - -class IOATAPIDVDDriveNub : public IODVDBlockStorageDevice -{ - OSDeclareDefaultStructors(IOATAPIDVDDriveNub) - -protected: - IOATAPIDVDDrive * _provider; - -public: - /* - * Overrides from IOService. - */ - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - /* - * Mandatory overrides from IOBlockStorageDevice. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doSynchronizeCache(); - virtual IOReturn doEjectMedia(); - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual char * getVendorString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getAdditionalDeviceInfoString(); - virtual IOReturn reportBlockSize(UInt64 * blockSize); - virtual IOReturn reportEjectability(bool * isEjectable); - virtual IOReturn reportLockability(bool * isLockable); - virtual IOReturn reportMediaState(bool * mediaPresent, bool * changed); - virtual IOReturn reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive); - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize, UInt64 * max); - virtual IOReturn reportMaxValidBlock(UInt64 * maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize, UInt64 * max); - virtual IOReturn reportRemovability(bool * isRemovable); - virtual IOReturn reportWriteProtection(bool * isWriteProtected); - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - virtual UInt32 getMediaType(); - virtual IOReturn readISRC(UInt8 track, CDISRC isrc); - virtual IOReturn readMCN(CDMCN mcn); - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - virtual IOReturn audioPause(bool pause); - virtual IOReturn audioPlay(CDMSF timeStart, CDMSF timeStop); - virtual IOReturn audioScan(CDMSF timeStart, bool reverse); - virtual IOReturn audioStop(); - virtual IOReturn getAudioStatus(CDAudioStatus * status); - virtual IOReturn getAudioVolume(UInt8 * leftVolume, - UInt8 * rightVolume); - virtual IOReturn setAudioVolume(UInt8 leftVolume, - UInt8 rightVolume); - /*-----------------------------------------*/ - /* DVD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn reportKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt32 lba, - const UInt8 agid, - const DVDKeyFormat keyFormat); - - virtual IOReturn sendKey(IOMemoryDescriptor * buffer, - const DVDKeyClass keyClass, - const UInt8 agid, - const DVDKeyFormat keyFormat); -}; - -#endif /* !_IOATAPIDVDDRIVENUB_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPIHDDrive.h b/iokit/IOKit/storage/ata/IOATAPIHDDrive.h deleted file mode 100644 index 02ac00b7a..000000000 --- a/iokit/IOKit/storage/ata/IOATAPIHDDrive.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIHDDrive.h - Generic ATAPI Direct-Access driver. - * - * HISTORY - * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. - */ - -#ifndef _IOATAPIHDDRIVE_H -#define _IOATAPIHDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/ata/IOATAHDDrive.h> - -// ATAPI (inquiry) device type. -// -enum IOATAPIDeviceType -{ - kIOATAPIDeviceTypeDirectAccess = 0x00 -}; - -// ATAPI packet commands. -// -enum { - kIOATAPICommandTestUnitReady = 0x00, - kIOATAPICommandFormatUnit = 0x04, - kIOATAPICommandStartStopUnit = 0x1b, - kIOATAPICommandPreventAllow = 0x1e, - kIOATAPICommandSynchronizeCache = 0x35, - kIOATAPICommandModeSelect = 0x55, - kIOATAPICommandModeSense = 0x5a, - kIOATAPICommandRead = 0xa8, - kIOATAPICommandWrite = 0xaa -}; - -// ATAPI feature register flags. -// -enum { - kIOATAPIFeaturesDMA = 0x01, - kIOATAPIFeaturesOverlay = 0x02, -}; - -#define kIOATAPIMaxTransfer 65534 - - -//=========================================================================== -// IOATAPIHDDrive -//=========================================================================== - -class IOATAPIHDDrive : public IOATAHDDrive -{ - OSDeclareDefaultStructors(IOATAPIHDDrive) - -protected: - char _vendor[9]; - char _product[17]; - bool _mediaPresent; - bool _isRemovable; - ATAProtocol _atapiProtocol; - bool _isLocked; - - //----------------------------------------------------------------------- - // Selects a command protocol to use. The argument specifies whether - // the device supports DMA mode. - - virtual bool selectCommandProtocol(bool isDMA); - - //----------------------------------------------------------------------- - // Issues an ATAPI Start/Stop Unit command. - - virtual IOReturn doStartStop(bool doStart); - - //----------------------------------------------------------------------- - // Given the device type from the ATAPI Inquiry data, returns true if - // the device type is supported by this driver. - - virtual bool matchATAPIDeviceType(UInt8 type, SInt32 * score); - - //----------------------------------------------------------------------- - // Setup a ATATaskFile for an ATAPI packet command from the parameters - // given. - - virtual void setupPacketTaskFile(ATATaskfile * taskfile, - ATAProtocol protocol, - UInt16 byteCount); - - //----------------------------------------------------------------------- - // Create a generic ATAPI command object. - - virtual IOATACommand * atapiCommand(ATACDBInfo * packetCommand, - IOMemoryDescriptor * transferBuffer = 0); - - //----------------------------------------------------------------------- - // Allocates and return an IOATACommand to perform a read/write operation. - - virtual IOATACommand * atapiCommandReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - //----------------------------------------------------------------------- - // ATAPI Start/Stop Unit command (1B). - - virtual IOATACommand * atapiCommandStartStopUnit(bool doStart, - bool doLoadEject, - bool immediate); - - //----------------------------------------------------------------------- - // ATAPI Format Unit command (04). - - virtual IOATACommand * atapiCommandFormatUnit( - UInt16 interleave, - UInt8 flagBits, - UInt8 vendorBits, - IOMemoryDescriptor * formatData); - - //----------------------------------------------------------------------- - // ATAPI Synchronize Cache command (35). - - virtual IOATACommand * atapiCommandSynchronizeCache(); - - //----------------------------------------------------------------------- - // ATAPI Prevent/Allow medium removal command (1E). - - virtual IOATACommand * atapiCommandPreventAllowRemoval(bool doLock); - - //----------------------------------------------------------------------- - // ATAPI Test Unit Ready command (00). - - virtual IOATACommand * atapiCommandTestUnitReady(); - - //---------------------------------------------------------------------- - // ATAPI Mode Sense command (5a). - - virtual IOATACommand * atapiCommandModeSense( - IOMemoryDescriptor * buffer, - UInt8 pageCode, - UInt8 pageControl); - - //---------------------------------------------------------------------- - // ATAPI Mode Select command (55). - - virtual IOATACommand * atapiCommandModeSelect( - IOMemoryDescriptor * buffer); - - //----------------------------------------------------------------------- - // Overrides the method in IOATAHDDrive and returns an IOATAPIHDDriveNub - // instance. - - virtual IOService * instantiateNub(); - - //----------------------------------------------------------------------- - // Overrides the method in IOATAHDDrive. Inspect the ATAPI device. - - virtual bool inspectDevice(IOATADevice * device); - - //----------------------------------------------------------------------- - // Overrides the method in IOATAHDDrive. Add ATAPI wakeup handler. - - virtual void handleActiveStateTransition( UInt32 stage, - IOReturn status ); - -public: - /* - * IOATAHDDrive overrides. - */ - virtual bool init(OSDictionary * properties); - virtual IOService * probe(IOService * provider, SInt32 * score); - - virtual ATADeviceType reportATADeviceType() const; - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - - virtual IOReturn doEjectMedia(); - - virtual IOReturn doFormatMedia(UInt64 byteCapacity, - IOMemoryDescriptor * formatData = 0); - - virtual IOReturn doLockUnlockMedia(bool doLock); - - virtual IOReturn doSynchronizeCache(); - - virtual IOReturn doStart(); - virtual IOReturn doStop(); - - virtual char * getVendorString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getAdditionalDeviceInfoString(); - - virtual IOReturn reportEjectability(bool * isEjectable); - virtual IOReturn reportLockability(bool * isLockable); - virtual IOReturn reportPollRequirements(bool * pollRequired, - bool * pollIsExpensive); - - virtual IOReturn reportMediaState(bool * mediaPresent, - bool * changed); - - virtual IOReturn reportRemovability(bool * isRemovable); - - virtual IOReturn reportWriteProtection(bool * isWriteProtected); -}; - -#endif /* !_IOATAPIHDDRIVE_H */ diff --git a/iokit/IOKit/storage/ata/IOATAPIHDDriveNub.h b/iokit/IOKit/storage/ata/IOATAPIHDDriveNub.h deleted file mode 100644 index eb2933096..000000000 --- a/iokit/IOKit/storage/ata/IOATAPIHDDriveNub.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOATAPIHDDriveNub.h - * - * This subclass implements a relay to a protocol and device-specific - * provider. - * - * HISTORY - * 2-Sep-1999 Joe Liu (jliu) created. - */ - -#ifndef _IOATAPIHDDRIVENUB_H -#define _IOATAPIHDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOBlockStorageDevice.h> - -class IOATAPIHDDrive; - -class IOATAPIHDDriveNub : public IOBlockStorageDevice -{ - OSDeclareDefaultStructors(IOATAPIHDDriveNub) - -protected: - IOATAPIHDDrive * _provider; - -public: - /* Overrides from IOService */ - - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - /* Mandatory overrides from IOBlockStorageDevice */ - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks, - IOStorageCompletion completion); - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor * buffer, - UInt32 block, - UInt32 nblks); - virtual IOReturn doEjectMedia(); - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual IOReturn doSynchronizeCache(); - virtual char * getVendorString(); - virtual char * getProductString(); - virtual char * getRevisionString(); - virtual char * getAdditionalDeviceInfoString(); - virtual IOReturn reportBlockSize(UInt64 * blockSize); - virtual IOReturn reportEjectability(bool * isEjectable); - virtual IOReturn reportLockability(bool * isLockable); - virtual IOReturn reportMediaState(bool * mediaPresent, bool * changed); - virtual IOReturn reportPollRequirements(bool * pollIsRequired, - bool * pollIsExpensive); - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize,UInt64 * max); - virtual IOReturn reportMaxValidBlock(UInt64 * maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 * max); - virtual IOReturn reportRemovability(bool * isRemovable); - virtual IOReturn reportWriteProtection(bool * isWriteProtected); -}; - -#endif /* !_IOATAPIHDDRIVENUB_H */ diff --git a/iokit/IOKit/storage/ata/Makefile b/iokit/IOKit/storage/ata/Makefile deleted file mode 100644 index 7067075f2..000000000 --- a/iokit/IOKit/storage/ata/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = storage/ata -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = -INSTALL_MI_LCL_LIST = "" -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/storage/scsi/IOBasicSCSI.h b/iokit/IOKit/storage/scsi/IOBasicSCSI.h deleted file mode 100644 index 4c3b356e8..000000000 --- a/iokit/IOKit/storage/scsi/IOBasicSCSI.h +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* ============================================================================= - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * IOBasicSCSI.h - * - * This class implements generic SCSI functionality. - */ - -#ifndef _IOBASICSCSI_H -#define _IOBASICSCSI_H - -#include <IOKit/IOTypes.h> -#include <IOKit/IOService.h> -#include <IOKit/IOSyncer.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/IOStorage.h> - -const int kMinInqSize = 5; /* minimal, supported by all devs */ -const int kReadCapSize = 8; -const int kModeSenseSize = 64; -const int kMaxInqSize = 256; - -const int kCheckCondition = 0x02; -const int kUnitAttention = 0x06; - -/* SCSI operation codes: */ - -const UInt8 SOP_TUR = 0x00; /* test unit ready */ -const UInt8 SOP_INQUIRY = 0x12; /* inquiry */ -const UInt8 SOP_MODESELECT = 0x15; /* mode select */ -const UInt8 SOP_MODESENSE = 0x1a; /* mode sense */ -const UInt8 SOP_READCAP = 0x25; /* read capacity */ -const UInt8 SOP_READ10 = 0x28; /* read (10-byte) */ -const UInt8 SOP_WRITE10 = 0x2a; /* write (10-byte) */ - -struct IOTURcdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 reserved1; - UInt8 reserved2; - UInt8 reserved3; - UInt8 ctlbyte; -}; - -struct IORWcdb { /* CDB for read and write */ - UInt8 opcode; /* read=0x28, write=0x2a */ - UInt8 lunbits; /* lun and control bits */ - UInt8 lba_3; /* logical block address: msb */ - UInt8 lba_2; - UInt8 lba_1; - UInt8 lba_0; /* logical block address: lsb */ - UInt8 reserved; - UInt8 count_msb; /* block count: msb */ - UInt8 count_lsb; /* block count: lsb */ - UInt8 ctlbyte; -}; - -struct IOInquirycdb { /* inquiry */ - UInt8 opcode; /* 0x12 */ - UInt8 lunbits; /* lun and control bits */ - UInt8 pagecode; /* page code/op code */ - UInt8 reserved; - UInt8 len; /* allocation length */ - UInt8 ctlbyte; -}; - -struct IOReadCapcdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 lba_3; - UInt8 lba_2; - UInt8 lba_1; - UInt8 lba_0; - UInt8 reserved1; - UInt8 reserved2; - UInt8 reserved3; - UInt8 ctlbyte; -}; - -struct IOModeSensecdb { - UInt8 opcode; - UInt8 lunbits; /* lun and control bits */ - UInt8 pagecode; - UInt8 reserved; - UInt8 len; /* allocation length */ - UInt8 ctlbyte; -}; - -struct IOModeSelectcdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 reserved1; - UInt8 reserved2; - UInt8 paramlen; - UInt8 ctlbyte; -}; - -/*! - * @enum stateValues - * @discussion - * These state values are used to determin the state of an IO operation. - * Some are simply for debugging use. - * @constant kNone - * Nothing happening. - * @constant kAsyncReadWrite - * Doing an asynchronous IO operation. - * @constant kSimpleSynchIO - * Doing a simple synchronous IO operation. - * @constant kHandlingUnitAttention - * Currently handling a Unit-Attention condition. - * @constant kDoneHandlingUnitAttention - * Done handling Unit Attention; command should be reissued. - * @constant kAwaitingPower - * Awaiting power. - * @constant kMaxValidState - * The maximum valid state value. - * @constant kMaxStateValue - * The maximum state value possible. - */ -enum stateValues { - kNone = 0, - kAsyncReadWrite = 1, - kSimpleSynchIO = 2, - kHandlingUnitAttention = 3, - kHandlingRecoveryAfterBusReset = 4, - kAwaitingPower = 5, - - kMaxValidState = kAwaitingPower, - - kMaxStateValue = 255 -}; -/*! - * @typedef statevalue - * @discussion - * Shorthand for enum StateValues. - */ -typedef enum stateValues stateValue; - -const bool kSync = true; /* type info for requests awaiting power */ -const bool kAsync = false; - -const UInt32 kMaxRetries = 3; - -/*! - * @class - * IOBasicSCSI : public IOService - * @abstract - * Basic SCSI support functions. - * @discussion - * IOBasicSCSI provides a set of basic SCSI functions and support - * utilities. It is intended to be the base class for a SCSI Transport - * Driver. - */ - -class IOBasicSCSI : public IOService { - - OSDeclareAbstractStructors(IOBasicSCSI) - -public: - - /*! - * @struct completion - * @field action - * The C function called upon completion of the operation. - * @field target - * The C++ class pointer, passed to tha action function. - * @field param - * A value passed to the action function. This value is not touched. - */ - /*! - * @struct context - * @discussion - * The context structure contains all persistent information needed for a - * synchronous or asynchronous IO operation. - * @field completion - * The completion information for an asynchronous read or write operation. - * @field state - * The current state of the operation. - * @field step - * The current step value, if we are handling a Unit Attention. - * @field originalContext - * A pointer to the context for the command that caused the Unit Attention - * condition. - * @field scsireq - * A pointer to the IOSCSIRequest object. - * @field memory - * The data buffer for the operation. A pointer to an IOMemoryDescriptor. - * @field scsiresult - * A pointer to the IOSCSIResult object. - * @field desiredPower - * The desired power level for the operation to execute. - * @field isSync - * True if synchronous; False if asynchronous. - * @field next - * A pointer to a context structure, used as a queue forward-link. - * @field sync - * A syncer used to block a thread awaiting a power level, or for completion - * of a synchronous operation. - */ - struct context { - - /* Completion information for our client, used only for async operations. - * Typically this information will only be used by subclasses. - */ - IOStorageCompletion completion; /* function to call */ - - /* Parameters used during an IO retry: */ - - stateValue state; /* what state we're in */ - UInt32 step; - struct context *originalIOContext; /* original SCSI IO if doing a retry */ - bool retryInProgress; - UInt32 retryCount; - - IOMemoryDescriptor *memory; - - UInt32 desiredPower; /* desired power level state */ - bool isSync; /* true if sync, false if async */ - struct context *next; /* for queue of requests pending power */ - /* Parameters to hand off to the SCSI provider: */ - - IOSCSICommand *scsireq; - SCSISenseData *senseData; - IOMemoryDescriptor *senseDataDesc; - - IOSyncer *sync; /* to wait for completion */ - }; - - /* Overrides from IOService: */ - - virtual void free(void); - - virtual bool init(OSDictionary * properties); - - /*! - * @function message - * @discussion - * This override allows us to receive notification of Bus Reset events from - * the SCSI Device. - */ - virtual IOReturn message(UInt32 type,IOService * provider,void * argument); - - /*! - * @function probe - * @abstract - * Determine if device matches expected type. - * @discussion - * This method is responsible for matching the device type. It calls - * doInquiry to issue a SCSI Inquiry command to the device, then calls - * deviceTypeMatches to ensure that the device type matches the expected - * type. (The Vendor, Product, and Revision strings are unconditionally - * copied from the inquiry data). If deviceTypeMatches returns true, "this" is - * returned. If the device type does not match, NULL is returned. - * - * The default implementation passes the score parameter to deviceTypeMatches - * so that method may alter the match score. - */ - virtual IOService * probe(IOService * provider,SInt32 * score); - - virtual bool start(IOService *provider); - - /* --- end of IOService overrides --- */ - - /*! - * @function deviceTypeMatches - * @abstract - * Determine if device type matches expected type. - * @discussion - * This method must be implemented by a device-specific subclass. - * @param inqBuf - * A pointer to the SCSI inquiry data for the device. - * @param inqLen - * The size of the data in the inquiry buffer. - * @param score - * A pointer to the match score, which will be returned by probe. - * @result - * True indicates a match; False indicates a failure. - */ - virtual bool deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score) = 0; - - /*! - * @function getAdditionalDeviceInfoString - * @abstract - * Return additional informational string for the device. - * @result - * A pointer to a static character string. The default implementation - * returns "[SCSI]" . - */ - virtual char * getAdditionalDeviceInfoString(void); - - /*! - * @function getVendorString - * @abstract - * Return Vendor Name string - * @result - * A pointer to a static character string, copied from the inquiry data. - */ - virtual char * getVendorString(void); - - /*! - * @function getProductString - * @abstract - * Return Product Name string for the device. - * @result - A pointer to a static character string, copied from the inquiry data. - */ - virtual char * getProductString(void); - - /*! - * @function getRevisionString - * @abstract - * Return Product Revision string for the device. - * @result - * A pointer to a static character string, copied from the inquiry data. - */ - virtual char * getRevisionString(void); - - /*! - * @function reportBlockSize - * @abstract - * Report the block size for the device, in bytes. - * @discussion - * This method returns the block size for the media. The default - * implementation obtains the block size from the SCSI Read Capacity - * command. Since the result of the Read Capacity is used by this - * method and reportMaxValidBlock, this method either returns a cached - * value or calls doReadCapacity to issue the command and cache both - * values. - * @param blockSize - * Pointer to returned block size value. - */ - virtual IOReturn reportBlockSize(UInt64 *blockSize); - - /*! - * @function reportEjectability - * @abstract - * Report if the media is ejectable under software control. - * @discussion - * This method reports whether the media is ejectable under software - * control. The default implementation always reports that removable - * media is ejectable. - * - * This method should only be called if the media is known to be removable. - * @param isEjectable - * Pointer to returned result. True indicates the media is ejectable, False indicates - * the media cannot be ejected under software control. - */ - virtual IOReturn reportEjectability(bool *isEjectable); - - /*! - * @function reportLockability - * @abstract - * Report if the media is lockable under software control. - * @discussion - * This method reports whether the media can be locked under software - * control, to prevent the user from removing the media manually, e.g. - * by pressing a button on the drive. This method is only called by - * the generic driver when the media is known to be removable. The - * default implementation always returns true. - * - * This method should only be called if the media is known to be removable. - * @param isLockable - * Pointer to returned result. True indicates the media can be locked in place; False - * indicates the media cannot be locked by software. - */ - virtual IOReturn reportLockability(bool *isLockable); - - /*! - * @function reportMaxReadTransfer - * @abstract - * Report the maximum allowed byte transfer for read operations. - * @discussion - * Some devices impose a maximum data transfer size. Because this limit - * may be determined by the size of a block-count field in a command, the limit may - * depend on the block size of the transfer. - * The default implementation reports blocksize * 65536, which is the maximum - * number of bytes that can be transferred - * in a SCSI command with a standard 16-bit block count field. - * @param blockSize - * The block size desired for the transfer. - * @param max - * Pointer to returned result. - */ - virtual IOReturn reportMaxReadTransfer (UInt64 blocksize,UInt64 *max); - - /*! - * @function reportMaxValidBlock - * @abstract - * Report the highest valid block for the device. - * @discussion - * This method reports the maximum allowable block number. The default - * implementation obtains the block number from the SCSI Read Capacity - * command. Since the result of the Read Capacity is used by this - * method and reportBlockSize, this method either returns a cached - * value or calls doReadCapacity to issue the command and cache both - * values. - * @param maxBlock - * Pointer to returned result - */ - virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock); - - /*! - * @function reportMaxWriteTransfer - * @abstract - * Report the maximum allowed byte transfer for write operations. - * @discussion - * Some devices impose a maximum data transfer size. Because this limit - * may be determined by the size of a block-count field in a command, the limit may - * depend on the block size of the transfer. - * The default implementation reports blocksize * 65536, which is the maximum - * number of bytes that can be transferred - * in a SCSI command with a standard 16-bit block count field. - * @param blockSize - * The block size desired for the transfer. - * @param max - * Pointer to returned result. - */ - virtual IOReturn reportMaxWriteTransfer(UInt64 blocksize,UInt64 *max); - - /*! - * @function reportPollRequirements - * @abstract - * Report if it's necessary to poll for media insertion, and if polling is expensive. - * @discussion - * This method reports whether the device must be polled to detect media - * insertion, and whether a poll is expensive to perform. - * - * The term "expensive" typically implies a device that must be spun-up to detect media, - * as on a PC floppy. Most devices can detect media inexpensively. - * - * The default implementation of this method always reports an - * inexpensive poll (pollIsExpensive = false), and that all removable - * media must be polled. - * @param pollRequired - * Pointer to returned result. True indicates that polling is required; False indicates - * that polling is not required to detect media. - * @param pollIsExpensive - * Pointer to returned result. True indicates that the polling operation is expensive; - * False indicates that the polling operation is cheap. - */ - virtual IOReturn reportPollRequirements(bool *pollRequired,bool *pollIsExpensive); - - /*! - * @function reportRemovability - * @abstract - * Report whether the media is removable or not. - * @discussion - * This method reports whether the media is removable, but it does not - * provide detailed information regarding software eject or lock/unlock capability. - * - * The default implementation of this method examines the cached - * Inquiry data to determine if media is removable. If the RMB bit - * (0x80 of Inquiry data byte 1) is set, the media is removable. If - * there is no Inquiry data, the media is reported to be nonremovable. - * - * This method also sets the instance variable _removable. - * @param isRemovable - * Pointer to returned result. True indicates that the media is removable; False - * indicates the media is not removable. - */ - virtual IOReturn reportRemovability(bool *isRemovable); - - /*! - * @function reportWriteProtection - * @abstract - * Report whether the media is write-protected or not. - * @discussion - * The default implementation of this method issues a SCSI Mode Sense - * command to test the WP bit( 0x80 of byte 2 of the Mode Sense Header - * data). A request is made for Mode Sense Page 1, though any valid - * page will return a header. If the bit is set, the media is considered - * write-protected. - * @param isWriteProtected - * Pointer to returned result. True indicates that the media is write-protected (it - * cannot be written); False indicates that the media is not write-protected (it - * is permissible to write). - */ - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - -protected: - - /*! - * @function createReadCdb - * @abstract - * Create a SCSI CDB for a read operation. - * @discussion - * Override this to control the cdb created for a read operation. - * The default implementation creates a 10-byte read command with - * disconnect allowed, 8-byte autosense, and a 2-second timeout. - * @param cdb - * A pointer to the CDB bytes. - * @param cdbLength - * The length of the CDB in bytes. - * @param block - * The device block to be read. - * @param nblks - * The number of blocks to be transferred. - * @param maxAutoSenseLength - * The maximum size of the autosense data, in bytes. A value of zero - * will disable autosense. - * @param timeoutSeconds - * The command timeout in seconds. - * @result - * The IOSCSICommandOptions returned will be used to issue the command. - */ - virtual UInt32 createReadCdb( - UInt8 *cdb, /* in */ - UInt32 *cdbLength, /* out */ - UInt32 block, /* in */ - UInt32 nblks, /* in */ - UInt32 *maxAutoSenseLength, /* out */ - UInt32 *timeoutSeconds); /* out */ - - /*! - * @function createWriteCdb - * @abstract - * Create a SCSI CDB for a write operation. - * @discussion - * Override this to control the cdb created for a write operation. - * The default implementation creates a 10-byte write command with - * disconnect allowed, 8-byte autosense, and a 2-second timeout. - * @param cdb - * A pointer to the CDB bytes. - * @param cdbLength - * The length of the CDB in bytes. - * @param block - * The device block to be written. - * @param nblks - * The number of blocks to be transferred. - * @param maxAutoSenseLength - * The maximum size of the autosense data, in bytes. A value of zero - * will disable autosense. - * @param timeoutSeconds - * The command timeout in seconds. - * @result - * The IOSCSICommandOptions returned will be used to issue the command. - */ - virtual UInt32 createWriteCdb( - UInt8 *cdb, /* in */ - UInt32 *cdbLength, /* out */ - UInt32 block, /* in */ - UInt32 nblks, /* in */ - UInt32 *maxAutoSenseLength, /* out */ - UInt32 *timeoutSeconds); /* out */ - - - /*! - * @function doInquiry - * @abstract - * Obtain SCSI Inquiry data from the device. - * @discussion - * This method issues a SCSI Inquiry command to the device, to obtain - * the result in the supplied buffer. The method first issues an - * inquiry with a 5-byte length, to obtain the full length of the - * devices inquiry data. The second Inquiry command is issued to get - * the full inquiry data (limited to maxLen, of course). - * @param inqBuf - * A pointer to the buffer. - * @param maxLen - * The maximum number of bytes the buffer can contain. - * @param actualLen - * A pointer to the returned byte count actually transferred. - */ - virtual IOReturn doInquiry(UInt8 *inqBuf,UInt32 maxLen,UInt32 *actualLen); - - /* ---------------- Internally used methods. ---------------- */ - - /* - * @group - * Internally Used Methods - * @discussion - * These methods are used internally, and will not generally be modified. - */ - - /*! - * @function allocateContext - * @abstract - * Allocate a context structure for use with the current IO operation. - */ - virtual struct context * allocateContext(void); - - /*! - * @function allocateInquiryBuffer - * @abstract - * Allocate an inquiry buffer. - * @param buf - * A pointer for the returned buffer pointer. - * @param size - * The requested size of the buffer, in bytes. - */ - virtual IOReturn allocateInquiryBuffer(UInt8 **buf,UInt32 size); - - /*! - * @function allocateTempBuffer - * @abstract - * Allocate a buffer for temporary use. - * @param buf - * A pointer for the returned buffer pointer. - * @param size - * The requested size of the buffer, in bytes. - */ - virtual IOReturn allocateTempBuffer(UInt8 **buf,UInt32 size); - - /*! - * @function allocateReadCapacityBuffer - * @abstract - * Allocate a buffer for Read-Capacity data. - * @param buf - * A pointer for the returned buffer pointer. - * @param size - * The requested size of the buffer, in bytes. - */ - virtual IOReturn allocateReadCapacityBuffer(UInt8 **buf,UInt8 size); - - /*! - * @function automaticRetry - * @abstract - * Return TRUE if we should automatically retry the command just completed. - * @discussion - * The default implementation of this method reacts to Unit Attention and - * Bus Reset conditions, possibly starting the recovery processes for those - * conditions and arranging that the subject command is retried after - * the recovery procedure finishes. - * @param cx - * A pointer to the context for the command just completed. - */ - virtual bool automaticRetry(struct context *cx); - - /*! - * @function beginBusResetRecovery - * @abstract - * Begin the Bus Reset recovery process. - * @discussion - * This method can be overridden to issue the first command necessary - * to perform the Bus Reset recovery process for the device. - * - * The default implementation does nothing and simply calls finishBusResetRecovery. - */ - virtual void beginBusResetRecovery(void); - - /*! - * @function beginUnitAttentionRecovery - * @abstract - * Begin the Unit Attention recovery process. - * @discussion - * This method can be overridden to issue the first command necessary - * to perform the Bus Reset recovery process for the device. - * - * The default implementation does nothing and simply calls finishUnitAttentionRecovery. - */ - virtual void beginUnitAttentionRecovery(void); - - /*! - * @function busResetRecoveryCommandComplete - * @abstract - * Handle a command completion during the Bus Reset recovery process. - * @discussion - * This method can be overridden to check the result of each command issued - * during the Bus Reset recovery process for the device. Typically it would - * bump the "step" value and issue the next command, calling finishBusResetRecovery - * when the process is complete. - * - * The default implementation does nothing. - */ - virtual void busResetRecoveryCommandComplete(struct context *cx); - - /*! - * @function customAutomaticRetry - * @abstract - * Return TRUE if we should automatically retry the command just completed. - * @discussion - * This method should be overridden to allow checking for, and causing, an - * automatic retry of a command. - * - * The default implementation of this method does nothing except return FALSE. - * @param cx - * A pointer to the context for the command just completed. - */ - virtual bool customAutomaticRetry(struct context *cx); - - /*! - * @function deleteContext - * @abstract - * Delete a context structure. - * @discussion - * This method also issues a "release" for the IO buffer and/or lock, if any. - * @param cx - * A pointer to the context structure to be deleted. - */ - virtual void deleteContext(struct context *cx); - - /*! - * @function deleteInquiryBuffer - * @abstract - * Delete an inquiry data buffer. - * @param buf - * A pointer to the buffer. - * @param size - * The requested size of the buffer, in bytes. - */ - virtual void deleteInquiryBuffer(UInt8 *buf,UInt32 size); - - /*! - * @function deleteTempBuffer - * @abstract - * Delete a temporary data buffer. - * @param buf - * A pointer to the buffer. - * @param len - * The requested size of the buffer, in bytes. - */ - virtual void deleteTempBuffer(UInt8 *buf,UInt32 len); - - /*! - * @function deleteReadCapacityBuffer - * @abstract - * Delete a Read-Capacity data buffer. - * @param buf - * A pointer to the buffer. - * @param len - * The requested size of the buffer, in bytes. - */ - virtual void deleteReadCapacityBuffer(UInt8 *buf,UInt32 len); - - /*! - * @function doReadCapacity - * @abstract - * @discussion - * The default implementation of this method issues a standard SCSI - * Read Capacity command. The block size and maximum valid block are - * extracted from the returned data in an endian-neutral way. - * @param blockSize - * A pointer to the returned block size value. - * @param maxBlock - * A pointer to the returned maximum block number. - */ - virtual IOReturn doReadCapacity(UInt64 *blockSize,UInt64 *maxBlock); - - /*! - * @function finishBusResetRecovery - * @abstract - * Finish up after the Bus Reset recovery process is complete. - * @discussion - * This method would usually not require an override. - */ - virtual void finishBusResetRecovery(void); - - /*! - * @function finishUnitAttentionRecovery - * @abstract - * Finish up after the Unit Attention recovery process is complete. - * @discussion - * This method would usually not require an override. - */ - virtual void finishUnitAttentionRecovery(void); - - /*! - * @function getBlockSize - * @abstract - * Return the device block size. - * @discussion - * This method obtains the block size from the Read-Capacity data. If RC data is - * not yet cached, a call is made to doReadCapacity to obtain the data. - */ - virtual UInt64 getBlockSize(void); - - - /*! - * @function dequeueCommands - * @abstract - * Dequeue commands previously enqueued awaiting the proper device power level. - * @discussion - * This method is called when a command is queued (from queueCommand), when a call - * completes (from RWCompletion), and when the device power level changes. All commands - * for which the device power level is proper are immediately dequeued. - * - * Queued synchronous commands are simply "awakened" by unlocking a lock. The originating - * thread then continues and issues the command. Asynchronous commands are immediately - * dispatched via a call to standardAsyncReadWriteExecute. - */ - virtual void dequeueCommands(void); - - /*! - * @function queueCommand - * @abstract - * Queue commands awaiting the proper device power level. - * @discussion - * This method is called prior to issuing any IO command, so that each command can - * be enqueued awaiting its desired device power level. After queuing the command, a - * call is made to dequeueCommands to attempt to dequeue any available command that can - * be executed (including the one just queued). Putting commands into the queue ensures - * that the proper sequence is maintained. - * @param cx - * The context for the command being queued. - * @param isSync - * True if the command is synchronous; False if the command is asynchronous. - * @param desiredPower - * The device power level needed before the command can execute. - */ - virtual void queueCommand(struct context *cx,bool isSync,UInt32 desiredPower); - - /*! - * @function RWCompletion - * @abstract - * Asynchronous read/write completion routine. - * @discussion - * A subclass must implement the read-write completion, called upon completion - * of an IO started by doAsyncReadWrite. - * @param cx - * A pointer to the context structure for the completing command. - */ - virtual void RWCompletion(struct context *cx) = 0; - - /*! - * @function setupBusResetRecovery - * @abstract - * Set up to begin Bus Reset recovery. - * @discussion - * This method would usually not require an override. - */ - virtual void setupBusResetRecovery(void); - - /*! - * @function setupUnitAttentionRecovery - * @abstract - * Set up to begin Unit Attention recovery. - * @discussion - * This method would usually not require an override. - */ - virtual void setupUnitAttentionRecovery(struct context *cx); - - /*! - * @function simpleAsynchIO - * @abstract - * Issue a simple asynchronous SCSI command. - * @discussion - * This method issues a single SCSI command. - * The SCSI command must already be set up in the context structure. - * @param cx - * A pointer to the context structure for the command. - */ - virtual IOReturn simpleAsynchIO(struct context *cx); - - /*! - * @function simpleSynchIO - * @abstract - * Issue a simple synchronous SCSI command. - * @discussion - * This method issues a single SCSI command and waits for the command - * to complete. The SCSI command must already be set up in the context - * structure. - * @param cx - * A pointer to the context structure for the command. - */ - virtual IOReturn simpleSynchIO(struct context *cx); - - /*! - * @function standardAsyncReadWrite - * @abstract - * Start an asynchronous read or write operation. - * @discussion - * This method starts an asynchronous read or write operation. No - * incoming parameters are validated. The default implementation - * calls createReadCdb or createWriteCdb, - * then issues a SCSI command to IOSCSIDevice. If the command is - * accepted, then the completion will be called at some future time. - * @result - * The only possible returns from this method are: - * - * kIOReturnSuccess, meaning that the IO was accepted by the transport - * drivers provider (e.g. IOSCSIDevice), and that the completion - * function will be called when the IO completes, i.e. target->action(param). - * - * kIOReturnNoMemory, meaning that memory allocation failed. - * - * Other kIOReturn codes from the provider which occurred - * because the IO was not accepted in that provider's queue. This - * might indicate a full queue or bad parameter. - * @param buffer - * An IOMemoryDescriptor describing the data-transfer buffer. The data direction - * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor - * rests with the caller. - * @param block - * The starting block number of the data transfer. - * @param nblks - * The integral number of blocks to be transferred. - * @param action - * The C function called upon completion of the data transfer. - * @param target - * The C++ class "this" pointer, passed as an argument to "action." - * @param param - * This value is passed as an argument to "action." It is not validated or modified. - */ - virtual IOReturn standardAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - - /*! - * @function standardAsyncReadWriteExecute - * @abstract - * Issue an asynchronous read/write operation after dequeuing. - * @param cx - * A pointer to the context structure for the command. - */ - virtual IOReturn standardAsyncReadWriteExecute(struct context *cx); - - /*! - * @function standardSyncReadWrite - * Perform a synchronous read or write operation. - * @param buffer - * An IOMemoryDescriptor describing the data-transfer buffer. The data direction - * is contained in the IOMemoryDescriptor. Responsiblity for releasing the descriptor - * rests with the caller. - * @param block - * The starting block number of the data transfer. - * @param nblks - * The integral number of blocks to be transferred. - */ - virtual IOReturn standardSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /*! - * @function stringFromState - * @abstract - * Return a string description of a state value. - * @discussion - * Used for debugging. - * @param state - * The state to be converted to a string description. - */ - virtual char * stringFromState(stateValue state); - - /*! - * @function unitAttentionRecoveryCommandComplete - * @abstract - * Handle a command completion during the Unit Attention recovery process. - * @discussion - * This method can be overridden to check the result of each command issued - * during the Unit Attention recovery process for the device. Typically it would - * bump the "step" value and issue the next command, calling finishUnitAttentionRecovery - * when the process is complete. - * - * The default implementation does nothing. - */ - virtual void unitAttentionRecoveryCommandComplete(struct context *cx); - - /*! - * @function unitAttentionDetected - * @abstract - * Determine if a Unit Attention condition occurred. - * @param cx - * A pointer to the context structure for the command just executed. - */ - virtual bool unitAttentionDetected(struct context *cx); - -public: - - /*! - * @function genericCompletion - * @abstract - * Generic IO completion function. - * @discussion - * This method handles completion of a SCSI command. It implements a - * simple state machine to handle a Unit Attention condition on a - * command. - * - * This method must be public so we can reach it from - * the C-language callback "glue" routine. It should not be called - * from outside this class. - * - * - * - * If a Unit Attention condition occurs, we set the state to - * kHandlingUnitAttention and call handleUnitAttention to do whatever - * is necessary to clear the condition. Eventually, handleUnitAttention - * resets the state to kDoneHandlingUnitAttention, which will allow - * the state machine to reissue the original command. - * - * If we are already processing a Unit Attention, then genericCompletion - * increments a step counter and calls handleUnitAttention. The step - * counter allows handleUnitAttention to issue multiple SCSI commands - * to clear the condition. The handleUnitAttention method is called - * repeatedly, until the state is set to kDoneHandlingUnitAttention. - * - * If this operation is a normal asynchronous read or write (usually - * started by standardAsyncReadWrite, though this is not required), - * then a call is made to RWCompletion, followed by deletion of the - * context structure for the command. RWCompletion is implemented by - * the subclass of IOBasicSCSI, for example in IOSCSIHDDrive. - * @param cx - * A pointer to the context structure for the command. - */ - virtual void genericCompletion(struct context *cx); - - /* - * @endgroup - */ - -protected: - - /* - * @group - * Power Management Methods - * @discussion - * A subclass must implement these to report the power level required to do various commands. - */ - - /*! - * @function getExecuteCDBPowerState - * @abstract - * Return the required device power level to execute a client CDB. - */ - virtual UInt32 getExecuteCDBPowerState(void) = 0; - - /*! - * @function getInquiryPowerState - * @abstract - * Return the required device power level to issue an Inquiry command. - */ - virtual UInt32 getInquiryPowerState(void) = 0; - - /*! - * @function getReadCapacityPowerState - * @abstract - * Return the required device power level to issue a Read Capacity command. - */ - virtual UInt32 getReadCapacityPowerState(void) = 0; - - /*! - * @function getReadWritePowerState - * @abstract - * Return the required device power level to issue a data read or write. - */ - virtual UInt32 getReadWritePowerState(void) = 0; - - /*! - * @function getReportWriteProtectionPowerState - * @abstract - * Return the required device power level to determine media write protection. - */ - virtual UInt32 getReportWriteProtectionPowerState(void) = 0; - - /*! - * @function powerTickle - * @abstract - * Check for the device power state currently being in the desired state. - * @discussion - * A subclass must implement powerTickle, which is called when we desire power to - * execute a command. PowerTickle may handle generic or a subclass-expanded set of - * power states. The implementation will usually relay the call to the Power Management - * subsystem function activityTickle. For a device without power management capability, - * the implementation should always return True. - * @param desiredState - * The desired device power level. - * @result - * True if power is in the desired state (or better); False if the caller must wait - * until power is available. - */ - virtual bool powerTickle(UInt32 desiredState) = 0; - - /* - * @endgroup - */ - - /*! - * @var _provider - * A pointer to our provider. - */ - IOSCSIDevice * _provider; - - /*! - * @var _busResetContext - * A pointer to a context struct to be used by recoverAfterBusReset. - */ - struct context * _busResetContext; - - /*! - * @var _unitAttentionContext - * A pointer to a context struct to be used by handleUnitAttention. - */ - struct context * _unitAttentionContext; - - /*! - * @var _busResetRecoveryInProgress - * True if recovery from Bus Reset is in progress. - */ - bool _busResetRecoveryInProgress; - - /*! - * @var _unitAttentionRecoveryInProgress - * True if recovery from Unit Attention is in progress. - */ - bool _unitAttentionRecoveryInProgress; - - /* Device information : */ - - /*! - * @var _inqBuf - * A pointer to the allocate Inquiry Data buffer. - */ - UInt8 * _inqBuf; /* the Inquiry data buffer */ - - /*! - * @var _inqBufSize - * The size of the inquiry data buffer, in bytes. - */ - UInt32 _inqBufSize; /* size of the buffer */ - - /*! - * @var _inqLen - * The number of valid bytes of inquiry data. - */ - UInt32 _inqLen; /* valid bytes in buffer */ - - /*! - * @var _vendor - * The Vendor Name string from the inquiry data, null-terminated. - */ - char _vendor[9]; /* info from Inquiry data */ - - /*! - * @var _product - * The Product Name string from the inquiry data, null-terminated. - */ - char _product[17]; - - /*! - * @var _rev - * The Product Revision string from the inquiry data, null-terminated. - */ - char _rev[5]; - - /* Since we get both of these items from the same command, we - * just cache both values if we get either call, so we only - * have to issue the command once. - */ - - /*! - * @var _readCapDone - * True if we have issued a Read-Capacity command to obtain the - * values for _maxBlock and _blockSize. - */ - bool _readCapDone; - - /*! - * @var _removable - * True if the media is removable; False if the media is fixed. - */ - bool _removable; - - /*! - * @var _maxBlock - * The highest valid block on the media, relative to zero. - */ - UInt64 _maxBlock; - - /*! - * @var _blockSize - * The block size of the media in bytes. - */ - UInt64 _blockSize; - - /* The queue of pending requests awaiting power: */ - - /*! - * @struct queue - * @discussion - * A data structure for a queue. - * @field head - * A pointer to the head item. - * @field tail - * A pointer to the tail item. - * @field lock - * A lock used to protect the queue during changes. - */ - /*! - * @var _powerQueue - * A queue structure containing operations queued awaiting power level. - */ - struct queue { - struct context * head; - struct context * tail; - IOLock * lock; - } _powerQueue; - -}; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSICDDrive.h b/iokit/IOKit/storage/scsi/IOSCSICDDrive.h deleted file mode 100644 index 8acd8c08f..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSICDDrive.h +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOSCSICDDrive.h - * - * This class implements SCSI CDROM functionality. - * - * Subclasses may modify the operations to handle device-specific variations. - */ - -#ifndef _IOSCSICDDRIVE_H -#define _IOSCSICDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/IOCDTypes.h> -#include <IOKit/storage/scsi/IOSCSIHDDrive.h> - -/* SCSI (inquiry) device type. */ - -enum { - kIOSCSIDeviceTypeCDROM = 0x05 -}; - -/* SCSI commands. */ - -enum { - kIOSCSICommandReadSubChannel = 0x42, - kIOSCSICommandReadTOC = 0x43, - kIOSCSICommandPlayAudioMSF = 0x47, - kIOSCSICommandPauseResume = 0x4b, - kIOSCSICommandStopPlay = 0x4e, - kIOSCSICommandScan = 0xba, - kIOSCSICommandReadCD = 0xbe -}; - -struct IOAudioPlayMSFcdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 reserved1; - UInt8 start_m; - UInt8 start_s; - UInt8 start_f; - UInt8 end_m; - UInt8 end_s; - UInt8 end_f; - UInt8 ctlbyte; -}; - -struct IOReadToccdb { - UInt8 opcode; - UInt8 lunbits; -static const UInt8 kMSF = 0x02; /* set to get mm:ss:ff format, else logical addr */ - UInt8 reserved1; - UInt8 reserved2; - UInt8 reserved3; - UInt8 reserved4; - UInt8 start_trk_session; /* starting track/session number */ - UInt8 len_hi; - UInt8 len_lo; - UInt8 ctlbyte; /* and format code */ -static const UInt8 kTOC = 0x00; -static const UInt8 kSessionInfo = 0x01; -static const UInt8 kFullTOC = 0x02; -}; - -struct IORSCcdb { - UInt8 opcode; - UInt8 lunbits; -static const UInt8 kMSF = 0x02; /* set to get mm:ss:ff format, else logical addr */ - UInt8 subq; -static const UInt8 kSubq = 0x40; /* set to get subq data */ - UInt8 dataformat; -static const UInt8 kCurrentPosition = 1; -static const UInt8 kMCN = 2; -static const UInt8 kISRC = 3; - UInt8 reserved1; - UInt8 reserved2; - UInt8 track; - UInt8 len_hi; - UInt8 len_lo; - UInt8 ctlbyte; -}; - -/*! - * @class IOSCSICDDrive : public IOSCSIHDDrive - * @abstract - * Driver for SCSI CD-ROM drives. - * @discussion - * IOSCSICDDrive is a subclass of IOSCSIHDDrive. It adds appropriate CD-ROM - * APIs (e.g. audio), and overrides some methods of IOSCSIHDDrive in order - * to alter their behavior for CD-ROM devices. - */ -/*------------------------------------------------*/ -class IOSCSICDDrive : public IOSCSIHDDrive { - - OSDeclareDefaultStructors(IOSCSICDDrive) - -public: - - /* Overrides from IOService: */ - - virtual bool init(OSDictionary * properties); - - /* Overrides from IOBasicSCSI: */ - - /*! - * @function deviceTypeMatches - * @abstract - * Determine if the device type matches that which we expect. - * @discussion - * This override allows us to check for the SCSI CD-ROM - * device type instead of hard disk. - * See IOBasicSCSI for details. - */ - virtual bool deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score); - - /* End of IOBasicSCSI overrides */ - - /* IOSCSIHDDrive overrides: */ - - /*! - * @function doAsyncReadWrite - * @abstract - * Start an asynchronous read or write operation. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - - /*! - * @function doSyncReadWrite - * @abstract - * Perform a synchronous read or write operation. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /*! - * @function doFormatMedia - * @abstract - * Attempt to format the media. - * @discussion - * This override allows us to reject formatting attempts for CD-ROM. - */ - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - - /*! - * @function doGetFormatCapacities - * @abstract - * Report available formatting capacities for the device/media. - * @discussion - * This override allows us to reject formatting attempts for CD-ROM. - */ - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - - /*! - * @function doSynchronizeCache - * @abstract - * Issue a synchronize-cache command when finished with a drive. - * @discussion - * This override allows us to reject the operation, since we never write to CD-ROM. - */ - virtual IOReturn doSynchronizeCache(void); - - /*! - * @function getDeviceTypeName - * @abstract - * Return a character string for the device type. - * @discussion - * This override returns kIOBlockStorageDeviceTypeCDROM. - */ - virtual const char * getDeviceTypeName(void); - /*! - * @function instantiateNub - * @abstract - * Create the device nub. - * @discussion - * This override instantiates an IOSCSICDDriveNub instead of an IOSCSIHDDriveNub. - */ - virtual IOService * instantiateNub(void); - - /* We want to track media changes to do cleanup. */ - /*! - * @function reportMediaState - * @abstract - * Report the device's media state. - * @discussion - * This override allows us to reset device settings when media changes. - */ - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - - /* end of IOSCSIHDDrive overrides */ - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - /*! - * @abstract - * Start an asynchronous read CD operation. - * @param buffer - * An IOMemoryDescriptor describing the data-transfer buffer. Responsiblity for releasing the descriptor - * rests with the caller. - * @param timeStart - * The starting M:S:F address of the data transfer. - * @param timeStop - * The ending M:S:F address of the data transfer. - * @param sectorArea - * Sector area(s) to read. - * @param sectorType - * Sector type that is expected. The data transfer is terminated as soon as - * data is encountered that does not match the expected type. - * @param action - * The C function called upon completion of the data transfer. - * @param target - * The C++ class "this" pointer, passed as an argument to "action." - * @param param - * This value is passed as an argument to "action." It is not validated or modified. - */ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - - /*! - * @function readISRC - * @abstract - * Read the International Standard Recording Code for the specified track. - * @param track - * The track number from which to read the ISRC. - * @param isrc - * The buffer for the ISRC data. Buffer contents will be zero-terminated. - */ - virtual IOReturn readISRC(UInt8 track,CDISRC isrc); - - /*! - * @function readMCN - * @abstract - * Read the Media Catalog Number (also known as the Universal Product Code). - * @param mcn - * The buffer for the MCN data. Buffer contents will be zero-terminated. - */ - virtual IOReturn readMCN(CDMCN mcn); - - /*! - * @function readTOC - * @abstract - * Read the full Table Of Contents. - * @param buffer - * The buffer for the returned data. - */ - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - /*! - * @function reportMaxWriteTransfer - * @abstract - * Report the maximum allowed byte transfer for write operations. - * @discussion - * This override lets us return zero for the max write transfer, since - * we never write to CD-ROM media. See IOBasicSCSI for other details. - */ - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max); - - /*! - * @function reportWriteProtection - * @abstract - * Report whether the media is write-protected or not. - * @discussion - * This override lets us return TRUE in all cases. See IOBasicSCSI for details. - */ - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - /*! - * @function audioPause - * @abstract - * Pause or resume the audio playback. - * @param pause - * True to pause playback; False to resume. - */ - virtual IOReturn audioPause(bool pause); - /*! - * @function audioPlay - * @abstract - * Play audio. - * @param timeStart - * The M:S:F address from which to begin. - * @param timeStop - * The M:S:F address at which to stop. - */ - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop); - /*! - * @function audioScan - * @abstract - * Perform a fast-forward or fast-backward operation. - * @param timeStart - * The M:S:F address from which to begin. - * @param reverse - * True to go backward; False to go forward. - */ - virtual IOReturn audioScan(CDMSF timeStart,bool reverse); - /*! - * @function audioStop - * @abstract - * Stop the audio playback (or audio scan). - */ - virtual IOReturn audioStop(); - /*! - * @function getAudioStatus - * @abstract - * Get the current audio play status information. - * @param status - * The buffer for the returned information. - */ - virtual IOReturn getAudioStatus(CDAudioStatus *status); - /*! - * @function getAudioVolume - * @abstract - * Get the current audio volume. - * @param leftVolume - * A pointer to the returned left-channel volume. - * @param rightVolume - * A pointer to the returned right-channel volume. - */ - virtual IOReturn getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume); - /*! - * @function setAudioVolume - * @abstract - * Set the current audio volume. - * @param leftVolume - * The desired left-channel volume. - * @param rightVolume - * The desired right-channel volume. - */ - virtual IOReturn setAudioVolume(UInt8 leftVolume,UInt8 rightVolume); - -protected: - - /* Internally used methods: */ - - /*! - * @function doAudioPlayCommand - * @abstract - * Issue an audio play command to the device. - * @param timeStart - * The M:S:F address from which to begin. - * @param timeStop - * The M:S:F address at which to stop. - */ - virtual IOReturn doAudioPlayCommand(CDMSF timeStart,CDMSF timeStop); - - /*! - * @function mediaArrived - * @abstract - * React to new media arrival. - */ - virtual void mediaArrived(void); - - /*! - * @function mediaGone - * @abstract - * React to media going away. - */ - virtual void mediaGone(void); - - /*! - * @function readSubChannel - * @abstract - * Issue the command necessary to read subchannel data. - * @param buffer - * The buffer for the data. - * @param length - * The maximum data length desired. - * @param dataFormat - * The subchannel data desired. - * @param track - * The desired track from which to read the data - */ - virtual IOReturn readSubChannel(UInt8 *buffer,UInt32 length,UInt8 dataFormat,UInt8 trackNumber); -}; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSICDDriveNub.h b/iokit/IOKit/storage/scsi/IOSCSICDDriveNub.h deleted file mode 100644 index d8c2d4b23..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSICDDriveNub.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* IOSCSICDDriveNub.h created by rick on Wed 07-Apr-1999 */ - -/* This subclass implements a relay to a protocol- and device-specific provider. */ - -#ifndef _IOSCSICDDRIVENUB_H -#define _IOSCSICDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOCDBlockStorageDevice.h> - -class IOSCSICDDrive; - -class IOSCSICDDriveNub : public IOCDBlockStorageDevice { - - OSDeclareDefaultStructors(IOSCSICDDriveNub) - -public: - - /* Overrides from IOService */ - - virtual bool attach(IOService * provider); - - /* Overrides from IOBlockStorageDevice: */ - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /* --------------------------------------------------------------------------*/ - /* APIs used by the IOBlockStorageDevice portion of IOCDBlockStorageDevice: */ - /* --------------------------------------------------------------------------*/ - - virtual IOReturn doEjectMedia(void); - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual IOReturn doSynchronizeCache(void); - virtual char * getVendorString(void); - virtual char * getProductString(void); - virtual char * getRevisionString(void); - virtual char * getAdditionalDeviceInfoString(void); - virtual IOReturn reportBlockSize(UInt64 *blockSize); - virtual IOReturn reportEjectability(bool *isEjectable); - virtual IOReturn reportLockability(bool *isLockable); - virtual IOReturn reportPollRequirements(bool *pollIsRequired,bool *pollIsExpensive); - virtual IOReturn reportMaxReadTransfer(UInt64 blockSize,UInt64 *max); - virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max); - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - virtual IOReturn reportRemovability(bool *isRemovable); - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - virtual UInt32 getMediaType(void); - virtual IOReturn readISRC(UInt8 track,CDISRC isrc); - virtual IOReturn readMCN(CDMCN mcn); - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - virtual IOReturn audioPause(bool pause); - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop); - virtual IOReturn audioScan(CDMSF timeStart,bool reverse); - virtual IOReturn audioStop(); - virtual IOReturn getAudioStatus(CDAudioStatus *status); - virtual IOReturn getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume); - virtual IOReturn setAudioVolume(UInt8 leftVolume,UInt8 rightVolume); - -protected: - - IOSCSICDDrive * _provider; -}; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSIDVDDrive.h b/iokit/IOKit/storage/scsi/IOSCSIDVDDrive.h deleted file mode 100644 index 01d3f229e..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSIDVDDrive.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOSCSIDVDDrive.h - * - * This class implements SCSI DVD functionality. - * - * Subclasses may modify the operations to handle device-specific variations. - */ - -#ifndef _IOSCSIDVDDRIVE_H -#define _IOSCSIDVDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/scsi/IOSCSICDDrive.h> -#include <IOKit/storage/IODVDTypes.h> - -struct IOGCCdb { - UInt8 opcode; - UInt8 lunRT; - UInt8 startFeature_hi; - UInt8 startFeature_lo; - UInt8 reserved[3]; - UInt8 len_hi; - UInt8 len_lo; - UInt8 ctlbyte; -}; - -struct IORKCdb { - UInt8 opcode; - UInt8 lba_0; //msb - UInt8 lba_1; - UInt8 lba_2; - UInt8 lba_3; - UInt8 reserved; - UInt8 keyClass; - UInt8 len_hi; - UInt8 len_lo; - UInt8 agidKeyFormat; - UInt8 ctlbyte; -}; - -struct IOSKCdb { - UInt8 opcode; - UInt8 lun; - UInt8 reserved[5]; - UInt8 keyClass; - UInt8 len_hi; - UInt8 len_lo; - UInt8 agidKeyFormat; - UInt8 ctlbyte; -}; - -enum { - kIOSCSICommandGetConfiguration = 0x46, - kIOSCSICommandSendKey = 0xa3, - kIOSCSICommandReportKey = 0xa4 -}; - -const int kMaxConfigLength = 1024; -class IOMemoryDescriptor; - -/*------------------------------------------------*/ -class IOSCSIDVDDrive : public IOSCSICDDrive { - - OSDeclareDefaultStructors(IOSCSIDVDDrive) - -public: - - /* Overrides from IOService: */ - - virtual bool init(OSDictionary * properties); - - /* Overrides from IOBasicSCSI: */ - - virtual bool deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score); - - /*! - * @function reportWriteProtection - * @abstract - * Report whether the media is write-protected or not. - * @discussion - * This override allows us to return the cached write-protection status - * without interrogating the drive. - */ - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - - /* End of IOBasicSCSI overrides */ - - /* IOSCSIHDDrive overrides: */ - - /*! - * @function doAsyncReadWrite - * @abstract - * Start an asynchronous read or write operation. - * @discussion - * This override allows us to accept writes, which our superclass, IOSCSICDDrive, - * unconditionally rejects. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - - /*! - * @function doSyncReadWrite - * @abstract - * Perform a synchronous read or write operation. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /*! - * @function doFormatMedia - * @abstract - * Attempt to format the media. - * @discussion - * This override allows us to handle formatting for DVD-RAM. - */ - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - - /*! - * @function doGetFormatCapacities - * @abstract - * Report available formatting capacities for the device/media. - * @discussion - * This override allows us to handle formatting for DVD. - */ - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - - /*! - * @function doSynchronizeCache - * @abstract - * Force data blocks in the drive's buffer to be flushed to the media. - * @discussion - * This override allows us to issue a standard Synchronize-Cache command for DVD-RAM. - */ - virtual IOReturn doSynchronizeCache(void); - - virtual const char * getDeviceTypeName(void); - - /*! - * @function getGetConfigurationPowerState - * @abstract - * Return the required device power level to execute a Get Configuration command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getGetConfigurationPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getReportKeyPowerState - * @abstract - * Return the required device power level to execute a Report Key command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getReportKeyPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getSendKeyPowerState - * @abstract - * Return the required device power level to execute a Send Key command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getSendKeyPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function instantiateNub - * @abstract - * Instantiate the desired nub. - * @discussion - * This override allows us to instantiate an IOSCSIDVDDriveNub. - */ - virtual IOService * instantiateNub(void); - - /*! - * @function reportMediaState - * @abstract - * Report the device's media state. - * @discussion - * This override allows us to determine the media type after something is inserted. - */ - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - - /* end of IOSCSIHDDrive overrides */ - - /* DVD APIs: */ - - virtual UInt32 getMediaType(void); - virtual IOReturn reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass DVDKeyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat); - virtual IOReturn sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass DVDKeyClass, - const UInt8 agid,const DVDKeyFormat keyFormat); - -protected: - - virtual void checkConfig(UInt8 *buf,UInt32 actual); - virtual IOReturn determineMediaType(void); - virtual IOReturn getConfiguration(UInt8 *buffer,UInt32 length,UInt32 *actualLength,bool current); - - UInt8 _configBuf[kMaxConfigLength]; - - UInt32 _configSize; - bool _isDVDDrive; - bool _canDoCSS; - UInt32 _mediaType; - bool _isWriteProtected; - -}; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSIDVDDriveNub.h b/iokit/IOKit/storage/scsi/IOSCSIDVDDriveNub.h deleted file mode 100644 index c806dd049..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSIDVDDriveNub.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* This subclass implements a relay to a protocol- and device-specific provider. */ - -#ifndef _IOSCSIDVDDRIVENUB_H -#define _IOSCSIDVDDRIVENUB_H - -#include <IOKit/storage/IODVDBlockStorageDevice.h> -#include <IOKit/storage/IODVDTypes.h> - -class IOSCSIDVDDrive; - -class IOSCSIDVDDriveNub : public IODVDBlockStorageDevice { - - OSDeclareDefaultStructors(IOSCSIDVDDriveNub) - -public: - - /* Overrides from IOService */ - - virtual bool attach(IOService * provider); - - /* Overrides from IOBlockStorageDevice: */ - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /* --------------------------------------------------------------------------*/ - /* APIs used by the IOBlockStorageDevice portion of IODVDBlockStorageDevice: */ - /* --------------------------------------------------------------------------*/ - - virtual IOReturn doEjectMedia(void); - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual IOReturn doSynchronizeCache(void); - virtual char * getVendorString(void); - virtual char * getProductString(void); - virtual char * getRevisionString(void); - virtual char * getAdditionalDeviceInfoString(void); - virtual IOReturn reportBlockSize(UInt64 *blockSize); - virtual IOReturn reportEjectability(bool *isEjectable); - virtual IOReturn reportLockability(bool *isLockable); - virtual IOReturn reportPollRequirements(bool *pollIsRequired,bool *pollIsExpensive); - virtual IOReturn reportMaxReadTransfer(UInt64 blockSize,UInt64 *max); - virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max); - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - virtual IOReturn reportRemovability(bool *isRemovable); - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - - /*-----------------------------------------*/ - /* CD APIs */ - /*-----------------------------------------*/ - - virtual IOReturn doAsyncReadCD(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - CDSectorArea sectorArea, - CDSectorType sectorType, - IOStorageCompletion completion); - virtual UInt32 getMediaType(void); - virtual IOReturn readISRC(UInt8 track,CDISRC isrc); - virtual IOReturn readMCN(CDMCN mcn); - virtual IOReturn readTOC(IOMemoryDescriptor * buffer); - - /*-----------------------------------------*/ - /* APIs exported by IOCDAudioControl */ - /*-----------------------------------------*/ - - virtual IOReturn audioPause(bool pause); - virtual IOReturn audioPlay(CDMSF timeStart,CDMSF timeStop); - virtual IOReturn audioScan(CDMSF timeStart,bool reverse); - virtual IOReturn audioStop(); - virtual IOReturn getAudioStatus(CDAudioStatus *status); - virtual IOReturn getAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume); - virtual IOReturn setAudioVolume(UInt8 leftVolume,UInt8 rightVolume); - - /* DVD APIs beyond standard CD APIs: */ - - virtual IOReturn reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat); - virtual IOReturn sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass, - const UInt8 agid,const DVDKeyFormat keyFormat); -protected: - - IOSCSIDVDDrive * _provider; - -}; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSIHDDrive.h b/iokit/IOKit/storage/scsi/IOSCSIHDDrive.h deleted file mode 100644 index d60b2cb05..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSIHDDrive.h +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * IOSCSIHDDrive.h - * - * This class implements SCSI hard disk functionality. - * - * Subclasses may modify the operations to handle device-specific variations. - */ - -#ifndef _IOSCSIHDDRIVE_H -#define _IOSCSIHDDRIVE_H - -#include <IOKit/IOTypes.h> -#include <IOKit/scsi/IOSCSIDeviceInterface.h> -#include <IOKit/storage/scsi/IOBasicSCSI.h> - -/* SCSI (inquiry) device type. */ - -enum { - kIOSCSIDeviceTypeDirectAccess = 0x00 -}; - -/* SCSI commands. */ - -enum { - kIOSCSICommandTestUnitReady = 0x00, - kIOSCSICommandFormatUnit = 0x04, - kIOSCSICommandStartStopUnit = 0x1b, - kIOSCSICommandPreventAllow = 0x1e, - kIOSCSICommandSynchronizeCache = 0x35, - kIOSCSICommandModeSelect = 0x55, - kIOSCSICommandModeSense = 0x5a, - kIOSCSICommandRead = 0xa8, - kIOSCSICommandWrite = 0xaa -}; - -struct IOFormatcdb { - UInt8 opcode; /* 0x12 */ - UInt8 lunbits; /* lun and control bits */ - UInt8 vendor; - UInt8 interleave_msb; - UInt8 interleave_lsb; - UInt8 ctlbyte; -}; - -struct IOPrevAllowcdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 reserved1; - UInt8 reserved2; - UInt8 prevent; - UInt8 ctlbyte; -}; - -struct IOStartStopcdb { - UInt8 opcode; - UInt8 lunImmed; - UInt8 reserved1; - UInt8 reserved2; - - /* Control bits: */ - /* Power Conditions */ -static const UInt8 P_NOCHANGE = 0x00; /* 0 - no change */ -static const UInt8 P_ACTIVE = 0x10; /* 1 - change to Active */ -static const UInt8 P_IDLE = 0x20; /* 2 - change to Idle */ -static const UInt8 P_STANDBY = 0x30; /* 3 - change to Standby */ -static const UInt8 P_RESERVED4 = 0x40; /* 4 - reserved */ -static const UInt8 P_SLEEP = 0x50; /* 5 - change to Sleep */ -static const UInt8 P_RESERVED6 = 0x60; /* 6 - reserved */ -static const UInt8 P_LUNCONTROL = 0x70; /* 7 - give pwr ctl to LUN */ -static const UInt8 P_RESERVED8 = 0x80; /* 8 - reserved */ -static const UInt8 P_RESERVED9 = 0x90; /* 9 - reserved */ -static const UInt8 P_TIDLEZERO = 0xa0; /* a - force Idle Cond Timer = 0 */ -static const UInt8 P_TSTDBYZERO = 0xb0; /* b - force Stby Cond Timer = 0 */ - -static const UInt8 C_LOEJ = 0x02; /* load on start/eject on stop */ -static const UInt8 C_SPINUP = 0x01; -static const UInt8 C_SPINDOWN = 0x00; - - UInt8 controls; - UInt8 ctlbyte; -}; - -struct IOSyncCachecdb { - UInt8 opcode; - UInt8 lunbits; - UInt8 lba_3; /* msb */ - UInt8 lba_2; - UInt8 lba_1; - UInt8 lba_0; /* lsb */ - UInt8 reserved; - UInt8 nblks_msb; - UInt8 nblks_lsb; - UInt8 ctlbyte; -}; - -/*! - * @enum Power States - * @discussion - * We define and understand three basic, generic power states. A subclass may change - * the power management logic, but all power-management routines should be examined - * if anything is changed. The only routines that deal directly with these values - * are directly related to power management. All other functions merely ask for and - * pass along power state values. - * @constant kAllOff - * The power state for an all-off condition. - * @constant kElectronicsOn - * The power state for the electronics on, but the media off. - * @constant kAllOn - * The power state for the electronics and media on. - * @constant kNumberOfPowerStates - * The maximum enum value. - */ -enum { /* electronics mechanical */ - kAllOff = 0, /* OFF OFF */ - kElectronicsOn = 1, /* ON OFF */ - kAllOn = 2, /* ON ON */ - - kNumberOfPowerStates = 3 -}; - -/*! - * @class - * IOSCSIHDDrive : public IOBasicSCSI - * @abstract - * SCSI Hard Disk driver. - * @discussion - * IOSCSIHDDrive derives from IOBasicSCSI and adds all functionality - * needed to support removable or fixed hard disk drives. - */ - -class IOSCSIHDDrive : public IOBasicSCSI { - - OSDeclareDefaultStructors(IOSCSIHDDrive) - -public: - - /* Overrides from IOService: */ - - virtual bool init(OSDictionary * properties); - - /*! - * @function start - * @abstract - * Start the driver. - * @discussion - * We override IOBasicSCSI::start so we can initialize Power Management, - * then we call createNub to create an IOSCSIHDDriveNub. - */ - virtual bool start(IOService * provider); - - /* Overrides from IOBasicSCSI: */ - - /*! - * @function deviceTypeMatches - * @abstract - * Determine if device type matches expected type. - * @discussion - * We implement this function so we can return a match - * on the hard disk device type. - */ - virtual bool deviceTypeMatches(UInt8 inqBuf[],UInt32 inqLen,SInt32 *score); - - /*! - * @function constructDeviceProperties - * @abstract - * Construct a set of properties about the device. - * @discussion - * This function creates a set of properties reflecting information - * about the device. - * - * This function is presently not used. - * @result - * A pointer to an OSDictionary containing the properties. The caller - * is responsible for releasing the OSDictionary. - */ - virtual OSDictionary *constructDeviceProperties(void); - - /*! - * @function RWCompletion - * @abstract - * Asynchronous read/write completion routine. - * @discussion - * We implement this function in this class. It is called from the base - * class when an IO operation completes. - */ - virtual void RWCompletion(struct context *cx); - - /* End of IOBasicSCSI overrides */ - - /* Additional API added to IOBasicSCSI: */ - - /*! - * @function doAsyncReadWrite - * @abstract - * Start an asynchronous read or write operation. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - - /*! - * @function doSyncReadWrite - * @abstract - * Perform a synchronous read or write operation. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - - /*! - * @function doEjectMedia - * @abstract - * Eject the media. - * @discussion - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doEjectMedia(void); - - /*! - * @function doFormatMedia - * @abstract - * Format the media to the specified byte capacity. - * @discussion - * The default implementation calls standardFormatMedia. - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - - /*! - * @function doGetFormatCapacities - * @abstract - * Return the allowable formatting byte capacities. - * @discussion - * The default implementation of this method returns a value of block - * size * max block, and a capacities count of 1. - * See IOBlockStorageDevice for details. - */ - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - - /*! - * @function doLockUnlockMedia - * @abstract - * Lock or unlock the (removable) media in the drive. - * @discussion - * This method issues a standard SCSI Prevent/Allow command to lock - * or unlock the media in the drive. - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doLockUnlockMedia(bool doLock); - - /*! - * @function doSynchronizeCache - * @abstract - * Force data blocks in the drive's buffer to be flushed to the media. - * @discussion - * This method issues a SCSI Synchronize Cache command, to ensure that - * all blocks in the device cache are written to the media. - * See IOBlockStorageDevice for details. - */ - virtual IOReturn doSynchronizeCache(void); - - /*! - * @function reportMediaState - * @abstract - * Report the device's media state. - * @discussion - * This method reports whether media is present or not, and also - * whether the media state has changed since the last call to - * reportMediaState. The default implementation issues a SCSI Test - * Unit Ready command: depending on the result of that command, the - * following cases are reported: - * - * 1. TUR status == good completion: we report media present and return - * kIOReturnSuccess. - * - * 2. TUR status != good completion, but good autosense returned: - * - * 2a: sense key says not ready: we report media not present - * and return kIOReturnSuccess. - * - * 2b: sense key is anything else: we report media not present - * and return kIOReturnIOError. - * - * 3. TUR status != good completion, and no autosense data: we do not - * set mediaPresent or changedState, and we return whatever result - * came back from the SCSI operation. - */ - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - - /* --- end of additional API --- */ - -protected: - - /*! - * @function createFormatCdb - * @abstract - * Create a SCSI CDB for a format operation. - * @discussion - * Override this to control the cdb created for a format operation. - * The default implementation creates a 6-byte format command with - * no data buffer, disconnect allowed, 8-byte autosense, and a 15-minute timeout. - * - * See also: allocateFormatBuffer, deleteFormatBuffer, composeFormatBuffer. - * @param byteCapacity - * The requested byte capacity to which the media should be formatted. This value - * should have been previously validated, otherwise the device may return an error. - * @param cdb - * A pointer to the CDB bytes. - * @param cdbLength - * The length of the CDB in bytes. - * @param block - * The device block to be written. - * @param nblks - * The number of blocks to be transferred. - * @param maxAutoSenseLength - * The maximum size of the autosense data, in bytes. A value of zero - * will disable autosense. - * @param timeoutSeconds - * The command timeout in seconds. - * @result - * The IOSCSICommandOptions returned will be used to issue the command. - */ - virtual UInt32 createFormatCdb( - UInt64 byteCapacity, /* in */ - UInt8 *cdb, /* in */ - UInt32 *cdbLength, /* out */ - UInt8 buf[], /* in */ - UInt32 bufLen, /* in */ - UInt32 *maxAutoSenseLength, /* out */ - UInt32 *timeoutSeconds); /* out */ - - - /*! - * @function allocateFormatBuffer - * @abstract - * Create a data buffer to be used for formatting the media. - * @discussion - * If a format buffer is to be used, then "allocateFormatBuffer" and - * deleteFormatBuffer" must be overridden to manage the buffer. The - * buffer must be prepared for IO upon return from allocateFormatBuffer. - * The default implementations of these methods don't allocate a buffer. - * @param buf - * A pointer for the returned buffer pointer. - * @param buflen - * The desired length of the buffer, in bytes. - */ - virtual IOReturn allocateFormatBuffer(UInt8 **buf,UInt32 *buflen); - - /*! - * @function deleteFormatBuffer - * @abstract - * Delete the data buffer to be used for formatting the media. - * @discussion - * If a format buffer is to be used, then "allocateFormatBuffer" and - * deleteFormatBuffer" must be overridden to manage the buffer. - * The default implementation of this method does nothing. - * @param buf - * A pointer to the buffer to delete. - * @param buflen - * The size of the buffer, in bytes. - */ - virtual void deleteFormatBuffer(UInt8 *buf,UInt32 buflen); - - /*! - * @function composeFormatBuffer - * @abstract - * Compose the data in the buffer used for the format command. - * @discussion - * This method will be called to compose the data in the format buffer. - * - * The default implementation of this method does nothing. - * @param buf - * A pointer to the format data buffer. - * @param buflen - * The size of the format data buffer, in bytes. - * @result - * The return value should be the desired values for the "CmpLst" and Defect - * List Format bits in the CDB. The default implementation returns zero. - */ - virtual UInt8 composeFormatBuffer(UInt8 *buf,UInt32 buflen); - - /* Override these methods to save and restore the state of the device electronics - * when power is turned off and on. The defaults do nothing and return kIOReturnSuccess. - */ - - /*! - * @function restoreElectronicsState - * @abstract - * Restore the state of the device electronics when powering-up. - * @discussion - * This method is called just after the device transitions from a powered-off state. - * - * The default implementation of this method does nothing and returns kIOReturnSuccess. - */ - virtual IOReturn restoreElectronicsState(void); - - /*! - * @function saveElectronicsState - * @abstract - * Save the state of the device electronics when powering-down. - * @discussion - * This method is called just before the device transitions to a powered-off state. - * - * The default implementation of this method does nothing and returns kIOReturnSuccess. - */ - virtual IOReturn saveElectronicsState(void); - - /*! - * @function initialPowerStateForDomainState - * @abstract - * Return the initial power state for the device. - * @discussion - * This method is called to obtain the initial power state for the device, - * by calling getInitialPowerState. - * @param domainState - * Power domain state flags. - * @result - * The return value must be a valid power state value. - */ - virtual unsigned long initialPowerStateForDomainState ( IOPMPowerFlags domainState ); - - /*! - * @function maxCapabilityForDomainState - * @abstract - * Return the maximum power level obtainable for the given state. - * @discussion - * This method is called to obtain the maximum power level obtainable for the - * given state. - * @param domainState - * Power domain state flags. - * @result - * The return value must be a valid power state value. - */ - virtual unsigned long maxCapabilityForDomainState ( IOPMPowerFlags domainState ); - - /*! - * @function powerStateForDomainState - * Return the maximum power level obtainable for the given state. - * @discussion - * This method is called to obtain the maximum power level obtainable for the - * given state. - * @param domainState - * Power domain state flags. - * @result - * The return value must be a valid power state value. - */ - virtual unsigned long powerStateForDomainState ( IOPMPowerFlags domainState ); - - /*! - * @function powerStateDidChangeTo - * @abstract - * React to a change in power state. - * @discussion - * This method is called when the power state changes. We call restoreElectronicsState - * if necessary, then call dequeueCommands if we have changed to a state that has power. - * @param stateOrdinal - * The power level to which we have changed. - */ - virtual IOReturn powerStateDidChangeTo ( unsigned long, unsigned long stateOrdinal, IOService* ); - - /*! - * @function powerStateWillChangeTo - * @abstract - * Prepare for a power state change. - * @discussion - * This method is called when the power state will change. If we are powering-up from kAllOff, - * we schedule a call to restoreElectronicsState. If, instead, we are powering-down from an "on" state, - * we schedule a call to saveElectronicsState. - * @param stateOrdinal - * The power level to which we will change. - */ - virtual IOReturn powerStateWillChangeTo ( unsigned long, unsigned long stateOrdinal, IOService* ); - - /*! - * @function setPowerState - * @abstract - * Set the power state to the specified state. - * @discussion - * This method is called to cause a change in power state. We handle changes to and from - * kAllOn and kElectronicsOn, which are done by spinning up and down the media. - * @param powerStateOrdinal - * The power level to which we must change. - */ - virtual IOReturn setPowerState ( unsigned long powerStateOrdinal, IOService* ); - - /*! - * @function powerTickle - * Check for the device power state currently being in the desired state. - * @discussion - * This method simply "tickles" - * the Power Management subsystem to ensure that the device transitions to the desired - * state if necessary. - */ - virtual bool powerTickle(UInt32 desiredState); - - /* Override this method to report the initial device power state when its domain is - * powered up. The default implementation assumes the drive spins up. - */ - - /*! - * @function getInitialPowerState - * @abstract - * Report the initial power state of the device. - * @discussion - * The default implementation of this method returns kAllOn, assuming that the - * drive spindle spins up initially. - * @result - * The return value must be a valid power state value. - */ - virtual unsigned long getInitialPowerState(void); /* default = kAllOn */ - - /* Override these to change power level required to do various commands. */ - - /*! - * @function getEjectPowerState - * @abstract - * Return the required device power level to determine eject the media. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getEjectPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getExecuteCDBPowerState - * @abstract - * @discussion - * @param - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getExecuteCDBPowerState(void); /* default = kAllOn */ - - /*! - * @function getFormatMediaPowerState - * @abstract - * Return the required device power level to execute a client CDB. - * @discussion - * The default implementation of this method returns kAllOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getFormatMediaPowerState(void); /* default = kAllOn */ - - /*! - * @function getInquiryPowerState - * @abstract - * Return the required device power level to execute an Inquiry command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getInquiryPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getLockUnlockMediaPowerState - * @abstract - * Return the required device power level to lock or unlock the media. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getLockUnlockMediaPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getReadCapacityPowerState - * @abstract - * Return the required device power level to execute a Read-Capacity command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getReadCapacityPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getReadWritePowerState - * @abstract - * Return the required device power level to execute a Read or Write command. - * @discussion - * The default implementation of this method returns kAllOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getReadWritePowerState(void); /* default = kAllOn */ - - /*! - * @function getReportWriteProtectionPowerState - * @abstract - * Return the required device power level to report media write protection. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getReportWriteProtectionPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getStartPowerState - * @abstract - * Return the required device power level to start (spin up) the media. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getStartPowerState(void); /* default = kElectronicsOn */ - - /*! - * @function getStopPowerState - * @abstract - * Return the required device power level to stop (spin down) the media. - * @discussion - * The default implementation of this method returns kAllOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getStopPowerState(void); /* default = kAllOn */ - - /*! - * @function getSynchronizeCachePowerState - * @abstract - * Return the required device power level to issue a Synchronize-Cache command. - * @discussion - * The default implementation of this method returns kAllOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getSynchronizeCachePowerState(void); /* default = kAllOn */ - - /*! - * @function getTestUnitReadyPowerState - * @abstract - * Return the required device power level to issue a Test Unit Ready command. - * @discussion - * The default implementation of this method returns kElectronicsOn. - * @result - * The return value must be a valid power state value. - */ - virtual UInt32 getTestUnitReadyPowerState(void); /* default = kElectronicsOn */ - - /* - * @group - * Internally used methods. - */ - - /*! - * @function createNub - * @abstract - * Create, init, attach, and register the device nub. - * @discussion - * This method calls instantiateNub, then init, attach, and register. - * @result - * A pointer to the nub or NULL if something failed. - */ - virtual IOService * createNub(void); - - /*! - * @function getDeviceTypeName - * @abstract - * Return a character string for the device type. - * @discussion - * The default implementation of this method returns - * kIOBlockStorageDeviceTypeGeneric. - */ - virtual const char * getDeviceTypeName(void); - - /*! - * @function instantiateNub - * @abstract - * Create the device nub. - * @discussion - * A subclass will override this method to change the type of nub created. - * A CD driver, for example, will instantiate an IOSCSICDDriveNub instead - * of the default implementation's IOSCSIHDDriveNub. - */ - virtual IOService * instantiateNub(void); - - /*! - * @function doStart - * @abstract - * Start (spin up) the media. - * @discussion - * This method calls doStartStop. - */ - virtual IOReturn doStart(void); - - /*! - * @function doStartStop - * @abstract - * Perform the actual spin up/down command. - * @discussion - * This method issues a SCSI Start Stop Unit command to start or stop - * the device. Because the powerCondition value is only for use with - * SCSI-3 devices, the current implementation ignores powerCondition. - * @param start - * True to start (spin-up) the media; False to stop (spin-down) the media. - * @param loadEject - * True to eject; False to not eject. This parameter is applicable only to a stop - * operation. - * @param powerCondition - * The power condition to which the drive should transition. This is a SCSI-3 - * capability; it is presently unused. - */ - virtual IOReturn doStartStop(bool start,bool loadEject,UInt8 powerCondition); - - /*! - * @function doStop - * @abstract - * Stop (spin down) the media. - * @discussion - * This method calls doStartStop. - */ - virtual IOReturn doStop(void); - - /*! - * @function standardFormatMedia - * @abstract - * Perform a standard media format operation. - * @discussion - * See doFormatMedia for further information. - */ - virtual IOReturn standardFormatMedia(UInt64 byteCapacity); - - /*! - * @function standardSynchronizeCache - * @abstract - * Perform a standard Synchronize-Cache operation. - * @discussion - * See doFormatMedia for further information. - */ - virtual IOReturn standardSynchronizeCache(void); - - /* - * @endgroup - */ - - /* Device information : */ - - /*! - * @var _mediaPresent - * True if media is present; False if media is not present. - */ - bool _mediaPresent; - - /*! - * @var _startStopDisabled - * True if the start/stop commands are disabled due to an error. - */ - bool _startStopDisabled; - - /*! - * @var _restoreState - * True if we must restore the device electronics state after a power-up. - */ - bool _restoreState; /* true if we must restore after power-up */ }; -#endif diff --git a/iokit/IOKit/storage/scsi/IOSCSIHDDriveNub.h b/iokit/IOKit/storage/scsi/IOSCSIHDDriveNub.h deleted file mode 100644 index 94647d545..000000000 --- a/iokit/IOKit/storage/scsi/IOSCSIHDDriveNub.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* IOSCSIHDDriveNub.h created by rick on Tue 23-Mar-1999 */ - -/* This subclass implements a relay to a protocol- and device-specific provider. */ - -#ifndef _IOSCSIHDDRIVENUB_H -#define _IOSCSIHDDRIVENUB_H - -#include <IOKit/IOTypes.h> -#include <IOKit/storage/IOBlockStorageDevice.h> - -class IOSCSIHDDrive; - -class IOSCSIHDDriveNub : public IOBlockStorageDevice { - - OSDeclareDefaultStructors(IOSCSIHDDriveNub) - -public: - - /* Overrides from IOService */ - - virtual bool attach(IOService * provider); - virtual void detach(IOService * provider); - - /* Mandatory overrides from IOBlockStorageDevice: */ - - virtual IOReturn doAsyncReadWrite(IOMemoryDescriptor *buffer, - UInt32 block,UInt32 nblks, - IOStorageCompletion completion); - virtual IOReturn doSyncReadWrite(IOMemoryDescriptor *buffer,UInt32 block,UInt32 nblks); - virtual IOReturn doEjectMedia(void); - virtual IOReturn doFormatMedia(UInt64 byteCapacity); - virtual UInt32 doGetFormatCapacities(UInt64 * capacities, - UInt32 capacitiesMaxCount) const; - virtual IOReturn doLockUnlockMedia(bool doLock); - virtual IOReturn doSynchronizeCache(void); - virtual char * getVendorString(void); - virtual char * getProductString(void); - virtual char * getRevisionString(void); - virtual char * getAdditionalDeviceInfoString(void); - virtual IOReturn reportBlockSize(UInt64 *blockSize); - virtual IOReturn reportEjectability(bool *isEjectable); - virtual IOReturn reportLockability(bool *isLockable); - virtual IOReturn reportMediaState(bool *mediaPresent,bool *changed); - virtual IOReturn reportPollRequirements(bool *PollIsRequired,bool *pollIsExpensive); - virtual IOReturn reportMaxReadTransfer (UInt64 blockSize,UInt64 *max); - virtual IOReturn reportMaxValidBlock(UInt64 *maxBlock); - virtual IOReturn reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max); - virtual IOReturn reportRemovability(bool *isRemovable); - virtual IOReturn reportWriteProtection(bool *isWriteProtected); - -protected: - - IOSCSIHDDrive * _provider; -}; -#endif diff --git a/iokit/IOKit/storage/scsi/Makefile b/iokit/IOKit/storage/scsi/Makefile deleted file mode 100644 index 56003c286..000000000 --- a/iokit/IOKit/storage/scsi/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd -export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def -export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule -export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir - -IOKIT_FRAMEDIR = $(FRAMEDIR)/IOKit.framework/Versions/A -export INCDIR = $(IOKIT_FRAMEDIR)/Headers -export LCLDIR = $(IOKIT_FRAMEDIR)/PrivateHeaders - -include $(MakeInc_cmd) -include $(MakeInc_def) - -MI_DIR = storage/scsi -NOT_EXPORT_HEADERS = - -INSTINC_SUBDIRS = -INSTINC_SUBDIRS_PPC = -INSTINC_SUBDIRS_I386 = - -EXPINC_SUBDIRS = ${INSTINC_SUBDIRS} -EXPINC_SUBDIRS_PPC = ${INSTINC_SUBDIRS_PPC} -EXPINC_SUBDIRS_I386 = ${INSTINC_SUBDIRS_I386} - -ALL_HEADERS = $(shell (cd $(SOURCE); echo *.h)) - -INSTALL_MI_LIST = -INSTALL_MI_LCL_LIST = "" -INSTALL_MI_DIR = $(MI_DIR) - -EXPORT_MI_LIST = $(filter-out $(NOT_EXPORT_HEADERS), $(ALL_HEADERS)) -EXPORT_MI_DIR = IOKit/$(MI_DIR) - -include $(MakeInc_rule) -include $(MakeInc_dir) diff --git a/iokit/IOKit/system.h b/iokit/IOKit/system.h index 354ee70dd..53e19969a 100644 --- a/iokit/IOKit/system.h +++ b/iokit/IOKit/system.h @@ -63,6 +63,8 @@ extern int sscanf(const char *input, const char *fmt, ...); extern int sprintf(char *s, const char *format, ...); extern long strtol(const char *, char **, int); extern unsigned long strtoul(const char *, char **, int); +extern long long strtoq(const char *, char **, int); +extern unsigned long long strtouq(const char *, char **, int); extern #ifdef __GNUC__ diff --git a/iokit/Kernel/IOBufferMemoryDescriptor.cpp b/iokit/Kernel/IOBufferMemoryDescriptor.cpp index c209c7035..2bf4b50e8 100644 --- a/iokit/Kernel/IOBufferMemoryDescriptor.cpp +++ b/iokit/Kernel/IOBufferMemoryDescriptor.cpp @@ -124,7 +124,7 @@ bool IOBufferMemoryDescriptor::initWithOptions( kern_return_t kr; ipc_port_t sharedMem = (ipc_port_t) _memEntry; - vm_size_t size = _ranges.v[0].length; + vm_size_t size = round_page(_ranges.v[0].length); // must create the entry before any pages are allocated if( 0 == sharedMem) { @@ -132,7 +132,7 @@ bool IOBufferMemoryDescriptor::initWithOptions( &size, _ranges.v[0].address, VM_PROT_READ | VM_PROT_WRITE, &sharedMem, NULL ); - if( (KERN_SUCCESS == kr) && (size != _ranges.v[0].length)) { + if( (KERN_SUCCESS == kr) && (size != round_page(_ranges.v[0].length))) { ipc_port_release_send( sharedMem ); kr = kIOReturnVMError; } diff --git a/iokit/Kernel/IOCatalogue.cpp b/iokit/Kernel/IOCatalogue.cpp index 3fa1d62ee..f59e56bab 100644 --- a/iokit/Kernel/IOCatalogue.cpp +++ b/iokit/Kernel/IOCatalogue.cpp @@ -149,6 +149,7 @@ bool IOCatalogue::init(OSArray * initArray) kernelTables = OSCollectionIterator::withCollection( array ); lock = IOLockAlloc(); + kld_lock = IOLockAlloc(); kernelTables->reset(); while( (dict = (OSDictionary *) kernelTables->getNextObject())) { @@ -358,11 +359,6 @@ bool IOCatalogue::addDrivers(OSArray * drivers, } IOUnlock( lock ); - if ( doNubMatching ) { - (IOService::getServiceRoot())->waitQuiet(); - kmod_send_generic( kIOCatalogMatchIdle, 0, 0 ); - } - set->release(); iter->release(); @@ -452,9 +448,17 @@ bool IOCatalogue::isModuleLoaded( const char * moduleName ) const if ( !k_info ) { kern_return_t ret; + /* To make sure this operation completes even if a bad extension needs + * to be removed, take the kld lock for this whole block, spanning the + * kmod_load_function() and remove_startup_extension_function() calls. + */ + IOLockLock(kld_lock); + // If the module hasn't been loaded, then load it. if (kmod_load_function != 0) { + ret = kmod_load_function((char *)moduleName); + if ( ret != kIOReturnSuccess ) { IOLog("IOCatalogue: %s cannot be loaded.\n", moduleName); @@ -466,25 +470,30 @@ bool IOCatalogue::isModuleLoaded( const char * moduleName ) const if (kernelLinkerPresent && remove_startup_extension_function) { (*remove_startup_extension_function)(moduleName); } + IOLockUnlock(kld_lock); return false; } else if (kernelLinkerPresent) { // If kern linker is here, the driver is actually loaded, // so return true. + IOLockUnlock(kld_lock); return true; } else { // kern linker isn't here, a request has been queued // but the module isn't necessarily loaded yet, so stall. + IOLockUnlock(kld_lock); return false; } } else { - IOLog("IOCatalogue: %s cannot be loaded " - "(kmod load function not set).\n", - moduleName); + IOLog("IOCatalogue: %s cannot be loaded " + "(kmod load function not set).\n", + moduleName); } + IOLockUnlock(kld_lock); return false; } + /* Lock wasn't taken if we get here. */ return true; } @@ -761,13 +770,15 @@ bool IOCatalogue::serialize(OSSerialize * s) const bool IOCatalogue::recordStartupExtensions(void) { bool result = false; - if (record_startup_extensions_function) { + IOLockLock(kld_lock); + if (kernelLinkerPresent && record_startup_extensions_function) { result = (*record_startup_extensions_function)(); } else { IOLog("Can't record startup extensions; " "kernel linker is not present.\n"); result = false; } + IOLockUnlock(kld_lock); return result; } @@ -778,13 +789,15 @@ bool IOCatalogue::recordStartupExtensions(void) { bool IOCatalogue::addExtensionsFromArchive(OSData * mkext) { bool result = false; - if (add_from_mkext_function) { + IOLockLock(kld_lock); + if (kernelLinkerPresent && add_from_mkext_function) { result = (*add_from_mkext_function)(mkext); } else { IOLog("Can't add startup extensions from archive; " "kernel linker is not present.\n"); result = false; } + IOLockUnlock(kld_lock); return result; } @@ -805,7 +818,7 @@ kern_return_t IOCatalogue::removeKernelLinker(void) { /* This must be the very first thing done by this function. */ - IOTakeLock(lock); + IOLockLock(kld_lock); /* If the kernel linker isn't here, that's automatically @@ -871,7 +884,7 @@ finish: /* This must be the very last thing done before returning. */ - IOUnlock(lock); + IOLockUnlock(kld_lock); return result; } diff --git a/iokit/Kernel/IODeviceTreeSupport.cpp b/iokit/Kernel/IODeviceTreeSupport.cpp index 059598278..de364b87c 100644 --- a/iokit/Kernel/IODeviceTreeSupport.cpp +++ b/iokit/Kernel/IODeviceTreeSupport.cpp @@ -39,15 +39,16 @@ #include <DeviceTree.h> extern "C" { -#include <machine/machine_routines.h> -void DTInit( void * data ); + #include <machine/machine_routines.h> + void DTInit( void * data ); -int IODTGetLoaderInfo( char *key, void **infoAddr, int *infosize ); -void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); + int IODTGetLoaderInfo( char *key, void **infoAddr, int *infosize ); + void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); } #include <IOKit/assert.h> +#define IODTSUPPORTDEBUG 0 const IORegistryPlane * gIODTPlane; @@ -81,34 +82,33 @@ static void FreePhysicalMemory( vm_offset_t * range ); IORegistryEntry * IODeviceTreeAlloc( void * dtTop ) { - IORegistryEntry * parent; - IORegistryEntry * child; - IORegistryIterator * regIter; - DTEntryIterator iter; - DTEntry dtChild; - DTEntry mapEntry; - OSArray * stack; - OSData * prop; - OSObject * obj; - vm_offset_t * dtMap; - int propSize; - bool intMap; - bool freeDT; + IORegistryEntry *parent; + IORegistryEntry *child; + IORegistryIterator *regIter; + DTEntryIterator iter; + DTEntry dtChild; + DTEntry mapEntry; + OSArray *stack; + OSData *prop; + OSObject *obj; + vm_offset_t *dtMap; + int propSize; + bool intMap; + bool freeDT; IOLog("IODeviceTreeSupport "); gIODTPlane = IORegistryEntry::makePlane( kIODeviceTreePlane ); - gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); - gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); + gIODTNameKey = OSSymbol::withCStringNoCopy( "name" ); + gIODTUnitKey = OSSymbol::withCStringNoCopy( "AAPL,unit-string" ); gIODTCompatibleKey = OSSymbol::withCStringNoCopy( "compatible" ); - gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); - gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); + gIODTTypeKey = OSSymbol::withCStringNoCopy( "device_type" ); + gIODTModelKey = OSSymbol::withCStringNoCopy( "model" ); gIODTSizeCellKey = OSSymbol::withCStringNoCopy( "#size-cells" ); gIODTAddressCellKey = OSSymbol::withCStringNoCopy( "#address-cells" ); - gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); - - gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); + gIODTRangeKey = OSSymbol::withCStringNoCopy( "ranges" ); + gIODTPersistKey = OSSymbol::withCStringNoCopy( "IODTPersist" ); assert( gIODTPlane && gIODTCompatibleKey && gIODTTypeKey && gIODTModelKey @@ -116,23 +116,23 @@ IODeviceTreeAlloc( void * dtTop ) && gIODTPersistKey ); gIODTDefaultInterruptController - = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); + = OSSymbol::withCStringNoCopy("IOPrimaryInterruptController"); gIODTNWInterruptMappingKey - = OSSymbol::withCStringNoCopy("IONWInterrupts"); + = OSSymbol::withCStringNoCopy("IONWInterrupts"); gIODTAAPLInterruptsKey - = OSSymbol::withCStringNoCopy("AAPL,interrupts"); + = OSSymbol::withCStringNoCopy("AAPL,interrupts"); gIODTPHandleKey - = OSSymbol::withCStringNoCopy("AAPL,phandle"); + = OSSymbol::withCStringNoCopy("AAPL,phandle"); gIODTInterruptParentKey - = OSSymbol::withCStringNoCopy("interrupt-parent"); + = OSSymbol::withCStringNoCopy("interrupt-parent"); gIODTPHandles = OSArray::withCapacity( 1 ); gIODTPHandleMap = OSArray::withCapacity( 1 ); gIODTInterruptCellKey - = OSSymbol::withCStringNoCopy("#interrupt-cells"); + = OSSymbol::withCStringNoCopy("#interrupt-cells"); assert( gIODTDefaultInterruptController && gIODTNWInterruptMappingKey && gIODTAAPLInterruptsKey @@ -153,7 +153,7 @@ IODeviceTreeAlloc( void * dtTop ) do { parent = (IORegistryEntry *)stack->getObject( stack->getCount() - 1); - //parent->release(); + //parent->release(); stack->removeObject( stack->getCount() - 1); while( kSuccess == DTIterateEntries( iter, &dtChild) ) { @@ -161,18 +161,18 @@ IODeviceTreeAlloc( void * dtTop ) child = MakeReferenceTable( dtChild, freeDT ); child->attachToParent( parent, gIODTPlane); - AddPHandle( child ); + AddPHandle( child ); if( kSuccess == DTEnterEntry( iter, dtChild)) { stack->setObject( parent); parent = child; } - // only registry holds retain - child->release(); + // only registry holds retain + child->release(); } } while( stack->getCount() - && (kSuccess == DTExitEntry( iter, &dtChild))); + && (kSuccess == DTExitEntry( iter, &dtChild))); stack->release(); DTDisposeEntryIterator( iter); @@ -181,8 +181,8 @@ IODeviceTreeAlloc( void * dtTop ) // make root name first compatible entry (purely cosmetic) if( (prop = (OSData *) parent->getProperty( gIODTCompatibleKey))) { - parent->setName( parent->getName(), gIODTPlane ); - parent->setName( (const char *) prop->getBytesNoCopy() ); + parent->setName( parent->getName(), gIODTPlane ); + parent->setName( (const char *) prop->getBytesNoCopy() ); } // attach tree to meta root @@ -190,10 +190,10 @@ IODeviceTreeAlloc( void * dtTop ) parent->release(); if( freeDT ) { - // free original device tree + // free original device tree DTInit(0); IODTFreeLoaderInfo( "DeviceTree", - (void *)dtMap[0], round_page(dtMap[1]) ); + (void *)dtMap[0], round_page(dtMap[1]) ); } // adjust tree @@ -202,37 +202,36 @@ IODeviceTreeAlloc( void * dtTop ) kIORegistryIterateRecursively ); assert( regIter ); if( regIter) { - while( (child = regIter->getNextObject())) { - IODTMapInterrupts( child ); - if( !intMap && child->getProperty( gIODTInterruptParentKey)) - intMap = true; - - // Look for a "driver,AAPL,MacOSX,PowerPC" property. - if( (obj = child->getProperty( "driver,AAPL,MacOSX,PowerPC"))) { - gIOCatalogue->addExtensionsFromArchive((OSData *)obj); - - child->removeProperty( "driver,AAPL,MacOSX,PowerPC"); - } - - // some gross pruning - child->removeProperty( "lanLib,AAPL,MacOS,PowerPC"); - - if( (obj = child->getProperty( "driver,AAPL,MacOS,PowerPC"))) { - - if( (0 == (prop = (OSData *)child->getProperty( gIODTTypeKey ))) - || (strcmp( "display", (char *) prop->getBytesNoCopy())) ) { - - child->removeProperty( "driver,AAPL,MacOS,PowerPC"); + while( (child = regIter->getNextObject())) { + IODTMapInterrupts( child ); + if( !intMap && child->getProperty( gIODTInterruptParentKey)) + intMap = true; + + // Look for a "driver,AAPL,MacOSX,PowerPC" property. + if( (obj = child->getProperty( "driver,AAPL,MacOSX,PowerPC"))) { + gIOCatalogue->addExtensionsFromArchive((OSData *)obj); + + child->removeProperty( "driver,AAPL,MacOSX,PowerPC"); + } + + // some gross pruning + child->removeProperty( "lanLib,AAPL,MacOS,PowerPC"); + + if( (obj = child->getProperty( "driver,AAPL,MacOS,PowerPC"))) { + + if( (0 == (prop = (OSData *)child->getProperty( gIODTTypeKey ))) + || (strcmp( "display", (char *) prop->getBytesNoCopy())) ) { + child->removeProperty( "driver,AAPL,MacOS,PowerPC"); + } + } } - } - } - regIter->release(); + regIter->release(); } if( intMap) - // set a key in the root to indicate we found NW interrupt mapping - parent->setProperty( gIODTNWInterruptMappingKey, - (OSObject *) gIODTNWInterruptMappingKey ); + // set a key in the root to indicate we found NW interrupt mapping + parent->setProperty( gIODTNWInterruptMappingKey, + (OSObject *) gIODTNWInterruptMappingKey ); IOLog("done\n"); @@ -242,7 +241,7 @@ IODeviceTreeAlloc( void * dtTop ) int IODTGetLoaderInfo( char *key, void **infoAddr, int *infoSize ) { IORegistryEntry *chosen; - OSData *propObj; + OSData *propObj; unsigned int *propPtr; unsigned int propSize; @@ -294,73 +293,72 @@ static void FreePhysicalMemory( vm_offset_t * range ) static IORegistryEntry * MakeReferenceTable( DTEntry dtEntry, bool copy ) { - IORegistryEntry * regEntry; - OSDictionary * propTable; - const OSSymbol * nameKey; - OSData * data; - const OSSymbol * sym; + IORegistryEntry *regEntry; + OSDictionary *propTable; + const OSSymbol *nameKey; + OSData *data; + const OSSymbol *sym; DTPropertyIterator dtIter; - void * prop; - int propSize; - char * name; - char location[ 32 ]; - bool noLocation = true; + void *prop; + int propSize; + char *name; + char location[ 32 ]; + bool noLocation = true; regEntry = new IOService; if( regEntry && (false == regEntry->init())) { - regEntry->release(); - regEntry = 0; + regEntry->release(); + regEntry = 0; } if( regEntry && - (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { + (kSuccess == DTCreatePropertyIterator( dtEntry, &dtIter))) { propTable = regEntry->getPropertyTable(); - while( kSuccess == DTIterateProperties( dtIter, &name)) { - - if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) - continue; - - if( copy) { - nameKey = OSSymbol::withCString(name); - data = OSData::withBytes(prop, propSize); - } else { - nameKey = OSSymbol::withCStringNoCopy(name); - data = OSData::withBytesNoCopy(prop, propSize); - } - assert( nameKey && data ); - - propTable->setObject( nameKey, data); - data->release(); - nameKey->release(); - - if( nameKey == gIODTNameKey ) { - if( copy) - sym = OSSymbol::withCString( (const char *) prop); - else - sym = OSSymbol::withCStringNoCopy( (const char *) prop); - regEntry->setName( sym ); - sym->release(); - - } else if( nameKey == gIODTUnitKey ) { - // all OF strings are null terminated... except this one - if( propSize >= (int) sizeof( location)) - propSize = sizeof( location) - 1; - strncpy( location, (const char *) prop, propSize ); - location[ propSize ] = 0; - regEntry->setLocation( location ); - propTable->removeObject( gIODTUnitKey ); - noLocation = false; - - } else if( noLocation && (0 == strcmp( name, "reg"))) { - // default location - override later - sprintf( location, "%lX", *((UInt32 *) prop) ); - regEntry->setLocation( location ); - } - } - DTDisposePropertyIterator( dtIter); + while( kSuccess == DTIterateProperties( dtIter, &name)) { + + if( kSuccess != DTGetProperty( dtEntry, name, &prop, &propSize )) + continue; + + if( copy) { + nameKey = OSSymbol::withCString(name); + data = OSData::withBytes(prop, propSize); + } else { + nameKey = OSSymbol::withCStringNoCopy(name); + data = OSData::withBytesNoCopy(prop, propSize); + } + assert( nameKey && data ); + + propTable->setObject( nameKey, data); + data->release(); + nameKey->release(); + + if( nameKey == gIODTNameKey ) { + if( copy) + sym = OSSymbol::withCString( (const char *) prop); + else + sym = OSSymbol::withCStringNoCopy( (const char *) prop); + regEntry->setName( sym ); + sym->release(); + } else if( nameKey == gIODTUnitKey ) { + // all OF strings are null terminated... except this one + if( propSize >= (int) sizeof( location)) + propSize = sizeof( location) - 1; + strncpy( location, (const char *) prop, propSize ); + location[ propSize ] = 0; + regEntry->setLocation( location ); + propTable->removeObject( gIODTUnitKey ); + noLocation = false; + + } else if( noLocation && (0 == strcmp( name, "reg"))) { + // default location - override later + sprintf( location, "%lX", *((UInt32 *) prop) ); + regEntry->setLocation( location ); + } + } + DTDisposePropertyIterator( dtIter); } return( regEntry); @@ -371,26 +369,24 @@ static void AddPHandle( IORegistryEntry * regEntry ) OSData * data; if( regEntry->getProperty( gIODTInterruptCellKey) - && (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTPHandleKey )))) { - // a possible interrupt-parent - gIODTPHandles->setObject( data ); - gIODTPHandleMap->setObject( regEntry ); + && (data = OSDynamicCast( OSData, regEntry->getProperty( gIODTPHandleKey )))) { + // a possible interrupt-parent + gIODTPHandles->setObject( data ); + gIODTPHandleMap->setObject( regEntry ); } } static IORegistryEntry * FindPHandle( UInt32 phandle ) { - OSData * data; - IORegistryEntry * regEntry = 0; - int i; - - for( i = 0; - (data = (OSData *)gIODTPHandles->getObject( i )); - i++ ) { - if( phandle == *((UInt32 *)data->getBytesNoCopy())) { - regEntry = (IORegistryEntry *) - gIODTPHandleMap->getObject( i ); - break; + OSData *data; + IORegistryEntry *regEntry = 0; + int i; + + for( i = 0; (data = (OSData *)gIODTPHandles->getObject( i )); i++ ) { + if( phandle == *((UInt32 *)data->getBytesNoCopy())) { + regEntry = (IORegistryEntry *) + gIODTPHandleMap->getObject( i ); + break; } } @@ -400,14 +396,14 @@ static IORegistryEntry * FindPHandle( UInt32 phandle ) static bool GetUInt32( IORegistryEntry * regEntry, const OSSymbol * name, UInt32 * value ) { - OSData * data; + OSData *data; if( (data = OSDynamicCast( OSData, regEntry->getProperty( name ))) - && (4 == data->getLength())) { + && (4 == data->getLength())) { *value = *((UInt32 *) data->getBytesNoCopy()); - return( true ); + return( true ); } else - return( false ); + return( false ); } IORegistryEntry * IODTFindInterruptParent( IORegistryEntry * regEntry ) @@ -416,22 +412,22 @@ IORegistryEntry * IODTFindInterruptParent( IORegistryEntry * regEntry ) UInt32 phandle; if( GetUInt32( regEntry, gIODTInterruptParentKey, &phandle)) - parent = FindPHandle( phandle ); + parent = FindPHandle( phandle ); else if( 0 == regEntry->getProperty( "interrupt-controller")) - parent = regEntry->getParentEntry( gIODTPlane); + parent = regEntry->getParentEntry( gIODTPlane); else - parent = 0; + parent = 0; return( parent ); } const OSSymbol * IODTInterruptControllerName( IORegistryEntry * regEntry ) { - const OSSymbol * sym; - UInt32 phandle; - bool ok; - char buf[48]; + const OSSymbol *sym; + UInt32 phandle; + bool ok; + char buf[48]; ok = GetUInt32( regEntry, gIODTPHandleKey, &phandle); assert( ok ); @@ -440,7 +436,7 @@ const OSSymbol * IODTInterruptControllerName( IORegistryEntry * regEntry ) sprintf( buf, "IOInterruptController%08lX", phandle); sym = OSSymbol::withCString( buf ); } else - sym = 0; + sym = 0; return( sym ); } @@ -459,41 +455,87 @@ static void IODTGetICellCounts( IORegistryEntry * regEntry, UInt32 IODTMapOneInterrupt( IORegistryEntry * regEntry, UInt32 * intSpec, OSData ** spec, const OSSymbol ** controller ) { - IORegistryEntry * parent = 0; - OSData * data; - UInt32 * addrCmp; - UInt32 * maskCmp; - UInt32 * map; - UInt32 * endMap; - UInt32 acells, icells, pacells, picells, cell; - UInt32 i, skip = 0; - bool cmp, ok = false; + IORegistryEntry *parent = 0; + OSData *data; + UInt32 *addrCmp; + UInt32 *maskCmp; + UInt32 *map; + UInt32 *endMap; + UInt32 acells, icells, pacells, picells, cell; + UInt32 i, original_icells; + bool cmp, ok = false; + + + parent = IODTFindInterruptParent( regEntry ); + IODTGetICellCounts( parent, &icells, &acells ); + addrCmp = 0; + if( acells) { + data = OSDynamicCast( OSData, regEntry->getProperty( "reg" )); + if( data && (data->getLength() >= (acells * sizeof( UInt32)))) + addrCmp = (UInt32 *) data->getBytesNoCopy(); + } + original_icells = icells; + regEntry = parent; + + do { +#if IODTSUPPORTDEBUG + kprintf ("IODTMapOneInterrupt: current regEntry name %s\n", regEntry->getName()); + kprintf ("acells - icells: "); + for (i = 0; i < acells; i++) kprintf ("0x%08X ", addrCmp[i]); + kprintf ("- "); + for (i = 0; i < icells; i++) kprintf ("0x%08X ", intSpec[i]); + kprintf ("\n"); +#endif - do { - if( parent && (data = OSDynamicCast( OSData, - regEntry->getProperty( "interrupt-controller")))) { - // found a controller - don't want to follow cascaded controllers + if( parent && (data = OSDynamicCast( OSData, + regEntry->getProperty( "interrupt-controller")))) { + // found a controller - don't want to follow cascaded controllers parent = 0; *spec = OSData::withBytesNoCopy( (void *) intSpec, icells * sizeof( UInt32)); *controller = IODTInterruptControllerName( regEntry ); - ok = (*spec && *controller); - - } else if( parent && (data = OSDynamicCast( OSData, - regEntry->getProperty( "interrupt-map")))) { + ok = (*spec && *controller); + } else if( parent && (data = OSDynamicCast( OSData, + regEntry->getProperty( "interrupt-map")))) { // interrupt-map map = (UInt32 *) data->getBytesNoCopy(); endMap = map + (data->getLength() / sizeof(UInt32)); data = OSDynamicCast( OSData, regEntry->getProperty( "interrupt-map-mask" )); if( data && (data->getLength() >= ((acells + icells) * sizeof( UInt32)))) maskCmp = (UInt32 *) data->getBytesNoCopy(); - else - maskCmp = 0; - - do { - for( i = 0, cmp = true; - cmp && (i < (acells + icells)); - i++) { + else + maskCmp = 0; + +#if IODTSUPPORTDEBUG + if (maskCmp) { + kprintf (" maskCmp: "); + for (i = 0; i < acells + icells; i++) { + if (i == acells) + kprintf ("- "); + kprintf ("0x%08X ", maskCmp[i]); + } + kprintf ("\n"); + kprintf (" masked: "); + for (i = 0; i < acells + icells; i++) { + if (i == acells) + kprintf ("- "); + kprintf ("0x%08X ", ((i < acells) ? addrCmp[i] : intSpec[i-acells]) & maskCmp[i]); + } + kprintf ("\n"); + } else + kprintf ("no maskCmp\n"); +#endif + do { +#if IODTSUPPORTDEBUG + kprintf (" map: "); + for (i = 0; i < acells + icells; i++) { + if (i == acells) + kprintf ("- "); + kprintf ("0x%08X ", map[i]); + } + kprintf ("\n"); +#endif + for( i = 0, cmp = true; cmp && (i < (acells + icells)); i++) { cell = (i < acells) ? addrCmp[i] : intSpec[ i - acells ]; if( maskCmp) cell &= maskCmp[i]; @@ -504,67 +546,55 @@ UInt32 IODTMapOneInterrupt( IORegistryEntry * regEntry, UInt32 * intSpec, if( 0 == (parent = FindPHandle( *(map++) ))) unexpected(break); - if( cmp) - intSpec = map; - else { - IODTGetICellCounts( parent, &picells, &pacells ); + IODTGetICellCounts( parent, &picells, &pacells ); + if( cmp) { + addrCmp = map; + intSpec = map + pacells; + regEntry = parent; + } else { map += pacells + picells; - parent = 0; - } + } } while( !cmp && (map < endMap) ); + if (!cmp) + parent = 0; + } - } else - // first time (usually) - parent = IODTFindInterruptParent( regEntry ); - - if( parent) { + if( parent) { IODTGetICellCounts( parent, &icells, &acells ); - addrCmp = 0; - if( acells) { - data = OSDynamicCast( OSData, regEntry->getProperty( "reg" )); - if( data && (data->getLength() >= (acells * sizeof( UInt32)))) - addrCmp = (UInt32 *) data->getBytesNoCopy(); - } - regEntry = parent; - if( !skip) - skip = icells; - } - } while( parent); - - if( ok) - return( skip ); - else - return( 0 ); + regEntry = parent; + } + } while( parent); + + return( ok ? original_icells : 0 ); } bool IODTMapInterrupts( IORegistryEntry * regEntry ) { - IORegistryEntry * parent; - OSData * local; - OSData * local2; - UInt32 * localBits; - UInt32 * localEnd; - OSData * map; - OSArray * mapped; - const OSSymbol * controller; - OSArray * controllers; - UInt32 skip = 1; - bool ok, nw; + IORegistryEntry *parent; + OSData *local; + OSData *local2; + UInt32 *localBits; + UInt32 *localEnd; + OSData *map; + OSArray *mapped; + const OSSymbol *controller; + OSArray *controllers; + UInt32 skip = 1; + bool ok, nw; nw = (0 == (local = OSDynamicCast( OSData, - regEntry->getProperty( gIODTAAPLInterruptsKey)))); - if( nw - && (0 == (local = OSDynamicCast( OSData, - regEntry->getProperty( "interrupts"))))) - return( true ); // nothing to see here + regEntry->getProperty( gIODTAAPLInterruptsKey)))); + if( nw && (0 == (local = OSDynamicCast( OSData, + regEntry->getProperty( "interrupts"))))) + return( true ); // nothing to see here if( nw && (parent = regEntry->getParentEntry( gIODTPlane))) { - // check for bridges on old world - if( (local2 = OSDynamicCast( OSData, - parent->getProperty( gIODTAAPLInterruptsKey)))) { - local = local2; - nw = false; - } + // check for bridges on old world + if( (local2 = OSDynamicCast( OSData, + parent->getProperty( gIODTAAPLInterruptsKey)))) { + local = local2; + nw = false; + } } localBits = (UInt32 *) local->getBytesNoCopy(); @@ -579,12 +609,12 @@ bool IODTMapInterrupts( IORegistryEntry * regEntry ) skip = IODTMapOneInterrupt( regEntry, localBits, &map, &controller ); if( 0 == skip) { IOLog("%s: error mapping interrupt[%d]\n", - regEntry->getName(), mapped->getCount()); + regEntry->getName(), mapped->getCount()); break; } } else { map = OSData::withData( local, mapped->getCount() * sizeof( UInt32), - sizeof( UInt32)); + sizeof( UInt32)); controller = gIODTDefaultInterruptController; } @@ -599,7 +629,7 @@ bool IODTMapInterrupts( IORegistryEntry * regEntry ) ok &= (localBits == localEnd); if( ok ) { - // store results + // store results ok = regEntry->setProperty( gIOInterruptControllersKey, controllers); ok &= regEntry->setProperty( gIOInterruptSpecifiersKey, mapped); } @@ -619,16 +649,16 @@ static const char * CompareKey( OSString * key, const IORegistryEntry * table, const OSSymbol * propName ) { - OSObject * prop; - OSData * data; - OSString * string; - const char * ckey; - UInt32 keyLen; - const char * names; - const char * lastName; - bool wild; - bool matched; - const char * result = 0; + OSObject *prop; + OSData *data; + OSString *string; + const char *ckey; + UInt32 keyLen; + const char *names; + const char *lastName; + bool wild; + bool matched; + const char *result = 0; if( 0 == (prop = table->getProperty( propName ))) return( 0 ); @@ -636,13 +666,11 @@ CompareKey( OSString * key, if( (data = OSDynamicCast( OSData, prop ))) { names = (const char *) data->getBytesNoCopy(); lastName = names + data->getLength(); - } else if( (string = OSDynamicCast( OSString, prop ))) { names = string->getCStringNoCopy(); lastName = names + string->getLength() + 1; - } else - return( 0 ); + return( 0 ); ckey = key->getCStringNoCopy(); keyLen = key->getLength(); @@ -670,8 +698,8 @@ CompareKey( OSString * key, bool IODTCompareNubName( const IORegistryEntry * regEntry, OSString * name, OSString ** matchingName ) { - const char * result; - bool matched; + const char *result; + bool matched; matched = (0 != (result = CompareKey( name, regEntry, gIODTNameKey))) || (0 != (result = CompareKey( name, regEntry, gIODTCompatibleKey))) @@ -687,17 +715,17 @@ bool IODTCompareNubName( const IORegistryEntry * regEntry, bool IODTMatchNubWithKeys( IORegistryEntry * regEntry, const char * keys ) { - OSObject * obj; + OSObject *obj; bool result = false; obj = OSUnserialize( keys, 0 ); if( obj) { result = regEntry->compareNames( obj ); - obj->release(); + obj->release(); } #ifdef DEBUG - else IOLog("Couldn't unserialize %s\n", keys ); + else IOLog("Couldn't unserialize %s\n", keys ); #endif return( result ); @@ -706,32 +734,32 @@ bool IODTMatchNubWithKeys( IORegistryEntry * regEntry, OSCollectionIterator * IODTFindMatchingEntries( IORegistryEntry * from, IOOptionBits options, const char * keys ) { - OSSet * result; - IORegistryEntry * next; - IORegistryIterator * iter; - OSCollectionIterator * cIter; - bool cmp; - bool minus = options & kIODTExclusive; + OSSet *result; + IORegistryEntry *next; + IORegistryIterator *iter; + OSCollectionIterator *cIter; + bool cmp; + bool minus = options & kIODTExclusive; result = OSSet::withCapacity( 3 ); if( !result) - return( 0); + return( 0); iter = IORegistryIterator::iterateOver( from, gIODTPlane, - (options & kIODTRecursive) ? kIORegistryIterateRecursively : 0 ); + (options & kIODTRecursive) ? kIORegistryIterateRecursively : 0 ); if( iter) { while( (next = iter->getNextObject())) { // Look for existence of a debug property to skip if( next->getProperty("AAPL,ignore")) - continue; + continue; - if( keys) { + if( keys) { cmp = IODTMatchNubWithKeys( next, keys ); if( (minus && (false == cmp)) - || ((false == minus) && (false != cmp)) ) + || ((false == minus) && (false != cmp)) ) result->setObject( next); - } else + } else result->setObject( next); } iter->release(); @@ -754,16 +782,17 @@ void IODTSetResolving( IORegistryEntry * regEntry, IODTNVLocationFunc locationFunc ) { IODTPersistent persist; - OSData * prop; + OSData *prop; persist.compareFunc = compareFunc; persist.locationFunc = locationFunc; prop = OSData::withBytes( &persist, sizeof( persist)); if( !prop) - return; + return; regEntry->setProperty( gIODTPersistKey, prop); prop->release(); + return; } static SInt32 DefaultCompare( UInt32 cellCount, UInt32 left[], UInt32 right[] ) @@ -780,6 +809,7 @@ void IODTGetCellCounts( IORegistryEntry * regEntry, *sizeCount = 1; if( !GetUInt32( regEntry, gIODTAddressCellKey, addressCount)) *addressCount = 2; + return; } // Given addr & len cells from our child, find it in our ranges property, then @@ -792,20 +822,20 @@ bool IODTResolveAddressCell( IORegistryEntry * regEntry, UInt32 cellsIn[], IOPhysicalAddress * phys, IOPhysicalLength * len ) { - IORegistryEntry * parent; - OSData * prop; + IORegistryEntry *parent; + OSData *prop; // cells in addresses at regEntry - UInt32 sizeCells, addressCells; + UInt32 sizeCells, addressCells; // cells in addresses below regEntry - UInt32 childSizeCells, childAddressCells; - UInt32 childCells; - UInt32 cell[ 5 ], offset = 0, length; - UInt32 * range; - UInt32 * endRanges; - bool ok = true; - SInt32 diff; - - IODTPersistent * persist; + UInt32 childSizeCells, childAddressCells; + UInt32 childCells; + UInt32 cell[ 5 ], offset = 0, length; + UInt32 *range; + UInt32 *endRanges; + bool ok = true; + SInt32 diff; + + IODTPersistent *persist; IODTCompareAddressCellFunc compare; IODTGetCellCounts( regEntry, &childSizeCells, &childAddressCells ); @@ -814,20 +844,20 @@ bool IODTResolveAddressCell( IORegistryEntry * regEntry, bcopy( cellsIn, cell, 4 * childCells ); if( childSizeCells > 1) *len = IOPhysical32( cellsIn[ childAddressCells ], - cellsIn[ childAddressCells + 1 ] ); + cellsIn[ childAddressCells + 1 ] ); else *len = IOPhysical32( 0, cellsIn[ childAddressCells ] ); do { prop = OSDynamicCast( OSData, regEntry->getProperty( gIODTRangeKey )); if( 0 == prop) { - /* end of the road */ + /* end of the road */ *phys = IOPhysical32( 0, cell[ childAddressCells - 1 ] + offset); break; } parent = regEntry->getParentEntry( gIODTPlane ); - IODTGetCellCounts( parent, &sizeCells, &addressCells ); + IODTGetCellCounts( parent, &sizeCells, &addressCells ); if( (length = prop->getLength())) { // search @@ -849,6 +879,7 @@ bool IODTResolveAddressCell( IORegistryEntry * regEntry, diff = (*compare)( childAddressCells, cell, range ); if( diff < 0) continue; + // is cell + size <= range end? if( (diff + cell[ childCells - 1 ]) > range[ childCells + addressCells - 1 ]) @@ -865,10 +896,10 @@ bool IODTResolveAddressCell( IORegistryEntry * regEntry, } /* else zero length range => pass thru to parent */ - regEntry = parent; + regEntry = parent; childSizeCells = sizeCells; childAddressCells = addressCells; - childCells = childAddressCells + childSizeCells; + childCells = childAddressCells + childSizeCells; } while( ok && regEntry); @@ -880,24 +911,24 @@ OSArray * IODTResolveAddressing( IORegistryEntry * regEntry, const char * addressPropertyName, IODeviceMemory * parent ) { - IORegistryEntry * parentEntry; - OSData * addressProperty; - UInt32 sizeCells, addressCells, cells; - int i, num; - UInt32 * reg; + IORegistryEntry *parentEntry; + OSData *addressProperty; + UInt32 sizeCells, addressCells, cells; + int i, num; + UInt32 *reg; IOPhysicalAddress phys; IOPhysicalLength len; - OSArray * array; - IODeviceMemory * range; + OSArray *array; + IODeviceMemory *range; parentEntry = regEntry->getParentEntry( gIODTPlane ); addressProperty = (OSData *) regEntry->getProperty( addressPropertyName ); if( (0 == addressProperty) || (0 == parentEntry)) - return( 0); + return( 0); IODTGetCellCounts( parentEntry, &sizeCells, &addressCells ); if( 0 == sizeCells) - return( 0); + return( 0); cells = sizeCells + addressCells; reg = (UInt32 *) addressProperty->getBytesNoCopy(); @@ -905,22 +936,20 @@ OSArray * IODTResolveAddressing( IORegistryEntry * regEntry, array = OSArray::withCapacity( 1 ); if( 0 == array) - return( 0); + return( 0); for( i = 0; i < num; i++) { - - if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) { - - range = 0; - if( parent) - range = IODeviceMemory::withSubRange( parent, - phys - parent->getPhysicalAddress(), len ); - if( 0 == range) - range = IODeviceMemory::withRange( phys, len ); - if( range) - array->setObject( range ); - } - reg += cells; + if( IODTResolveAddressCell( parentEntry, reg, &phys, &len )) { + range = 0; + if( parent) + range = IODeviceMemory::withSubRange( parent, + phys - parent->getPhysicalAddress(), len ); + if( 0 == range) + range = IODeviceMemory::withRange( phys, len ); + if( range) + array->setObject( range ); + } + reg += cells; } regEntry->setProperty( gIODeviceMemoryKey, array); @@ -935,33 +964,27 @@ static void IODTGetNVLocation( UInt8 * busNum, UInt8 * deviceNum, UInt8 * functionNum ) { - OSData * prop; - IODTPersistent * persist; - UInt32 * cell; + OSData *prop; + IODTPersistent *persist; + UInt32 *cell; prop = (OSData *) parent->getProperty( gIODTPersistKey ); if( prop) { persist = (IODTPersistent *) prop->getBytesNoCopy(); - (*persist->locationFunc)( regEntry, busNum, deviceNum, functionNum ); - + (*persist->locationFunc)( regEntry, busNum, deviceNum, functionNum ); } else { prop = (OSData *) regEntry->getProperty( "reg" ); *functionNum = 0; if( prop) { cell = (UInt32 *) prop->getBytesNoCopy(); -#if 0 - if( (regHi & 0xf0000000) != 0xf0000000) { - *bus = 0x03 & (regHi >> 16); - *function = 0x07 & (regHi >> 8); - *device = 0x1f & (regHi >> 11); -#endif *busNum = 3; *deviceNum = 0x1f & (cell[ 0 ] >> 24); } else { *busNum = 0; *deviceNum = 0; - } + } } + return; } /* @@ -971,32 +994,29 @@ static void IODTGetNVLocation( IOReturn IODTMakeNVDescriptor( IORegistryEntry * regEntry, IONVRAMDescriptor * hdr ) { - IORegistryEntry * parent; - UInt32 level; - UInt32 bridgeDevices; - UInt8 busNum; - UInt8 deviceNum; - UInt8 functionNum; + IORegistryEntry *parent; + UInt32 level; + UInt32 bridgeDevices; + UInt8 busNum; + UInt8 deviceNum; + UInt8 functionNum; hdr->format = 1; hdr->marker = 0; - for( - level = 0, bridgeDevices = 0; - (parent = regEntry->getParentEntry( gIODTPlane )) - && (level < 7); - level++ ) { + for(level = 0, bridgeDevices = 0; + (parent = regEntry->getParentEntry( gIODTPlane )) && (level < 7); level++ ) { IODTGetNVLocation( parent, regEntry, - &busNum, &deviceNum, &functionNum ); - if( level) - bridgeDevices |= ((deviceNum & 0x1f) << ((level - 1) * 5)); - else { + &busNum, &deviceNum, &functionNum ); + if( level) + bridgeDevices |= ((deviceNum & 0x1f) << ((level - 1) * 5)); + else { hdr->busNum = busNum; hdr->deviceNum = deviceNum; hdr->functionNum = functionNum; - } - regEntry = parent; + } + regEntry = parent; } hdr->bridgeCount = level - 2; hdr->bridgeDevices = bridgeDevices; @@ -1006,49 +1026,47 @@ IOReturn IODTMakeNVDescriptor( IORegistryEntry * regEntry, OSData * IODTFindSlotName( IORegistryEntry * regEntry, UInt32 deviceNumber ) { - IORegistryEntry * parent; - OSData * data; - OSData * ret = 0; - UInt32 * bits; - UInt32 i; - char * names; - char * lastName; - UInt32 mask; + IORegistryEntry *parent; + OSData *data; + OSData *ret = 0; + UInt32 *bits; + UInt32 i; + char *names; + char *lastName; + UInt32 mask; data = (OSData *) regEntry->getProperty("AAPL,slot-name"); if( data) - return( data); + return( data); parent = regEntry->getParentEntry( gIODTPlane ); if( !parent) - return( 0 ); + return( 0 ); data = OSDynamicCast( OSData, parent->getProperty("slot-names")); if( !data) - return( 0 ); + return( 0 ); if( data->getLength() <= 4) - return( 0 ); + return( 0 ); bits = (UInt32 *) data->getBytesNoCopy(); mask = *bits; if( (0 == (mask & (1 << deviceNumber)))) - return( 0 ); + return( 0 ); names = (char *)(bits + 1); lastName = names + (data->getLength() - 4); - for( i = 0; - (i <= deviceNumber) && (names < lastName); - i++ ) { + for( i = 0; (i <= deviceNumber) && (names < lastName); i++ ) { - if( mask & (1 << i)) { + if( mask & (1 << i)) { if( i == deviceNumber) { - data = OSData::withBytesNoCopy( names, 1 + strlen( names)); - if( data) { - regEntry->setProperty("AAPL,slot-name", data); - ret = data; - data->release(); - } + data = OSData::withBytesNoCopy( names, 1 + strlen( names)); + if( data) { + regEntry->setProperty("AAPL,slot-name", data); + ret = data; + data->release(); + } } else - names += 1 + strlen( names); + names += 1 + strlen( names); } } diff --git a/iokit/Kernel/IOInterruptController.cpp b/iokit/Kernel/IOInterruptController.cpp index c41df7e8c..3b7d49b5a 100644 --- a/iokit/Kernel/IOInterruptController.cpp +++ b/iokit/Kernel/IOInterruptController.cpp @@ -244,7 +244,17 @@ IOReturn IOInterruptController::enableInterrupt(IOService *nub, int source) if (vector->interruptDisabledSoft) { vector->interruptDisabledSoft = 0; +#if __ppc__ + sync(); + isync(); +#endif + if (!getPlatform()->atInterruptLevel()) { + while (vector->interruptActive); +#if __ppc__ + isync(); +#endif + } if (vector->interruptDisabledHard) { vector->interruptDisabledHard = 0; @@ -554,9 +564,8 @@ IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub, vector = &vectors[vectorNumber]; if (vector->interruptDisabledSoft) { - vector->interruptDisabledSoft = 0; - interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); + vector->interruptDisabledSoft = 0; vectorsEnabled++; IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); @@ -584,13 +593,12 @@ IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub, vector = &vectors[vectorNumber]; if (!vector->interruptDisabledSoft) { + interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); vector->interruptDisabledSoft = 1; #if __ppc__ sync(); isync(); #endif - - interruptState = IOSimpleLockLockDisableInterrupt(controllerLock); vectorsEnabled--; IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState); } diff --git a/iokit/Kernel/IOKitDebug.cpp b/iokit/Kernel/IOKitDebug.cpp index e7be3a62a..b694bcbb3 100644 --- a/iokit/Kernel/IOKitDebug.cpp +++ b/iokit/Kernel/IOKitDebug.cpp @@ -67,11 +67,16 @@ void IOPrintPlane( const IORegistryPlane * plane ) iter->reset(); while( (next = iter->getNextObjectRecursive())) { - sprintf( format + 1, "%ds", next->getDepth( plane )); + sprintf( format + 1, "%ds", 2 * next->getDepth( plane )); IOLog( format, ""); + IOLog( "\033[33m%s", next->getName( plane )); + if( (next->getLocation( plane ))) + IOLog("@%s", next->getLocation( plane )); + IOLog("\033[0m <class %s", next->getMetaClass()->getClassName()); if( (service = OSDynamicCast(IOService, next))) - IOLog("<%ld>", service->getBusyState()); - IOLog( "%s\n", next->getName()); + IOLog(", busy %ld", service->getBusyState()); + IOLog( ">\n"); + IOSleep(250); } iter->release(); } diff --git a/iokit/Kernel/IOLib.c b/iokit/Kernel/IOLib.c index 525094a7c..2721732a0 100644 --- a/iokit/Kernel/IOLib.c +++ b/iokit/Kernel/IOLib.c @@ -53,7 +53,7 @@ static lock_t * threadArgLock; enum { kIOMaxPageableMaps = 16 }; enum { kIOPageableMapSize = 16 * 1024 * 1024 }; -enum { kIOPageableMaxMapSize = 32 * 1024 * 1024 }; +enum { kIOPageableMaxMapSize = 64 * 1024 * 1024 }; typedef struct { vm_map_t map; @@ -342,27 +342,26 @@ void IOFreeContiguous(void * address, vm_size_t size) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -void * IOMallocPageable(vm_size_t size, vm_size_t alignment) +typedef kern_return_t (*IOIteratePageableMapsCallback)(vm_map_t map, void * ref); + +kern_return_t IOIteratePageableMaps(vm_size_t size, + IOIteratePageableMapsCallback callback, void * ref) { kern_return_t kr = kIOReturnNotReady; - vm_address_t address; vm_size_t segSize; UInt32 attempts; UInt32 index; vm_offset_t min; vm_map_t map; - if (alignment > page_size) - return( 0 ); if (size > kIOPageableMaxMapSize) - return( 0 ); + return( kIOReturnBadArgument ); do { index = gIOKitPageableSpace.hint; attempts = gIOKitPageableSpace.count; while( attempts--) { - kr = kmem_alloc_pageable( gIOKitPageableSpace.maps[index].map, - &address, size); + kr = (*callback)(gIOKitPageableSpace.maps[index].map, ref); if( KERN_SUCCESS == kr) { gIOKitPageableSpace.hint = index; break; @@ -410,15 +409,46 @@ void * IOMallocPageable(vm_size_t size, vm_size_t alignment) } while( true ); - if( KERN_SUCCESS != kr) - address = 0; + return kr; +} + +struct IOMallocPageableRef +{ + vm_address_t address; + vm_size_t size; +}; + +static kern_return_t IOMallocPageableCallback(vm_map_t map, void * _ref) +{ + struct IOMallocPageableRef * ref = (struct IOMallocPageableRef *) _ref; + kern_return_t kr; + + kr = kmem_alloc_pageable( map, &ref->address, ref->size ); + + return( kr ); +} + +void * IOMallocPageable(vm_size_t size, vm_size_t alignment) +{ + kern_return_t kr = kIOReturnNotReady; + struct IOMallocPageableRef ref; + + if (alignment > page_size) + return( 0 ); + if (size > kIOPageableMaxMapSize) + return( 0 ); + + ref.size = size; + kr = IOIteratePageableMaps( size, &IOMallocPageableCallback, &ref ); + if( kIOReturnSuccess != kr) + ref.address = 0; #if IOALLOCDEBUG - if( address) - debug_iomalloc_size += round_page(size); + if( ref.address) + debug_iomalloc_size += round_page(size); #endif - return (void *) address; + return( (void *) ref.address ); } vm_map_t IOPageableMapForAddress( vm_address_t address ) @@ -605,3 +635,8 @@ unsigned int IOAlignmentToSize(IOAlignment align) } return size; } + +IOReturn IONDRVLibrariesInitialize( void ) +{ + return( kIOReturnUnsupported ); +} diff --git a/iokit/Kernel/IOLocks.cpp b/iokit/Kernel/IOLocks.cpp index f9940461e..49ce8de91 100644 --- a/iokit/Kernel/IOLocks.cpp +++ b/iokit/Kernel/IOLocks.cpp @@ -49,8 +49,6 @@ void IOLockFree( IOLock * lock) void IOLockInitWithState( IOLock * lock, IOLockState state) { - mutex_init( lock, ETAP_IO_AHA); - if( state == kIOLockStateLocked) IOLockLock( lock); } @@ -96,7 +94,7 @@ void IORecursiveLockLock( IORecursiveLock * _lock) if( lock->thread == IOThreadSelf()) lock->count++; else { - _mutex_lock( lock->mutex ); + mutex_lock( lock->mutex ); assert( lock->thread == 0 ); assert( lock->count == 0 ); lock->thread = IOThreadSelf(); @@ -112,7 +110,7 @@ boolean_t IORecursiveLockTryLock( IORecursiveLock * _lock) lock->count++; return( true ); } else { - if( _mutex_try( lock->mutex )) { + if( mutex_try( lock->mutex )) { assert( lock->thread == 0 ); assert( lock->count == 0 ); lock->thread = IOThreadSelf(); @@ -159,7 +157,7 @@ int IORecursiveLockSleep(IORecursiveLock *_lock, void *event, UInt32 interType) res = thread_block(0); if (THREAD_AWAKENED == res) { - _mutex_lock(lock->mutex); + mutex_lock(lock->mutex); assert(lock->thread == 0); assert(lock->count == 0); lock->thread = IOThreadSelf(); diff --git a/iokit/Kernel/IOMemoryDescriptor.cpp b/iokit/Kernel/IOMemoryDescriptor.cpp index dc0ad9b50..007b22d2f 100644 --- a/iokit/Kernel/IOMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMemoryDescriptor.cpp @@ -38,10 +38,26 @@ __BEGIN_DECLS #include <vm/pmap.h> +#include <device/device_port.h> +void bcopy_phys(char *from, char *to, int size); void pmap_enter(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, boolean_t wired); void ipc_port_release_send(ipc_port_t port); vm_offset_t vm_map_get_phys_page(vm_map_t map, vm_offset_t offset); + +memory_object_t +device_pager_setup( + memory_object_t pager, + int device_handle, + vm_size_t size, + int flags); +kern_return_t +device_pager_populate_object( + memory_object_t pager, + vm_object_offset_t offset, + vm_offset_t phys_addr, + vm_size_t size); + __END_DECLS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -53,7 +69,16 @@ OSDefineAbstractStructors( IOMemoryDescriptor, OSObject ) OSDefineMetaClassAndStructors(IOGeneralMemoryDescriptor, IOMemoryDescriptor) -extern "C" vm_map_t IOPageableMapForAddress( vm_address_t address ); +extern "C" { + +vm_map_t IOPageableMapForAddress( vm_address_t address ); + +typedef kern_return_t (*IOIteratePageableMapsCallback)(vm_map_t map, void * ref); + +kern_return_t IOIteratePageableMaps(vm_size_t size, + IOIteratePageableMapsCallback callback, void * ref); + +} /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -65,6 +90,62 @@ inline vm_map_t IOGeneralMemoryDescriptor::getMapForTask( task_t task, vm_addres return( get_task_map( task )); } +inline vm_offset_t pmap_extract_safe(task_t task, vm_offset_t va) +{ + vm_offset_t pa = pmap_extract(get_task_pmap(task), va); + + if ( pa == 0 ) + { + pa = vm_map_get_phys_page(get_task_map(task), trunc_page(va)); + if ( pa ) pa += va - trunc_page(va); + } + + return pa; +} + +inline void bcopy_phys_safe(char * from, char * to, int size) +{ + boolean_t enabled = ml_set_interrupts_enabled(FALSE); + + bcopy_phys(from, to, size); + + ml_set_interrupts_enabled(enabled); +} + +#define next_page(a) ( trunc_page(a) + page_size ) + + +extern "C" { + +kern_return_t device_data_action( + int device_handle, + ipc_port_t device_pager, + vm_prot_t protection, + vm_object_offset_t offset, + vm_size_t size) +{ + IOMemoryDescriptor * memDesc = (IOMemoryDescriptor *) device_handle; + + assert( OSDynamicCast( IOMemoryDescriptor, memDesc )); + + return( memDesc->handleFault( device_pager, 0, 0, + offset, size, kIOMapDefaultCache /*?*/)); +} + +kern_return_t device_close( + int device_handle) +{ + IOMemoryDescriptor * memDesc = (IOMemoryDescriptor *) device_handle; + + assert( OSDynamicCast( IOMemoryDescriptor, memDesc )); + + memDesc->release(); + + return( kIOReturnSuccess ); +} + +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* @@ -342,86 +423,86 @@ void IOGeneralMemoryDescriptor::free() super::free(); } -void IOGeneralMemoryDescriptor::unmapFromKernel() -{ - kern_return_t krtn; - vm_offset_t off; - // Pull the shared pages out of the task map - // Do we need to unwire it first? - for ( off = 0; off < _kernSize; off += page_size ) - { - pmap_change_wiring( - kernel_pmap, - _kernPtrAligned + off, - FALSE); - - pmap_remove( - kernel_pmap, - _kernPtrAligned + off, - _kernPtrAligned + off + page_size); - } - // Free the former shmem area in the task - krtn = vm_deallocate(kernel_map, - _kernPtrAligned, - _kernSize ); - assert(krtn == KERN_SUCCESS); - _kernPtrAligned = 0; -} - -void IOGeneralMemoryDescriptor::mapIntoKernel(unsigned rangeIndex) -{ - kern_return_t krtn; - vm_offset_t off; - - if (_kernPtrAligned) - { - if (_kernPtrAtIndex == rangeIndex) return; - unmapFromKernel(); - assert(_kernPtrAligned == 0); - } - - vm_offset_t srcAlign = trunc_page(_ranges.v[rangeIndex].address); - - _kernSize = trunc_page(_ranges.v[rangeIndex].address + - _ranges.v[rangeIndex].length + - page_size - 1) - srcAlign; - - /* Find some memory of the same size in kernel task. We use vm_allocate() - to do this. vm_allocate inserts the found memory object in the - target task's map as a side effect. */ - krtn = vm_allocate( kernel_map, - &_kernPtrAligned, - _kernSize, - VM_FLAGS_ANYWHERE|VM_MAKE_TAG(VM_MEMORY_IOKIT) ); // Find first fit - assert(krtn == KERN_SUCCESS); - if(krtn) return; - - /* For each page in the area allocated from the kernel map, - find the physical address of the page. - Enter the page in the target task's pmap, at the - appropriate target task virtual address. */ - for ( off = 0; off < _kernSize; off += page_size ) - { - vm_offset_t kern_phys_addr, phys_addr; - if( _task) - phys_addr = pmap_extract( get_task_pmap(_task), srcAlign + off ); - else - phys_addr = srcAlign + off; - assert(phys_addr); - if(phys_addr == 0) return; - - // Check original state. - kern_phys_addr = pmap_extract( kernel_pmap, _kernPtrAligned + off ); - // Set virtual page to point to the right physical one - pmap_enter( - kernel_pmap, - _kernPtrAligned + off, - phys_addr, - VM_PROT_READ|VM_PROT_WRITE, - TRUE); - } - _kernPtrAtIndex = rangeIndex; -} +/* DEPRECATED */ void IOGeneralMemoryDescriptor::unmapFromKernel() +/* DEPRECATED */ { +/* DEPRECATED */ kern_return_t krtn; +/* DEPRECATED */ vm_offset_t off; +/* DEPRECATED */ // Pull the shared pages out of the task map +/* DEPRECATED */ // Do we need to unwire it first? +/* DEPRECATED */ for ( off = 0; off < _kernSize; off += page_size ) +/* DEPRECATED */ { +/* DEPRECATED */ pmap_change_wiring( +/* DEPRECATED */ kernel_pmap, +/* DEPRECATED */ _kernPtrAligned + off, +/* DEPRECATED */ FALSE); +/* DEPRECATED */ +/* DEPRECATED */ pmap_remove( +/* DEPRECATED */ kernel_pmap, +/* DEPRECATED */ _kernPtrAligned + off, +/* DEPRECATED */ _kernPtrAligned + off + page_size); +/* DEPRECATED */ } +/* DEPRECATED */ // Free the former shmem area in the task +/* DEPRECATED */ krtn = vm_deallocate(kernel_map, +/* DEPRECATED */ _kernPtrAligned, +/* DEPRECATED */ _kernSize ); +/* DEPRECATED */ assert(krtn == KERN_SUCCESS); +/* DEPRECATED */ _kernPtrAligned = 0; +/* DEPRECATED */ } +/* DEPRECATED */ +/* DEPRECATED */ void IOGeneralMemoryDescriptor::mapIntoKernel(unsigned rangeIndex) +/* DEPRECATED */ { +/* DEPRECATED */ kern_return_t krtn; +/* DEPRECATED */ vm_offset_t off; +/* DEPRECATED */ +/* DEPRECATED */ if (_kernPtrAligned) +/* DEPRECATED */ { +/* DEPRECATED */ if (_kernPtrAtIndex == rangeIndex) return; +/* DEPRECATED */ unmapFromKernel(); +/* DEPRECATED */ assert(_kernPtrAligned == 0); +/* DEPRECATED */ } +/* DEPRECATED */ +/* DEPRECATED */ vm_offset_t srcAlign = trunc_page(_ranges.v[rangeIndex].address); +/* DEPRECATED */ +/* DEPRECATED */ _kernSize = trunc_page(_ranges.v[rangeIndex].address + +/* DEPRECATED */ _ranges.v[rangeIndex].length + +/* DEPRECATED */ page_size - 1) - srcAlign; +/* DEPRECATED */ +/* DEPRECATED */ /* Find some memory of the same size in kernel task. We use vm_allocate() */ +/* DEPRECATED */ /* to do this. vm_allocate inserts the found memory object in the */ +/* DEPRECATED */ /* target task's map as a side effect. */ +/* DEPRECATED */ krtn = vm_allocate( kernel_map, +/* DEPRECATED */ &_kernPtrAligned, +/* DEPRECATED */ _kernSize, +/* DEPRECATED */ VM_FLAGS_ANYWHERE|VM_MAKE_TAG(VM_MEMORY_IOKIT) ); // Find first fit +/* DEPRECATED */ assert(krtn == KERN_SUCCESS); +/* DEPRECATED */ if(krtn) return; +/* DEPRECATED */ +/* DEPRECATED */ /* For each page in the area allocated from the kernel map, */ +/* DEPRECATED */ /* find the physical address of the page. */ +/* DEPRECATED */ /* Enter the page in the target task's pmap, at the */ +/* DEPRECATED */ /* appropriate target task virtual address. */ +/* DEPRECATED */ for ( off = 0; off < _kernSize; off += page_size ) +/* DEPRECATED */ { +/* DEPRECATED */ vm_offset_t kern_phys_addr, phys_addr; +/* DEPRECATED */ if( _task) +/* DEPRECATED */ phys_addr = pmap_extract( get_task_pmap(_task), srcAlign + off ); +/* DEPRECATED */ else +/* DEPRECATED */ phys_addr = srcAlign + off; +/* DEPRECATED */ assert(phys_addr); +/* DEPRECATED */ if(phys_addr == 0) return; +/* DEPRECATED */ +/* DEPRECATED */ // Check original state. +/* DEPRECATED */ kern_phys_addr = pmap_extract( kernel_pmap, _kernPtrAligned + off ); +/* DEPRECATED */ // Set virtual page to point to the right physical one +/* DEPRECATED */ pmap_enter( +/* DEPRECATED */ kernel_pmap, +/* DEPRECATED */ _kernPtrAligned + off, +/* DEPRECATED */ phys_addr, +/* DEPRECATED */ VM_PROT_READ|VM_PROT_WRITE, +/* DEPRECATED */ TRUE); +/* DEPRECATED */ } +/* DEPRECATED */ _kernPtrAtIndex = rangeIndex; +/* DEPRECATED */ } /* * getDirection: @@ -454,318 +535,333 @@ IOOptionBits IOMemoryDescriptor::getTag( void ) return( _tag); } -/* - * setPosition - * - * Set the logical start position inside the client buffer. - * - * It is convention that the position reflect the actual byte count that - * is successfully transferred into or out of the buffer, before the I/O - * request is "completed" (ie. sent back to its originator). - */ +IOPhysicalAddress IOMemoryDescriptor::getSourceSegment( IOByteCount offset, + IOByteCount * length ) +{ + IOPhysicalAddress physAddr; -void IOGeneralMemoryDescriptor::setPosition(IOByteCount position) + prepare(); + physAddr = getPhysicalSegment( offset, length ); + complete(); + + return( physAddr ); +} + +IOByteCount IOMemoryDescriptor::readBytes( IOByteCount offset, + void * bytes, + IOByteCount withLength ) { - assert(position <= _length); + IOByteCount bytesCopied = 0; - if (position >= _length) - { - _position = _length; - _positionAtIndex = _rangesCount; /* careful: out-of-bounds */ - _positionAtOffset = 0; - return; - } + assert(offset <= _length); + assert(offset <= _length - withLength); - if (position < _position) + if ( offset < _length ) { - _positionAtOffset = position; - _positionAtIndex = 0; - } - else - { - _positionAtOffset += (position - _position); - } - _position = position; + withLength = min(withLength, _length - offset); - while (_positionAtOffset >= _ranges.v[_positionAtIndex].length) - { - _positionAtOffset -= _ranges.v[_positionAtIndex].length; - _positionAtIndex++; - } -} + while ( withLength ) // (process another source segment?) + { + IOPhysicalAddress sourceSegment; + IOByteCount sourceSegmentLength; -/* - * readBytes: - * - * Copy data from the memory descriptor's buffer into the specified buffer, - * relative to the current position. The memory descriptor's position is - * advanced based on the number of bytes copied. - */ + sourceSegment = getPhysicalSegment(offset, &sourceSegmentLength); + if ( sourceSegment == 0 ) goto readBytesErr; -IOByteCount IOGeneralMemoryDescriptor::readBytes(IOByteCount offset, - void * bytes, IOByteCount withLength) -{ - IOByteCount bytesLeft; - void * segment; - IOByteCount segmentLength; + sourceSegmentLength = min(sourceSegmentLength, withLength); - if( offset != _position) - setPosition( offset ); + while ( sourceSegmentLength ) // (process another target segment?) + { + IOPhysicalAddress targetSegment; + IOByteCount targetSegmentLength; - withLength = min(withLength, _length - _position); - bytesLeft = withLength; + targetSegment = pmap_extract_safe(kernel_task, (vm_offset_t) bytes); + if ( targetSegment == 0 ) goto readBytesErr; -#if 0 - while (bytesLeft && (_position < _length)) - { - /* Compute the relative length to the end of this virtual segment. */ - segmentLength = min(_ranges.v[_positionAtIndex].length - _positionAtOffset, bytesLeft); - - /* Compute the relative address of this virtual segment. */ - segment = (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset); - - if (KERN_SUCCESS != vm_map_read_user(getMapForTask(_task, segment), - /* from */ (vm_offset_t) segment, /* to */ (vm_offset_t) bytes, - /* size */ segmentLength)) - { - assert( false ); - bytesLeft = withLength; - break; - } - bytesLeft -= segmentLength; - offset += segmentLength; - setPosition(offset); + targetSegmentLength = min(next_page(targetSegment) - targetSegment, sourceSegmentLength); + + if ( sourceSegment + targetSegmentLength > next_page(sourceSegment) ) + { + IOByteCount pageLength; + + pageLength = next_page(sourceSegment) - sourceSegment; + + bcopy_phys_safe( /* from */ (char *) sourceSegment, + /* to */ (char *) targetSegment, + /* size */ (int ) pageLength ); + + ((UInt8 *) bytes) += pageLength; + bytesCopied += pageLength; + offset += pageLength; + sourceSegment += pageLength; + sourceSegmentLength -= pageLength; + targetSegment += pageLength; + targetSegmentLength -= pageLength; + withLength -= pageLength; + } + + bcopy_phys_safe( /* from */ (char *) sourceSegment, + /* to */ (char *) targetSegment, + /* size */ (int ) targetSegmentLength ); + + ((UInt8 *) bytes) += targetSegmentLength; + bytesCopied += targetSegmentLength; + offset += targetSegmentLength; + sourceSegment += targetSegmentLength; + sourceSegmentLength -= targetSegmentLength; + withLength -= targetSegmentLength; + } + } } -#else - while (bytesLeft && (segment = getVirtualSegment(offset, &segmentLength))) + +readBytesErr: + + if ( bytesCopied ) { - segmentLength = min(segmentLength, bytesLeft); - bcopy(/* from */ segment, /* to */ bytes, /* size */ segmentLength); - bytesLeft -= segmentLength; - offset += segmentLength; - bytes = (void *) (((UInt32) bytes) + segmentLength); + // We mark the destination pages as modified, just + // in case they are made pageable later on in life. + + pmap_modify_pages( /* pmap */ kernel_pmap, + /* start */ trunc_page(((vm_offset_t) bytes) - bytesCopied), + /* end */ round_page(((vm_offset_t) bytes)) ); } -#endif - return withLength - bytesLeft; + return bytesCopied; } -/* - * writeBytes: - * - * Copy data to the memory descriptor's buffer from the specified buffer, - * relative to the current position. The memory descriptor's position is - * advanced based on the number of bytes copied. - */ -IOByteCount IOGeneralMemoryDescriptor::writeBytes(IOByteCount offset, - const void* bytes,IOByteCount withLength) +IOByteCount IOMemoryDescriptor::writeBytes( IOByteCount offset, + const void * bytes, + IOByteCount withLength ) { - IOByteCount bytesLeft; - void * segment; - IOByteCount segmentLength; - - if( offset != _position) - setPosition( offset ); + IOByteCount bytesCopied = 0; - withLength = min(withLength, _length - _position); - bytesLeft = withLength; + assert(offset <= _length); + assert(offset <= _length - withLength); -#if 0 - while (bytesLeft && (_position < _length)) + if ( offset < _length ) { - assert(_position <= _length); + withLength = min(withLength, _length - offset); - /* Compute the relative length to the end of this virtual segment. */ - segmentLength = min(_ranges.v[_positionAtIndex].length - _positionAtOffset, bytesLeft); + while ( withLength ) // (process another target segment?) + { + IOPhysicalAddress targetSegment; + IOByteCount targetSegmentLength; - /* Compute the relative address of this virtual segment. */ - segment = (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset); + targetSegment = getPhysicalSegment(offset, &targetSegmentLength); + if ( targetSegment == 0 ) goto writeBytesErr; - if (KERN_SUCCESS != vm_map_write_user(getMapForTask(_task, segment), - /* from */ (vm_offset_t) bytes, - /* to */ (vm_offset_t) segment, - /* size */ segmentLength)) - { - assert( false ); - bytesLeft = withLength; - break; - } - bytesLeft -= segmentLength; - offset += segmentLength; - setPosition(offset); - } -#else - while (bytesLeft && (segment = getVirtualSegment(offset, &segmentLength))) - { - segmentLength = min(segmentLength, bytesLeft); - bcopy(/* from */ bytes, /* to */ segment, /* size */ segmentLength); - // Flush cache in case we're copying code around, eg. handling a code page fault - IOFlushProcessorCache(kernel_task, (vm_offset_t) segment, segmentLength ); - - bytesLeft -= segmentLength; - offset += segmentLength; - bytes = (void *) (((UInt32) bytes) + segmentLength); - } -#endif + targetSegmentLength = min(targetSegmentLength, withLength); - return withLength - bytesLeft; -} + while ( targetSegmentLength ) // (process another source segment?) + { + IOPhysicalAddress sourceSegment; + IOByteCount sourceSegmentLength; -/* - * getPhysicalSegment: - * - * Get the physical address of the buffer, relative to the current position. - * If the current position is at the end of the buffer, a zero is returned. - */ -IOPhysicalAddress -IOGeneralMemoryDescriptor::getPhysicalSegment(IOByteCount offset, - IOByteCount * lengthOfSegment) -{ - vm_address_t virtualAddress; - IOByteCount virtualLength; - pmap_t virtualPMap; - IOPhysicalAddress physicalAddress; - IOPhysicalLength physicalLength; + sourceSegment = pmap_extract_safe(kernel_task, (vm_offset_t) bytes); + if ( sourceSegment == 0 ) goto writeBytesErr; - if( kIOMemoryRequiresWire & _flags) - assert( _wireCount ); + sourceSegmentLength = min(next_page(sourceSegment) - sourceSegment, targetSegmentLength); - if ((0 == _task) && (1 == _rangesCount)) - { - assert(offset <= _length); - if (offset >= _length) - { - physicalAddress = 0; - physicalLength = 0; - } - else - { - physicalLength = _length - offset; - physicalAddress = offset + _ranges.v[0].address; - } + if ( targetSegment + sourceSegmentLength > next_page(targetSegment) ) + { + IOByteCount pageLength; - if (lengthOfSegment) - *lengthOfSegment = physicalLength; - return physicalAddress; - } + pageLength = next_page(targetSegment) - targetSegment; - if( offset != _position) - setPosition( offset ); + bcopy_phys_safe( /* from */ (char *) sourceSegment, + /* to */ (char *) targetSegment, + /* size */ (int ) pageLength ); - assert(_position <= _length); + // We flush the data cache in case it is code we've copied, + // such that the instruction cache is in the know about it. - /* Fail gracefully if the position is at (or past) the end-of-buffer. */ - if (_position >= _length) - { - *lengthOfSegment = 0; - return 0; - } + flush_dcache(targetSegment, pageLength, true); - /* Prepare to compute the largest contiguous physical length possible. */ + ((UInt8 *) bytes) += pageLength; + bytesCopied += pageLength; + offset += pageLength; + sourceSegment += pageLength; + sourceSegmentLength -= pageLength; + targetSegment += pageLength; + targetSegmentLength -= pageLength; + withLength -= pageLength; + } - virtualAddress = _ranges.v[_positionAtIndex].address + _positionAtOffset; - virtualLength = _ranges.v[_positionAtIndex].length - _positionAtOffset; - vm_address_t virtualPage = trunc_page(virtualAddress); - if( _task) - virtualPMap = get_task_pmap(_task); - else - virtualPMap = 0; + bcopy_phys_safe( /* from */ (char *) sourceSegment, + /* to */ (char *) targetSegment, + /* size */ (int ) sourceSegmentLength ); - physicalAddress = (virtualAddress == _cachedVirtualAddress) ? - _cachedPhysicalAddress : /* optimization */ - virtualPMap ? - pmap_extract(virtualPMap, virtualAddress) : - virtualAddress; - physicalLength = trunc_page(physicalAddress) + page_size - physicalAddress; + // We flush the data cache in case it is code we've copied, + // such that the instruction cache is in the know about it. - if (!physicalAddress && _task) - { - physicalAddress = - vm_map_get_phys_page(get_task_map(_task), virtualPage); - physicalAddress += virtualAddress - virtualPage; + flush_dcache(targetSegment, sourceSegmentLength, true); + + ((UInt8 *) bytes) += sourceSegmentLength; + bytesCopied += sourceSegmentLength; + offset += sourceSegmentLength; + targetSegment += sourceSegmentLength; + targetSegmentLength -= sourceSegmentLength; + withLength -= sourceSegmentLength; + } + } } - if (physicalAddress == 0) /* memory must be wired in order to proceed */ +writeBytesErr: + + return bytesCopied; +} + +/* DEPRECATED */ void IOGeneralMemoryDescriptor::setPosition(IOByteCount position) +/* DEPRECATED */ { +/* DEPRECATED */ assert(position <= _length); +/* DEPRECATED */ +/* DEPRECATED */ if (position >= _length) +/* DEPRECATED */ { +/* DEPRECATED */ _position = _length; +/* DEPRECATED */ _positionAtIndex = _rangesCount; /* careful: out-of-bounds */ +/* DEPRECATED */ _positionAtOffset = 0; +/* DEPRECATED */ return; +/* DEPRECATED */ } +/* DEPRECATED */ +/* DEPRECATED */ if (position < _position) +/* DEPRECATED */ { +/* DEPRECATED */ _positionAtOffset = position; +/* DEPRECATED */ _positionAtIndex = 0; +/* DEPRECATED */ } +/* DEPRECATED */ else +/* DEPRECATED */ { +/* DEPRECATED */ _positionAtOffset += (position - _position); +/* DEPRECATED */ } +/* DEPRECATED */ _position = position; +/* DEPRECATED */ +/* DEPRECATED */ while (_positionAtOffset >= _ranges.v[_positionAtIndex].length) +/* DEPRECATED */ { +/* DEPRECATED */ _positionAtOffset -= _ranges.v[_positionAtIndex].length; +/* DEPRECATED */ _positionAtIndex++; +/* DEPRECATED */ } +/* DEPRECATED */ } + +IOPhysicalAddress IOGeneralMemoryDescriptor::getPhysicalSegment( IOByteCount offset, + IOByteCount * lengthOfSegment ) +{ + IOPhysicalAddress address = 0; + IOPhysicalLength length = 0; + + +// assert(offset <= _length); + + if ( offset < _length ) // (within bounds?) { - assert(physicalAddress); - *lengthOfSegment = 0; - return 0; - } + unsigned rangesIndex = 0; - /* Compute the largest contiguous physical length possible, within range. */ - IOPhysicalAddress physicalPage = trunc_page(physicalAddress); + for ( ; offset >= _ranges.v[rangesIndex].length; rangesIndex++ ) + { + offset -= _ranges.v[rangesIndex].length; // (make offset relative) + } - while (physicalLength < virtualLength) - { - physicalPage += page_size; - virtualPage += page_size; - _cachedVirtualAddress = virtualPage; - _cachedPhysicalAddress = virtualPMap ? - pmap_extract(virtualPMap, virtualPage) : - virtualPage; - if (!_cachedPhysicalAddress && _task) - { - _cachedPhysicalAddress = - vm_map_get_phys_page(get_task_map(_task), virtualPage); - } + if ( _task == 0 ) // (physical memory?) + { + address = _ranges.v[rangesIndex].address + offset; + length = _ranges.v[rangesIndex].length - offset; - if (_cachedPhysicalAddress != physicalPage) break; + for ( ++rangesIndex; rangesIndex < _rangesCount; rangesIndex++ ) + { + if ( address + length != _ranges.v[rangesIndex].address ) break; - physicalLength += page_size; - } + length += _ranges.v[rangesIndex].length; // (coalesce ranges) + } + } + else // (virtual memory?) + { + vm_address_t addressVirtual = _ranges.v[rangesIndex].address + offset; - /* Clip contiguous physical length at the end of this range. */ - if (physicalLength > virtualLength) - physicalLength = virtualLength; + assert((0 == (kIOMemoryRequiresWire & _flags)) || _wireCount); - if( lengthOfSegment) - *lengthOfSegment = physicalLength; + address = pmap_extract_safe(_task, addressVirtual); + length = next_page(addressVirtual) - addressVirtual; + length = min(_ranges.v[rangesIndex].length - offset, length); + } - return physicalAddress; -} + assert(address); + if ( address == 0 ) length = 0; + } + if ( lengthOfSegment ) *lengthOfSegment = length; -/* - * getVirtualSegment: - * - * Get the virtual address of the buffer, relative to the current position. - * If the memory wasn't mapped into the caller's address space, it will be - * mapped in now. If the current position is at the end of the buffer, a - * null is returned. - */ -void * IOGeneralMemoryDescriptor::getVirtualSegment(IOByteCount offset, - IOByteCount * lengthOfSegment) + return address; +} + +IOPhysicalAddress IOGeneralMemoryDescriptor::getSourceSegment( IOByteCount offset, + IOByteCount * lengthOfSegment ) { - if( offset != _position) - setPosition( offset ); + IOPhysicalAddress address = 0; + IOPhysicalLength length = 0; - assert(_position <= _length); + assert(offset <= _length); - /* Fail gracefully if the position is at (or past) the end-of-buffer. */ - if (_position >= _length) + if ( offset < _length ) // (within bounds?) { - *lengthOfSegment = 0; - return 0; - } + unsigned rangesIndex = 0; - /* Compute the relative length to the end of this virtual segment. */ - *lengthOfSegment = _ranges.v[_positionAtIndex].length - _positionAtOffset; + for ( ; offset >= _ranges.v[rangesIndex].length; rangesIndex++ ) + { + offset -= _ranges.v[rangesIndex].length; // (make offset relative) + } - /* Compute the relative address of this virtual segment. */ - if (_task == kernel_task) - return (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset); - else - { - vm_offset_t off; + address = _ranges.v[rangesIndex].address + offset; + length = _ranges.v[rangesIndex].length - offset; - mapIntoKernel(_positionAtIndex); + for ( ++rangesIndex; rangesIndex < _rangesCount; rangesIndex++ ) + { + if ( address + length != _ranges.v[rangesIndex].address ) break; - off = _ranges.v[_kernPtrAtIndex].address; - off -= trunc_page(off); + length += _ranges.v[rangesIndex].length; // (coalesce ranges) + } - return (void *) (_kernPtrAligned + off + _positionAtOffset); + assert(address); + if ( address == 0 ) length = 0; } -} + + if ( lengthOfSegment ) *lengthOfSegment = length; + + return address; +} + +/* DEPRECATED */ /* USE INSTEAD: map(), readBytes(), writeBytes() */ +/* DEPRECATED */ void * IOGeneralMemoryDescriptor::getVirtualSegment(IOByteCount offset, +/* DEPRECATED */ IOByteCount * lengthOfSegment) +/* DEPRECATED */ { +/* DEPRECATED */ if( offset != _position) +/* DEPRECATED */ setPosition( offset ); +/* DEPRECATED */ +/* DEPRECATED */ assert(_position <= _length); +/* DEPRECATED */ +/* DEPRECATED */ /* Fail gracefully if the position is at (or past) the end-of-buffer. */ +/* DEPRECATED */ if (_position >= _length) +/* DEPRECATED */ { +/* DEPRECATED */ *lengthOfSegment = 0; +/* DEPRECATED */ return 0; +/* DEPRECATED */ } +/* DEPRECATED */ +/* DEPRECATED */ /* Compute the relative length to the end of this virtual segment. */ +/* DEPRECATED */ *lengthOfSegment = _ranges.v[_positionAtIndex].length - _positionAtOffset; +/* DEPRECATED */ +/* DEPRECATED */ /* Compute the relative address of this virtual segment. */ +/* DEPRECATED */ if (_task == kernel_task) +/* DEPRECATED */ return (void *)(_ranges.v[_positionAtIndex].address + _positionAtOffset); +/* DEPRECATED */ else +/* DEPRECATED */ { +/* DEPRECATED */ vm_offset_t off; +/* DEPRECATED */ +/* DEPRECATED */ mapIntoKernel(_positionAtIndex); +/* DEPRECATED */ +/* DEPRECATED */ off = _ranges.v[_kernPtrAtIndex].address; +/* DEPRECATED */ off -= trunc_page(off); +/* DEPRECATED */ +/* DEPRECATED */ return (void *) (_kernPtrAligned + off + _positionAtOffset); +/* DEPRECATED */ } +/* DEPRECATED */ } +/* DEPRECATED */ /* USE INSTEAD: map(), readBytes(), writeBytes() */ /* * prepare @@ -787,7 +883,22 @@ IOReturn IOGeneralMemoryDescriptor::prepare( if(forDirection == kIODirectionNone) forDirection = _direction; - vm_prot_t access = VM_PROT_DEFAULT; // Could be cleverer using direction + vm_prot_t access; + + switch (forDirection) + { + case kIODirectionIn: + access = VM_PROT_WRITE; + break; + + case kIODirectionOut: + access = VM_PROT_READ; + break; + + default: + access = VM_PROT_READ | VM_PROT_WRITE; + break; + } // // Check user read/write access to the data buffer. @@ -837,12 +948,6 @@ IOReturn IOGeneralMemoryDescriptor::prepare( vm_map_t taskVMMap = getMapForTask(_task, srcAlign); - rc = vm_map_wire(taskVMMap, srcAlign, srcAlignEnd, access, FALSE); - if (KERN_SUCCESS != rc) { - IOLog("IOMemoryDescriptor::prepare vm_map_wire failed: %d\n", rc); - goto abortExit; - } - // If this I/O is for a user land task then protect ourselves // against COW and other vm_shenanigans if (_task && _task != kernel_task) { @@ -875,6 +980,12 @@ IOReturn IOGeneralMemoryDescriptor::prepare( } while (desiredSize); } } + + rc = vm_map_wire(taskVMMap, srcAlign, srcAlignEnd, access, FALSE); + if (KERN_SUCCESS != rc) { + IOLog("IOMemoryDescriptor::prepare vm_map_wire failed: %d\n", rc); + goto abortExit; + } } } _wireCount++; @@ -962,8 +1073,6 @@ IOReturn IOGeneralMemoryDescriptor::complete( _memoryEntries->release(); _memoryEntries = 0; } - - _cachedVirtualAddress = 0; } return kIOReturnSuccess; } @@ -976,6 +1085,7 @@ IOReturn IOGeneralMemoryDescriptor::doMap( IOByteCount length = 0 ) { kern_return_t kr; + ipc_port_t sharedMem = (ipc_port_t) _memEntry; // mapping source == dest? (could be much better) if( _task && (addressMap == get_task_map(_task)) && (options & kIOMapAnywhere) @@ -985,53 +1095,73 @@ IOReturn IOGeneralMemoryDescriptor::doMap( return( kIOReturnSuccess ); } - if( _task && _memEntry && (_flags & kIOMemoryRequiresWire)) { + if( 0 == sharedMem) { - do { + vm_size_t size = 0; - if( (1 != _rangesCount) - || (kIOMapDefaultCache != (options & kIOMapCacheMask)) ) { - kr = kIOReturnUnsupported; - continue; - } + for (unsigned index = 0; index < _rangesCount; index++) + size += round_page(_ranges.v[index].address + _ranges.v[index].length) + - trunc_page(_ranges.v[index].address); - if( 0 == length) - length = getLength(); - if( (sourceOffset + length) > _ranges.v[0].length) { - kr = kIOReturnBadArgument; - continue; + if( _task) { +#if NOTYET + vm_object_offset_t actualSize = size; + kr = mach_make_memory_entry_64( get_task_map(_task), + &actualSize, _ranges.v[0].address, + VM_PROT_READ | VM_PROT_WRITE, &sharedMem, + NULL ); + + if( (KERN_SUCCESS == kr) && (actualSize != size)) { +#if IOASSERT + IOLog("mach_make_memory_entry_64 (%08lx) size (%08lx:%08lx)\n", + _ranges.v[0].address, (UInt32)actualSize, size); +#endif + kr = kIOReturnVMError; + ipc_port_release_send( sharedMem ); } - ipc_port_t sharedMem = (ipc_port_t) _memEntry; - vm_prot_t prot = VM_PROT_READ - | ((options & kIOMapReadOnly) ? 0 : VM_PROT_WRITE); + if( KERN_SUCCESS != kr) +#endif /* NOTYET */ + sharedMem = MACH_PORT_NULL; - // vm_map looks for addresses above here, even when VM_FLAGS_ANYWHERE - if( options & kIOMapAnywhere) - *atAddress = 0; + } else do { + + memory_object_t pager; + + if( !reserved) { + reserved = IONew( ExpansionData, 1 ); + if( !reserved) + continue; + } + reserved->pagerContig = (1 == _rangesCount); + + pager = device_pager_setup( (memory_object_t) 0, (int) this, size, + reserved->pagerContig ? DEVICE_PAGER_CONTIGUOUS : 0 ); + assert( pager ); + + if( pager) { + retain(); // pager has a ref + kr = mach_memory_object_memory_entry_64( (host_t) 1, false /*internal*/, + size, VM_PROT_READ | VM_PROT_WRITE, pager, &sharedMem ); + + assert( KERN_SUCCESS == kr ); + if( KERN_SUCCESS != kr) { +// chris? +// ipc_port_release_send( (ipc_port_t) pager ); + pager = MACH_PORT_NULL; + sharedMem = MACH_PORT_NULL; + } + } + reserved->devicePager = pager; - if( 0 == sharedMem) - kr = kIOReturnVMError; - else - kr = KERN_SUCCESS; - - if( KERN_SUCCESS == kr) - kr = vm_map( addressMap, - atAddress, - length, 0 /* mask */, - (( options & kIOMapAnywhere ) ? VM_FLAGS_ANYWHERE : VM_FLAGS_FIXED) - | VM_MAKE_TAG(VM_MEMORY_IOKIT), - sharedMem, sourceOffset, - false, // copy - prot, // cur - prot, // max - VM_INHERIT_NONE); - } while( false ); - } else - kr = super::doMap( addressMap, atAddress, + _memEntry = (void *) sharedMem; + } + + kr = super::doMap( addressMap, atAddress, options, sourceOffset, length ); + return( kr ); } @@ -1216,6 +1346,62 @@ bool _IOMemoryMap::init( return( ok ); } +struct IOMemoryDescriptorMapAllocRef +{ + ipc_port_t sharedMem; + vm_size_t size; + vm_offset_t mapped; + IOByteCount sourceOffset; + IOOptionBits options; +}; + +static kern_return_t IOMemoryDescriptorMapAlloc(vm_map_t map, void * _ref) +{ + IOMemoryDescriptorMapAllocRef * ref = (IOMemoryDescriptorMapAllocRef *)_ref; + IOReturn err; + + do { + if( ref->sharedMem) { + vm_prot_t prot = VM_PROT_READ + | ((ref->options & kIOMapReadOnly) ? 0 : VM_PROT_WRITE); + + err = vm_map( map, + &ref->mapped, + ref->size, 0 /* mask */, + (( ref->options & kIOMapAnywhere ) ? VM_FLAGS_ANYWHERE : VM_FLAGS_FIXED) + | VM_MAKE_TAG(VM_MEMORY_IOKIT), + ref->sharedMem, ref->sourceOffset, + false, // copy + prot, // cur + prot, // max + VM_INHERIT_NONE); + + if( KERN_SUCCESS != err) { + ref->mapped = 0; + continue; + } + + } else { + + err = vm_allocate( map, &ref->mapped, ref->size, + ((ref->options & kIOMapAnywhere) ? VM_FLAGS_ANYWHERE : VM_FLAGS_FIXED) + | VM_MAKE_TAG(VM_MEMORY_IOKIT) ); + + if( KERN_SUCCESS != err) { + ref->mapped = 0; + continue; + } + + // we have to make sure that these guys don't get copied if we fork. + err = vm_inherit( map, ref->mapped, ref->size, VM_INHERIT_NONE); + assert( KERN_SUCCESS == err ); + } + + } while( false ); + + return( err ); +} + IOReturn IOMemoryDescriptor::doMap( vm_map_t addressMap, IOVirtualAddress * atAddress, @@ -1224,55 +1410,117 @@ IOReturn IOMemoryDescriptor::doMap( IOByteCount length = 0 ) { IOReturn err = kIOReturnSuccess; - vm_size_t ourSize; - vm_size_t bytes; - vm_offset_t mapped; + memory_object_t pager; vm_address_t logical; IOByteCount pageOffset; - IOPhysicalLength segLen; - IOPhysicalAddress physAddr; + IOPhysicalAddress sourceAddr; + IOMemoryDescriptorMapAllocRef ref; - if( 0 == length) - length = getLength(); + ref.sharedMem = (ipc_port_t) _memEntry; + ref.sourceOffset = sourceOffset; + ref.options = options; - physAddr = getPhysicalSegment( sourceOffset, &segLen ); - assert( physAddr ); + do { - pageOffset = physAddr - trunc_page( physAddr ); - ourSize = length + pageOffset; - physAddr -= pageOffset; + if( 0 == length) + length = getLength(); - logical = *atAddress; - if( 0 == (options & kIOMapAnywhere)) { - mapped = trunc_page( logical ); - if( (logical - mapped) != pageOffset) - err = kIOReturnVMError; - } - if( kIOReturnSuccess == err) - err = vm_allocate( addressMap, &mapped, ourSize, - ((options & kIOMapAnywhere) ? VM_FLAGS_ANYWHERE : VM_FLAGS_FIXED) - | VM_MAKE_TAG(VM_MEMORY_IOKIT) ); + sourceAddr = getSourceSegment( sourceOffset, NULL ); + assert( sourceAddr ); + pageOffset = sourceAddr - trunc_page( sourceAddr ); - if( err) { + ref.size = round_page( length + pageOffset ); + + logical = *atAddress; + if( options & kIOMapAnywhere) + // vm_map looks for addresses above here, even when VM_FLAGS_ANYWHERE + ref.mapped = 0; + else { + ref.mapped = trunc_page( logical ); + if( (logical - ref.mapped) != pageOffset) { + err = kIOReturnVMError; + continue; + } + } + + if( ref.sharedMem && (addressMap == kernel_map) && (kIOMemoryRequiresWire & _flags)) + err = IOIteratePageableMaps( ref.size, &IOMemoryDescriptorMapAlloc, &ref ); + else + err = IOMemoryDescriptorMapAlloc( addressMap, &ref ); + + if( err != KERN_SUCCESS) + continue; + + if( reserved) + pager = (memory_object_t) reserved->devicePager; + else + pager = MACH_PORT_NULL; + + if( !ref.sharedMem || pager ) + err = handleFault( pager, addressMap, ref.mapped, sourceOffset, length, options ); + + } while( false ); + + if( err != KERN_SUCCESS) { + if( ref.mapped) + doUnmap( addressMap, ref.mapped, ref.size ); + *atAddress = NULL; + } else + *atAddress = ref.mapped + pageOffset; + + return( err ); +} + +enum { + kIOMemoryRedirected = 0x00010000 +}; + +IOReturn IOMemoryDescriptor::handleFault( + void * _pager, + vm_map_t addressMap, + IOVirtualAddress address, + IOByteCount sourceOffset, + IOByteCount length, + IOOptionBits options ) +{ + IOReturn err = kIOReturnSuccess; + memory_object_t pager = (memory_object_t) _pager; + vm_size_t size; + vm_size_t bytes; + vm_size_t page; + IOByteCount pageOffset; + IOPhysicalLength segLen; + IOPhysicalAddress physAddr; + + if( !addressMap) { + + LOCK; + + if( kIOMemoryRedirected & _flags) { #ifdef DEBUG - kprintf("IOMemoryDescriptor::doMap: vm_allocate() " - "returned %08x\n", err); + IOLog("sleep mem redirect %x, %lx\n", address, sourceOffset); #endif - return( err); - } + do { + assert_wait( (event_t) this, THREAD_UNINT ); + UNLOCK; + thread_block((void (*)(void)) 0); + LOCK; + } while( kIOMemoryRedirected & _flags ); + } - // we have to make sure that these guys don't get copied if we fork. - err = vm_inherit( addressMap, mapped, ourSize, VM_INHERIT_NONE); - if( err != KERN_SUCCESS) { - doUnmap( addressMap, mapped, ourSize); // back out - return( err); + UNLOCK; + return( kIOReturnSuccess ); } - logical = mapped; - *atAddress = mapped + pageOffset; + physAddr = getPhysicalSegment( sourceOffset, &segLen ); + assert( physAddr ); + pageOffset = physAddr - trunc_page( physAddr ); + + size = length + pageOffset; + physAddr -= pageOffset; segLen += pageOffset; - bytes = ourSize; + bytes = size; do { // in the middle of the loop only map whole pages if( segLen >= bytes) @@ -1284,18 +1532,41 @@ IOReturn IOMemoryDescriptor::doMap( #ifdef DEBUG if( kIOLogMapping & gIOKitDebug) - kprintf("_IOMemoryMap::map(%x) %08x->%08x:%08x\n", - addressMap, mapped + pageOffset, physAddr + pageOffset, + IOLog("_IOMemoryMap::map(%p) %08lx->%08lx:%08lx\n", + addressMap, address + pageOffset, physAddr + pageOffset, segLen - pageOffset); #endif - if( kIOReturnSuccess == err) - err = IOMapPages( addressMap, mapped, physAddr, segLen, options ); + if( addressMap && (kIOReturnSuccess == err)) + err = IOMapPages( addressMap, address, physAddr, segLen, options ); + assert( KERN_SUCCESS == err ); if( err) break; + if( pager) { + if( reserved && reserved->pagerContig) { + IOPhysicalLength allLen; + IOPhysicalAddress allPhys; + + allPhys = getPhysicalSegment( 0, &allLen ); + assert( allPhys ); + err = device_pager_populate_object( pager, 0, trunc_page(allPhys), round_page(allPhys + allLen) ); + + } else { + + for( page = 0; + (page < segLen) && (KERN_SUCCESS == err); + page += page_size) { + err = device_pager_populate_object( pager, sourceOffset + page, + physAddr + page, page_size ); + } + } + assert( KERN_SUCCESS == err ); + if( err) + break; + } sourceOffset += segLen - pageOffset; - mapped += segLen; + address += segLen; bytes -= segLen; pageOffset = 0; @@ -1304,10 +1575,6 @@ IOReturn IOMemoryDescriptor::doMap( if( bytes) err = kIOReturnBadArgument; - if( err) - doUnmap( addressMap, logical, ourSize ); - else - mapped = true; return( err ); } @@ -1325,9 +1592,14 @@ IOReturn IOMemoryDescriptor::doUnmap( addressMap, logical, length ); #endif - if( (addressMap == kernel_map) || (addressMap == get_task_map(current_task()))) + if( (addressMap == kernel_map) || (addressMap == get_task_map(current_task()))) { + + if( _memEntry && (addressMap == kernel_map) && (kIOMemoryRequiresWire & _flags)) + addressMap = IOPageableMapForAddress( logical ); + err = vm_deallocate( addressMap, logical, length ); - else + + } else err = kIOReturnSuccess; return( err ); @@ -1350,6 +1622,13 @@ IOReturn IOMemoryDescriptor::redirect( task_t safeTask, bool redirect ) } } while( false ); + if( redirect) + _flags |= kIOMemoryRedirected; + else { + _flags &= ~kIOMemoryRedirected; + thread_wakeup( (event_t) this); + } + UNLOCK; // temporary binary compatibility @@ -1364,7 +1643,6 @@ IOReturn IOMemoryDescriptor::redirect( task_t safeTask, bool redirect ) IOReturn IOSubMemoryDescriptor::redirect( task_t safeTask, bool redirect ) { -// temporary binary compatibility IOMemoryDescriptor::redirect( safeTask, redirect ); return( _parent->redirect( safeTask, redirect )); } @@ -1385,11 +1663,12 @@ IOReturn _IOMemoryMap::redirect( task_t safeTask, bool redirect ) if( !redirect) { err = vm_deallocate( addressMap, logical, length ); err = memory->doMap( addressMap, &logical, - (options & ~kIOMapAnywhere) /*| kIOMapReserve*/ ); + (options & ~kIOMapAnywhere) /*| kIOMapReserve*/, + offset, length ); } else err = kIOReturnSuccess; #ifdef DEBUG - IOLog("IOMemoryMap::redirect(%d, %x) %x from %lx\n", redirect, err, logical, addressMap); + IOLog("IOMemoryMap::redirect(%d, %x) %x from %p\n", redirect, err, logical, addressMap); #endif } UNLOCK; @@ -1550,6 +1829,9 @@ void IOMemoryDescriptor::free( void ) if( _mappings) _mappings->release(); + if( reserved) + IODelete( reserved, ExpansionData, 1 ); + super::free(); } @@ -1739,6 +2021,28 @@ IOPhysicalAddress IOSubMemoryDescriptor::getPhysicalSegment( IOByteCount offset, return( address ); } +IOPhysicalAddress IOSubMemoryDescriptor::getSourceSegment( IOByteCount offset, + IOByteCount * length ) +{ + IOPhysicalAddress address; + IOByteCount actualLength; + + assert(offset <= _length); + + if( length) + *length = 0; + + if( offset >= _length) + return( 0 ); + + address = _parent->getSourceSegment( offset + _start, &actualLength ); + + if( address && length) + *length = min( _length - offset, actualLength ); + + return( address ); +} + void * IOSubMemoryDescriptor::getVirtualSegment(IOByteCount offset, IOByteCount * lengthOfSegment) { @@ -1821,6 +2125,12 @@ IOMemoryMap * IOSubMemoryDescriptor::makeMapping( options | kIOMapReference, _start + offset, length ); + if( !mapping) + mapping = (IOMemoryMap *) _parent->makeMapping( + _parent, intoTask, + toAddress, + options, _start + offset, length ); + if( !mapping) mapping = super::makeMapping( owner, intoTask, toAddress, options, offset, length ); @@ -1878,7 +2188,7 @@ IOSubMemoryDescriptor::initWithPhysicalRanges( IOPhysicalRange * ranges, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -OSMetaClassDefineReservedUnused(IOMemoryDescriptor, 0); +OSMetaClassDefineReservedUsed(IOMemoryDescriptor, 0); OSMetaClassDefineReservedUnused(IOMemoryDescriptor, 1); OSMetaClassDefineReservedUnused(IOMemoryDescriptor, 2); OSMetaClassDefineReservedUnused(IOMemoryDescriptor, 3); diff --git a/iokit/Kernel/IOMultiMemoryDescriptor.cpp b/iokit/Kernel/IOMultiMemoryDescriptor.cpp index 174fb7d91..98eb04d82 100644 --- a/iokit/Kernel/IOMultiMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMultiMemoryDescriptor.cpp @@ -289,6 +289,34 @@ IOPhysicalAddress IOMultiMemoryDescriptor::getPhysicalSegment( // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +IOPhysicalAddress IOMultiMemoryDescriptor::getSourceSegment( + IOByteCount offset, + IOByteCount * length ) +{ + // + // This method returns the physical address of the byte at the given offset + // into the memory, and optionally the length of the physically contiguous + // segment from that offset. + // + + assert(offset <= _length); + + for ( unsigned index = 0; index < _descriptorsCount; index++ ) + { + if ( offset < _descriptors[index]->getLength() ) + { + return _descriptors[index]->getSourceSegment(offset, length); + } + offset -= _descriptors[index]->getLength(); + } + + if ( length ) *length = 0; + + return 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + void * IOMultiMemoryDescriptor::getVirtualSegment( IOByteCount /* offset */ , IOByteCount * /* length */ ) { diff --git a/iokit/Kernel/IOPMPagingPlexus.cpp b/iokit/Kernel/IOPMPagingPlexus.cpp new file mode 100644 index 000000000..187e0a1b7 --- /dev/null +++ b/iokit/Kernel/IOPMPagingPlexus.cpp @@ -0,0 +1,235 @@ +/* + * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. + * + * HISTORY + * 9 May 01 suurballe. + */ + +#include <IOKit/pwr_mgt/IOPMPagingPlexus.h> +#include <IOKit/pwr_mgt/IOPM.h> +#include <IOKit/pwr_mgt/RootDomain.h> +#include <IOKit/pwr_mgt/IOPowerConnection.h> +#include <IOKit/IOLib.h> + +extern char rootdevice[]; + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#define super IOService +OSDefineMetaClassAndStructors(IOPMPagingPlexus,IOService) + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// stub driver has two power states, off and on + +enum { kIOPlexusPowerStateCount = 2 }; + +static const IOPMPowerState powerStates[ kIOPlexusPowerStateCount ] = { + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, IOPMPagingAvailable, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +//* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// initialize +// +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +bool IOPMPagingPlexus::start ( IOService * provider ) +{ + super::start(provider); + + ourLock = IOLockAlloc(); + systemBooting = true; + + PMinit(); // initialize superclass variables + + registerPowerDriver(this,(IOPMPowerState *)powerStates,kIOPlexusPowerStateCount); + + return true; +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// setAggressiveness +// +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +IOReturn IOPMPagingPlexus::setAggressiveness ( unsigned long type, unsigned long ) +{ + OSDictionary * dict; + OSIterator * iter; + OSObject * next; + IOService * candidate = 0; + IOService * pagingProvider; + + if( type != kPMMinutesToSleep) + return IOPMNoErr; + + IOLockLock(ourLock); + if ( systemBooting ) { + systemBooting = false; + IOLockUnlock(ourLock); + dict = IOBSDNameMatching(rootdevice); + if ( dict ) { + iter = getMatchingServices(dict); + if ( iter ) { + while ( (next = iter->getNextObject()) ) { + if ( (candidate = OSDynamicCast(IOService,next)) ) { + break; + } + } + iter->release(); + } + } + if ( candidate ) { + pagingProvider = findProvider(candidate); + if ( pagingProvider ) { + processSiblings(pagingProvider); + pagingProvider->addPowerChild(this); + getPMRootDomain()->removePowerChild(((IOPowerConnection *)getParentEntry(gIOPowerPlane))); + processChildren(); + } + } + } + else { + IOLockUnlock(ourLock); + } + return IOPMNoErr; +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// findProvider +// +// Climb upward in the power tree from the node pointed to by the parameter. +// Return a pointer to the first power-managed entity encountered. +// This is the provider of paging services (the root device disk driver). +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +IOService * IOPMPagingPlexus::findProvider ( IOService * mediaObject ) +{ + IORegistryEntry * node = mediaObject; + + if ( mediaObject == NULL ) { + return NULL; + } + + while ( node ) { + if ( node->inPlane(gIOPowerPlane) ) { + return (IOService *)node; + } + node = node->getParentEntry(gIOServicePlane); + } + return NULL; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// processSiblings +// +// Climb upward in the power tree from the node pointed to by the parameter. +// "Other" children of each ancestor (not the nodes in our upward path) are +// made children of this plexus, so they get paging services from here. +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void IOPMPagingPlexus::processSiblings ( IOService * aNode ) +{ + OSIterator * parentIterator; + IORegistryEntry * nextNub; + IORegistryEntry * nextParent; + OSIterator * siblingIterator; + IORegistryEntry * nextSibling; + + parentIterator = aNode->getParentIterator(gIOPowerPlane); // iterate parents of this node + + if ( parentIterator ) { + while ( true ) { + if ( ! (nextNub = (IORegistryEntry *)(parentIterator->getNextObject())) ) { + parentIterator->release(); + break; + } + if ( OSDynamicCast(IOPowerConnection,nextNub) ) { + nextParent = nextNub->getParentEntry(gIOPowerPlane); + if ( nextParent == getPMRootDomain() ) { + continue; // plexus already has root's children + } + if ( nextParent == this ) { + parentIterator->release(); + removePowerChild((IOPowerConnection *)nextNub); + break; + } + siblingIterator = nextParent->getChildIterator(gIOPowerPlane); + // iterate children of this parent + if ( siblingIterator ) { + while ( (nextSibling = (IORegistryEntry *)(siblingIterator->getNextObject())) ) { + if ( OSDynamicCast(IOPowerConnection,nextSibling) ) { + nextSibling = nextSibling->getChildEntry(gIOPowerPlane); + if ( nextSibling != aNode ) { // non-ancestor of driver gets + addPowerChild((IOService *)nextSibling); // plexus as parent + } + } + } + siblingIterator->release(); + } + processSiblings((IOService *)nextParent); // do the same thing to this parent + } + } + } +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// processChildren +// +// Now invent the need for paging services: alter our children's arrays +// to show that they need paging. +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +void IOPMPagingPlexus::processChildren ( void ) +{ + OSIterator * childIterator; + IOPowerConnection * nextChildNub; + IORegistryEntry * nextChild; + IOService * child; + unsigned int i; + + childIterator = getChildIterator(gIOPowerPlane); + + if ( childIterator ) { + while ( (nextChild = (IORegistryEntry *)(childIterator->getNextObject())) ) { + if ( (nextChildNub = OSDynamicCast(IOPowerConnection,nextChild)) ) { + child = (IOService *)nextChild->getChildEntry(gIOPowerPlane); + if ( child->pm_vars->theControllingDriver ) { + for ( i = 1; i < child->pm_vars->theNumberOfPowerStates; i++ ) { + child->pm_vars->thePowerStates[i].inputPowerRequirement |= IOPMPagingAvailable; + } + } + if ( child->pm_vars->myCurrentState ) { + nextChildNub->setDesiredDomainState(kIOPlexusPowerStateCount-1); + } + } + } + childIterator->release(); + } +} diff --git a/iokit/Kernel/IOPowerConnection.cpp b/iokit/Kernel/IOPowerConnection.cpp index 2cc0e72e6..cc3242765 100644 --- a/iokit/Kernel/IOPowerConnection.cpp +++ b/iokit/Kernel/IOPowerConnection.cpp @@ -47,6 +47,67 @@ unsigned long IOPowerConnection::getDesiredDomainState ( void ) } +// ********************************************************************************** +// setChildHasRequestedPower +// +// Parent of the connection calls here when the child requests power +// ********************************************************************************** +void IOPowerConnection::setChildHasRequestedPower ( void ) +{ + requestFlag = true; +} + +// ********************************************************************************** +// childHasRequestedPower +// +// Parent of the connection calls here when the child requests power +// ********************************************************************************** +bool IOPowerConnection::childHasRequestedPower ( void ) +{ + return requestFlag; +} + + +// ********************************************************************************** +// setPreventIdleSleepFlag +// +// ********************************************************************************** +void IOPowerConnection::setPreventIdleSleepFlag ( unsigned long flag ) +{ + preventIdleSleepFlag = (flag != 0); +} + + +// ********************************************************************************** +// getPreventIdleSleepFlag +// +// ********************************************************************************** +bool IOPowerConnection::getPreventIdleSleepFlag ( void ) +{ + return preventIdleSleepFlag; +} + + +// ********************************************************************************** +// setPreventSystemSleepFlag +// +// ********************************************************************************** +void IOPowerConnection::setPreventSystemSleepFlag ( unsigned long flag ) +{ + preventSystemSleepFlag = (flag != 0); +} + + +// ********************************************************************************** +// getPreventSystemSleepFlag +// +// ********************************************************************************** +bool IOPowerConnection::getPreventSystemSleepFlag ( void ) +{ + return preventSystemSleepFlag; +} + + // ********************************************************************************** // setParentKnowsState // @@ -91,3 +152,21 @@ IOPMPowerFlags IOPowerConnection::parentCurrentPowerFlags (void ) } +// ********************************************************************************** +// setAwaitingAck +// +// ********************************************************************************** +void IOPowerConnection::setAwaitingAck ( bool value ) +{ + awaitingAck = value; +} + + +// ********************************************************************************** +// getAwaitingAck +// +// ********************************************************************************** +bool IOPowerConnection::getAwaitingAck ( void ) +{ + return awaitingAck; +} diff --git a/iokit/Kernel/IORegistryEntry.cpp b/iokit/Kernel/IORegistryEntry.cpp index bb72bda03..e309047d4 100644 --- a/iokit/Kernel/IORegistryEntry.cpp +++ b/iokit/Kernel/IORegistryEntry.cpp @@ -98,6 +98,8 @@ static SInt32 gIORegistryGenerationCount; #define registryTable() fPropertyTable #endif +#define DEBUG_FREE 1 + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ struct s_lock_t { @@ -468,28 +470,18 @@ bool IORegistryEntry::init( IORegistryEntry * old, void IORegistryEntry::free( void ) { -#ifdef DEBUG - OSArray * links; - const OSSymbol * key; - const IORegistryPlane * plane; - OSCollectionIterator * iter; - - if( registryTable()) { - iter = OSCollectionIterator::withCollection( gIORegistryPlanes ); - if( iter) { - while( (key = (const OSSymbol *) iter->getNextObject())) { - if( 0 == (plane = (const IORegistryPlane *) - OSDynamicCast( IORegistryPlane, - gIORegistryPlanes->getObject( key )))) - continue; - if( (links = getParentSetReference( plane )) - || (links = getChildSetReference( plane )) ) { - - IOLog("%s: Still attached in %s at free()\n", - getName(), plane->nameKey->getCStringNoCopy()); - } - } - iter->release(); +#if DEBUG_FREE +#define msg ": attached at free()" + char buf[ strlen(msg) + 40 ]; + + if( registryTable() && gIOServicePlane) { + if( getParentSetReference( gIOServicePlane ) + || getChildSetReference( gIOServicePlane )) { + + strncpy( buf, getName(), 32); + buf[32] = 0; + strcat( buf, msg ); + IOPanic( buf ); } } #endif @@ -563,15 +555,41 @@ IORegistryEntry::getProperty( type * aKey, \ { \ OSObject * obj = getProperty( aKey ); \ \ - if ( (0 == obj) && (options & kIORegistryIterateRecursively) ) { \ + if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \ + IORegistryEntry * entry = (IORegistryEntry *) this; \ + IORegistryIterator * iter; \ + iter = IORegistryIterator::iterateOver( entry, plane, options ); \ + \ + if(iter) { \ + while ( (0 == obj) && (entry = iter->getNextObject()) ) { \ + obj = entry->getProperty( aKey ); \ + } \ + iter->release(); \ + } \ + } \ + \ + return( obj ); \ +} + +#define wrap5(type,constant) \ +OSObject * \ +IORegistryEntry::copyProperty( type * aKey, \ + const IORegistryPlane * plane, \ + IOOptionBits options ) constant \ +{ \ + OSObject * obj = copyProperty( aKey ); \ + \ + if ( (0 == obj) && plane && (options & kIORegistryIterateRecursively) ) { \ IORegistryEntry * entry = (IORegistryEntry *) this; \ IORegistryIterator * iter; \ iter = IORegistryIterator::iterateOver( entry, plane, options ); \ \ - while ( (0 == obj) && (entry = iter->getNextObject()) ) { \ - obj = entry->getProperty( aKey ); \ + if(iter) { \ + while ( (0 == obj) && (entry = iter->getNextObject()) ) { \ + obj = entry->copyProperty( aKey ); \ + } \ + iter->release(); \ } \ - iter->release(); \ } \ \ return( obj ); \ @@ -623,6 +641,11 @@ wrap4(const OSSymbol, const) // getProperty() w/plane definition wrap4(const OSString, const) // getProperty() w/plane definition wrap4(const char, const) // getProperty() w/plane definition +wrap5(const OSSymbol, const) // copyProperty() w/plane definition +wrap5(const OSString, const) // copyProperty() w/plane definition +wrap5(const char, const) // copyProperty() w/plane definition + + bool IORegistryEntry::setProperty( const OSSymbol * aKey, OSObject * anObject) { @@ -1031,16 +1054,16 @@ const char * IORegistryEntry::matchPathLocation( const char * cmp, { const char * str; const char * result = 0; - int num1, num2; + u_quad_t num1, num2; char c1, c2; str = getLocation( plane ); if( str) { c2 = str[0]; do { - num1 = strtoul( cmp, (char **) &cmp, 16 ); + num1 = strtouq( cmp, (char **) &cmp, 16 ); if( c2) { - num2 = strtoul( str, (char **) &str, 16 ); + num2 = strtouq( str, (char **) &str, 16 ); c2 = str[0]; } else num2 = 0; @@ -1080,6 +1103,7 @@ IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath, unsigned int index; const char * path; const char * cmp = 0; + char c; size_t len; const char * str; @@ -1100,8 +1124,12 @@ IORegistryEntry * IORegistryEntry::getChildFromComponent( const char ** opath, if( strncmp( str, cmp, len )) continue; cmp += len; - if( *cmp != '@' ) - break; + + c = *cmp; + if( (c == 0) || (c == '/') || (c == ':')) + break; + if( c != '@') + continue; } cmp++; if( (cmp = entry->matchPathLocation( cmp, plane ))) @@ -1402,21 +1430,34 @@ OSIterator * IORegistryEntry::getParentIterator( return( iter ); } -IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const +IORegistryEntry * IORegistryEntry::copyParentEntry( const IORegistryPlane * plane ) const { IORegistryEntry * entry = 0; OSArray * links; RLOCK; - if( (links = getParentSetReference( plane ))) + if( (links = getParentSetReference( plane ))) { entry = (IORegistryEntry *) links->getObject( 0 ); + entry->retain(); + } UNLOCK; return( entry); } +IORegistryEntry * IORegistryEntry::getParentEntry( const IORegistryPlane * plane ) const +{ + IORegistryEntry * entry; + + entry = copyParentEntry( plane ); + if( entry) + entry->release(); + + return( entry ); +} + OSArray * IORegistryEntry::getChildSetReference( const IORegistryPlane * plane ) const { if( plane) @@ -1451,7 +1492,7 @@ OSIterator * IORegistryEntry::getChildIterator( const IORegistryPlane * plane ) } -IORegistryEntry * IORegistryEntry::getChildEntry( +IORegistryEntry * IORegistryEntry::copyChildEntry( const IORegistryPlane * plane ) const { IORegistryEntry * entry = 0; @@ -1459,14 +1500,28 @@ IORegistryEntry * IORegistryEntry::getChildEntry( RLOCK; - if( (links = getChildSetReference( plane ))) + if( (links = getChildSetReference( plane ))) { entry = (IORegistryEntry *) links->getObject( 0 ); + entry->retain(); + } UNLOCK; return( entry); } +IORegistryEntry * IORegistryEntry::getChildEntry( + const IORegistryPlane * plane ) const +{ + IORegistryEntry * entry; + + entry = copyChildEntry( plane ); + if( entry) + entry->release(); + + return( entry ); +} + void IORegistryEntry::applyToChildren( IORegistryEntryApplierFunction applier, void * context, const IORegistryPlane * plane ) const @@ -1965,11 +2020,12 @@ OSOrderedSet * IORegistryIterator::iterateAll( void ) return( done); } -OSMetaClassDefineReservedUnused(IORegistryEntry, 0); -OSMetaClassDefineReservedUnused(IORegistryEntry, 1); -OSMetaClassDefineReservedUnused(IORegistryEntry, 2); -OSMetaClassDefineReservedUnused(IORegistryEntry, 3); -OSMetaClassDefineReservedUnused(IORegistryEntry, 4); +OSMetaClassDefineReservedUsed(IORegistryEntry, 0); +OSMetaClassDefineReservedUsed(IORegistryEntry, 1); +OSMetaClassDefineReservedUsed(IORegistryEntry, 2); +OSMetaClassDefineReservedUsed(IORegistryEntry, 3); +OSMetaClassDefineReservedUsed(IORegistryEntry, 4); + OSMetaClassDefineReservedUnused(IORegistryEntry, 5); OSMetaClassDefineReservedUnused(IORegistryEntry, 6); OSMetaClassDefineReservedUnused(IORegistryEntry, 7); diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 51a544089..e84f9d9c0 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -46,17 +46,17 @@ #include <IOKit/IOKitKeys.h> #include <IOKit/IOBSD.h> #include <IOKit/IOUserClient.h> +#include <IOKit/IOWorkLoop.h> +#include <mach/sync_policy.h> +#include <IOKit/assert.h> +#include <sys/errno.h> -//#define LESS_THREAD_CREATE //#define LOG kprintf #define LOG IOLog #include "IOServicePrivate.h" -#include <mach/sync_policy.h> - -#include <IOKit/assert.h> -#include <sys/errno.h> +// take lockForArbitration before LOCKNOTIFY /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -81,6 +81,7 @@ OSDefineMetaClassAndAbstractStructors(IONotifier, OSObject) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ static IOPlatformExpert * gIOPlatform; +static class IOPMrootDomain * gIOPMRootDomain; const IORegistryPlane * gIOServicePlane; const IORegistryPlane * gIOPowerPlane; const OSSymbol * gIODeviceMemoryKey; @@ -116,6 +117,7 @@ const OSSymbol * gIOTerminatedNotification; const OSSymbol * gIOGeneralInterest; const OSSymbol * gIOBusyInterest; const OSSymbol * gIOAppPowerStateInterest; +const OSSymbol * gIOPriorityPowerStateInterest; static OSDictionary * gNotifications; static IORecursiveLock * gNotificationLock; @@ -131,6 +133,13 @@ static int gNumConfigThreads; static int gNumWaitingThreads; static IOLock * gIOServiceBusyLock; +static thread_t gIOTerminateThread; +static UInt32 gIOTerminateWork; +static OSArray * gIOTerminatePhase2List; +static OSArray * gIOStopList; +static OSArray * gIOStopProviderList; +static OSArray * gIOFinalizeList; + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #define LOCKREADNOTIFY() \ @@ -141,6 +150,11 @@ static IOLock * gIOServiceBusyLock; #define UNLOCKNOTIFY() \ IORecursiveLockUnlock( gNotificationLock ) +#define randomDelay() \ + int del = read_processor_clock(); \ + del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \ + IOSleep( del ); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ struct ArbitrationLockQueueElement { @@ -197,6 +211,7 @@ void IOService::initialize( void ) gIOGeneralInterest = OSSymbol::withCStringNoCopy( kIOGeneralInterest ); gIOBusyInterest = OSSymbol::withCStringNoCopy( kIOBusyInterest ); gIOAppPowerStateInterest = OSSymbol::withCStringNoCopy( kIOAppPowerStateInterest ); + gIOPriorityPowerStateInterest = OSSymbol::withCStringNoCopy( kIOPriorityPowerStateInterest ); gNotifications = OSDictionary::withCapacity( 1 ); gIOPublishNotification = OSSymbol::withCStringNoCopy( @@ -240,11 +255,11 @@ void IOService::initialize( void ) assert( gArbitrationLockQueueLock ); -#ifdef LESS_THREAD_CREATE - for( int i = 0; i < kMaxConfigThreads; i++) - _IOConfigThread::configThread(); -#endif - + gIOTerminatePhase2List = OSArray::withCapacity( 2 ); + gIOStopList = OSArray::withCapacity( 16 ); + gIOStopProviderList = OSArray::withCapacity( 16 ); + gIOFinalizeList = OSArray::withCapacity( 16 ); + assert( gIOTerminatePhase2List && gIOStopList && gIOStopProviderList && gIOFinalizeList ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -272,8 +287,8 @@ static UInt64 getDebugFlags( OSDictionary * props ) // The default score is from the property table, & may be altered // during probe to change the start order. -IOService * IOService::probe( IOService * /* provider */, - SInt32 * /* score */) +IOService * IOService::probe( IOService * provider, + SInt32 * score ) { return( this ); } @@ -283,10 +298,18 @@ bool IOService::start( IOService * provider ) return( true ); } -void IOService::stop( IOService * /* provider */ ) +void IOService::stop( IOService * provider ) { } +void IOService::free( void ) +{ + if( getPropertyTable()) + unregisterAllInterest(); + PMfree(); + super::free(); +} + /* * Attach in service plane */ @@ -308,12 +331,8 @@ bool IOService::attach( IOService * provider ) provider->unlockForArbitration(); } else { - gIOServiceRoot = this; ok = attachToParent( getRegistryRoot(), gIOServicePlane); - gIOResources->attachToParent( getRegistryRoot(), - gIOServicePlane ); - publishResource("IOKit"); } return( ok ); @@ -326,18 +345,44 @@ IOService * IOService::getServiceRoot( void ) void IOService::detach( IOService * provider ) { + IOService * newProvider = 0; + SInt32 busy; + bool adjParent; + if( gIOKitDebug & kIOLogAttach) LOG("%s::detach(%s)\n", getName(), provider->getName()); lockForArbitration(); - if( (__state[1] & kIOServiceBusyStateMask) - && (provider == getProvider())) - provider->adjustBusy( -1 ); + adjParent = ((busy = (__state[1] & kIOServiceBusyStateMask)) + && (provider == getProvider())); detachFromParent( provider, gIOServicePlane ); + if( busy) { + newProvider = getProvider(); + if( busy && (__state[1] & kIOServiceTermPhase3State) && (0 == newProvider)) + _adjustBusy( -busy ); + } + unlockForArbitration(); + + if( newProvider) { + newProvider->lockForArbitration(); + newProvider->_adjustBusy(1); + newProvider->unlockForArbitration(); + } + + // check for last client detach from a terminated service + if( provider->lockForArbitration( true )) { + if( adjParent) + provider->_adjustBusy( -1 ); + if( (provider->__state[1] & kIOServiceTermPhase3State) + && (0 == provider->getClient())) { + provider->scheduleFinalize(); + } + provider->unlockForArbitration(); + } } /* @@ -400,40 +445,77 @@ void IOService::registerService( IOOptionBits options = 0 ) void IOService::startMatching( IOOptionBits options = 0 ) { IOService * provider; + UInt32 prevBusy = 0; bool needConfig; + bool needWake = false; bool ok; bool sync; + bool waitAgain; lockForArbitration(); sync = (options & kIOServiceSynchronous) || ((provider = getProvider()) && (provider->__state[1] & kIOServiceSynchronousState)); - if( sync) - __state[1] |= kIOServiceSynchronousState; - else - __state[1] &= ~kIOServiceSynchronousState; - needConfig = (0 == (__state[1] & kIOServiceConfigState)) - && (0 == (__state[0] & kIOServiceInactiveState)) - && (kIOServiceRegisteredState != - (__state[0] & (kIOServiceRegisteredState - | kIOServiceMatchedState))); - __state[1] |= kIOServiceConfigState; + + needConfig = (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState))) + && (0 == (__state[0] & kIOServiceInactiveState)); + + __state[1] |= kIOServiceNeedConfigState; + // __state[0] &= ~kIOServiceInactiveState; // if( sync) LOG("OSKernelStackRemaining = %08x @ %s\n", // OSKernelStackRemaining(), getName()); + if( needConfig) { + prevBusy = _adjustBusy( 1 ); + needWake = (0 != (kIOServiceSyncPubState & __state[1])); + } + + if( sync) + __state[1] |= kIOServiceSynchronousState; + else + __state[1] &= ~kIOServiceSynchronousState; + unlockForArbitration(); if( needConfig) { - adjustBusy( 1 ); - if( sync) { - doServiceMatch( options ); - waitQuiet(); - } else + + if( needWake) { + IOLockLock( gIOServiceBusyLock ); + thread_wakeup( (event_t) this/*&__state[1]*/ ); + IOLockUnlock( gIOServiceBusyLock ); + + } else if( !sync || (kIOServiceAsynchronous & options)) { + ok = (0 != _IOServiceJob::startJob( this, kMatchNubJob, options )); + + } else do { + + if( (__state[1] & kIOServiceNeedConfigState)) + doServiceMatch( options ); + + lockForArbitration(); + IOLockLock( gIOServiceBusyLock ); + + waitAgain = (prevBusy != (__state[1] & kIOServiceBusyStateMask)); + if( waitAgain) + __state[1] |= kIOServiceSyncPubState | kIOServiceBusyWaiterState; + else + __state[1] &= ~kIOServiceSyncPubState; + + unlockForArbitration(); + + if( waitAgain) + assert_wait( (event_t) this/*&__state[1]*/, THREAD_UNINT); + + IOLockUnlock( gIOServiceBusyLock ); + if( waitAgain) + thread_block((void (*)(void)) 0); + + } while( waitAgain ); } } @@ -452,11 +534,11 @@ IOReturn IOService::catalogNewDrivers( OSOrderedSet * newTables ) LOCKWRITENOTIFY(); iter = (OSIterator *) getExistingServices( table, - kIOServiceMatchedState ); + kIOServiceRegisteredState ); UNLOCKNOTIFY(); if( iter) { while( (service = (IOService *) iter->getNextObject())) { - service->startMatching(); + service->startMatching(kIOServiceAsynchronous); #if IOMATCHDEBUG count++; #endif @@ -687,7 +769,7 @@ IOReturn IOService::callPlatformFunction( const char * functionName, /* - * Platform expert accessors + * Accessors for global services */ IOPlatformExpert * IOService::getPlatform( void ) @@ -695,9 +777,26 @@ IOPlatformExpert * IOService::getPlatform( void ) return( gIOPlatform); } +class IOPMrootDomain * IOService::getPMRootDomain( void ) +{ + return( gIOPMRootDomain); +} + +IOService * IOService::getResourceService( void ) +{ + return( gIOResources ); +} + void IOService::setPlatform( IOPlatformExpert * platform) { gIOPlatform = platform; + gIOResources->attachToParent( gIOServiceRoot, gIOServicePlane ); +} + +void IOService::setPMRootDomain( class IOPMrootDomain * rootDomain) +{ + gIOPMRootDomain = rootDomain; + publishResource("IOKit"); } /* @@ -1212,7 +1311,8 @@ IONotifier * IOService::registerInterest( const OSSymbol * typeOfInterest, if( (typeOfInterest != gIOGeneralInterest) && (typeOfInterest != gIOBusyInterest) - && (typeOfInterest != gIOAppPowerStateInterest)) + && (typeOfInterest != gIOAppPowerStateInterest) + && (typeOfInterest != gIOPriorityPowerStateInterest)) return( 0 ); lockForArbitration(); @@ -1274,6 +1374,8 @@ void IOService::unregisterAllInterest( void ) { cleanInterestArray( getProperty( gIOGeneralInterest )); cleanInterestArray( getProperty( gIOBusyInterest )); + cleanInterestArray( getProperty( gIOAppPowerStateInterest )); + cleanInterestArray( getProperty( gIOPriorityPowerStateInterest )); } /* @@ -1359,239 +1461,569 @@ void _IOServiceInterestNotifier::enable( bool was ) UNLOCKNOTIFY(); } +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* - * Terminate + * Termination */ -// a method in case someone needs to override it -bool IOService::terminateClient( IOService * client, IOOptionBits options ) +#define tailQ(o) setObject(o) +#define headQ(o) setObject(0, o) +#define TLOG(fmt, args...) { if(kIOLogYield & gIOKitDebug) IOLog(fmt, ## args); } + +inline void _workLoopAction( IOWorkLoop::Action action, + IOService * service, + void * p0 = 0, void * p1 = 0, + void * p2 = 0, void * p3 = 0 ) +{ + IOWorkLoop * wl; + + if( (wl = service->getWorkLoop())) { + wl->retain(); + wl->runAction( action, service, p0, p1, p2, p3 ); + wl->release(); + } else + (*action)( service, p0, p1, p2, p3 ); +} + +bool IOService::requestTerminate( IOService * provider, IOOptionBits options ) { bool ok; - if( client->isParent( this, gIOServicePlane, true)) - // we are the clients only provider - ok = client->terminate( options ); - else - ok = true; + // if its our only provider + ok = isParent( provider, gIOServicePlane, true); + + // -- compat + if( ok) { + provider->terminateClient( this, options | kIOServiceRecursing ); + ok = (0 != (__state[1] & kIOServiceRecursing)); + } + // -- return( ok ); } -struct TerminateClientsContext { - IOService * provider; - IOOptionBits options; -}; - -static void terminateInterestApplier( OSObject * object, void * ctx ) +bool IOService::terminatePhase1( IOOptionBits options = 0 ) { - TerminateClientsContext * context = (TerminateClientsContext *) ctx; + IOService * victim; + IOService * client; + OSIterator * iter; + OSArray * makeInactive; + bool ok; + bool didInactive; + bool startPhase2 = false; - context->provider->messageClient( kIOMessageServiceIsTerminated, - object, (void *) context->options ); -} + TLOG("%s::terminatePhase1(%08lx)\n", getName(), options); -static void terminateClientsApplier( IOService * client, void * ctx ) -{ - TerminateClientsContext * context = (TerminateClientsContext *) ctx; + // -- compat + if( options & kIOServiceRecursing) { + __state[1] |= kIOServiceRecursing; + return( true ); + } + // -- + + makeInactive = OSArray::withCapacity( 16 ); + if( !makeInactive) + return( false ); + + victim = this; + victim->retain(); + + while( victim ) { + + didInactive = victim->lockForArbitration( true ); + if( didInactive) { + didInactive = (0 == (victim->__state[0] & kIOServiceInactiveState)); + if( didInactive) { + victim->__state[0] |= kIOServiceInactiveState; + victim->__state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState + | kIOServiceFirstPublishState | kIOServiceFirstMatchState); + victim->_adjustBusy( 1 ); + } + victim->unlockForArbitration(); + } + if( victim == this) + startPhase2 = didInactive; + if( didInactive) { + + victim->deliverNotification( gIOTerminatedNotification, 0, 0xffffffff ); + IOUserClient::destroyUserReferences( victim ); + victim->unregisterAllInterest(); + + iter = victim->getClientIterator(); + if( iter) { + while( (client = (IOService *) iter->getNextObject())) { + TLOG("%s::requestTerminate(%s, %08lx)\n", + client->getName(), victim->getName(), options); + ok = client->requestTerminate( victim, options ); + TLOG("%s::requestTerminate(%s, ok = %d)\n", + client->getName(), victim->getName(), ok); + if( ok) + makeInactive->setObject( client ); + } + iter->release(); + } + } + victim->release(); + victim = (IOService *) makeInactive->getObject(0); + if( victim) { + victim->retain(); + makeInactive->removeObject(0); + } + } - if( gIOKitDebug & kIOLogYield) - LOG("%s::terminateClient(%s,%08lx)\n", - context->provider->getName(), - client->getName(), context->options); + makeInactive->release(); - context->provider->terminateClient( client, - ((context->options) | kIOServiceRecursing) & ~kIOServiceSynchronous ); + if( startPhase2) + scheduleTerminatePhase2( options ); + + return( true ); } -static void terminateRequestClose( IOService * client, void * ctx ) +void IOService::scheduleTerminatePhase2( IOOptionBits options = 0 ) { - TerminateClientsContext * context = (TerminateClientsContext *) ctx; - IOService * provider = context->provider; + AbsoluteTime deadline; + int waitResult; + bool wait, haveDeadline = false; + + options |= kIOServiceRequired; + + retain(); + + IOLockLock( gJobsLock ); + + if( (options & kIOServiceSynchronous) + && (current_thread() != gIOTerminateThread)) { + + do { + wait = (gIOTerminateThread != 0); + if( wait) { + // wait to become the terminate thread + assert_wait( (event_t) &gIOTerminateThread, THREAD_UNINT ); + IOLockUnlock( gJobsLock ); + thread_block((void (*)(void)) 0); + IOLockLock( gJobsLock ); + } + } while( wait ); + + gIOTerminateThread = current_thread(); + gIOTerminatePhase2List->setObject( this ); + gIOTerminateWork++; - if( provider->isOpen( client)) { - if( gIOKitDebug & kIOLogYield) - LOG("%s::terminate request close(%s,%08lx)\n", - provider->getName(), - client->getName(), context->options); - provider->messageClient( kIOMessageServiceIsRequestingClose, - client, (void *) context->options ); + do { + terminateWorker( options ); + wait = (0 != (__state[1] & kIOServiceBusyStateMask)); + if( wait) { + // wait for the victim to go non-busy + assert_wait( (event_t) &gIOTerminateWork, THREAD_UNINT ); + if( !haveDeadline) { + clock_interval_to_deadline( 15, kSecondScale, &deadline ); + haveDeadline = true; + } + thread_set_timer_deadline( deadline ); + IOLockUnlock( gJobsLock ); + waitResult = thread_block((void (*)(void)) 0); + if( waitResult == THREAD_TIMED_OUT) { + TLOG("%s::terminate(kIOServiceSynchronous) timeout", getName()); + } else + thread_cancel_timer(); + IOLockLock( gJobsLock ); + } + } while( wait && (waitResult != THREAD_TIMED_OUT)); + + gIOTerminateThread = 0; + thread_wakeup( (event_t) &gIOTerminateThread ); + + } else { + // ! kIOServiceSynchronous + + gIOTerminatePhase2List->setObject( this ); + if( 0 == gIOTerminateWork++) + gIOTerminateThread = IOCreateThread( &terminateThread, (void *) options ); } + + IOLockUnlock( gJobsLock ); + + release(); } -bool IOService::terminate( IOOptionBits options = 0 ) +void IOService::terminateThread( void * arg ) { - bool ok; - bool wasClosed; - bool madeInactive; - TerminateClientsContext context; + IOLockLock( gJobsLock ); - if( false == lockForArbitration( (options & kIOServiceRequired) )) - return false; + terminateWorker( (IOOptionBits) arg ); - retain(); + gIOTerminateThread = 0; + thread_wakeup( (event_t) &gIOTerminateThread ); - context.provider = this; - context.options = options; + IOLockUnlock( gJobsLock ); +} - ok = (options & kIOServiceRequired); - wasClosed = (false == handleIsOpen( 0 )); - if( !ok) - ok = wasClosed; +void IOService::scheduleStop( IOService * provider ) +{ + TLOG("%s::scheduleStop(%s)\n", getName(), provider->getName()); - if( !ok) { - applyToClients( &terminateRequestClose, (void *) &context ); - wasClosed = (false == handleIsOpen( 0 )); - ok = wasClosed; + IOLockLock( gJobsLock ); + gIOStopList->tailQ( this ); + gIOStopProviderList->tailQ( provider ); + + if( 0 == gIOTerminateWork++) { + if( !gIOTerminateThread) + gIOTerminateThread = IOCreateThread( &terminateThread, (void *) 0 ); + else + thread_wakeup( (event_t) &gIOTerminateWork ); } - if( ok) { - madeInactive = (0 == (__state[0] & kIOServiceInactiveState)); - if( madeInactive) { - __state[0] |= kIOServiceInactiveState; - __state[0] &= ~(kIOServiceRegisteredState | kIOServiceMatchedState); - if( 0 == (options & kIOServiceRecursing)) - __state[1] |= kIOServiceTerminatedState; - } - } else - madeInactive = false; + IOLockUnlock( gJobsLock ); +} - unlockForArbitration(); +void IOService::scheduleFinalize( void ) +{ + TLOG("%s::scheduleFinalize\n", getName()); - if( madeInactive) { + IOLockLock( gJobsLock ); + gIOFinalizeList->tailQ( this ); - adjustBusy( 1 ); - applyToInterested( gIOGeneralInterest, - &terminateInterestApplier, (void *) &context ); + if( 0 == gIOTerminateWork++) { + if( !gIOTerminateThread) + gIOTerminateThread = IOCreateThread( &terminateThread, (void *) 0 ); + else + thread_wakeup( (event_t) &gIOTerminateWork ); + } - deliverNotification( gIOTerminatedNotification, 0, 0xffffffff ); + IOLockUnlock( gJobsLock ); +} - applyToClients( &terminateClientsApplier, (void *) &context ); +bool IOService::willTerminate( IOService * provider, IOOptionBits options ) +{ + return( true ); +} - if( wasClosed && (0 == (options & kIOServiceRecursing))) { - if( options & kIOServiceSynchronous) - doServiceTerminate( 0 ); - else - ok = (0 != _IOServiceJob::startJob( this, kTerminateNubJob, 0 )); - } - if( options & kIOServiceSynchronous) - waitQuiet(); +bool IOService::didTerminate( IOService * provider, IOOptionBits options, bool * defer ) +{ + if( false == *defer) { + + if( lockForArbitration( true )) { + if( false == provider->handleIsOpen( this )) + scheduleStop( provider ); + // -- compat + else { + message( kIOMessageServiceIsRequestingClose, provider, (void *) options ); + if( false == provider->handleIsOpen( this )) + scheduleStop( provider ); + } + // -- + unlockForArbitration(); + } } - release(); + return( true ); +} - return( ok ); +void IOService::actionWillTerminate( IOService * victim, IOOptionBits options, + OSArray * doPhase2List ) +{ + OSIterator * iter; + IOService * client; + bool ok; + + iter = victim->getClientIterator(); + if( iter) { + while( (client = (IOService *) iter->getNextObject())) { + TLOG("%s::willTerminate(%s, %08lx)\n", + client->getName(), victim->getName(), options); + ok = client->willTerminate( victim, options ); + doPhase2List->tailQ( client ); + } + iter->release(); + } } -void IOService::doServiceTerminate( IOOptionBits options ) +void IOService::actionDidTerminate( IOService * victim, IOOptionBits options ) { - IOService * next; - OSIterator * iter; - IOService * client; - OSArray * deathList = 0; - unsigned int index; - bool finalize; - bool ok = true; + OSIterator * iter; + IOService * client; + bool defer = false; - next = this; - deathList = OSArray::withObjects( & (const OSObject *) next, 1, 1 ); - assert( deathList ); - if( !deathList) - return; + victim->messageClients( kIOMessageServiceIsTerminated, (void *) options ); - index = 0; - do { - iter = next->getClientIterator(); - assert( iter ); - if( iter) { + iter = victim->getClientIterator(); + if( iter) { + while( (client = (IOService *) iter->getNextObject())) { + TLOG("%s::didTerminate(%s, %08lx)\n", + client->getName(), victim->getName(), options); + client->didTerminate( victim, options, &defer ); + TLOG("%s::didTerminate(%s, defer %d)\n", + client->getName(), victim->getName(), defer); + } + iter->release(); + } +} - while( (client = (IOService *) iter->getNextObject())) { +void IOService::actionFinalize( IOService * victim, IOOptionBits options ) +{ + TLOG("%s::finalize(%08lx)\n", victim->getName(), options); + victim->finalize( options ); +} - if( gIOKitDebug & kIOLogYield) - LOG("%s::actionClients(%s)\n", - next->getName(), client->getName()); +void IOService::actionStop( IOService * provider, IOService * client ) +{ + TLOG("%s::stop(%s)\n", client->getName(), provider->getName()); + client->stop( provider ); + if( provider->isOpen( client )) + provider->close( client ); + TLOG("%s::detach(%s)\n", client->getName(), provider->getName()); + client->detach( provider ); +} - client->stop( next ); +void IOService::terminateWorker( IOOptionBits options ) +{ + OSArray * doPhase2List; + OSArray * didPhase2List; + OSSet * freeList; + UInt32 workDone; + IOService * victim; + IOService * client; + IOService * provider; + unsigned int idx; + bool moreToDo; + bool doPhase2; + bool doPhase3; - if( next->isOpen( client )) - next->close( client ); + options |= kIOServiceRequired; - client->detach( next ); + doPhase2List = OSArray::withCapacity( 16 ); + didPhase2List = OSArray::withCapacity( 16 ); + freeList = OSSet::withCapacity( 16 ); + if( (0 == doPhase2List) || (0 == didPhase2List) || (0 == freeList)) + return; - client->lockForArbitration(); - if( (client->__state[0] & kIOServiceInactiveState) - && (0 == (client->__state[1] & kIOServiceTerminatedState)) - && (0 == client->getProvider()) ) { - client->__state[1] |= kIOServiceTerminatedState; - finalize = (false == client->handleIsOpen( 0 )); - } else - finalize = false; - client->unlockForArbitration(); + do { + workDone = gIOTerminateWork; - if( finalize) - deathList->setObject( client ); + while( (victim = (IOService *) gIOTerminatePhase2List->getObject(0) )) { + + victim->retain(); + gIOTerminatePhase2List->removeObject(0); + IOLockUnlock( gJobsLock ); + + while( victim ) { + + doPhase2 = victim->lockForArbitration( true ); + if( doPhase2) { + doPhase2 = (0 != (kIOServiceInactiveState & victim->__state[0])); + if( doPhase2) { + doPhase2 = (0 == (victim->__state[1] & kIOServiceTermPhase2State)) + && (0 == (victim->__state[1] & kIOServiceConfigState)); + if( doPhase2) + victim->__state[1] |= kIOServiceTermPhase2State; + } + victim->unlockForArbitration(); + } + if( doPhase2) { + if( 0 == victim->getClient()) { + // no clients - will go to finalize + IOLockLock( gJobsLock ); + gIOFinalizeList->tailQ( victim ); + IOLockUnlock( gJobsLock ); + } else { + _workLoopAction( (IOWorkLoop::Action) &actionWillTerminate, + victim, (void *) options, (void *) doPhase2List ); + } + didPhase2List->headQ( victim ); + } + victim->release(); + victim = (IOService *) doPhase2List->getObject(0); + if( victim) { + victim->retain(); + doPhase2List->removeObject(0); + } } - iter->release(); + + while( (victim = (IOService *) didPhase2List->getObject(0)) ) { + + if( victim->lockForArbitration( true )) { + victim->__state[1] |= kIOServiceTermPhase3State; + victim->unlockForArbitration(); + } + _workLoopAction( (IOWorkLoop::Action) &actionDidTerminate, + victim, (void *) options ); + didPhase2List->removeObject(0); + } + IOLockLock( gJobsLock ); } - } while( (next = (IOService *) deathList->getObject( ++index )) ); - - while( index--) { + // phase 3 + do { + doPhase3 = false; + // finalize leaves + while( (victim = (IOService *) gIOFinalizeList->getObject(0))) { + + IOLockUnlock( gJobsLock ); + _workLoopAction( (IOWorkLoop::Action) &actionFinalize, + victim, (void *) options ); + IOLockLock( gJobsLock ); + // hold off free + freeList->setObject( victim ); + // safe if finalize list is append only + gIOFinalizeList->removeObject(0); + } + + for( idx = 0; + (!doPhase3) && (client = (IOService *) gIOStopList->getObject(idx)); ) { + + provider = (IOService *) gIOStopProviderList->getObject(idx); + assert( provider ); + + if( !provider->isChild( client, gIOServicePlane )) { + // may be multiply queued - nop it + TLOG("%s::nop stop(%s)\n", client->getName(), provider->getName()); + } else { + // not ready for stop if it has clients, skip it + if( (client->__state[1] & kIOServiceTermPhase3State) && client->getClient()) { + TLOG("%s::defer stop(%s)\n", client->getName(), provider->getName()); + idx++; + continue; + } + + IOLockUnlock( gJobsLock ); + _workLoopAction( (IOWorkLoop::Action) &actionStop, + provider, (void *) client ); + IOLockLock( gJobsLock ); + // check the finalize list now + doPhase3 = true; + } + // hold off free + freeList->setObject( client ); + freeList->setObject( provider ); + + // safe if stop list is append only + gIOStopList->removeObject( idx ); + gIOStopProviderList->removeObject( idx ); + idx = 0; + } - next = (IOService *) deathList->getObject( index ); - assert( next ); - next->retain(); - deathList->removeObject( index ); + } while( doPhase3 ); - IOUserClient::destroyUserReferences( next ); + gIOTerminateWork -= workDone; + moreToDo = (gIOTerminateWork != 0); - next->unregisterAllInterest(); + if( !moreToDo) { + TLOG("iokit terminate done, %d stops remain\n", gIOStopList->getCount()); + } - ok = next->finalize( options ); - assert( ok ); + } while( moreToDo ); - if( gIOKitDebug & kIOLogYield) - LOG("%s __state = %08lx:%08lx\n", next->getName(), - next->__state[0], next->__state[1]); - next->adjustBusy( -1 ); + IOLockUnlock( gJobsLock ); - next->release(); - } + freeList->release(); + doPhase2List->release(); + didPhase2List->release(); - deathList->release(); + IOLockLock( gJobsLock ); } bool IOService::finalize( IOOptionBits options ) { OSIterator * iter; IOService * provider; - + iter = getProviderIterator(); assert( iter ); if( iter) { - while( (provider = (IOService *) iter->getNextObject())) { - /* we come down here on programmatic terminate */ - stop( provider ); - if( provider->isOpen( this )) - provider->close( this ); - detach( provider ); - } - iter->release(); + while( (provider = (IOService *) iter->getNextObject())) { + + // -- compat + if( 0 == (__state[1] & kIOServiceTermPhase3State)) { + /* we come down here on programmatic terminate */ + stop( provider ); + if( provider->isOpen( this )) + provider->close( this ); + detach( provider ); + } else { + //-- + if( provider->lockForArbitration( true )) { + if( 0 == (provider->__state[1] & kIOServiceTermPhase3State)) + scheduleStop( provider ); + provider->unlockForArbitration(); + } + } + } + iter->release(); } return( true ); } +#undef tailQ(o) +#undef headQ(o) + +/* + * Terminate + */ + +void IOService::doServiceTerminate( IOOptionBits options ) +{ +} + +// a method in case someone needs to override it +bool IOService::terminateClient( IOService * client, IOOptionBits options ) +{ + bool ok; + + if( client->isParent( this, gIOServicePlane, true)) + // we are the clients only provider + ok = client->terminate( options ); + else + ok = true; + + return( ok ); +} + +bool IOService::terminate( IOOptionBits options = 0 ) +{ + options |= kIOServiceTerminate; + + return( terminatePhase1( options )); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + /* * Open & close */ +struct ServiceOpenMessageContext +{ + IOService * service; + UInt32 type; + IOService * excludeClient; + IOOptionBits options; +}; + +static void serviceOpenMessageApplier( OSObject * object, void * ctx ) +{ + ServiceOpenMessageContext * context = (ServiceOpenMessageContext *) ctx; + + if( object != context->excludeClient) + context->service->messageClient( context->type, object, (void *) context->options ); +} + bool IOService::open( IOService * forClient, IOOptionBits options = 0, void * arg = 0 ) { - bool ok; + bool ok; + ServiceOpenMessageContext context; + + context.service = this; + context.type = kIOMessageServiceIsAttemptingOpen; + context.excludeClient = forClient; + context.options = options; + + applyToInterested( gIOGeneralInterest, + &serviceOpenMessageApplier, &context ); if( false == lockForArbitration(false) ) return false; @@ -1608,40 +2040,33 @@ bool IOService::open( IOService * forClient, void IOService::close( IOService * forClient, IOOptionBits options = 0 ) { - bool ok; bool wasClosed; bool last = false; - OSIterator * iter; - IOService * client; lockForArbitration(); wasClosed = handleIsOpen( forClient ); if( wasClosed) { handleClose( forClient, options ); - - last = ( (__state[1] & kIOServiceTerminatedState) - && (false == handleIsOpen( 0 )) ); + last = (__state[1] & kIOServiceTermPhase3State); } unlockForArbitration(); - if( last) { - ok = (0 != _IOServiceJob::startJob( this, kTerminateNubJob, 0 )); - assert( ok ); + if( last) + forClient->scheduleStop( this ); - } else if( wasClosed) { + else if( wasClosed) { - iter = getClientIterator(); - assert( iter ); + ServiceOpenMessageContext context; + + context.service = this; + context.type = kIOMessageServiceWasClosed; + context.excludeClient = forClient; + context.options = options; - if( iter) { - while( (client = (IOService *) iter->getNextObject())) { - if( client != forClient) - messageClient( kIOMessageServiceWasClosed, client, 0 ); - } - iter->release(); - } + applyToInterested( gIOGeneralInterest, + &serviceOpenMessageApplier, &context ); } } @@ -1671,11 +2096,12 @@ bool IOService::handleOpen( IOService * forClient, else if( options & kIOServiceSeize ) { ok = (kIOReturnSuccess == messageClient( kIOMessageServiceIsRequestingClose, - __owner, (void *) options )); - if( ok && (0 == __owner )) + __owner, (void *) options )); + if( ok && (0 == __owner )) __owner = forClient; + else + ok = false; } - return( ok ); } @@ -2074,6 +2500,24 @@ void IOService::probeCandidates( OSOrderedSet * matches ) iter->release(); } + + // adjust the busy count by -1 if matching is stalled for a module, + // or +1 if a previously stalled matching is complete. + lockForArbitration(); + SInt32 adjBusy = 0; + if( needReloc) { + adjBusy = (__state[1] & kIOServiceModuleStallState) ? 0 : 1; + if( adjBusy) + __state[1] |= kIOServiceModuleStallState; + + } else if( __state[1] & kIOServiceModuleStallState) { + __state[1] &= ~kIOServiceModuleStallState; + adjBusy = -1; + } + if( adjBusy) + _adjustBusy( adjBusy ); + unlockForArbitration(); + if( startDict) startDict->release(); } @@ -2095,6 +2539,7 @@ bool IOService::startCandidate( IOService * service ) // stall for any driver resources service->checkResources(); + ok = service->start( this ); if( !ok) service->detach( this ); @@ -2268,7 +2713,8 @@ void IOService::doServiceMatch( IOOptionBits options ) deliverNotification( gIOFirstPublishNotification, kIOServiceFirstPublishState, 0xffffffff ); LOCKREADNOTIFY(); - __state[1] &= ~kIOServiceConfigState; + __state[1] &= ~kIOServiceNeedConfigState; + __state[1] |= kIOServiceConfigState; __state[0] |= kIOServiceRegisteredState; if( reRegistered && (0 == (__state[0] & kIOServiceInactiveState))) { @@ -2297,7 +2743,7 @@ void IOService::doServiceMatch( IOOptionBits options ) } lockForArbitration(); - reRegistered = (0 != (__state[1] & kIOServiceConfigState)); + reRegistered = (0 != (__state[1] & kIOServiceNeedConfigState)); keepGuessing = (reRegistered || (catalogGeneration != gIOCatalogue->getGenerationCount())) @@ -2307,7 +2753,8 @@ void IOService::doServiceMatch( IOOptionBits options ) unlockForArbitration(); } - if( 0 == (__state[0] & kIOServiceInactiveState)) { + if( (0 == (__state[0] & kIOServiceInactiveState)) + && (0 == (__state[1] & kIOServiceModuleStallState)) ) { deliverNotification( gIOMatchedNotification, kIOServiceMatchedState, 0xffffffff ); if( 0 == (__state[0] & kIOServiceFirstMatchState)) @@ -2315,33 +2762,43 @@ void IOService::doServiceMatch( IOOptionBits options ) kIOServiceFirstMatchState, 0xffffffff ); } - unlockForArbitration(); + __state[1] &= ~kIOServiceConfigState; + if( __state[0] & kIOServiceInactiveState) + scheduleTerminatePhase2(); - adjustBusy( -1 ); + _adjustBusy( -1 ); + unlockForArbitration(); } -void IOService::adjustBusy( SInt32 delta ) +UInt32 IOService::_adjustBusy( SInt32 delta ) { IOService * next; UInt32 count; - bool wasQuiet, nowQuiet; + UInt32 result; + bool wasQuiet, nowQuiet, needWake; - if( 0 == delta) - return; - - IOTakeLock( gIOServiceBusyLock ); next = this; + result = __state[1] & kIOServiceBusyStateMask; - do { + if( delta) do { + if( next != this) + next->lockForArbitration(); count = next->__state[1] & kIOServiceBusyStateMask; assert( count < kIOServiceBusyMax); wasQuiet = (0 == count); assert( (!wasQuiet) || (delta > 0)); next->__state[1] += delta; nowQuiet = (0 == (next->__state[1] & kIOServiceBusyStateMask)); + needWake = (0 != (kIOServiceBusyWaiterState & next->__state[1])); - if( nowQuiet) + if( needWake) { + next->__state[1] &= ~kIOServiceBusyWaiterState; + IOLockLock( gIOServiceBusyLock ); thread_wakeup( (event_t) next); + IOLockUnlock( gIOServiceBusyLock ); + } + if( next != this) + next->unlockForArbitration(); if( (wasQuiet || nowQuiet) ) { OSArray * array; @@ -2368,7 +2825,14 @@ void IOService::adjustBusy( SInt32 delta ) } while( (wasQuiet || nowQuiet) && (next = next->getProvider())); - IOUnlock( gIOServiceBusyLock ); + return( result ); +} + +void IOService::adjustBusy( SInt32 delta ) +{ + lockForArbitration(); + _adjustBusy( delta ); + unlockForArbitration(); } UInt32 IOService::getBusyState( void ) @@ -2385,15 +2849,15 @@ IOReturn IOService::waitForState( UInt32 mask, UInt32 value, AbsoluteTime abstime; do { - IOTakeLock( gIOServiceBusyLock ); + lockForArbitration(); + IOLockLock( gIOServiceBusyLock ); wait = (value != (__state[1] & mask)); - if( wait) - { + if( wait) { + __state[1] |= kIOServiceBusyWaiterState; + unlockForArbitration(); assert_wait( (event_t) this, THREAD_UNINT ); - if ( timeout ) - { - if ( computeDeadline ) - { + if( timeout ) { + if( computeDeadline ) { AbsoluteTime nsinterval; clock_interval_to_absolutetime_interval( timeout->tv_sec, kSecondScale, &abstime ); @@ -2406,18 +2870,18 @@ IOReturn IOService::waitForState( UInt32 mask, UInt32 value, } thread_set_timer_deadline( abstime ); } - } - IOUnlock( gIOServiceBusyLock ); - if( wait) - { + } else + unlockForArbitration(); + IOLockUnlock( gIOServiceBusyLock ); + if( wait) { waitResult = thread_block((void (*)(void)) 0); - if ( timeout && (waitResult != THREAD_TIMED_OUT)) + if( timeout && (waitResult != THREAD_TIMED_OUT)) thread_cancel_timer(); } - } while( wait && ( waitResult != THREAD_TIMED_OUT ) ); + } while( wait && (waitResult != THREAD_TIMED_OUT)); - if ( waitResult == THREAD_TIMED_OUT ) + if( waitResult == THREAD_TIMED_OUT) return( kIOReturnTimeout ); else return( kIOReturnSuccess ); @@ -2446,13 +2910,7 @@ void _IOConfigThread::main( _IOConfigThread * self ) do { -#if 0 -#define randomDelay() \ - int del = read_processor_clock(); \ - del = (((int)IOThreadSelf()) ^ del ^ (del >> 10)) & 0x3ff; \ - IOSleep( del ); - randomDelay(); -#endif +// randomDelay(); semaphore_wait( gJobsSemaphore ); @@ -2462,10 +2920,8 @@ void _IOConfigThread::main( _IOConfigThread * self ) gJobs->removeObject(job); if( job) { gOutstandingJobs--; -#ifndef LESS_THREAD_CREATE // gNumConfigThreads--; // we're out of service gNumWaitingThreads--; // we're out of service -#endif } IOUnlock( gJobsLock ); @@ -2483,10 +2939,6 @@ void _IOConfigThread::main( _IOConfigThread * self ) nub->doServiceMatch( job->options ); break; - case kTerminateNubJob: - nub->doServiceTerminate( job->options ); - break; - default: LOG("config(%x): strange type (%d)\n", (int) IOThreadSelf(), job->type ); @@ -2497,14 +2949,16 @@ void _IOConfigThread::main( _IOConfigThread * self ) job->release(); IOTakeLock( gJobsLock ); -#ifndef LESS_THREAD_CREATE alive = (gOutstandingJobs > gNumWaitingThreads); if( alive) gNumWaitingThreads++; // back in service // gNumConfigThreads++; - else - gNumConfigThreads--; -#endif + else { + if( 0 == --gNumConfigThreads) { +// IOLog("MATCH IDLE\n"); + thread_wakeup( (event_t) &gNumConfigThreads); + } + } IOUnlock( gJobsLock ); } @@ -2516,6 +2970,44 @@ void _IOConfigThread::main( _IOConfigThread * self ) self->release(); } +IOReturn IOService::waitMatchIdle( UInt32 msToWait ) +{ + bool wait; + int waitResult = THREAD_AWAKENED; + bool computeDeadline = true; + AbsoluteTime abstime; + + do { + IOLockLock( gJobsLock ); + wait = (0 != gNumConfigThreads); + if( wait) { + assert_wait( (event_t) &gNumConfigThreads, THREAD_UNINT ); + if( msToWait) { + if( computeDeadline ) { + clock_interval_to_absolutetime_interval( + msToWait, kMillisecondScale, &abstime ); + clock_absolutetime_interval_to_deadline( + abstime, &abstime ); + computeDeadline = false; + } + thread_set_timer_deadline( abstime ); + } + } + IOUnlock( gJobsLock ); + if( wait) { + waitResult = thread_block((void (*)(void)) 0); + if( msToWait && (waitResult != THREAD_TIMED_OUT)) + thread_cancel_timer(); + } + + } while( wait && (waitResult != THREAD_TIMED_OUT)); + + if( waitResult == THREAD_TIMED_OUT) + return( kIOReturnTimeout ); + else + return( kIOReturnSuccess ); +} + void _IOServiceJob::pingConfig( _IOServiceJob * job ) { int count; @@ -2606,7 +3098,7 @@ OSIterator * IOService::getMatchingServices( OSDictionary * matching ) LOCKWRITENOTIFY(); iter = (OSIterator *) getExistingServices( matching, - kIOServiceRegisteredState ); + kIOServiceMatchedState ); UNLOCKNOTIFY(); @@ -2673,9 +3165,12 @@ IONotifier * IOService::doInstallNotification( if( !matching) return( 0 ); - if( (type == gIOPublishNotification) - || (type == gIOFirstPublishNotification)) + if( type == gIOPublishNotification) inState = kIOServiceRegisteredState; + + else if( type == gIOFirstPublishNotification) + inState = kIOServiceFirstPublishState; + else if( (type == gIOMatchedNotification) || (type == gIOFirstMatchNotification)) inState = kIOServiceMatchedState; @@ -3245,7 +3740,7 @@ bool IOService::passiveMatch( OSDictionary * table, bool changesOK ) || (iter && (0 != (nextDict = OSDynamicCast(OSDictionary, iter->getNextObject()))))) { match = dict->isEqualTo( nextDict, nextDict); - if( !match) + if( match) break; nextDict = 0; } @@ -3799,9 +4294,10 @@ IOReturn IOService::causeInterrupt(int source) return interruptController->causeInterrupt(this, source); } -OSMetaClassDefineReservedUnused(IOService, 0); -OSMetaClassDefineReservedUnused(IOService, 1); -OSMetaClassDefineReservedUnused(IOService, 2); +OSMetaClassDefineReservedUsed(IOService, 0); +OSMetaClassDefineReservedUsed(IOService, 1); +OSMetaClassDefineReservedUsed(IOService, 2); + OSMetaClassDefineReservedUnused(IOService, 3); OSMetaClassDefineReservedUnused(IOService, 4); OSMetaClassDefineReservedUnused(IOService, 5); diff --git a/iokit/Kernel/IOServicePM.cpp b/iokit/Kernel/IOServicePM.cpp index 4c72153e3..5d225355d 100644 --- a/iokit/Kernel/IOServicePM.cpp +++ b/iokit/Kernel/IOServicePM.cpp @@ -36,6 +36,8 @@ #include "IOKit/pwr_mgt/IOPowerConnection.h" #include <kern/clock.h> +#define super IORegistryEntry + static void ack_timer_expired(thread_call_param_t); static void settle_timer_expired(thread_call_param_t); void PMreceiveCmd ( OSObject *, void *, void *, void *, void * ); @@ -61,12 +63,14 @@ extern const IORegistryPlane * gIOPowerPlane; enum { IOPMour_prechange_03 = 1, + IOPMour_prechange_04, IOPMour_prechange_05, IOPMour_prechange_1, IOPMour_prechange_2, IOPMour_prechange_3, IOPMour_prechange_4, IOPMparent_down_0, + IOPMparent_down_05, IOPMparent_down_2, IOPMparent_down_3, IOPMparent_down_4, @@ -80,6 +84,11 @@ enum { IOPMfinished }; +enum { // values of outofbandparameter + kNotifyApps, + kNotifyPriority +}; + struct context { // used for applyToInterested OSArray * responseFlags; UInt16 serialNumber; @@ -88,11 +97,13 @@ struct context { // used for applyToInterested int msgType; IOService * us; IOLock * flags_lock; + unsigned long stateNumber; + IOPMPowerFlags stateFlags; }; // five minutes in microseconds #define FIVE_MINUTES 5*60*1000000 -#define k15seconds 15*1000000 +#define k30seconds 30*1000000 /* There are two different kinds of power state changes. One is initiated by a subclassed device object which has either @@ -220,6 +231,9 @@ void IOService::PMinit ( void ) pm_vars->theControllingDriver = NULL; priv->our_lock = IOLockAlloc(); priv->flags_lock = IOLockAlloc(); + priv->queue_lock = IOLockAlloc(); + pm_vars->childLock = IOLockAlloc(); + pm_vars->parentLock = IOLockAlloc(); priv->interestedDrivers = new IOPMinformeeList; priv->interestedDrivers->initialize(); priv->changeList = new IOPMchangeNoteList; @@ -231,7 +245,6 @@ void IOService::PMinit ( void ) } pm_vars->myCurrentState = 0; priv->imminentState = 0; - priv->askingFor = 0; priv->ourDesiredPowerState = 0; pm_vars->parentsCurrentPowerFlags = 0; pm_vars->maxCapability = 0; @@ -263,18 +276,87 @@ void IOService::PMinit ( void ) } +//********************************************************************************* +// PMfree +// +// Free up the data created in PMinit, if it exists. +//********************************************************************************* +void IOService::PMfree ( void ) +{ + if ( priv ) { + if ( priv->clampTimerEventSrc != NULL ) { + getPMworkloop()->removeEventSource(priv->clampTimerEventSrc); + priv->clampTimerEventSrc->release(); + priv->clampTimerEventSrc = NULL; + } + if ( priv->timerEventSrc != NULL ) { + pm_vars->PMworkloop->removeEventSource(priv->timerEventSrc); + priv->timerEventSrc->release(); + priv->timerEventSrc = NULL; + } + if ( priv->settleTimer ) { + thread_call_cancel(priv->settleTimer); + thread_call_free(priv->settleTimer); + priv->settleTimer = NULL; + } + if ( priv->ackTimer ) { + thread_call_cancel(priv->ackTimer); + thread_call_free(priv->ackTimer); + priv->ackTimer = NULL; + } + if ( priv->our_lock ) { + IOLockFree(priv->our_lock); + priv->our_lock = NULL; + } + if ( priv->flags_lock ) { + IOLockFree(priv->flags_lock); + priv->flags_lock = NULL; + } + if ( priv->activityLock ) { + IOLockFree(priv->activityLock); + priv->activityLock = NULL; + } + priv->interestedDrivers->release(); + priv->changeList->release(); + priv->release(); // remove instance variables + } + + if ( pm_vars ) { + if ( pm_vars->commandQueue ) { + pm_vars->commandQueue->release(); + pm_vars->commandQueue = NULL; + } + if ( pm_vars->PMcommandGate ) { + pm_vars->PMcommandGate->release(); + pm_vars->PMcommandGate = NULL; + } + if ( pm_vars->PMworkloop ) { + // The work loop object returned from getPMworkLoop() is + // never retained, therefore it should not be released. + // pm_vars->PMworkloop->release(); + pm_vars->PMworkloop = NULL; + } + if ( pm_vars->responseFlags ) { + pm_vars->responseFlags->release(); + pm_vars->responseFlags = NULL; + } + pm_vars->release(); // remove instance variables + } +} + + //********************************************************************************* // PMstop // -// Free up the data created in PMinit. +// Disconnect the node from its parents and children in the Power Plane. //********************************************************************************* void IOService::PMstop ( void ) { OSIterator * iter; OSObject * next; IOPowerConnection * connection; - - initialized = false; + IOService * theChild; + IOService * theParent; removeProperty(prot_key); // remove the properties removeProperty(priv_key); @@ -284,7 +366,11 @@ void IOService::PMstop ( void ) if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { - ((IOService *)(connection->getParentEntry(gIOPowerPlane)))->removePowerChild(connection); + theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane); + if ( theParent ) { + theParent->removePowerChild(connection); + theParent->release(); + } } } iter->release(); @@ -292,43 +378,38 @@ void IOService::PMstop ( void ) detachAbove( gIOPowerPlane ); // detach IOConnections pm_vars->parentsKnowState = false; // no more power state changes -#if 0 - -// This loop is insufficient. Currently only leaf nodes are removed, and it's not clear today what -// it means to remove a subtree from the tree. Should the IOPowerConnection at the top of it stay -// or go? Should its child be notified of a change in the domain state? iter = getChildIterator(gIOPowerPlane); // detach children if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { - removePowerChild(connection); + theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane))); + if ( theChild ) { + connection->detachFromChild(theChild,gIOPowerPlane); // detach nub from child + theChild->release(); + } + detachFromChild(connection,gIOPowerPlane); // detach us from nub } } iter->release(); } -#endif - if ( priv->clampTimerEventSrc != NULL ) { - getPMworkloop()->removeEventSource(priv->clampTimerEventSrc); - priv->clampTimerEventSrc->release(); - priv->clampTimerEventSrc = NULL; - } - if ( priv->timerEventSrc != NULL ) { - pm_vars->PMworkloop->removeEventSource(priv->timerEventSrc); - priv->timerEventSrc->release(); - priv->timerEventSrc = NULL; - } - thread_call_free(priv->settleTimer); - thread_call_free(priv->ackTimer); + // Remove all interested drivers from the list, including the power + // controlling driver. + // + // Usually, the controlling driver and the policy-maker functionality + // are implemented by the same object, and without the deregistration, + // the object will be holding an extra retain on itself, and cannot + // be freed. + + if ( priv && priv->interestedDrivers ) + { + IOPMinformee * informee; - priv->interestedDrivers->release(); // remove lists - priv->changeList->release(); - pm_vars->release(); // remove the instance variables - priv->release(); - pm_vars = NULL; - priv = NULL; + while (( informee = priv->interestedDrivers->firstInList() )) + deRegisterInterestedDriver( informee->whatObject ); + } } @@ -388,6 +469,8 @@ IOReturn IOService::setPowerParent ( IOPowerConnection * theParent, bool stateKn pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetParent,stateKnown,currentState); + IOLockLock(pm_vars->parentLock); + if ( stateKnown && ((pm_vars->PMworkloop == NULL) || (pm_vars->PMcommandGate == NULL)) ) { getPMworkloop(); // we have a path to the root if ( pm_vars->PMworkloop != NULL ) { // find out the workloop @@ -400,6 +483,8 @@ IOReturn IOService::setPowerParent ( IOPowerConnection * theParent, bool stateKn } } + IOLockUnlock(pm_vars->parentLock); + theParent->setParentCurrentPowerFlags(currentState); // set our connection data theParent->setParentKnowsState(stateKnown); @@ -423,9 +508,12 @@ IOReturn IOService::setPowerParent ( IOPowerConnection * theParent, bool stateKn pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags); tempDesire = priv->deviceDesire; // initially change into the state we are already in priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentsCurrentPowerFlags); + computeDesiredState(); + priv->previousRequest = 0xffffffff; changeState(); priv->deviceDesire = tempDesire; // put this back like before } + return IOPMNoErr; } @@ -450,6 +538,7 @@ IOReturn IOService::addPowerChild ( IOService * theChild ) connection->init(); connection->start(this); + connection->setAwaitingAck(false); attachToChild( connection,gIOPowerPlane ); // connect it up connection->attachToChild( theChild,gIOPowerPlane ); @@ -485,11 +574,42 @@ IOReturn IOService::addPowerChild ( IOService * theChild ) // removePowerChild // //********************************************************************************* -IOReturn IOService::removePowerChild ( IOPowerConnection * theChild ) -{ +IOReturn IOService::removePowerChild ( IOPowerConnection * theNub ) +{ + IORegistryEntry * theChild; + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveChild,0,0); - detachFromChild(theChild,gIOPowerPlane); // remove the departing child + theNub->retain(); + + theChild = theNub->copyChildEntry(gIOPowerPlane); // detach nub from child + if ( theChild ) { + theNub->detachFromChild(theChild, gIOPowerPlane); + theChild->release(); + } + detachFromChild(theNub,gIOPowerPlane); // detach from the nub + + if ( theNub->getAwaitingAck() ) { // are we awaiting an ack from this child? + theNub->setAwaitingAck(false); // yes, pretend we got one + if ( acquire_lock() ) { + if (priv->head_note_pendingAcks != 0 ) { + priv->head_note_pendingAcks -= 1; // that's one fewer ack to worry about + if ( priv->head_note_pendingAcks == 0 ) { // is that the last? + stop_ack_timer(); // yes, stop the timer + IOUnlock(priv->our_lock); + all_acked(); // and now we can continue our power change + } + else { + IOUnlock(priv->our_lock); + } + } + else { + IOUnlock(priv->our_lock); + } + } + } + + theNub->release(); if ( (pm_vars->theControllingDriver == NULL) || // if not fully initialized ! (inPlane(gIOPowerPlane)) || @@ -497,6 +617,7 @@ IOReturn IOService::removePowerChild ( IOPowerConnection * theChild ) return IOPMNoErr; // we can do no more } + computeDesiredState(); // this may be different now changeState(); // change state if we can now tolerate lower power return IOPMNoErr; @@ -573,6 +694,7 @@ IOReturn IOService::registerPowerDriver ( IOService * controllingDriver, IOPMPow pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags); tempDesire = priv->deviceDesire; // initially change into the state we are already in priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentsCurrentPowerFlags); + computeDesiredState(); changeState(); priv->deviceDesire = tempDesire; // put this back like before } @@ -671,6 +793,8 @@ IOReturn IOService::deRegisterInterestedDriver ( IOService * theDriver ) IOReturn IOService::acknowledgePowerChange ( IOService * whichObject ) { IOPMinformee * ackingObject; + unsigned long childPower = kIOPMUnknown; + IOService * theChild; ackingObject = priv->interestedDrivers->findItem(whichObject); // one of our interested drivers? if ( ackingObject == NULL ) { @@ -680,11 +804,11 @@ IOReturn IOService::acknowledgePowerChange ( IOService * whichObject ) return IOPMNoErr; // no, just return } else { - pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChildAcknowledge,0,0); + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChildAcknowledge,priv->head_note_pendingAcks,0); } } else { - pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDriverAcknowledge,0,0); + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDriverAcknowledge,priv->head_note_pendingAcks,0); } if (! acquire_lock() ) { @@ -695,9 +819,9 @@ IOReturn IOService::acknowledgePowerChange ( IOService * whichObject ) if ( ackingObject != NULL ) { // it's an interested driver if ( ackingObject->timer != 0 ) { // make sure we're expecting this ack ackingObject->timer = 0; // mark it acked - priv->head_note_pendingAcks -= 1; // that's one fewer to worry about - if ( priv->head_note_pendingAcks == 0 ) { // is that the last? - stop_ack_timer(); // yes, stop the timer + priv->head_note_pendingAcks -= 1; // that's one fewer to worry about + if ( priv->head_note_pendingAcks == 0 ) { // is that the last? + stop_ack_timer(); // yes, stop the timer IOUnlock(priv->our_lock); all_acked(); // and now we can continue return IOPMNoErr; @@ -709,14 +833,30 @@ IOReturn IOService::acknowledgePowerChange ( IOService * whichObject ) } } else { // it's a child - priv->head_note_pendingAcks -= 1; // that's one fewer to worry about - if ( priv->head_note_pendingAcks == 0 ) { // is that the last? - stop_ack_timer(); // yes, stop the timer - IOUnlock(priv->our_lock); - all_acked(); // and now we can continue - return IOPMNoErr; - } - } + if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() ) { // make sure we're expecting this ack + priv->head_note_pendingAcks -= 1; // that's one fewer to worry about + ((IOPowerConnection *)whichObject)->setAwaitingAck(false); + theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane); + if ( theChild ) { + childPower = theChild->currentPowerConsumption(); + theChild->release(); + } + if ( childPower == kIOPMUnknown ) { + pm_vars->thePowerStates[priv->head_note_state].staticPower = kIOPMUnknown; + } + else { + if ( pm_vars->thePowerStates[priv->head_note_state].staticPower != kIOPMUnknown ) { + pm_vars->thePowerStates[priv->head_note_state].staticPower += childPower; + } + } + if ( priv->head_note_pendingAcks == 0 ) { // is that the last? + stop_ack_timer(); // yes, stop the timer + IOUnlock(priv->our_lock); + all_acked(); // and now we can continue + return IOPMNoErr; + } + } + } } else { pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr3,0,0); // not expecting anybody to ack @@ -808,6 +948,8 @@ IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags, return IOPMAckImplied; // somebody goofed } + IOLockLock(pm_vars->parentLock); + if ( (pm_vars->PMworkloop == NULL) || (pm_vars->PMcommandGate == NULL) ) { getPMworkloop(); // we have a path to the root, if ( pm_vars->PMworkloop != NULL ) { // so find out the workloop @@ -820,6 +962,8 @@ IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags, } } + IOLockUnlock(pm_vars->parentLock); + combinedPowerFlags = 0; // combine parents' power states iter = getParentIterator(gIOPowerPlane); @@ -837,12 +981,13 @@ IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags, } iter->release(); } - + if ( pm_vars->theControllingDriver == NULL ) { // we can't take any more action return IOPMAckImplied; } newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(combinedPowerFlags); - return enqueuePowerChange(IOPMParentInitiated | IOPMDomainWillChange, newStateNumber,combinedPowerFlags,whichParent); //make the change + return enqueuePowerChange(IOPMParentInitiated | IOPMDomainWillChange, + newStateNumber,combinedPowerFlags,whichParent,newPowerStateFlags); //make the change } @@ -858,16 +1003,40 @@ IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags, IOReturn IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags, IOPowerConnection * whichParent ) { - OSIterator * iter; - OSObject * next; - IOPowerConnection * connection; - unsigned long newStateNumber; + unsigned long newStateNumber; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDidChange,newPowerStateFlags,0); + setParentInfo(newPowerStateFlags,whichParent); + + if ( pm_vars->theControllingDriver == NULL ) { + return IOPMAckImplied; + } + + newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags); + return enqueuePowerChange(IOPMParentInitiated | IOPMDomainDidChange, + newStateNumber,pm_vars->parentsCurrentPowerFlags,whichParent,0); // tell interested parties about it +} + + +//********************************************************************************* +// setParentInfo +// +// Set our connection data for one specific parent, and then combine all the parent +// data together. +//********************************************************************************* + +void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags, IOPowerConnection * whichParent ) +{ + OSIterator * iter; + OSObject * next; + IOPowerConnection * connection; + whichParent->setParentCurrentPowerFlags(newPowerStateFlags); // set our connection data whichParent->setParentKnowsState(true); + IOLockLock(pm_vars->parentLock); + pm_vars->parentsCurrentPowerFlags = 0; // recompute our parent info pm_vars->parentsKnowState = true; @@ -882,24 +1051,21 @@ IOReturn IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags, } iter->release(); } - - if ( pm_vars->theControllingDriver == NULL ) { - return IOPMAckImplied; - } - - newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags); - return enqueuePowerChange(IOPMParentInitiated | IOPMDomainDidChange, newStateNumber,pm_vars->parentsCurrentPowerFlags,whichParent); // tell interested parties about it + IOLockUnlock(pm_vars->parentLock); } //********************************************************************************* // requestPowerDomainState // -// +// The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter. +// It is not considered part of the state specification. //********************************************************************************* IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPowerConnection * whichChild, unsigned long specification ) { unsigned long i; + unsigned long computedState; + unsigned long theDesiredState = desiredState & ~(kIOPMPreventIdleSleep | kIOPMPreventSystemSleep); OSIterator * iter; OSObject * next; IOPowerConnection * connection; @@ -915,7 +1081,7 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow case IOPMLowestState: i = 0; while ( i < pm_vars->theNumberOfPowerStates ) { - if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == (desiredState & pm_vars->myCharacterFlags) ) { + if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) ) { break; } i++; @@ -928,7 +1094,7 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow case IOPMNextLowerState: i = pm_vars->myCurrentState - 1; while ( i >= 0 ) { - if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == (desiredState & pm_vars->myCharacterFlags) ) { + if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) ) { break; } i--; @@ -942,7 +1108,7 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow i = pm_vars->theNumberOfPowerStates; while ( i >= 0 ) { i--; - if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == (desiredState & pm_vars->myCharacterFlags) ) { + if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) ) { break; } } @@ -954,7 +1120,7 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow case IOPMNextHigherState: i = pm_vars->myCurrentState + 1; while ( i < pm_vars->theNumberOfPowerStates ) { - if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == (desiredState & pm_vars->myCharacterFlags) ) { + if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) ) { break; } i++; @@ -968,9 +1134,20 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow return IOPMBadSpecification; } + computedState = i; + + IOLockLock(pm_vars->childLock); + +// A child's desires has changed. We need to rebuild the child-clamp bits in our +// power state array. Start by clearing the bits in each power state. + + for ( i = 0; i < pm_vars->theNumberOfPowerStates; i++ ) { + pm_vars->thePowerStates[i].capabilityFlags &= ~(kIOPMChildClamp | kIOPMChildClamp2); + } + // Now loop through the children. When we encounter the calling child, save -// the new state as this child's desire. Then, compute a new maximum -// of everybody's desires. +// the computed state as this child's desire. And while we're at it, set the ChildClamp bits +// in any of our states that some child has requested with clamp on. iter = getChildIterator(gIOPowerPlane); @@ -978,12 +1155,25 @@ IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPow while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { if ( connection == whichChild ) { - connection->setDesiredDomainState(i); + connection->setDesiredDomainState(computedState); + connection->setPreventIdleSleepFlag(desiredState & kIOPMPreventIdleSleep); + connection->setPreventSystemSleepFlag(desiredState & kIOPMPreventSystemSleep); + connection->setChildHasRequestedPower(); + } + if ( connection->getPreventIdleSleepFlag() ) { + pm_vars->thePowerStates[connection->getDesiredDomainState()].capabilityFlags |= kIOPMChildClamp; + } + if ( connection->getPreventSystemSleepFlag() ) { + pm_vars->thePowerStates[connection->getDesiredDomainState()].capabilityFlags |= kIOPMChildClamp2; } } } iter->release(); } + + IOLockUnlock(pm_vars->childLock); + + computeDesiredState(); // this may be different now if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) ) { @@ -1037,6 +1227,7 @@ IOReturn IOService::makeUsable ( void ) return IOPMNoErr; } priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1; + computeDesiredState(); if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) ) { return changeState(); } @@ -1076,6 +1267,7 @@ IOReturn IOService::changePowerStateTo ( unsigned long ordinal ) return IOPMParameterError; } priv->driverDesire = ordinal; + computeDesiredState(); if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) ) { return changeState(); } @@ -1102,6 +1294,7 @@ IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal ) return IOPMParameterError; } priv->deviceDesire = ordinal; + computeDesiredState(); if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) ) { return changeState(); } @@ -1111,14 +1304,11 @@ IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal ) //********************************************************************************* -// changeState +// computeDesiredState // -// A subclass object, our controlling driver, or a power domain child -// has asked for a different power state. Here we compute what new -// state we should enter and enqueue the change (or start it). //********************************************************************************* -IOReturn IOService::changeState ( void ) +void IOService::computeDesiredState ( void ) { OSIterator * iter; OSObject * next; @@ -1151,14 +1341,26 @@ IOReturn IOService::changeState ( void ) } priv->ourDesiredPowerState = newDesiredState; +} + +//********************************************************************************* +// changeState +// +// A subclass object, our controlling driver, or a power domain child +// has asked for a different power state. Here we compute what new +// state we should enter and enqueue the change (or start it). +//********************************************************************************* + +IOReturn IOService::changeState ( void ) +{ if ( (pm_vars->theControllingDriver == NULL) || // if not fully initialized ! (inPlane(gIOPowerPlane)) || ! (pm_vars->parentsKnowState) ) { return IOPMNoErr; // we can do no more } - return enqueuePowerChange(IOPMWeInitiated,newDesiredState,0,0); + return enqueuePowerChange(IOPMWeInitiated,priv->ourDesiredPowerState,0,0,0); } @@ -1170,11 +1372,12 @@ IOReturn IOService::changeState ( void ) unsigned long IOService::currentPowerConsumption ( void ) { if ( pm_vars->theControllingDriver == NULL ) { - return 0; + return kIOPMUnknown; } - else { + if ( pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags & kIOPMStaticPowerValid ) { return pm_vars->thePowerStates[pm_vars->myCurrentState].staticPower; } + return kIOPMUnknown; } //********************************************************************************* @@ -1194,7 +1397,7 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber=0 if ( type == kIOPMSuperclassPolicy1 ) { if ( (priv->activityLock == NULL) || (pm_vars->theControllingDriver == NULL) || - ( pm_vars->commandQueue == NULL) ) { + (pm_vars->commandQueue == NULL) ) { return true; } IOTakeLock(priv->activityLock); @@ -1208,7 +1411,7 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber=0 return true; } IOUnlock(priv->activityLock); // send a message on the command queue - pm_vars->commandQueue->enqueueCommand(true, (void *)kPMunIdleDevice, (void *)stateNumber); + pm_vars->commandQueue->enqueueCommand(true, (void *)kIOPMUnidleDevice, (void *)stateNumber); return false; } return true; @@ -1223,15 +1426,21 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber=0 IOWorkLoop * IOService::getPMworkloop ( void ) { -IOService * aParent; +IOService * nub; +IOService * parent; if ( ! inPlane(gIOPowerPlane) ) { return NULL; } if ( pm_vars->PMworkloop == NULL ) { // we have no workloop yet - aParent = (IOService *)getParentEntry(gIOPowerPlane)->getParentEntry(gIOPowerPlane); - if ( aParent != NULL ) { // ask one of our parents for the workloop - pm_vars->PMworkloop = aParent->getPMworkloop(); + nub = (IOService *)copyParentEntry(gIOPowerPlane); + if ( nub ) { + parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); + nub->release(); + if ( parent ) { // ask one of our parents for the workloop + pm_vars->PMworkloop = parent->getPMworkloop(); + parent->release(); + } } } return pm_vars->PMworkloop; @@ -1363,7 +1572,6 @@ void IOService::PM_idle_timer_expiration ( void ) } if ( pm_vars->myCurrentState > 0 ) { IOUnlock(priv->activityLock); - priv->askingFor = pm_vars->myCurrentState - 1; changePowerStateToPriv(pm_vars->myCurrentState - 1); start_PM_idle_timer(); return; @@ -1399,11 +1607,9 @@ void IOService::command_received ( void * command, void *stateNumber , void * , return; // we're unloading } - if ( command == (void *)kPMunIdleDevice ) { + if ( command == (void *)kIOPMUnidleDevice ) { if ( (pm_vars->myCurrentState < (unsigned long)stateNumber) && - (priv->imminentState < (unsigned long)stateNumber ) && - ((unsigned long)stateNumber > priv->askingFor) ) { - priv->askingFor = (unsigned long)stateNumber; + (priv->imminentState < (unsigned long)stateNumber) ) { changePowerStateToPriv((unsigned long)stateNumber); } } @@ -1419,9 +1625,10 @@ void IOService::command_received ( void * command, void *stateNumber , void * , IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel ) { - OSIterator * iter; - OSObject * next; + OSIterator * iter; + OSObject * next; IOPowerConnection * connection; + IOService * child; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetAggressiveness,type, newLevel); @@ -1435,7 +1642,11 @@ IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLev if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { - ((IOService *)(connection->getChildEntry(gIOPowerPlane)))->setAggressiveness(type, newLevel); + child = ((IOService *)(connection->copyChildEntry(gIOPowerPlane))); + if ( child ) { + child->setAggressiveness(type, newLevel); + child->release(); + } } } iter->release(); @@ -1467,9 +1678,10 @@ IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * curr IOReturn IOService::systemWake ( void ) { - OSIterator * iter; - OSObject * next; + OSIterator * iter; + OSObject * next; IOPowerConnection * connection; + IOService * theChild; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSystemWake,0, 0); @@ -1478,7 +1690,11 @@ IOReturn IOService::systemWake ( void ) if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { - ((IOService *)(connection->getChildEntry(gIOPowerPlane)))->systemWake(); + theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane); + if ( theChild ) { + theChild->systemWake(); + theChild->release(); + } } } iter->release(); @@ -1501,10 +1717,21 @@ IOReturn IOService::systemWake ( void ) IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone ) { + IOService * theParent; + IOService * theNub; + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCriticalTemp,0,0); if ( inPlane(gIOPowerPlane) && ! (priv->we_are_root) ) { - ((IOService *)(getParentEntry(gIOPowerPlane)->getParentEntry(gIOPowerPlane)))->temperatureCriticalForZone(whichZone); + theNub = (IOService *)copyParentEntry(gIOPowerPlane); + if ( theNub ) { + theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane); + theNub->release(); + if ( theParent ) { + theParent->temperatureCriticalForZone(whichZone); + theParent->release(); + } + } } return IOPMNoErr; } @@ -1521,6 +1748,7 @@ IOReturn IOService::powerOverrideOnPriv ( void ) pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOn,0,0); priv->device_overrides = true; // turn on the override + computeDesiredState(); return changeState(); // change state if that changed something } @@ -1534,7 +1762,11 @@ IOReturn IOService::powerOverrideOffPriv ( void ) pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOff,0,0); priv->device_overrides = false; // turn off the override - return changeState(); // change state if that changed something + computeDesiredState(); + if( priv->clampOn) + return makeUsable(); + else + return changeState(); // change state if that changed something } @@ -1554,15 +1786,17 @@ IOReturn IOService::powerOverrideOffPriv ( void ) // needn't perform the previous change, so we collapse the list a little. //********************************************************************************* -IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long whatStateOrdinal, unsigned long domainState, IOPowerConnection * whichParent ) +IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long whatStateOrdinal, unsigned long domainState, IOPowerConnection * whichParent, unsigned long singleParentState ) { long newNote; long previousNote; // Create and initialize the new change note + IOLockLock(priv->queue_lock); newNote = priv->changeList->createChangeNote(); if ( newNote == -1 ) { + IOLockUnlock(priv->queue_lock); pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogEnqueueErr,0,0); return IOPMAckImplied; // uh-oh, our list is full } @@ -1575,6 +1809,8 @@ IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long wha if (flags & IOPMParentInitiated ) { priv->changeList->changeNote[newNote].domainState = domainState; priv->changeList->changeNote[newNote].parent = whichParent; + whichParent->retain(); + priv->changeList->changeNote[newNote].singleParentState = singleParentState; } previousNote = priv->changeList->previousChangeNote(newNote); @@ -1584,10 +1820,12 @@ IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long wha // Queue is empty, we can start this change. if (flags & IOPMWeInitiated ) { + IOLockUnlock(priv->queue_lock); start_our_change(newNote); return 0; } else { + IOLockUnlock(priv->queue_lock); return start_parent_change(newNote); } } @@ -1603,16 +1841,17 @@ IOReturn IOService::enqueuePowerChange ( unsigned long flags, unsigned long wha priv->changeList->changeNote[previousNote].outputPowerCharacter = priv->changeList->changeNote[newNote].outputPowerCharacter; priv->changeList->changeNote[previousNote].inputPowerRequirement = priv->changeList->changeNote[newNote].inputPowerRequirement; priv->changeList->changeNote[previousNote].capabilityFlags =priv-> changeList->changeNote[newNote].capabilityFlags; + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCollapseQueue,priv->changeList->changeNote[newNote].newStateNumber, + priv->changeList->changeNote[previousNote].newStateNumber); priv->changeList->changeNote[previousNote].newStateNumber = priv->changeList->changeNote[newNote].newStateNumber; priv->changeList->releaseTailChangeNote(); newNote = previousNote; previousNote = priv->changeList->previousChangeNote(newNote); - pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCollapseQueue,0,0); } + IOLockUnlock(priv->queue_lock); return IOPMWillAckLater; // in any case, we can't start yet } - //********************************************************************************* // notifyAll // @@ -1637,7 +1876,6 @@ IOReturn IOService::notifyAll ( bool is_prechange ) // OK, we will go through the lists of interested drivers and power domain children // and notify each one of this change. - nextObject = priv->interestedDrivers->firstInList(); // notify interested drivers while ( nextObject != NULL ) { priv->head_note_pendingAcks +=1; @@ -1655,7 +1893,8 @@ IOReturn IOService::notifyAll ( bool is_prechange ) } IOUnlock(priv->our_lock); // either way - iter = getChildIterator(gIOPowerPlane); + iter = getChildIterator(gIOPowerPlane); // notify children + pm_vars->thePowerStates[priv->head_note_state].staticPower = 0; // summing their power consumption if ( iter ) { while ( (next = iter->getNextObject()) ) { @@ -1690,19 +1929,39 @@ IOReturn IOService::notifyAll ( bool is_prechange ) bool IOService::notifyChild ( IOPowerConnection * theNub, bool is_prechange ) { - IOReturn k = IOPMAckImplied; + IOReturn k = IOPMAckImplied; + unsigned long childPower; + IOService * theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane)); + theNub->setAwaitingAck(true); // in case they don't ack + + if ( ! theChild ) { + return true; + } + if ( is_prechange ) { - k =((IOService *)(theNub->getChildEntry(gIOPowerPlane)))->powerDomainWillChangeTo( priv->head_note_outputFlags,theNub); + k = theChild->powerDomainWillChangeTo(priv->head_note_outputFlags,theNub); } else { - k =((IOService *)(theNub->getChildEntry(gIOPowerPlane)))->powerDomainDidChangeTo( priv->head_note_outputFlags,theNub); + k = theChild->powerDomainDidChangeTo(priv->head_note_outputFlags,theNub); } - if ( k == IOPMAckImplied ) { // did the return code ack? - priv->head_note_pendingAcks -=1; // yes - return true; + if ( k == IOPMAckImplied ) { // did the return code ack? + priv->head_note_pendingAcks -=1; // yes + theNub->setAwaitingAck(false); + childPower = theChild->currentPowerConsumption(); + if ( childPower == kIOPMUnknown ) { + pm_vars->thePowerStates[priv->head_note_state].staticPower = kIOPMUnknown; + } + else { + if ( pm_vars->thePowerStates[priv->head_note_state].staticPower != kIOPMUnknown ) { + pm_vars->thePowerStates[priv->head_note_state].staticPower += childPower; + } + } + theChild->release(); + return true; } + theChild->release(); return false; } @@ -1731,7 +1990,6 @@ bool IOService::inform ( IOPMinformee * nextObject, bool is_prechange ) (unsigned long)priv->head_note_capabilityFlags,(unsigned long)priv->head_note_state); k = nextObject->whatObject->powerStateDidChangeTo(priv->head_note_capabilityFlags,priv->head_note_state,this); } - if ( nextObject->timer == 0 ) { // did it ack behind our back? return true; // yes } @@ -1760,9 +2018,27 @@ bool IOService::inform ( IOPMinformee * nextObject, bool is_prechange ) //********************************************************************************* void IOService::our_prechange_03 ( void ) +{ + priv->machine_state = IOPMour_prechange_04; // next state + if ( tellChangeDown1(priv->head_note_state) ) { // are we waiting for responses? + our_prechange_04(); // no, notify priority clients + } +} + + +//********************************************************************************* +// our_prechange_04 +// +// All registered applications and kernel clients have positively acknowledged our +// intention of lowering power. Here we notify "priority" clients that we are +// lowering power. If we don't have to wait for any of them to acknowledge, we +// carry on by notifying interested drivers. Otherwise, we do wait. +//********************************************************************************* + +void IOService::our_prechange_04 ( void ) { priv->machine_state = IOPMour_prechange_05; // next state - if ( tellChangeDown(priv->head_note_state) ) { // are we waiting for responses? + if ( tellChangeDown2(priv->head_note_state) ) { // are we waiting for responses? return our_prechange_05(); // no, notify interested drivers } } @@ -1869,12 +2145,31 @@ void IOService::our_prechange_4 ( void ) // // All applications and kernel clients have been notified of a power lowering // initiated by the parent and we didn't have to wait for any responses. Here +// we notify any priority clients. If they all ack, we continue with the power change. +// If at least one doesn't, we have to wait for it to acknowledge and then continue. +//********************************************************************************* + +IOReturn IOService::parent_down_0 ( void ) +{ + priv->machine_state = IOPMparent_down_05; // in case they don't all ack + if ( tellChangeDown2(priv->head_note_state) ) { // are we waiting for responses? + return parent_down_02(); // no, notify interested drivers + } + return IOPMWillAckLater; // they didn't +} + + +//********************************************************************************* +// parent_down_02 +// +// All priority kernel clients have been notified of a power lowering +// initiated by the parent and we didn't have to wait for any responses. Here // we notify any interested drivers and power domain children. If they all ack, // we continue with the power change. // If at least one doesn't, we have to wait for it to acknowledge and then continue. //********************************************************************************* -IOReturn IOService::parent_down_0 ( void ) +IOReturn IOService::parent_down_02 ( void ) { priv->machine_state = IOPMparent_down_4; // in case they don't all ack if ( notifyAll(true) == IOPMAckImplied ) { @@ -1884,6 +2179,24 @@ IOReturn IOService::parent_down_0 ( void ) } +//********************************************************************************* +// parent_down_04 +// +// All applications and kernel clients have been notified of a power lowering +// initiated by the parent and we had to wait for responses. Here +// we notify any priority clients. If they all ack, we continue with the power change. +// If at least one doesn't, we have to wait for it to acknowledge and then continue. +//********************************************************************************* + +void IOService::parent_down_04 ( void ) +{ + priv->machine_state = IOPMparent_down_05; // in case they don't all ack + if ( tellChangeDown2(priv->head_note_state) ) { // are we waiting for responses? + parent_down_05(); // no, notify interested drivers + } +} + + //********************************************************************************* // parent_down_05 // @@ -1963,11 +2276,15 @@ void IOService::parent_down_4 ( void ) IOReturn IOService::parent_down_2 ( void ) { + IOService * nub; + priv->settle_time = compute_settle_time(); if ( priv->settle_time == 0 ) { priv->machine_state = IOPMparent_down_6; // in case they don't all ack if ( notifyAll(false) == IOPMAckImplied ) { + nub = priv->head_note_parent; all_done(); + nub->release(); return IOPMAckImplied; } return IOPMWillAckLater; // they didn't @@ -2014,13 +2331,19 @@ void IOService::parent_down_5 ( void ) void IOService::parent_down_3 ( void ) { - IOService * parent; + IORegistryEntry * nub; + IOService * parent; priv->machine_state = IOPMparent_down_6; // in case they don't all ack if ( notifyAll(false) == IOPMAckImplied ) { - parent = priv->head_note_parent; + nub = priv->head_note_parent; all_done(); - ((IOService *)(parent->getParentEntry(gIOPowerPlane)))->acknowledgePowerChange(parent); + parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); + if ( parent ) { + parent->acknowledgePowerChange((IOService *)nub); + parent->release(); + } + nub->release(); } } @@ -2036,11 +2359,17 @@ void IOService::parent_down_3 ( void ) void IOService::parent_down_6 ( void ) { - IOService * parent; + IORegistryEntry * nub; + IOService * parent; - parent = priv->head_note_parent; + nub = priv->head_note_parent; all_done(); - ((IOService *)(parent->getParentEntry(gIOPowerPlane)))->acknowledgePowerChange(parent); + parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); + if ( parent ) { + parent->acknowledgePowerChange((IOService *)nub); + parent->release(); + } + nub->release(); } @@ -2153,9 +2482,13 @@ void IOService::parent_up_4 ( void ) IOReturn IOService::parent_up_3 ( void ) { + IOService * nub; + priv->machine_state = IOPMparent_up_6; // in case they don't all ack if ( notifyAll(false) == IOPMAckImplied ) { + nub = priv->head_note_parent; all_done(); + nub->release(); return IOPMAckImplied; } return IOPMWillAckLater; // they didn't @@ -2190,11 +2523,17 @@ void IOService::parent_up_5 ( void ) void IOService::parent_up_6 ( void ) { - IOService * parent; + IORegistryEntry * nub; + IOService * parent; - parent = priv->head_note_parent; + nub = priv->head_note_parent; all_done(); - ((IOService *)(parent->getParentEntry(gIOPowerPlane)))->acknowledgePowerChange(parent); + parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); + if ( parent ) { + parent->acknowledgePowerChange((IOService *)nub); + parent->release(); + } + nub->release(); } @@ -2207,7 +2546,11 @@ void IOService::parent_up_6 ( void ) //********************************************************************************* void IOService::all_done ( void ) -{ +{ + unsigned long previous_state; + IORegistryEntry * nub; + IOService * parent; + priv->machine_state = IOPMfinished; if ( priv->head_note_flags & IOPMWeInitiated ) { // our power change @@ -2220,9 +2563,11 @@ void IOService::all_done ( void ) ask_parent(priv->head_note_state); // power requirements, tell the parent } } + previous_state = pm_vars->myCurrentState; pm_vars->myCurrentState = priv->head_note_state; // either way + priv->imminentState = pm_vars->myCurrentState; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0); - powerChangeDone(pm_vars->myCurrentState); // inform subclass policy-maker + powerChangeDone(previous_state); // inform subclass policy-maker } // else { // no // pm_vars->myCurrentState = pm_vars->theControllingDriver->powerStateForDomainState(pm_vars->parentsCurrentPowerFlags); @@ -2234,28 +2579,38 @@ void IOService::all_done ( void ) if ( pm_vars->myCurrentState < priv->head_note_state ) { // did power raise? tellChangeUp (priv->head_note_state); // yes, inform clients and apps } - pm_vars->myCurrentState = priv->head_note_state; // either way + previous_state = pm_vars->myCurrentState; // either way + pm_vars->myCurrentState = priv->head_note_state; + priv->imminentState = pm_vars->myCurrentState; pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(priv->head_note_domainState); pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0); - powerChangeDone(pm_vars->myCurrentState); // inform subclass policy-maker + powerChangeDone(previous_state); // inform subclass policy-maker } } + IOLockLock(priv->queue_lock); priv->changeList->releaseHeadChangeNote(); // we're done with this - priv->head_note = priv->changeList->currentChange(); // start next one in queue + priv->head_note = priv->changeList->currentChange(); // start next one in queue if ( priv->head_note != -1 ) { + IOLockUnlock(priv->queue_lock); if (priv->changeList->changeNote[priv->head_note].flags & IOPMWeInitiated ) { start_our_change(priv->head_note); } else { + nub = priv->changeList->changeNote[priv->head_note].parent; if ( start_parent_change(priv->head_note) == IOPMAckImplied ) { - ((IOService *)(priv->head_note_parent->getParentEntry(gIOPowerPlane)))->acknowledgePowerChange(priv->head_note_parent); + parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); + if ( parent ) { + parent->acknowledgePowerChange((IOService *)nub); + parent->release(); + } } } } + IOLockUnlock(priv->queue_lock); } @@ -2450,6 +2805,18 @@ void IOService::ack_timer_ticked ( void ) break; case IOPMparent_down_0: // apps didn't respond to parent-down notification + IOUnlock(priv->our_lock); + IOLockLock(priv->flags_lock); + if (pm_vars->responseFlags) { + pm_vars->responseFlags->release(); // get rid of this stuff + pm_vars->responseFlags = NULL; + } + IOLockUnlock(priv->flags_lock); + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,5); + parent_down_04(); // carry on with the change + break; + + case IOPMparent_down_05: IOUnlock(priv->our_lock); IOLockLock(priv->flags_lock); if (pm_vars->responseFlags) { @@ -2475,6 +2842,18 @@ void IOService::ack_timer_ticked ( void ) all_done(); // and we're done break; + case IOPMour_prechange_04: // clients didn't respond to our power-down note + IOUnlock(priv->our_lock); + IOLockLock(priv->flags_lock); + if (pm_vars->responseFlags) { + pm_vars->responseFlags->release(); // get rid of this stuff + pm_vars->responseFlags = NULL; + } + IOLockUnlock(priv->flags_lock); + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,4); + our_prechange_04(); // carry on with the change + break; + case IOPMour_prechange_05: // apps didn't respond to our power-down notification IOUnlock(priv->our_lock); IOLockLock(priv->flags_lock); @@ -2670,6 +3049,7 @@ IOReturn IOService::start_parent_change ( unsigned long queue_head ) priv->head_note = queue_head; priv->head_note_flags = priv-> changeList->changeNote[priv->head_note].flags; priv->head_note_state = priv->changeList->changeNote[priv->head_note].newStateNumber; + priv->imminentState = priv->head_note_state; priv->head_note_outputFlags = priv->changeList->changeNote[priv->head_note].outputPowerCharacter; priv->head_note_domainState = priv->changeList->changeNote[priv->head_note].domainState; priv->head_note_parent = priv->changeList->changeNote[priv->head_note].parent; @@ -2681,10 +3061,11 @@ IOReturn IOService::start_parent_change ( unsigned long queue_head ) ask_parent( priv->ourDesiredPowerState); // if we need something and haven't told the parent, do so if ( priv->head_note_state < pm_vars->myCurrentState ) { // power domain is lowering + setParentInfo(priv->changeList->changeNote[priv->head_note].singleParentState,priv->head_note_parent); priv->initial_change = false; priv->machine_state = IOPMparent_down_0; // tell apps and kernel clients - if ( tellChangeDown(priv->head_note_state) ) { // are we waiting for responses? - return parent_down_0(); // no, notify interested drivers + if ( tellChangeDown1(priv->head_note_state) ) { // are we waiting for responses? + return parent_down_0(); // no, notify priority clients } return IOPMWillAckLater; // yes } @@ -2693,13 +3074,15 @@ IOReturn IOService::start_parent_change ( unsigned long queue_head ) if ( priv->ourDesiredPowerState > pm_vars->myCurrentState ) { if ( priv->ourDesiredPowerState < priv->head_note_state ) { priv->head_note_state = priv->ourDesiredPowerState; // we do, but not all the way + priv->imminentState = priv->head_note_state; priv->head_note_outputFlags = pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter; priv->head_note_capabilityFlags = pm_vars->thePowerStates[priv->head_note_state].capabilityFlags; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0); } } else { - priv-> head_note_state = pm_vars->myCurrentState; // we don't + priv->head_note_state = pm_vars->myCurrentState; // we don't + priv->imminentState = priv->head_note_state; priv->head_note_outputFlags = pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter; priv->head_note_capabilityFlags = pm_vars->thePowerStates[priv->head_note_state].capabilityFlags; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0); @@ -2743,6 +3126,7 @@ void IOService::start_our_change ( unsigned long queue_head ) priv->head_note = queue_head; priv->head_note_flags = priv->changeList->changeNote[priv->head_note].flags; priv->head_note_state = priv->changeList->changeNote[priv->head_note].newStateNumber; + priv->imminentState = priv->head_note_state; priv->head_note_outputFlags = priv->changeList->changeNote[priv->head_note].outputPowerCharacter; priv->head_note_capabilityFlags = priv->changeList->changeNote[priv->head_note].capabilityFlags; @@ -2810,26 +3194,40 @@ void IOService::start_our_change ( unsigned long queue_head ) IOReturn IOService::ask_parent ( unsigned long requestedState ) { - OSIterator * iter; - OSObject * next; + OSIterator * iter; + OSObject * next; IOPowerConnection * connection; + IOService * parent; + unsigned long ourRequest = pm_vars->thePowerStates[requestedState].inputPowerRequirement; - if ( priv->previousRequest == pm_vars->thePowerStates[requestedState].inputPowerRequirement ) { // is this a new desire? - return IOPMNoErr; // no, the parent knows already, just return + if ( pm_vars->thePowerStates[requestedState].capabilityFlags & (kIOPMChildClamp | kIOPMPreventIdleSleep) ) { + ourRequest |= kIOPMPreventIdleSleep; + } + if ( pm_vars->thePowerStates[requestedState].capabilityFlags & (kIOPMChildClamp2 | kIOPMPreventSystemSleep) ) { + ourRequest |= kIOPMPreventSystemSleep; + } + + if ( priv->previousRequest == ourRequest ) { // is this a new desire? + return IOPMNoErr; // no, the parent knows already, just return } if ( priv->we_are_root ) { return IOPMNoErr; } - priv->previousRequest = pm_vars->thePowerStates[requestedState].inputPowerRequirement; + priv->previousRequest = ourRequest; iter = getParentIterator(gIOPowerPlane); if ( iter ) { while ( (next = iter->getNextObject()) ) { if ( (connection = OSDynamicCast(IOPowerConnection,next)) ) { - if ( ((IOService *)(connection->getParentEntry(gIOPowerPlane)))->requestPowerDomainState( priv->previousRequest,connection,IOPMLowestState)!= IOPMNoErr ) { - pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDenied,(unsigned long)priv->previousRequest,0); + parent = (IOService *)connection->copyParentEntry(gIOPowerPlane); + if ( parent ) { + if ( parent->requestPowerDomainState(ourRequest,connection,IOPMLowestState)!= IOPMNoErr ) { + pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDenied, + (unsigned long)priv->previousRequest,0); + } + parent->release(); } } } @@ -2848,7 +3246,6 @@ IOReturn IOService::ask_parent ( unsigned long requestedState ) // we return IOPMAckImplied. Otherwise, it will ack when the change // is done; we return IOPMWillAckLater. //********************************************************************************* - IOReturn IOService::instruct_driver ( unsigned long newState ) { IOReturn return_code; @@ -2859,7 +3256,8 @@ IOReturn IOService::instruct_driver ( unsigned long newState ) priv->driver_timer = -1; pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogProgramHardware,newState,0); - return_code = pm_vars->theControllingDriver->setPowerState( newState,this ); // yes, instruct it + + return_code = pm_vars->theControllingDriver->setPowerState( newState,this ); // yes, instruct it if ( return_code == IOPMAckImplied ) { // it finished priv->driver_timer = 0; return IOPMAckImplied; @@ -2872,7 +3270,6 @@ IOReturn IOService::instruct_driver ( unsigned long newState ) if ( return_code < 0 ) { // somebody goofed return IOPMAckImplied; } - priv->driver_timer = (return_code * ns_per_us / ACK_TIMER_PERIOD) + 1; // it didn't finish return IOPMWillAckLater; } @@ -2922,12 +3319,43 @@ bool IOService::acquire_lock ( void ) // Return true if we don't have to wait for acknowledgements //********************************************************************************* -bool IOService::askChangeDown ( unsigned long ) +bool IOService::askChangeDown ( unsigned long stateNum ) { return tellClientsWithResponse(kIOMessageCanDevicePowerOff); } +//********************************************************************************* +// tellChangeDown1 +// +// Notify registered applications and kernel clients that we are definitely +// dropping power. +// +// Return true if we don't have to wait for acknowledgements +//********************************************************************************* + +bool IOService::tellChangeDown1 ( unsigned long stateNum ) +{ + pm_vars->outofbandparameter = kNotifyApps; + return tellChangeDown(stateNum); +} + + +//********************************************************************************* +// tellChangeDown2 +// +// Notify priority clients that we are definitely dropping power. +// +// Return true if we don't have to wait for acknowledgements +//********************************************************************************* + +bool IOService::tellChangeDown2 ( unsigned long stateNum ) +{ + pm_vars->outofbandparameter = kNotifyPriority; + return tellChangeDown(stateNum); +} + + //********************************************************************************* // tellChangeDown // @@ -2940,7 +3368,7 @@ bool IOService::askChangeDown ( unsigned long ) // Return true if we don't have to wait for acknowledgements //********************************************************************************* -bool IOService::tellChangeDown ( unsigned long ) +bool IOService::tellChangeDown ( unsigned long stateNum ) { return tellClientsWithResponse(kIOMessageDeviceWillPowerOff); } @@ -2971,15 +3399,24 @@ bool IOService::tellClientsWithResponse ( int messageType ) theContext.msgType = messageType; theContext.us = this; theContext.maxTimeRequested = 0; - + theContext.stateNumber = priv->head_note_state; + theContext.stateFlags = priv->head_note_capabilityFlags; + IOLockLock(priv->flags_lock); aBool = OSBoolean::withBoolean(false); // position zero is false to theContext.responseFlags->setObject(0,aBool); // prevent allowCancelCommon from succeeding aBool->release(); IOLockUnlock(priv->flags_lock); - applyToInterested(gIOAppPowerStateInterest,tellAppWithResponse,(void *)&theContext); - applyToInterested(gIOGeneralInterest,tellClientWithResponse,(void *)&theContext); + switch ( pm_vars->outofbandparameter ) { + case kNotifyApps: + applyToInterested(gIOAppPowerStateInterest,tellAppWithResponse,(void *)&theContext); + applyToInterested(gIOGeneralInterest,tellClientWithResponse,(void *)&theContext); + break; + case kNotifyPriority: + applyToInterested(gIOPriorityPowerStateInterest,tellClientWithResponse,(void *)&theContext); + break; + } if (! acquire_lock() ) { return true; @@ -3037,8 +3474,8 @@ void tellAppWithResponse ( OSObject * object, void * context) aBool->release(); IOLockUnlock(theContext->flags_lock); theContext->us->messageClient(theContext->msgType,object,(void *)refcon); - if ( theContext->maxTimeRequested < k15seconds ) { - theContext->maxTimeRequested = k15seconds; + if ( theContext->maxTimeRequested < k30seconds ) { + theContext->maxTimeRequested = k30seconds; } } theContext->counter += 1; @@ -3057,12 +3494,12 @@ void tellAppWithResponse ( OSObject * object, void * context) //********************************************************************************* void tellClientWithResponse ( OSObject * object, void * context) { - struct context * theContext = (struct context *)context; - sleepWakeNote paramBlock; - UInt32 refcon; - IOReturn retCode; - OSBoolean * aBool; - OSObject * theFlag; + struct context * theContext = (struct context *)context; + IOPowerStateChangeNotification notify; + UInt32 refcon; + IOReturn retCode; + OSBoolean * aBool; + OSObject * theFlag; refcon = ((theContext->serialNumber & 0xFFFF)<<16) + (theContext->counter & 0xFFFF); IOLockLock(theContext->flags_lock); @@ -3070,11 +3507,14 @@ void tellClientWithResponse ( OSObject * object, void * context) theContext->responseFlags->setObject(theContext->counter,aBool); aBool->release(); IOLockUnlock(theContext->flags_lock); - paramBlock.powerRef = (void *)refcon; - paramBlock.returnValue = 0; - retCode = theContext->us->messageClient(theContext->msgType,object,(void *)¶mBlock); + + notify.powerRef = (void *)refcon; + notify.returnValue = 0; + notify.stateNumber = theContext->stateNumber; + notify.stateFlags = theContext->stateFlags; + retCode = theContext->us->messageClient(theContext->msgType,object,(void *)¬ify); if ( retCode == kIOReturnSuccess ) { - if ( paramBlock.returnValue == 0 ) { // client doesn't want time to respond + if ( notify.returnValue == 0 ) { // client doesn't want time to respond IOLockLock(theContext->flags_lock); aBool = OSBoolean::withBoolean(true); theContext->responseFlags->replaceObject(theContext->counter,aBool); // so set its flag true @@ -3086,8 +3526,8 @@ void tellClientWithResponse ( OSObject * object, void * context) theFlag = theContext->responseFlags->getObject(theContext->counter); // it does want time, and it hasn't if ( theFlag != 0 ) { // responded yet if ( ((OSBoolean *)theFlag)->isFalse() ) { // so note its time requirement - if ( theContext->maxTimeRequested < paramBlock.returnValue ) { - theContext->maxTimeRequested = paramBlock.returnValue; + if ( theContext->maxTimeRequested < notify.returnValue ) { + theContext->maxTimeRequested = notify.returnValue; } } } @@ -3148,6 +3588,8 @@ void IOService::tellClients ( int messageType ) theContext.msgType = messageType; theContext.us = this; + theContext.stateNumber = priv->head_note_state; + theContext.stateFlags = priv->head_note_capabilityFlags; applyToInterested(gIOAppPowerStateInterest,tellClient,(void *)&theContext); applyToInterested(gIOGeneralInterest,tellClient,(void *)&theContext); @@ -3161,9 +3603,15 @@ void IOService::tellClients ( int messageType ) //********************************************************************************* void tellClient ( OSObject * object, void * context) { - struct context * theContext = (struct context *)context; + struct context * theContext = (struct context *)context; + IOPowerStateChangeNotification notify; - theContext->us->messageClient(theContext->msgType,object,0); + notify.powerRef = (void *) 0; + notify.returnValue = 0; + notify.stateNumber = theContext->stateNumber; + notify.stateFlags = theContext->stateFlags; + + theContext->us->messageClient(theContext->msgType,object, ¬ify); } @@ -3345,14 +3793,19 @@ IOReturn IOService::allowCancelCommon ( void ) all_done(); // and we're done } break; + case IOPMour_prechange_04: + our_prechange_04(); + break; case IOPMour_prechange_05: our_prechange_05(); // our change, continue break; case IOPMparent_down_0: - parent_down_05(); // parent change, continueq8q + parent_down_04(); // parent change, continue + break; + case IOPMparent_down_05: + parent_down_05(); // parent change, continue break; } - return kIOReturnSuccess; } IOUnlock(priv->our_lock); // not done yet @@ -3384,7 +3837,7 @@ void IOService::clampPowerOn (unsigned long duration) } } - priv->clampTimerEventSrc->setTimeout(kFiveMinutesInNanoSeconds, NSEC_PER_SEC); + priv->clampTimerEventSrc->setTimeout(kFiveMinutesInNanoSeconds, NSEC_PER_SEC); } //********************************************************************************* @@ -3443,7 +3896,7 @@ unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainStat return 0; } for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) { - if ( pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) { + if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement ) { return i; } } @@ -3467,7 +3920,7 @@ unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domain return 0; } for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) { - if ( pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) { + if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement ) { return i; } } @@ -3491,7 +3944,7 @@ unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState ) return 0; } for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) { - if ( pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) { + if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement ) { return i; } } diff --git a/iokit/Kernel/IOServicePrivate.h b/iokit/Kernel/IOServicePrivate.h index 6ff2870a3..3f0f8b505 100644 --- a/iokit/Kernel/IOServicePrivate.h +++ b/iokit/Kernel/IOServicePrivate.h @@ -39,9 +39,15 @@ enum { enum { kIOServiceBusyStateMask = 0x000000ff, kIOServiceBusyMax = 255, - kIOServiceTerminatedState = 0x80000000, - kIOServiceConfigState = 0x40000000, - kIOServiceSynchronousState = 0x20000000, + kIOServiceNeedConfigState = 0x80000000, + kIOServiceSynchronousState = 0x40000000, + kIOServiceModuleStallState = 0x20000000, + kIOServiceBusyWaiterState = 0x10000000, + + kIOServiceSyncPubState = 0x08000000, + kIOServiceConfigState = 0x04000000, + kIOServiceTermPhase2State = 0x01000000, + kIOServiceTermPhase3State = 0x00800000, }; // options for terminate() @@ -49,11 +55,10 @@ enum { kIOServiceRecursing = 0x00100000, }; - // notify state enum { - kIOServiceNotifyEnable = 0x00000001, - kIOServiceNotifyWaiter = 0x00000002 + kIOServiceNotifyEnable = 0x00000001, + kIOServiceNotifyWaiter = 0x00000002 }; struct _IOServiceNotifierInvocation @@ -133,7 +138,6 @@ enum { enum { kMatchNubJob = 10, - kTerminateNubJob, }; class _IOServiceJob : public OSObject diff --git a/iokit/Kernel/IOStartIOKit.cpp b/iokit/Kernel/IOStartIOKit.cpp index 23268cd62..ba2387f42 100644 --- a/iokit/Kernel/IOStartIOKit.cpp +++ b/iokit/Kernel/IOStartIOKit.cpp @@ -36,8 +36,6 @@ #include <IOKit/IOLib.h> #include <IOKit/IOKitKeys.h> #include <IOKit/IOKitDebug.h> -#include <IOKit/network/IONetworkController.h> -#include <IOKit/graphics/IODisplay.h> #include <IOKit/assert.h> @@ -48,6 +46,45 @@ extern void IOLibInit(void); #include <kern/clock.h> +/*XXX power management hacks XXX*/ +#include <IOKit/IOReturn.h> +#include <IOKit/IOMessage.h> + +extern void *registerSleepWakeInterest( + void *callback, + void *target, + void *refCon); +/*XXX power management hacks XXX*/ + +static void +calend_wakeup_resynch( + thread_call_param_t p0, + thread_call_param_t p1) +{ + void IOKitResetTime(void); + + IOKitResetTime(); +} + +static thread_call_t calend_sleep_wake_call; + +static IOReturn +calend_sleep_wake_notif( + void *target, + void *refCon, + unsigned int messageType, + void *provider, + void *messageArg, + vm_size_t argSize) +{ + if (messageType != kIOMessageSystemHasPoweredOn) + return (kIOReturnUnsupported); + + if (calend_sleep_wake_call != NULL) + thread_call_enter(calend_sleep_wake_call); + + return (kIOReturnSuccess); +} void IOKitResetTime( void ) { @@ -62,6 +99,13 @@ void IOKitResetTime( void ) IOService::resourceMatching("IONVRAM"), &t ); #endif + if (calend_sleep_wake_call == NULL) { + calend_sleep_wake_call = thread_call_allocate( + calend_wakeup_resynch, NULL); + + registerSleepWakeInterest(calend_sleep_wake_notif, NULL, NULL); + } + clock_initialize_calendar(); } @@ -143,8 +187,6 @@ void StartIOKit( void * p1, void * p2, void * p3, void * p4 ) IOCatalogue::initialize(); IOUserClient::initialize(); IOMemoryDescriptor::initialize(); - IONetworkController::initialize(); - IODisplay::initialize(); obj = OSString::withCString( iokit_version ); assert( obj ); @@ -158,11 +200,6 @@ void StartIOKit( void * p1, void * p2, void * p3, void * p4 ) obj->release(); } -#ifdef i386 - // pretend there's no device-tree for intel - p1 = 0; -#endif - rootNub = new IOPlatformExpertDevice; if( rootNub && rootNub->initWithArgs( p1, p2, p3, p4)) { diff --git a/iokit/Kernel/IOStringFuncs.c b/iokit/Kernel/IOStringFuncs.c index 8fe5ddec5..0e20f8c50 100644 --- a/iokit/Kernel/IOStringFuncs.c +++ b/iokit/Kernel/IOStringFuncs.c @@ -70,6 +70,7 @@ #include <stdlib.h> #include <limits.h> */ +#include <sys/types.h> #include <stddef.h> #include <machine/limits.h> @@ -257,6 +258,172 @@ strtoul(nptr, endptr, base) return (acc); } +/* + * Convert a string to a quad integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +quad_t +strtoq(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s; + register u_quad_t acc; + register int c; + register u_quad_t qbase, cutoff; + register int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + qbase = (unsigned)base; + cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; + cutlim = cutoff % qbase; + cutoff /= qbase; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= qbase; + acc += c; + } + } + if (any < 0) { + acc = neg ? QUAD_MIN : QUAD_MAX; +// errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + + +/* + * Convert a string to an unsigned quad integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +u_quad_t +strtouq(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; +{ + register const char *s = nptr; + register u_quad_t acc; + register int c; + register u_quad_t qbase, cutoff; + register int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + qbase = (unsigned)base; + cutoff = (u_quad_t)UQUAD_MAX / qbase; + cutlim = (u_quad_t)UQUAD_MAX % qbase; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= qbase; + acc += c; + } + } + if (any < 0) { + acc = UQUAD_MAX; +// errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + + /* * */ diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index 83e846bca..acdfedc89 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -802,47 +802,6 @@ IOReturn IOUserClient::sendAsyncResult(OSAsyncReference reference, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include <IOKit/pci/IOPCIDevice.h> - -static void makeMatchingCompatible( OSDictionary * dict ) -{ - const char * key; - const char * newKey; - OSObject * value; - OSString * str; - int i = 0; - - static const char * gratuitousNameChanges[] = { - "IOImports", kIOProviderClassKey, - "IOClass Names", kIOClassKey, - "IOProbe Score", kIOProbeScoreKey, - "IOKit Debug", kIOKitDebugKey, - "IONeededResources", kIOResourceMatchKey, - "IOName Match", kIONameMatchKey, - "IOPCI Match", kIOPCIMatchKey, - "IOPCI Primary Match", kIOPCIPrimaryMatchKey, - "IOPCI Secondary Match",kIOPCISecondaryMatchKey, - "IOPCI Class Match", kIOPCIClassMatchKey, - 0 - }; - - while( (key = gratuitousNameChanges[i++])) { - newKey = gratuitousNameChanges[i++]; - if( (value = dict->getObject( key)) - && (0 == dict->getObject( newKey))) { - - dict->setObject( newKey, value); - dict->removeObject( key); - - if( (str = OSDynamicCast(OSString, dict->getObject("CFBundleIdentifier")))) - IOLog("kext \"%s\" ", str->getCStringNoCopy()); - IOLog("must change \"%s\" to \"%s\"\n", key, newKey); - } - } -} - -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - extern "C" { #define CHECK(cls,obj,out) \ @@ -970,7 +929,6 @@ kern_return_t is_io_service_get_matching_services( obj = OSUnserializeXML( matching ); if( (dict = OSDynamicCast( OSDictionary, obj))) { - makeMatchingCompatible( dict ); // temp for binary compatibility *existing = IOService::getMatchingServices( dict ); kr = kIOReturnSuccess; } else @@ -1015,7 +973,6 @@ kern_return_t is_io_service_add_notification( err = kIOReturnBadArgument; continue; } - makeMatchingCompatible( dict ); // temp for binary compatibility if( (sym == gIOPublishNotification) || (sym == gIOFirstPublishNotification)) @@ -1277,17 +1234,45 @@ kern_return_t is_io_registry_entry_get_name( /* Routine io_registry_entry_get_name_in_plane */ kern_return_t is_io_registry_entry_get_name_in_plane( io_object_t registry_entry, - io_name_t plane, + io_name_t planeName, io_name_t name ) { + const IORegistryPlane * plane; CHECK( IORegistryEntry, registry_entry, entry ); - strncpy( name, entry->getName( IORegistryEntry::getPlane( plane )), - sizeof( io_name_t)); + if( planeName[0]) + plane = IORegistryEntry::getPlane( planeName ); + else + plane = 0; + + strncpy( name, entry->getName( plane), sizeof( io_name_t)); return( kIOReturnSuccess ); } +/* Routine io_registry_entry_get_location_in_plane */ +kern_return_t is_io_registry_entry_get_location_in_plane( + io_object_t registry_entry, + io_name_t planeName, + io_name_t location ) +{ + const IORegistryPlane * plane; + CHECK( IORegistryEntry, registry_entry, entry ); + + if( planeName[0]) + plane = IORegistryEntry::getPlane( planeName ); + else + plane = 0; + + const char * cstr = entry->getLocation( plane ); + + if( cstr) { + strncpy( location, cstr, sizeof( io_name_t)); + return( kIOReturnSuccess ); + } else + return( kIOReturnNotFound ); +} + // Create a vm_map_copy_t or kalloc'ed data for memory // to be copied out. ipc will free after the copyout. @@ -1297,15 +1282,178 @@ static kern_return_t copyoutkdata( void * data, vm_size_t len, kern_return_t err; vm_map_copy_t copy; - err = vm_map_copyin( kernel_map, (vm_offset_t) data, len, - false /* src_destroy */, ©); + err = vm_map_copyin( kernel_map, (vm_offset_t) data, len, + false /* src_destroy */, ©); + + assert( err == KERN_SUCCESS ); + if( err == KERN_SUCCESS ) + *buf = (char *) copy; + + return( err ); +} + +/* Routine io_registry_entry_get_property */ +kern_return_t is_io_registry_entry_get_property_bytes( + io_object_t registry_entry, + io_name_t property_name, + io_scalar_inband_t buf, + mach_msg_type_number_t *dataCnt ) +{ + OSObject * obj; + OSData * data; + OSString * str; + OSBoolean * boo; + OSNumber * off; + UInt64 offsetBytes; + unsigned int len = 0; + const void * bytes = 0; + IOReturn ret = kIOReturnSuccess; + + CHECK( IORegistryEntry, registry_entry, entry ); + +#if 0 + // need virtual + obj = entry->copyProperty(property_name); +#else + obj = entry->getProperty(property_name); + if( obj) + obj->retain(); +#endif + if( !obj) + return( kIOReturnNoResources ); + + // One day OSData will be a common container base class + // until then... + if( (data = OSDynamicCast( OSData, obj ))) { + len = data->getLength(); + bytes = data->getBytesNoCopy(); + + } else if( (str = OSDynamicCast( OSString, obj ))) { + len = str->getLength() + 1; + bytes = str->getCStringNoCopy(); + + } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { + len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); + bytes = boo->isTrue() ? "Yes" : "No"; + + } else if( (off = OSDynamicCast( OSNumber, obj ))) { + offsetBytes = off->unsigned64BitValue(); + len = off->numberOfBytes(); + bytes = &offsetBytes; +#if __BIG_ENDIAN__ + bytes = (const void *) + (((UInt32) bytes) + (sizeof( UInt64) - len)); +#endif + + } else + ret = kIOReturnBadArgument; + + if( bytes) { + if( *dataCnt < len) + ret = kIOReturnIPCError; + else { + *dataCnt = len; + bcopy( bytes, buf, len ); + } + } + obj->release(); + + return( ret ); +} + +/* Routine io_registry_entry_get_property */ +kern_return_t is_io_registry_entry_get_property( + io_object_t registry_entry, + io_name_t property_name, + io_buf_ptr_t *properties, + mach_msg_type_number_t *propertiesCnt ) +{ + kern_return_t err; + vm_size_t len; + OSObject * obj; + + CHECK( IORegistryEntry, registry_entry, entry ); + +#if 0 + // need virtual + obj = entry->copyProperty(property_name); +#else + obj = entry->getProperty(property_name); + if( obj) + obj->retain(); +#endif + if( !obj) + return( kIOReturnNotFound ); + + OSSerialize * s = OSSerialize::withCapacity(4096); + if( !s) { + obj->release(); + return( kIOReturnNoMemory ); + } + s->clearText(); + + if( obj->serialize( s )) { + len = s->getLength(); + *propertiesCnt = len; + err = copyoutkdata( s->text(), len, properties ); + + } else + err = kIOReturnUnsupported; + + s->release(); + obj->release(); - assert( err == KERN_SUCCESS ); - if( err == KERN_SUCCESS ) - *buf = (char *) copy; return( err ); } +/* Routine io_registry_entry_get_property_recursively */ +kern_return_t is_io_registry_entry_get_property_recursively( + io_object_t registry_entry, + io_name_t plane, + io_name_t property_name, + int options, + io_buf_ptr_t *properties, + mach_msg_type_number_t *propertiesCnt ) +{ + kern_return_t err; + vm_size_t len; + OSObject * obj; + + CHECK( IORegistryEntry, registry_entry, entry ); + +#if 0 + obj = entry->copyProperty( property_name, + IORegistryEntry::getPlane( plane ), options); +#else + obj = entry->getProperty( property_name, + IORegistryEntry::getPlane( plane ), options); + if( obj) + obj->retain(); +#endif + if( !obj) + return( kIOReturnNotFound ); + + OSSerialize * s = OSSerialize::withCapacity(4096); + if( !s) { + obj->release(); + return( kIOReturnNoMemory ); + } + + s->clearText(); + + if( obj->serialize( s )) { + len = s->getLength(); + *propertiesCnt = len; + err = copyoutkdata( s->text(), len, properties ); + + } else + err = kIOReturnUnsupported; + + s->release(); + obj->release(); + + return( err ); +} /* Routine io_registry_entry_get_properties */ kern_return_t is_io_registry_entry_get_properties( @@ -1319,7 +1467,6 @@ kern_return_t is_io_registry_entry_get_properties( CHECK( IORegistryEntry, registry_entry, entry ); OSSerialize * s = OSSerialize::withCapacity(4096); - if( !s) return( kIOReturnNoMemory ); @@ -1333,7 +1480,7 @@ kern_return_t is_io_registry_entry_get_properties( } else err = kIOReturnUnsupported; - s->release(); + s->release(); return( err ); } @@ -1373,69 +1520,6 @@ kern_return_t is_io_registry_entry_set_properties return( err ); } - -/* Routine io_registry_entry_get_property */ -kern_return_t is_io_registry_entry_get_property( - io_object_t registry_entry, - io_name_t property_name, - io_scalar_inband_t buf, - mach_msg_type_number_t *dataCnt ) -{ - OSObject * obj; - OSData * data; - OSString * str; - OSBoolean * boo; - OSNumber * off; - UInt64 offsetBytes; - unsigned int len = 0; - const void * bytes = 0; - IOReturn ret = kIOReturnSuccess; - - CHECK( IORegistryEntry, registry_entry, entry ); - - obj = entry->getProperty( property_name ); - if( !obj) - return( kIOReturnNoResources ); - - // One day OSData will be a common container base class - // until then... - if( (data = OSDynamicCast( OSData, obj ))) { - len = data->getLength(); - bytes = data->getBytesNoCopy(); - - } else if( (str = OSDynamicCast( OSString, obj ))) { - len = str->getLength() + 1; - bytes = str->getCStringNoCopy(); - - } else if( (boo = OSDynamicCast( OSBoolean, obj ))) { - len = boo->isTrue() ? sizeof("Yes") : sizeof("No"); - bytes = boo->isTrue() ? "Yes" : "No"; - - } else if( (off = OSDynamicCast( OSNumber, obj ))) { - offsetBytes = off->unsigned64BitValue(); - len = off->numberOfBytes(); - bytes = &offsetBytes; -#if __BIG_ENDIAN__ - bytes = (const void *) - (((UInt32) bytes) + (sizeof( UInt64) - len)); -#endif - - } else - ret = kIOReturnBadArgument; - - if( bytes) { - if( *dataCnt < len) - ret = kIOReturnIPCError; - else { - *dataCnt = len; - bcopy( bytes, buf, len ); - } - } - - return( ret ); -} - - /* Routine io_registry_entry_get_child_iterator */ kern_return_t is_io_registry_entry_get_child_iterator( io_object_t registry_entry, @@ -1633,8 +1717,8 @@ kern_return_t is_io_connect_unmap_memory( IOLockLock( gIOObjectPortLock); if( client->mappings) client->mappings->removeObject( map); - IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT ); IOLockUnlock( gIOObjectPortLock); + IOMachPort::releasePortForObject( map, IKOT_IOKIT_OBJECT ); map->release(); } else err = kIOReturnBadArgument; @@ -2337,12 +2421,6 @@ kern_return_t is_io_catalog_send_data( array = OSDynamicCast(OSArray, obj); if ( array ) { -//-- - OSDictionary * dict; - int i = 0; - while( (dict = OSDynamicCast(OSDictionary, array->getObject(i++)))) - makeMatchingCompatible( dict ); -//-- if ( !gIOCatalogue->addDrivers( array , flag == kIOCatalogAddDrivers) ) { kr = kIOReturnError; @@ -2360,7 +2438,6 @@ kern_return_t is_io_catalog_send_data( dict = OSDynamicCast(OSDictionary, obj); if ( dict ) { - makeMatchingCompatible( dict ); if ( !gIOCatalogue->removeDrivers( dict, flag == kIOCatalogRemoveDrivers ) ) { kr = kIOReturnError; @@ -2377,7 +2454,6 @@ kern_return_t is_io_catalog_send_data( dict = OSDynamicCast(OSDictionary, obj); if ( dict ) { - makeMatchingCompatible( dict ); if ( !gIOCatalogue->startMatching( dict ) ) { kr = kIOReturnError; } @@ -2568,31 +2644,34 @@ kern_return_t is_io_catalog_reset( return kIOReturnSuccess; } -kern_return_t iokit_user_client_trap(io_object_t userClientRef, UInt32 index, void *p1, void *p2, void *p3, void *p4, void *p5, void *p6) +kern_return_t iokit_user_client_trap(io_object_t userClientRef, UInt32 index, + void *p1, void *p2, void *p3, + void *p4, void *p5, void *p6) { - kern_return_t result = kIOReturnBadArgument; - IOUserClient *userClient; + kern_return_t result = kIOReturnBadArgument; + IOUserClient *userClient; - if ((userClient = OSDynamicCast(IOUserClient, iokit_lookup_connect_ref_current_task(userClientRef)))) { - IOExternalTrap *trap; - IOService *target = NULL; + if ((userClient = OSDynamicCast(IOUserClient, + iokit_lookup_connect_ref_current_task(userClientRef)))) { + IOExternalTrap *trap; + IOService *target = NULL; - trap = userClient->getTargetAndTrapForIndex(&target, index); + trap = userClient->getTargetAndTrapForIndex(&target, index); - if (trap && target) { - IOTrap func; + if (trap && target) { + IOTrap func; - func = trap->func; + func = trap->func; - if (func) { - result = (target->*func)(p1, p2, p3, p4, p5, p6); - } - } + if (func) { + result = (target->*func)(p1, p2, p3, p4, p5, p6); + } + } - userClient->release(); - } + userClient->release(); + } - return result; + return result; } }; /* extern "C" */ diff --git a/iokit/Kernel/IOWorkLoop.cpp b/iokit/Kernel/IOWorkLoop.cpp index 99205ee24..1581f38ca 100644 --- a/iokit/Kernel/IOWorkLoop.cpp +++ b/iokit/Kernel/IOWorkLoop.cpp @@ -37,7 +37,8 @@ HISTORY OSDefineMetaClassAndStructors(IOWorkLoop, OSObject); // Block of unused functions intended for future use -OSMetaClassDefineReservedUnused(IOWorkLoop, 0); +OSMetaClassDefineReservedUsed(IOWorkLoop, 0); + OSMetaClassDefineReservedUnused(IOWorkLoop, 1); OSMetaClassDefineReservedUnused(IOWorkLoop, 2); OSMetaClassDefineReservedUnused(IOWorkLoop, 3); @@ -374,6 +375,20 @@ void IOWorkLoop::wakeupGate(void *event, bool oneThread) IORecursiveLockWakeup(gateLock, event, oneThread); } +IOReturn IOWorkLoop::runAction(Action inAction, OSObject *target, + void *arg0 = 0, void *arg1 = 0, + void *arg2 = 0, void *arg3 = 0) +{ + IOReturn res; + + // closeGate is recursive so don't worry if we already hold the lock. + closeGate(); + res = (*inAction)(target, arg0, arg1, arg2, arg3); + openGate(); + + return res; +} + IOReturn IOWorkLoop::_maintRequest(void *inC, void *inD, void *, void *) { maintCommandEnum command = (maintCommandEnum) (vm_address_t) inC; diff --git a/iokit/KernelConfigTables.cpp b/iokit/KernelConfigTables.cpp index c3ff58157..e82a7f617 100644 --- a/iokit/KernelConfigTables.cpp +++ b/iokit/KernelConfigTables.cpp @@ -28,21 +28,13 @@ */ const char * gIOKernelKmods = "{ - 'com.apple.kernel' = '1.3.7'; - 'com.apple.kernel.bsd' = '1.0.7'; - 'com.apple.kernel.iokit' = '1.0.7'; - 'com.apple.kernel.libkern' = '1.0.7'; - 'com.apple.kernel.mach' = '1.0.7'; - 'com.apple.iokit.IOADBFamily' = '1.0.7'; - 'com.apple.iokit.IOCDStorageFamily' = '1.0.7'; - 'com.apple.iokit.IODVDStorageFamily' = '1.0.7'; - 'com.apple.iokit.IOGraphicsFamily' = '1.0.7'; - 'com.apple.iokit.IOHIDSystem' = '1.0.7'; - 'com.apple.iokit.IONDRVSupport' = '1.0.7'; - 'com.apple.iokit.IONetworkingFamily' = '1.0.7'; - 'com.apple.iokit.IOPCIFamily' = '1.0.7'; - 'com.apple.iokit.IOStorageFamily' = '1.0.7'; - 'com.apple.iokit.IOSystemManagementFamily' = '1.0.7'; + 'com.apple.kernel' = '1.4'; + 'com.apple.kernel.bsd' = '1.1'; + 'com.apple.kernel.iokit' = '1.1'; + 'com.apple.kernel.libkern' = '1.1'; + 'com.apple.kernel.mach' = '1.1'; + 'com.apple.iokit.IOADBFamily' = '1.1'; + 'com.apple.iokit.IOSystemManagementFamily' = '1.1'; }"; @@ -52,301 +44,6 @@ const char * gIOKernelConfigTables = 'IOClass' = IOPanicPlatform; 'IOProviderClass' = IOPlatformExpertDevice; 'IOProbeScore' = '-1'; - }, - { - 'IOClass' = IOHIDSystem; - 'IOProviderClass' = IOResources; - 'IOResourceMatch' = IOKit; - 'IOMatchCategory' = IOHID; - }, - { - 'IOClass' = IOBSDConsole; - 'IOProviderClass' = IOResources; - 'IOResourceMatch' = IOBSD; - 'IOMatchCategory' = IOBSDConsole; - }, - { - 'IOClass' = IODisplayWrangler; - 'IOProviderClass' = IOResources; - 'IOResourceMatch' = IOKit; - 'IOMatchCategory' = IOGraphics; - }, - { - 'IOClass' = IOApplePartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 2000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Whole' = .true.; - }; - 'Content Mask' = 'Apple_partition_scheme'; - }, - { - 'IOClass' = IOApplePartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 2000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Content Hint' = 'CD_ROM_Mode_1'; - }; - 'Content Mask' = 'Apple_partition_scheme'; - }, - { - 'IOClass' = IOApplePartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 2000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Content Hint' = 'CD_ROM_Mode_2_Form_1'; - }; - 'Content Mask' = 'Apple_partition_scheme'; - }, - { - 'IOClass' = IONeXTPartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 1000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Whole' = .true.; - }; - 'Content Mask' = 'NeXT_partition_scheme'; - 'Content Table' = - { - '4.4BSD' = 'Apple_UFS'; - '4.1BSD' = 'Unknown'; - '4.2BSD' = 'Unknown'; - '4.4LFS' = 'Unknown'; - }; - }, - { - 'IOClass' = IONeXTPartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 1000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Content Hint' = 'CD_ROM_Mode_1'; - }; - 'Content Mask' = 'NeXT_partition_scheme'; - 'Content Table' = - { - '4.4BSD' = 'Apple_UFS'; - '4.1BSD' = 'Unknown'; - '4.2BSD' = 'Unknown'; - '4.4LFS' = 'Unknown'; - }; - }, - { - 'IOClass' = IONeXTPartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 1000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Content Hint' = 'Apple_Rhapsody_UFS'; - }; - 'Content Mask' = 'NeXT_partition_scheme'; - 'Content Table' = - { - '4.4BSD' = 'Apple_UFS'; - '4.1BSD' = 'Unknown'; - '4.2BSD' = 'Unknown'; - '4.4LFS' = 'Unknown'; - }; - }, - { - 'IOClass' = IOFDiskPartitionScheme; - 'IOProviderClass' = IOMedia; - 'IOProbeScore' = 3000:32; - 'IOMatchCategory' = IOStorage; - 'IOPropertyMatch' = - { - 'Whole' = .true.; - }; - 'Content Mask' = 'FDisk_partition_scheme'; - 'Content Table' = - { - '0x01' = 'DOS_FAT_12'; - '0x04' = 'DOS_FAT_16_S'; - '0x05' = 'DOS_Extended'; - '0x06' = 'DOS_FAT_16'; - '0x07' = 'Windows_NTFS'; - '0x0A' = 'Boot_Manager'; - '0x0B' = 'DOS_FAT_32'; - '0x0C' = 'Windows_FAT_32'; - '0x0E' = 'Windows_FAT_16'; - '0x0F' = 'Windows_Extended'; - '0x11' = 'DOS_FAT_12_Hidden'; - '0x14' = 'DOS_FAT_16_S_Hidden'; - '0x16' = 'DOS_FAT_16_Hidden'; - '0x17' = 'Windows_NTFS_Hidden'; - '0x1B' = 'DOS_FAT_32_Hidden'; - '0x1C' = 'Windows_FAT_32_Hidden'; - '0x1E' = 'Windows_FAT_16_Hidden'; - '0x63' = 'UNIX'; - '0x82' = 'Linux_Swap'; - '0x83' = 'Linux_Ext2FS'; - '0x84' = 'Hibernation'; - '0x85' = 'Linux_Extended'; - '0x86' = 'Windows_FAT_16_FT'; - '0x87' = 'Windows_NTFS_FT'; - '0xA5' = 'FreeBSD'; - '0xA6' = 'OpenBSD'; - '0xA7' = 'NeXTSTEP'; - '0xA8' = 'Apple_UFS'; - '0xA9' = 'NetBSD'; - '0xAB' = 'Apple_Boot'; - '0xAF' = 'Apple_HFS'; - '0xB7' = 'BSDI'; - '0xB8' = 'BSDI_Swap'; - '0xC6' = 'Windows_FAT_16_FT_Corrupt'; - '0xC7' = 'Windows_NTFS_FT_Corrupt'; - '0xEB' = 'BeOS'; - '0xF2' = 'DOS_Secondary'; - '0xFD' = 'Linux_RAID'; - }; - }, - { - 'IOClass' = IOCDPartitionScheme; - 'IOProviderClass' = IOCDMedia; - 'IOMatchCategory' = IOStorage; - 'Content Mask' = 'CD_partition_scheme'; - 'Content Table' = - { - '0x01' = 'CD_DA'; - '0x02' = 'CD_ROM_Mode_1'; - '0x03' = 'CD_ROM_Mode_2'; - '0x04' = 'CD_ROM_Mode_2_Form_1'; - '0x05' = 'CD_ROM_Mode_2_Form_2'; - }; - }, - { - 'IOClass' = IOMediaBSDClient; - 'IOProviderClass' = IOResources; - 'IOMatchCategory' = IOMediaBSDClient; - 'IOResourceMatch' = IOBSD; - }, - { - 'IOClass' = AppleDDCDisplay; - 'IOProviderClass' = IODisplayConnect; - 'IOProbeScore' = 2000:32; - appleDDC = <00000082 00ff2140 0000008c 00043147 " - "00000096 00053140 00000098 0003314c " - "0000009a 0002314f 0000009c 00ff3159 " - "000000aa 000d494f 000000b4 0001fffc " - "000000b6 00004540 000000b8 000f454c " - "000000ba 000e454f 000000bc 00ff4559 " - "000000be 000b6140 000000c8 000a614a " - "000000cc 0009614f 000000d0 00ff6159 " - "000000d2 00ff614f 000000dc 0017ffc4 " - "000000fa 00ff814f 00000104 00ff8180 " - "00000106 0008818f 0000010c 00ff8199 " - "00000118 00ffa940 0000011a 00ffa945 " - "0000011c 00ffa94a 0000011e 00ffa94f " - "00000120 00ffa954 00000121 00ffa959 " - "00000128 00ffc140 0000012a 00ffc14f " - "0000012c 00ffc940 0000012e 00ffc94f " - "00000130 00ffd140 00000132 00ffd14f " - "000001fe 00ffd1c0 00000208 00ffd1cc>; - overrides = ( { ID = 0x06105203:32; - additions = <0000010c>; }, - { ID = 0x0610049c:32; - deletions = <000000b6>; }, - { ID = 0x0610059c:32; - deletions = <000000b6>; }, - { ID = 0x0610069c:32; - deletions = <000000b6>; }, - { ID = 0x0610079c:32; - deletions = <000000b6>; }, - { ID = 0x0610089c:32; - deletions = <000000b6>; }, - { ID = 0x06101092:32; - additions = <00000121>; }, - { ID = 0x0610029d:32; - additions = <0000009e>; } ); - }, - { - 'IOClass' = AppleG3SeriesDisplay; - 'IOProviderClass' = IODisplayConnect; - 'IOProbeScore' = 1500:32; - }, - { - 'IOClass' = AppleSenseDisplay; - 'IOProviderClass' = IODisplayConnect; - 'IOProbeScore' = 1000:32; - }, - { - 'IOClass' = AppleNoSenseDisplay; - 'IOProviderClass' = IODisplayConnect; - 'IOProbeScore' = 500:32; - }, - { - 'IOClass' = IOBlockStorageDriver; - 'IOProviderClass' = IOBlockStorageDevice; - 'IOPropertyMatch' = - { - 'device-type' = 'Generic'; - }; - }, - { - 'IOClass' = IOSCSIHDDrive; - 'IOProviderClass' = IOSCSIDevice; - }, - { - 'IOClass' = IOCDBlockStorageDriver; - 'IOProviderClass' = IOCDBlockStorageDevice; - 'IOPropertyMatch' = - { - 'device-type' = 'CDROM'; - }; - }, - { - 'IOClass' = IOSCSICDDrive; - 'IOProviderClass' = IOSCSIDevice; - }, - { - 'IOClass' = IODVDBlockStorageDriver; - 'IOProviderClass' = IODVDBlockStorageDevice; - 'IOPropertyMatch' = - { - 'device-type' = 'DVD'; - }; - }, - { - 'IOClass' = IOSCSIDVDDrive; - 'IOProviderClass' = IOSCSIDevice; - }, -" -#if defined(__i386__) -" - { - 'IOClass' = IOATAHDDrive; - 'IOProviderClass' = IOATADevice; - }, - { - 'IOClass' = IOATAPIHDDrive; - 'IOProviderClass' = IOATADevice; - }, - { - 'IOClass' = IOATAPICDDrive; - 'IOProviderClass' = IOATADevice; - }, - { - 'IOClass' = IOATAPIDVDDrive; - 'IOProviderClass' = IOATADevice; - }, -" -#endif -" - { - 'IOClass' = IONetworkStack; - 'IOProviderClass' = IOResources; - 'IOResourceMatch' = IOBSD; - 'IOMatchCategory' = IONetworkStack; } " #ifdef PPC @@ -414,40 +111,6 @@ const char * gIOKernelConfigTables = }, " #endif -" - { - 'IOClass' = AppleGracklePCI; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = ('grackle', 'MOT,PPC106'); - }, - { - 'IOClass' = AppleMacRiscPCI; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = ('bandit', 'uni-north'); - }, - { - 'IOClass' = AppleMacRiscAGP; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = 'uni-north'; - 'IOProbeScore' = 1000:32; - 'IOAGPFlags' = 1:32; - }, - { - 'IOClass' = AppleMacRiscVCI; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = chaos; - }, - { - 'IOClass' = IOPCI2PCIBridge; - 'IOProviderClass' = IOPCIDevice; - 'IONameMatch' = 'pci-bridge'; - }, - { - 'IOClass' = IOPCI2PCIBridge; - 'IOProviderClass' = IOPCIDevice; - 'IOPCIMatch' = '0x00261011'; - }, -" #if 0 " { @@ -490,155 +153,6 @@ const char * gIOKernelConfigTables = 'IOClass' = AppleNVRAM; 'IOProviderClass' = AppleMacIODevice; 'IONameMatch' = nvram; - }, - { - 'IOClass' = IOADBBus; - 'IOProviderClass' = IOADBController; - }, - { - 'IOClass' = AppleADBKeyboard; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '2'; - }, - { - 'IOClass' = AppleADBButtons; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '7'; - }, - { - 'IOClass' = AppleADBMouseType1; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '3'; - 'IOProbeScore' = 5000:32; - }, - { - 'IOClass' = AppleADBMouseType2; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '3'; - 'IOProbeScore' = 10000:32; - }, - { - 'IOClass' = AppleADBMouseType4; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '3-01'; - 'IOProbeScore' = 20000:32; - 'accltpad' = <" - "0000b000" - "74706164000700000000000100010000" - "00010000000020000005000123c60001" - "00000002fe3c0003800000055719000b" - "000000082ebf001a0000000a3ff1002e" - "0000000050000005000123c600010000" - "0002de8a000410000005682c000fe000" - "00081ebf00226000000a1f680037e000" - "000080000007000123c6000100000001" - "c378000280000002ac150004a0000004" - "5402000dc00000061285001bb0000007" - "e68b002d1000000a44eb004a90000000" - "b000000900012429000100000001b37c" - "0002800000025e5f000580000003bf2c" - "000f00000004bc350017a00000061e38" - "0027b00000075d4500385000000899a2" - "004bb000000a91050066b0000000e000" - "000a00011855000130000001b2280002" - "f000000253690006a00000036f4a0010" - "d00000046aab001f100000054aab002d" - "500000062555003f400000071aab0051" - "c00000089aab00663000000a8aab007d" - "700000010000000b0001185500013000" - "0001b228000310000002536900071000" - "00032f4a001180000003acfb001c8800" - "00043aab0028e0000004caab00384000" - "000555550048f00000063aab005c9000" - "0007aaab00731000000a3aab008b7000" - ">; - }, - { - 'IOClass' = IONDRVFramebuffer; - 'IOProviderClass' = IOPCIDevice; - 'IONameMatch' = display; - 'IOProbeScore' = 20000:32; - 'IOMatchCategory' = IOFramebuffer; - }, - { - 'IOClass' = IONDRVFramebuffer; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = display; - 'IOProbeScore' = 20000:32; - 'IOMatchCategory' = IOFramebuffer; - }, - { - 'IOClass' = IOBootFramebuffer; - 'IOProviderClass' = IOPCIDevice; - 'IONameMatch' = display; - 'IOMatchCategory' = IOFramebuffer; - }, - { - 'IOClass' = AppleADBDisplay; - 'IOProbeScore' = 1000:32; - 'IOProviderClass' = IOADBDevice; - 'ADB Match' = '*-c0'; - modes850 = <000000dc 0000008c 0000009a 0000009e " - "000000aa 000000d2 000000d0 000000fa " - "00000106 0000010c 00000118 0000011a " - "0000011c 0000011e>; - modes750 = <000000dc 0000008c 000000aa 000000d2 " - "000000fa 00000106 00000118>; - modesStudio = <000000d2 0000008c 000000aa>; - adb2Modes = modes750; - adb3Modes = modes850; - adb4Modes = modes850; - adb5Modes = modes750; - adb6Modes = modesStudio; - }, - { - 'IOClass' = BMacEnet; - 'IOProviderClass' = AppleMacIODevice; - 'IONameMatch' = ('bmac', 'bmac+'); - }, -" -#if 0 -" - { - 'IOClass' = Sym8xxSCSIController; - 'IOProviderClass' = IOPCIDevice; - 'IONameMatch' = ('apple53C8xx', 'Apple53C875Card', 'ATTO,ExpressPCIProLVD', 'ATTO,ExpressPCIProUL2D', 'ATTO,ExpressPCIProUL3D'); - }, -" -#endif -" -" -#if 0 -" - { - 'IOClass' = MaceEnet; - 'IOProviderClass' = AppleMacIODevice; - 'IONameMatch' = mace; - }, - { - 'IOClass' = Intel82557; - 'IOProviderClass' = IOPCIDevice; - 'IOPCIMatch' = '0x12298086'; - 'IODefaultMedium' = '00000020'; - 'Flow Control' = .true.; - 'Verbose' = .false.; - }, -" -#endif /* 0 */ -" - { - 'IOClass' = IOKDP; - 'IOProviderClass' = IOKernelDebugger; - 'IOMatchCategory' = IOKDP; - 'IOEnableKDP' = .true.; - 'IODriverMatch' = - { - 'IOClass' = ('BMacEnet', 'UniNEnet', 'MaceEnet'); - }; - 'IODriverNubMatch' = - { - 'built-in' = <>; - }; } " #endif /* PPC */ @@ -674,29 +188,6 @@ const char * gIOKernelConfigTables = 'IOProviderClass' = IOPlatformDevice; 'IONameMatch' = intel-clock; }, - { - 'IOClass' = AppleI386PCI; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = pci; - }, - { - 'IOClass' = ApplePS2Controller; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = ps2controller; - }, - { - 'IOClass' = ApplePS2Keyboard; - 'IOProviderClass' = ApplePS2KeyboardDevice; - }, - { - 'IOClass' = ApplePS2Mouse; - 'IOProviderClass' = ApplePS2MouseDevice; - }, - { - 'IOClass' = IOBootFramebuffer; - 'IOProviderClass' = IOPlatformDevice; - 'IONameMatch' = display; - }, { 'IOClass' = AppleATAPIIX; 'IOProviderClass' = IOPCIDevice; @@ -708,33 +199,8 @@ const char * gIOKernelConfigTables = 'IOProviderClass' = IOPCIDevice; 'IOPCIMatch' = '0x12308086 0x70108086 0x71118086 0x24118086 0x24218086 0x244a8086 0x244b8086'; 'IOMatchCategory' = AppleATAPIIXChannel1; - }, - { - 'IOClass' = IOPCI2PCIBridge; - 'IOProviderClass' = IOPCIDevice; - 'IOPCIClassMatch' = '0x06040000&0xffff0000'; - }, - { - 'IOClass' = Intel82557; - 'IOProviderClass' = IOPCIDevice; - 'IOPCIMatch' = '0x12298086'; - 'IODefaultMedium' = '00000020'; - 'Flow Control' = .true.; - 'Verbose' = .false.; - }, - { - 'IOClass' = IOKDP; - 'IOProviderClass' = IOKernelDebugger; - 'IOMatchCategory' = IOKDP; - 'IOEnableKDP' = .true.; - 'IODriverMatch' = - { - 'IOClass' = ('Intel82557', 'DEC21x4'); - }; - 'IODriverNubMatch' = - { - }; } " #endif /* i386 */ ")"; + diff --git a/iokit/bsddev/IOBSDConsole.cpp b/iokit/bsddev/IOBSDConsole.cpp deleted file mode 100644 index b2a82e4e9..000000000 --- a/iokit/bsddev/IOBSDConsole.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#include <IOKit/assert.h> -#include <IOKit/IOMessage.h> -#include <IOKit/IOLib.h> -#include "IOBSDConsole.h" -#include <IOKit/hidsystem/IOHIKeyboard.h> -#include <IOKit/hidsystem/IOLLEvent.h> - -static IOBSDConsole * gBSDConsoleInst = 0; -bool displayWranglerPublished( OSObject *, void *, IOService * ); - -#define super IOService -OSDefineMetaClassAndStructors(IOBSDConsole, IOService); - -//************************************************************************ - -bool IOBSDConsole::start(IOService * provider) -{ - OSObject * notify; - - if (!super::start(provider)) return false; - - assert( gBSDConsoleInst == 0 ); - gBSDConsoleInst = this; - - notify = addNotification( gIOPublishNotification, - serviceMatching("IOHIKeyboard"), - (IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler, - this, 0 ); - assert( notify ); - - notify = addNotification( gIOPublishNotification, - serviceMatching("IODisplayWrangler"), - (IOServiceNotificationHandler)displayWranglerPublished, - this, 0 ); - assert( notify ); - - notify = addNotification( gIOPublishNotification, - serviceMatching("IOAudioStream"), - (IOServiceNotificationHandler) &IOBSDConsole::publishNotificationHandler, - this, this ); - assert( notify ); - - return( true ); -} - -bool IOBSDConsole::publishNotificationHandler( - IOBSDConsole * self, - void * ref, - IOService * newService ) - -{ - IOHIKeyboard * keyboard = 0; - IOService * audio = 0; - - if( ref) { - audio = OSDynamicCast(IOService, newService->metaCast("IOAudioStream")); - if (audio != 0) { - OSNumber *out; - out = OSDynamicCast(OSNumber, newService->getProperty("Out")); - if (out) { - if (out->unsigned8BitValue() == 1) { - self->fAudioOut = newService; - } - } - } - } else { - audio = 0; - keyboard = OSDynamicCast( IOHIKeyboard, newService ); - - if( keyboard && self->attach( keyboard )) { - self->arbitrateForKeyboard( keyboard ); - } - } - - if( !keyboard && !audio) - IOLog("%s: strange service notify \"%s\"\n", - self->getName(), newService->getName()); - - return true; -} - -// ********************************************************************************** -// displayWranglerPublished -// -// The Display Wrangler has appeared. We will be calling its -// ActivityTickle method when there is user activity. -// ********************************************************************************** -bool displayWranglerPublished( OSObject * us, void * ref, IOService * yourDevice ) -{ - if ( yourDevice != NULL ) { - ((IOBSDConsole *)us)->displayManager = yourDevice; - } - return true; -} - - -//************************************************************************ -// Keyboard client stuff -//************************************************************************ - -void IOBSDConsole::arbitrateForKeyboard( IOHIKeyboard * nub ) -{ - nub->open(this, 0, - keyboardEvent, 0, updateEventFlags); - // failure can be expected if the HID system already has it -} - -IOReturn IOBSDConsole::message(UInt32 type, IOService * provider, - void * argument) -{ - IOReturn status = kIOReturnSuccess; - - switch (type) - { - case kIOMessageServiceIsTerminated: - case kIOMessageServiceIsRequestingClose: - provider->close( this ); - break; - - case kIOMessageServiceWasClosed: - arbitrateForKeyboard( (IOHIKeyboard *) provider ); - break; - - default: - status = super::message(type, provider, argument); - break; - } - - return status; -} - -extern "C" { - void cons_cinput( char c); -} -#warning REMOVE cons_cinput DECLARATION FROM HERE - -void IOBSDConsole::keyboardEvent(OSObject * target, - /* eventType */ unsigned eventType, - /* flags */ unsigned /* flags */, - /* keyCode */ unsigned /* key */, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned /* origCharCode */, - /* originalCharSet */ unsigned /* origCharSet */, - /* keyboardType */ unsigned /* keyboardType */, - /* repeat */ bool /* repeat */, - /* atTime */ AbsoluteTime /* ts */) -{ - static const char cursorCodes[] = { 'D', 'A', 'C', 'B' }; - - if ( ((IOBSDConsole *)target)->displayManager != NULL ) { // if there is a display manager, - ((IOBSDConsole *)target)->displayManager->activityTickle(kIOPMSuperclassPolicy1); // tell it there is user activity - } - - if( eventType == NX_KEYDOWN) { - if( (charSet == NX_SYMBOLSET) - && (charCode >= 0xac) && (charCode <= 0xaf)) { - cons_cinput( '\033'); - cons_cinput( 'O'); - charCode = cursorCodes[ charCode - 0xac ]; - } - cons_cinput( charCode); - } -} - -void IOBSDConsole::updateEventFlags(OSObject * /*target*/, unsigned /*flags*/) -{ - return; -} - -//************************************************************************ -// Utility sound making stuff, callable from C -//************************************************************************ -extern "C" { - int asc_ringbell(); -} - - -bool (*playBeep)(IOService *outputStream) = 0; - -/* -* Make some sort of noise if possible -*/ - -int asc_ringbell() -{ - IOService *output; - - if (gBSDConsoleInst && playBeep && (output = gBSDConsoleInst->getAudioOut())) { - playBeep(output); - } - - return true; -} - diff --git a/iokit/bsddev/IOBSDConsole.h b/iokit/bsddev/IOBSDConsole.h deleted file mode 100644 index 240ff84c5..000000000 --- a/iokit/bsddev/IOBSDConsole.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _IOBSDCONSOLE_H -#define _IOBSDCONSOLE_H - -#include <IOKit/IOService.h> - -class IOHIKeyboard; - -class IOBSDConsole : public IOService -{ - OSDeclareDefaultStructors(IOBSDConsole); - -private: - IOService * fAudioOut; - - static bool publishNotificationHandler( - IOBSDConsole * self, void * ref, - IOService * newService ); - - virtual void arbitrateForKeyboard( IOHIKeyboard * kb ); - -public: - IOService * displayManager; // we send user activity tickles to the display manager - - static void keyboardEvent(OSObject * target, - /* eventType */ unsigned eventType, - /* flags */ unsigned flags, - /* keyCode */ unsigned key, - /* charCode */ unsigned charCode, - /* charSet */ unsigned charSet, - /* originalCharCode */ unsigned origCharCode, - /* originalCharSet */ unsigned origCharSet, - /* keyboardType */ unsigned keyboardType, - /* repeat */ bool repeat, - /* atTime */ AbsoluteTime ts); - - static void updateEventFlags(OSObject * target, unsigned flags); - - virtual bool start(IOService * provider); - - virtual IOReturn message(UInt32 type, IOService * provider, - void * argument); - - IOService * getAudioOut() { return fAudioOut; }; -}; - -#endif /* _IOBSDCONSOLE_H */ diff --git a/iokit/bsddev/IOKitBSDInit.cpp b/iokit/bsddev/IOKitBSDInit.cpp index b161dbf60..ff860483f 100644 --- a/iokit/bsddev/IOKitBSDInit.cpp +++ b/iokit/bsddev/IOKitBSDInit.cpp @@ -24,9 +24,6 @@ #include <IOKit/IOService.h> #include <IOKit/IODeviceTreeSupport.h> #include <IOKit/IOKitKeys.h> -#include <IOKit/storage/IOMedia.h> -#include <IOKit/network/IONetworkStack.h> -#include <IOKit/network/IONetworkInterface.h> #include <IOKit/IOPlatformExpert.h> #include <sys/disklabel.h> @@ -78,6 +75,28 @@ OSDictionary * IOBSDNameMatching( const char * name ) return( 0 ); } +OSDictionary * IOCDMatching( const char * name ) +{ + OSDictionary * dict; + const OSSymbol * str; + + dict = IOService::serviceMatching( "IOMedia" ); + if( dict == 0 ) { + IOLog("Unable to find IOMedia\n"); + return 0; + } + + str = OSSymbol::withCString( "CD_ROM_Mode_1" ); + if( str == 0 ) { + dict->release(); + return 0; + } + + dict->setObject( "Content", (OSObject *)str ); + str->release(); + return( dict ); +} + OSDictionary * IONetworkMatching( const char * path, char * buf, int maxLen ) { @@ -152,7 +171,7 @@ OSDictionary * IONetworkNamePrefixMatching( const char * prefix ) if ( str == 0 ) continue; - propDict->setObject( kIOInterfaceNamePrefix, (OSObject *) str ); + propDict->setObject( "IOInterfaceNamePrefix", (OSObject *) str ); str->release(); str = 0; @@ -174,26 +193,57 @@ OSDictionary * IONetworkNamePrefixMatching( const char * prefix ) return( 0 ); } -static bool IORegisterNetworkInterface( IONetworkInterface * netif ) +static bool IORegisterNetworkInterface( IOService * netif ) { - IONetworkStack * stack; + // A network interface is typically named and registered + // with BSD after receiving a request from a user space + // "namer". However, for cases when the system needs to + // root from the network, this registration task must be + // done inside the kernel and completed before the root + // device is handed to BSD. + + IOService * stack; + OSNumber * zero = 0; + OSString * path = 0; + OSDictionary * dict = 0; + char * pathBuf = 0; + int len; + enum { kMaxPathLen = 512 }; - if (( stack = IONetworkStack::getNetworkStack() )) - { - stack->registerInterface( netif, netif->getNamePrefix() ); - } + do { + stack = IOService::waitForService( + IOService::serviceMatching("IONetworkStack") ); + if ( stack == 0 ) break; - return ( netif->getProperty( kIOBSDNameKey ) != 0 ); -} + dict = OSDictionary::withCapacity(3); + if ( dict == 0 ) break; -static void IORegisterPrimaryNetworkInterface() -{ - IONetworkStack * stack; + zero = OSNumber::withNumber((UInt64) 0, 32); + if ( zero == 0 ) break; - if (( stack = IONetworkStack::getNetworkStack() )) - { - stack->registerPrimaryInterface( true ); - } + pathBuf = (char *) IOMalloc( kMaxPathLen ); + if ( pathBuf == 0 ) break; + + len = kMaxPathLen; + if ( netif->getPath( pathBuf, &len, gIOServicePlane ) + == false ) break; + + path = OSString::withCStringNoCopy( pathBuf ); + if ( path == 0 ) break; + + dict->setObject( "IOInterfaceUnit", zero ); + dict->setObject( kIOPathMatchKey, path ); + + stack->setProperties( dict ); + } + while ( false ); + + if ( zero ) zero->release(); + if ( path ) path->release(); + if ( dict ) dict->release(); + if ( pathBuf ) IOFree(pathBuf, kMaxPathLen); + + return ( netif->getProperty( kIOBSDNameKey ) != 0 ); } OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) @@ -293,6 +343,7 @@ kern_return_t IOFindBSDRoot( char * rootName, const char * look = 0; int len; bool forceNet = false; + bool debugInfoPrintedOnce = false; static int mountAttempts = 0; @@ -340,10 +391,11 @@ kern_return_t IOFindBSDRoot( char * rootName, // from OpenFirmware path IOLog("From path: \"%s\", ", look); - if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) ) - matching = IONetworkMatching( look, str, kMaxPathBuf ); - else + if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) ) { + matching = IONetworkMatching( look, str, kMaxPathBuf ); + } else { matching = IODiskMatching( look, str, kMaxPathBuf ); + } } if( (!matching) && rdBootVar[0] ) { @@ -352,10 +404,13 @@ kern_return_t IOFindBSDRoot( char * rootName, if( look[0] == '*') look++; - if ( strncmp( look, "en", strlen( "en" )) == 0 ) - matching = IONetworkNamePrefixMatching( "en" ); - else - matching = IOBSDNameMatching( look ); + if ( strncmp( look, "en", strlen( "en" )) == 0 ) { + matching = IONetworkNamePrefixMatching( "en" ); + } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) { + matching = IOCDMatching( look ); + } else { + matching = IOBSDNameMatching( look ); + } } if( !matching) { @@ -364,7 +419,7 @@ kern_return_t IOFindBSDRoot( char * rootName, matching = IOService::serviceMatching( "IOMedia" ); astring = OSString::withCStringNoCopy("Apple_UFS"); if ( astring ) { - matching->setObject(kIOMediaContentKey, astring); + matching->setObject("Content", astring); astring->release(); } } @@ -378,8 +433,6 @@ kern_return_t IOFindBSDRoot( char * rootName, } } - IOService::waitForService(IOService::serviceMatching("IOMediaBSDClient")); - do { t.tv_sec = ROOTDEVICETIMEOUT; t.tv_nsec = 0; @@ -388,6 +441,20 @@ kern_return_t IOFindBSDRoot( char * rootName, if( (!service) || (mountAttempts == 10)) { PE_display_icon( 0, "noroot"); IOLog( "Still waiting for root device\n" ); + + if( !debugInfoPrintedOnce) { + debugInfoPrintedOnce = true; + if( gIOKitDebug & kIOLogDTree) { + IOLog("\nDT plane:\n"); + IOPrintPlane( gIODTPlane ); + } + if( gIOKitDebug & kIOLogServiceTree) { + IOLog("\nService plane:\n"); + IOPrintPlane( gIOServicePlane ); + } + if( gIOKitDebug & kIOLogMemory) + IOPrintMemory(); + } } } while( !service); matching->release(); @@ -401,11 +468,10 @@ kern_return_t IOFindBSDRoot( char * rootName, if ( service && service->metaCast( "IONetworkInterface" ) - && !IORegisterNetworkInterface( (IONetworkInterface *) service ) ) + && !IORegisterNetworkInterface( service ) ) { service = 0; } - IORegisterPrimaryNetworkInterface(); if( service) { @@ -444,10 +510,9 @@ kern_return_t IOFindBSDRoot( char * rootName, IOFree( str, kMaxPathBuf + kMaxBootVar ); - if( gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) { + if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) { - IOSleep(10 * 1000); -// IOService::getPlatform()->waitQuiet(); + IOService::getPlatform()->waitQuiet(); if( gIOKitDebug & kIOLogDTree) { IOLog("\nDT plane:\n"); IOPrintPlane( gIODTPlane ); diff --git a/iokit/conf/Makefile b/iokit/conf/Makefile index 4b64836c7..42a0c8b7b 100644 --- a/iokit/conf/Makefile +++ b/iokit/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(IOKIT_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(IOKIT_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(IOKIT_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(IOKIT_KERNEL_CONFIG) $(IOKIT_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(IOKIT_KERNEL_CONFIG) $(IOKIT_KERNEL_CONFIG); \ ); .ORDER: $(COMPOBJROOT)/$(IOKIT_KERNEL_CONFIG)/Makefile @@ -52,6 +52,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(IOKIT_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(IOKIT_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/iokit/conf/Makefile.template b/iokit/conf/Makefile.template index 1debf49ee..35daa9e5a 100644 --- a/iokit/conf/Makefile.template +++ b/iokit/conf/Makefile.template @@ -104,9 +104,6 @@ do_build_all: do_depend %RULES --include Makedep - include $(MakeInc_rule) - include $(MakeInc_dir) diff --git a/iokit/conf/files b/iokit/conf/files index 8d6ee281c..886d822a3 100644 --- a/iokit/conf/files +++ b/iokit/conf/files @@ -24,6 +24,7 @@ iokit/Kernel/IOPMinformeeList.cpp optional iokitcpp iokit/Kernel/IOCatalogue.cpp optional iokitcpp iokit/Kernel/IOPMPowerSource.cpp optional iokitcpp iokit/Kernel/IOPMPowerSourceList.cpp optional iokitcpp +iokit/Kernel/IOPMPagingPlexus.cpp optional iokitcpp iokit/Kernel/IOWorkLoop.cpp optional iokitcpp iokit/Kernel/IOEventSource.cpp optional iokitcpp @@ -65,89 +66,8 @@ iokit/Kernel/IOStringFuncs.c standard iokit/KernelConfigTables.cpp optional iokitcpp -# Networking - -iokit/Families/IONetworking/IOPacketQueue.cpp optional iokitcpp -iokit/Families/IONetworking/IOMbufMemoryCursor.cpp optional iokitcpp -iokit/Families/IONetworking/IOOutputQueue.cpp optional iokitcpp -iokit/Families/IONetworking/IOKernelDebugger.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkController.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkInterface.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkData.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkMedium.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkStack.cpp optional iokitcpp -iokit/Families/IONetworking/IONetworkUserClient.cpp optional iokitcpp -iokit/Families/IONetworking/IOEthernetController.cpp optional iokitcpp -iokit/Families/IONetworking/IOEthernetInterface.cpp optional iokitcpp - -# PCI support - -iokit/Families/IOPCIBus/IOPCIBridge.cpp optional iokitcpp -iokit/Families/IOPCIBus/IOPCIDevice.cpp optional iokitcpp - -# Event driver - -iokit/Families/IOHIDSystem/IOHIDevice.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDIO.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDSystem.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIKeyboard.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIKeyboardMapper.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIPointing.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHITablet.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHITabletPointer.cpp optional iokitcpp§ -iokit/Families/IOHIDSystem/IOHIDUserClient.cpp optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCheckReport.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDCountDescriptorItems.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonCaps.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtons.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetButtonsOnPage.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCaps.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetCollectionNodes.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetData.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextButtonInfo.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetNextUsageValueInfo.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetReportLength.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetUsageValueArray.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDGetValueCaps.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDHasUsage.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDInitReport.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDIsButtonOrValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDMaxUsageListLength.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDNextItem.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDOpenCloseDescriptor.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDParseDescriptor.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPostProcessRIValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessCollection.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessGlobalItem.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessLocalItem.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessMainItem.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDProcessReportItem.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDPutData.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDScaleUsageValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetButtons.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetScaledUsageValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValue.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDSetUsageValueArray.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageAndPageFromIndex.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageInRange.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/HIDUsageListDifference.c optional iokitcpp -iokit/Families/IOHIDSystem/IOHIDDescriptorParser/PoolAlloc.c optional iokitcpp - -# Graphics support - -iokit/Families/IOGraphics/IOGraphicsDevice.cpp optional iokitcpp -iokit/Families/IOGraphics/IOFramebuffer.cpp optional iokitcpp -iokit/Families/IOGraphics/IOFramebufferUserClient.cpp optional iokitcpp -iokit/Families/IOGraphics/IODisplay.cpp optional iokitcpp -iokit/Families/IOGraphics/IODisplayWrangler.cpp optional iokitcpp -iokit/Families/IOGraphics/AppleDDCDisplay.cpp optional iokitcpp -iokit/Families/IOGraphics/IOBootFramebuffer.cpp optional iokitcpp -iokit/Families/IOGraphics/IOAccelerator.cpp optional iokitcpp - # BSD shim files -iokit/bsddev/IOBSDConsole.cpp optional iokitcpp iokit/bsddev/IOKitBSDInit.cpp optional iokitcpp # SCSI support @@ -171,63 +91,5 @@ iokit/Families/IOSCSIParallel/queueHelpers.cpp optional iokitcpp iokit/Drivers/platform/drvAppleRootDomain/RootDomainUserClient.cpp optional iokitcpp iokit/Kernel/IOPowerConnection.cpp optional iokitcpp - -# Storage Family -iokit/Families/IOStorage/IOApplePartitionScheme.cpp optional iokitcpp -iokit/Families/IOStorage/IOBlockStorageDriver.cpp optional iokitcpp -iokit/Families/IOStorage/IOFDiskPartitionScheme.cpp optional iokitcpp -iokit/Families/IOStorage/IOMedia.cpp optional iokitcpp -iokit/Families/IOStorage/IOMediaBSDClient.cpp optional iokitcpp -iokit/Families/IOStorage/IONeXTPartitionScheme.cpp optional iokitcpp -iokit/Families/IOStorage/IOPartitionScheme.cpp optional iokitcpp -iokit/Families/IOStorage/IOStorage.cpp optional iokitcpp - -# Storage Family: CDs -iokit/Families/IOCDStorage/IOCDAudioControl.cpp optional iokitcpp -iokit/Families/IOCDStorage/IOCDAudioControlUserClient.cpp optional iokitcpp -iokit/Families/IOCDStorage/IOCDBlockStorageDriver.cpp optional iokitcpp -iokit/Families/IOCDStorage/IOCDMedia.cpp optional iokitcpp -iokit/Families/IOCDStorage/IOCDPartitionScheme.cpp optional iokitcpp - -# Storage Family: DVDs -iokit/Families/IODVDStorage/IODVDBlockStorageDriver.cpp optional iokitcpp -iokit/Families/IODVDStorage/IODVDMedia.cpp optional iokitcpp - - -# Block Storage Family -iokit/Families/IOBlockStorage/IOBlockStorageDevice.cpp optional iokitcpp -iokit/Families/IOCDBlockStorage/IOCDBlockStorageDevice.cpp optional iokitcpp -iokit/Families/IODVDBlockStorage/IODVDBlockStorageDevice.cpp optional iokitcpp - -# Block Storage Family: SCSI -iokit/Families/IOSCSIHDDrive/IOBasicSCSI.cpp optional iokitcpp -iokit/Families/IOSCSIHDDrive/IOSCSIHDDrive.cpp optional iokitcpp -iokit/Families/IOSCSIHDDrive/IOSCSIHDDriveNub.cpp optional iokitcpp - -iokit/Families/IOSCSICDDrive/IOSCSICDDrive.cpp optional iokitcpp -iokit/Families/IOSCSICDDrive/IOSCSICDDriveNub.cpp optional iokitcpp - -iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDrive.cpp optional iokitcpp -iokit/Families/IOSCSIDVDDrive/IOSCSIDVDDriveNub.cpp optional iokitcpp - -# Block Storage Family: ATA -#iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp optional iokitcpp -#iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp optional iokitcpp -#iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp optional iokitcpp -#iokit/Families/IOATAHDDrive/IOATAHDPower.cpp optional iokitcpp - -# Block Storage Family: ATAPI -#iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp optional iokitcpp -#iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp optional iokitcpp -#iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp optional iokitcpp - -#iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp optional iokitcpp -#iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp optional iokitcpp -#iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp optional iokitcpp - -#iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp optional iokitcpp -#iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp optional iokitcpp -#iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp optional iokitcpp - # System Management iokit/Families/IOSystemManagement/IOWatchDogTimer.cpp optional iokitcpp diff --git a/iokit/conf/files.i386 b/iokit/conf/files.i386 index bd7ca34d4..016060a1f 100644 --- a/iokit/conf/files.i386 +++ b/iokit/conf/files.i386 @@ -4,25 +4,11 @@ iokit/Drivers/platform/drvAppleI386Generic/AppleI386PlatformExpert.cpp optional iokitcpp iokit/Drivers/platform/drvAppleI386Generic/AppleI386CPU.cpp optional iokitcpp -# PCI support - -iokit/Families/IOPCIBus/IOPCIDeviceI386.cpp optional iokitcpp -iokit/Drivers/pci/drvApplePCI/AppleI386PCI.cpp optional iokitcpp - # Shared lock iokit/Kernel/i386/IOSharedLock.s standard iokit/Kernel/i386/IOAsmSupport.s standard -# PS2 support - -iokit/Drivers/platform/drvApplePS2Controller/ApplePS2Controller.cpp optional iokitcpp -iokit/Drivers/platform/drvApplePS2Controller/ApplePS2KeyboardDevice.cpp optional iokitcpp -iokit/Drivers/platform/drvApplePS2Controller/ApplePS2MouseDevice.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvApplePS2Keyboard/ApplePS2Keyboard.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvApplePS2Mouse/ApplePS2Mouse.cpp optional iokitcpp - - # Interrupt Controller iokit/Drivers/platform/drvAppleIntelClassicPIC/PIC8259.cpp optional iokitcpp @@ -32,12 +18,6 @@ iokit/Drivers/platform/drvAppleIntelClock/IntelClock.cpp optional iokitcpp # Power Domains iokit/Drivers/platform/drvAppleRootDomain/RootDomain.cpp optional iokitcpp -# Intel EtherExpress Pro driver (i82557/i82558) -iokit/Drivers/network/drvIntel82557/i82557.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557Private.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557PHY.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp optional iokitcpp - # ATA support iokit/Families/IOATAStandard/IOATAStandardController.cpp optional iokitcpp iokit/Families/IOATAStandard/IOATAStandardDevice.cpp optional iokitcpp @@ -49,24 +29,5 @@ iokit/Families/IOATAStandard/IOATAStandardDriver.cpp optional iokitcp iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp optional iokitcpp iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp optional iokitcpp -# Block Storage Family: ATA -iokit/Families/IOATAHDDrive/IOATAHDDrive.cpp optional iokitcpp -iokit/Families/IOATAHDDrive/IOATAHDDriveNub.cpp optional iokitcpp -iokit/Families/IOATAHDDrive/IOATAHDCommand.cpp optional iokitcpp -iokit/Families/IOATAHDDrive/IOATAHDPower.cpp optional iokitcpp - -# Block Storage Family: ATAPI -iokit/Families/IOATAPIHDDrive/IOATAPIHDDrive.cpp optional iokitcpp -iokit/Families/IOATAPIHDDrive/IOATAPIHDDriveNub.cpp optional iokitcpp -iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp optional iokitcpp - -iokit/Families/IOATAPICDDrive/IOATAPICDDrive.cpp optional iokitcpp -iokit/Families/IOATAPICDDrive/IOATAPICDDriveNub.cpp optional iokitcpp -iokit/Families/IOATAPICDDrive/IOATAPICDCommand.cpp optional iokitcpp - -iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDrive.cpp optional iokitcpp -iokit/Families/IOATAPIDVDDrive/IOATAPIDVDDriveNub.cpp optional iokitcpp -iokit/Families/IOATAPIDVDDrive/IOATAPIDVDCommand.cpp optional iokitcpp - # ATA (Intel PIIX IDE) controller driver iokit/Drivers/ata/drvApplePIIXATA/AppleATAPIIX.cpp optional iokitcpp diff --git a/iokit/conf/files.ppc b/iokit/conf/files.ppc index 4a56a7717..a129bfc6d 100644 --- a/iokit/conf/files.ppc +++ b/iokit/conf/files.ppc @@ -5,30 +5,15 @@ iokit/Kernel/ppc/IOSharedLock.s standard iokit/Families/IOADBBus/IOADBBus.cpp optional iokitcpp iokit/Families/IOADBBus/IOADBController.cpp optional iokitcpp +iokit/Families/IOADBBus/IOADBDevice.cpp optional iokitcpp iokit/Families/IOADBBus/IOADBControllerUserClient.cpp optional iokitcpp -iokit/Families/IOPCIBus/IOPCIDevicePPC.cpp optional iokitcpp - -# ndrv support - -iokit/Families/IONDRVSupport/IOPEFLoader.c standard -iokit/Families/IONDRVSupport/IOPEFInternals.c standard -iokit/Families/IONDRVSupport/IONDRV.cpp optional iokitcpp -iokit/Families/IONDRVSupport/IONDRVLibraries.cpp optional iokitcpp -iokit/Families/IONDRVSupport/IONDRVFramebuffer.cpp optional iokitcpp - -iokit/Drivers/hidsystem/drvAppleADBDevices/IOADBDevice.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBMouse.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBKeyboard.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBDisplay.cpp optional iokitcpp -iokit/Drivers/hidsystem/drvAppleADBDevices/AppleADBButtons.cpp optional iokitcpp iokit/Families/IONVRAM/IONVRAMController.cpp optional iokitcpp iokit/Drivers/platform/drvAppleNVRAM/AppleNVRAM.cpp optional iokitcpp -#iokit/Drivers/platform/drvApplePMU/IOPMUNVRAMController.cpp optional iokitcpp - iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp optional iokitcpp iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp optional iokitcpp +iokit/Drivers/platform/drvAppleCuda/AppleCudaUserClient.cpp optional iokitcpp #iokit/Drivers/platform/drvApplePMU/AppleViaInterface.cpp optional iokitcpp #iokit/Drivers/platform/drvApplePMU/ApplePMU.cpp optional iokitcpp @@ -39,10 +24,6 @@ iokit/Drivers/platform/drvAppleCuda/IOCudaADBController.cpp optional iokitcpp iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp optional iokitcpp -iokit/Drivers/pci/drvApplePCI/AppleMacRiscPCI.cpp optional iokitcpp -iokit/Drivers/pci/drvApplePCI/AppleGracklePCI.cpp optional iokitcpp - - # Apple Platform Expert iokit/Drivers/platform/drvApplePlatformExpert/ApplePlatformExpert.cpp optional iokitcpp iokit/Drivers/platform/drvApplePlatformExpert/AppleCPU.cpp optional iokitcpp @@ -68,32 +49,6 @@ iokit/Drivers/platform/drvApplePowerExpressPE/PowerExpress.cpp optional iokitcpp iokit/Drivers/platform/drvAppleGrandCentral/GrandCentral.cpp optional disabled-iokitcpp iokit/Drivers/platform/drvAppleOHare/OHare.cpp optional iokitcpp - - -# BMac driver - -iokit/Drivers/network/drvPPCBMac/BMacEnetHW.cpp optional iokitcpp -iokit/Drivers/network/drvPPCBMac/BMacEnetPrivate.cpp optional iokitcpp -iokit/Drivers/network/drvPPCBMac/BMacEnet.cpp optional iokitcpp -iokit/Drivers/network/drvPPCBMac/BMacEnetMII.cpp optional iokitcpp - - -# Mace driver -iokit/Drivers/network/drvMaceEnet/MaceEnetHW.cpp optional disabled-iokitcpp -iokit/Drivers/network/drvMaceEnet/MaceEnetPrivate.cpp optional disabled-iokitcpp -iokit/Drivers/network/drvMaceEnet/MaceEnet.cpp optional disabled-iokitcpp - -# Display drivers - -iokit/Families/IOGraphics/AppleG3SeriesDisplay.cpp optional iokitcpp - - -# Intel EtherExpress Pro driver (i82557/i82558) -iokit/Drivers/network/drvIntel82557/i82557.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557Private.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557PHY.cpp optional iokitcpp -iokit/Drivers/network/drvIntel82557/i82557eeprom.cpp optional iokitcpp - # Symbios 8xx SCSI Driver #iokit/Drivers/scsi/drvSymbios8xx/Sym8xxClient.cpp optional iokitcpp #iokit/Drivers/scsi/drvSymbios8xx/Sym8xxExecute.cpp optional iokitcpp diff --git a/iokit/conf/version.minor b/iokit/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/iokit/conf/version.minor +++ b/iokit/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/iokit/conf/version.variant b/iokit/conf/version.variant index 7f8f011eb..e69de29bb 100644 --- a/iokit/conf/version.variant +++ b/iokit/conf/version.variant @@ -1 +0,0 @@ -7 diff --git a/libkern/c++/OSMetaClass.cpp b/libkern/c++/OSMetaClass.cpp index 4c5a81f39..8dbbd30e5 100644 --- a/libkern/c++/OSMetaClass.cpp +++ b/libkern/c++/OSMetaClass.cpp @@ -318,10 +318,10 @@ void *OSMetaClass::preModLoad(const char *kmodName) { if (!loadLock) { loadLock = mutex_alloc(ETAP_IO_AHA); - _mutex_lock(loadLock); + mutex_lock(loadLock); } else - _mutex_lock(loadLock); + mutex_lock(loadLock); sStalled = (StalledData *) kalloc(sizeof(*sStalled)); if (sStalled) { @@ -464,10 +464,10 @@ bool OSMetaClass::modHasInstance(const char *kmodName) if (!loadLock) { loadLock = mutex_alloc(ETAP_IO_AHA); - _mutex_lock(loadLock); + mutex_lock(loadLock); } else - _mutex_lock(loadLock); + mutex_lock(loadLock); do { OSSet *kmodClasses; @@ -535,7 +535,7 @@ static void _OSMetaClassConsiderUnloads(thread_call_param_t p0, kern_return_t ret; bool didUnload; - _mutex_lock(loadLock); + mutex_lock(loadLock); do { @@ -584,7 +584,7 @@ void OSMetaClass::considerUnloads() static thread_call_t unloadCallout; AbsoluteTime when; - _mutex_lock(loadLock); + mutex_lock(loadLock); if (!unloadCallout) unloadCallout = thread_call_allocate(&_OSMetaClassConsiderUnloads, 0); @@ -630,7 +630,7 @@ const OSMetaClass *OSMetaClass::getMetaClassWithName(const OSSymbol *name) OSObject *OSMetaClass::allocClassWithName(const OSSymbol *name) { OSObject * result; - _mutex_lock(loadLock); + mutex_lock(loadLock); const OSMetaClass * const meta = getMetaClassWithName(name); @@ -665,7 +665,7 @@ OSMetaClassBase *OSMetaClass:: checkMetaCastWithName(const OSSymbol *name, const OSMetaClassBase *in) { OSMetaClassBase * result; - _mutex_lock(loadLock); + mutex_lock(loadLock); const OSMetaClass * const meta = getMetaClassWithName(name); if (meta) diff --git a/libkern/c++/OSNumber.cpp b/libkern/c++/OSNumber.cpp index 2f94543e6..3a1306a82 100644 --- a/libkern/c++/OSNumber.cpp +++ b/libkern/c++/OSNumber.cpp @@ -26,7 +26,7 @@ #include <libkern/c++/OSSerialize.h> #include <libkern/c++/OSLib.h> -#define sizeMask ((1ULL << (size)) - 1) +#define sizeMask (~0ULL >> (64 - size)) #define super OSObject diff --git a/libkern/c++/OSUnserialize.cpp b/libkern/c++/OSUnserialize.cpp index bf5d57040..78001bdbe 100644 --- a/libkern/c++/OSUnserialize.cpp +++ b/libkern/c++/OSUnserialize.cpp @@ -1564,9 +1564,9 @@ OSUnserialize(const char *buffer, OSString **errorString) if (!lock) { lock = mutex_alloc(ETAP_IO_AHA); - _mutex_lock(lock); + mutex_lock(lock); } else { - _mutex_lock(lock); + mutex_lock(lock); } diff --git a/libkern/c++/OSUnserializeXML.cpp b/libkern/c++/OSUnserializeXML.cpp index 825cfb9e5..f169f7720 100644 --- a/libkern/c++/OSUnserializeXML.cpp +++ b/libkern/c++/OSUnserializeXML.cpp @@ -1996,9 +1996,9 @@ OSUnserializeXML(const char *buffer, OSString **errorString) if (!lock) { lock = mutex_alloc(ETAP_IO_AHA); - _mutex_lock(lock); + mutex_lock(lock); } else { - _mutex_lock(lock); + mutex_lock(lock); } diff --git a/libkern/conf/Makefile b/libkern/conf/Makefile index c744dea55..85e1a341a 100644 --- a/libkern/conf/Makefile +++ b/libkern/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(LIBKERN_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(LIBKERN_KERNEL_CONFIG) $(LIBKERN_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(LIBKERN_KERNEL_CONFIG) $(LIBKERN_KERNEL_CONFIG); \ ); .ORDER: $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile @@ -52,6 +52,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(LIBKERN_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(LIBKERN_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/libkern/conf/Makefile.template b/libkern/conf/Makefile.template index 0524aad2d..966e827c8 100644 --- a/libkern/conf/Makefile.template +++ b/libkern/conf/Makefile.template @@ -101,9 +101,6 @@ do_build_all: do_depend %RULES --include Makedep - include $(MakeInc_rule) - include $(MakeInc_dir) diff --git a/libkern/conf/files.ppc b/libkern/conf/files.ppc index b1cd7ebc2..b3cfa98f9 100644 --- a/libkern/conf/files.ppc +++ b/libkern/conf/files.ppc @@ -1,2 +1,5 @@ libkern/ppc/OSAtomic.s standard +libkern/ppc/bcmp.s standard +libkern/ppc/memcmp.s standard +libkern/ppc/strlen.s standard diff --git a/libkern/conf/version.minor b/libkern/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/libkern/conf/version.minor +++ b/libkern/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/libkern/conf/version.variant b/libkern/conf/version.variant index 7f8f011eb..e69de29bb 100644 --- a/libkern/conf/version.variant +++ b/libkern/conf/version.variant @@ -1 +0,0 @@ -7 diff --git a/libkern/gen/OSAtomicOperations.c b/libkern/gen/OSAtomicOperations.c index 735fa2ac3..c6e86aaca 100644 --- a/libkern/gen/OSAtomicOperations.c +++ b/libkern/gen/OSAtomicOperations.c @@ -96,45 +96,23 @@ UInt32 OSBitXorAtomic(UInt32 mask, UInt32 * value) return OSBitwiseAtomic((UInt32) -1, 0, mask, value); } - -static Boolean OSCompareAndSwap8(UInt8 oldValue8, UInt8 newValue8, UInt8 * value8) +static Boolean OSCompareAndSwap8(UInt8 oldValue8, UInt8 newValue8, UInt8 * value8) { - UInt32 mask = 0x000000ff; - UInt32 newbits = (UInt32) newValue8; - int shift; - UInt32 alignment = ((UInt32) value8) & (sizeof(UInt32) - 1); - UInt32 oldValue; - UInt32 newValue; - UInt32 * value; - - switch (alignment) { - default: - // assert(false); - case 0: - value = (UInt32 *) value8; - shift = 24; - break; - case 1: - value = (UInt32 *) (value8 + 1); - shift = 16; - break; - case 2: - value = (UInt32 *) (value8 + 2); - shift = 8; - break; - case 3: - value = (UInt32 *) (value8 + 3); - shift = 0; - break; - } + UInt32 mask = 0x000000ff; + UInt32 alignment = ((UInt32) value8) & (sizeof(UInt32) - 1); + UInt32 shiftValues = (24 << 24) | (16 << 16) | (8 << 8); + int shift = (UInt32) *(((UInt8 *) &shiftValues) + alignment); + UInt32 * value32 = (UInt32 *) (value8 - alignment); + UInt32 oldValue; + UInt32 newValue; - mask <<= shift; - newbits <<= shift; - - oldValue = *value; - newValue = (oldValue & ~mask) | (newbits & mask); - - return OSCompareAndSwap(oldValue, newValue, value); + mask <<= shift; + + oldValue = *value32; + oldValue = (oldValue & ~mask) | (oldValue8 << shift); + newValue = (oldValue & ~mask) | (newValue8 << shift); + + return OSCompareAndSwap(oldValue, newValue, value32); } static Boolean OSTestAndSetClear(UInt32 bit, Boolean wantSet, UInt8 * startAddress) @@ -253,34 +231,23 @@ UInt8 OSBitXorAtomic8(UInt32 mask, UInt8 * value) return OSBitwiseAtomic8((UInt32) -1, 0, mask, value); } - -static Boolean OSCompareAndSwap16(UInt16 oldValue16, UInt16 newValue16, UInt16 * value16) +static Boolean OSCompareAndSwap16(UInt16 oldValue16, UInt16 newValue16, UInt16 * value16) { - UInt32 mask = 0x0000ffff; - UInt32 newbits = (UInt32) newValue16; - int shift; - UInt32 alignment = ((UInt32) value16) & (sizeof(UInt32) - 1); - UInt32 oldValue; - UInt32 newValue; - UInt32 * value; - - if (alignment == 2) { - value = (UInt32 *) (value16 - 1); - shift = 0; - } - else { - // assert(alignment == 0); - value = (UInt32 *) value16; - shift = 16; - } - - mask <<= shift; - newbits <<= shift; - - oldValue = *value; - newValue = (oldValue & ~mask) | (newbits & mask); - - return OSCompareAndSwap(oldValue, newValue, value); + UInt32 mask = 0x0000ffff; + UInt32 alignment = ((UInt32) value16) & (sizeof(UInt32) - 1); + UInt32 shiftValues = (16 << 24) | (16 << 16); + UInt32 shift = (UInt32) *(((UInt8 *) &shiftValues) + alignment); + UInt32 * value32 = (UInt32 *) (((UInt32) value16) - alignment); + UInt32 oldValue; + UInt32 newValue; + + mask <<= shift; + + oldValue = *value32; + oldValue = (oldValue & ~mask) | (oldValue16 << shift); + newValue = (oldValue & ~mask) | (newValue16 << shift); + + return OSCompareAndSwap(oldValue, newValue, value32); } SInt16 OSIncrementAtomic16(SInt16 * value) diff --git a/libkern/kmod/Makefile.kmod b/libkern/kmod/Makefile.kmod index c49e1fe69..4adb8c5fb 100644 --- a/libkern/kmod/Makefile.kmod +++ b/libkern/kmod/Makefile.kmod @@ -14,7 +14,7 @@ include $(MakeInc_def) INSTALL_DIR = $(DSTROOT)/usr/lib KMOD_NAME = libkmod KMODCPP_NAME = libkmodc++ -LIB_INSTALL_FLAGS = -c -m 444 -S "-S" +LIB_INSTALL_FLAGS = -p -m 444 CFLAGS += -Wall -Wno-four-char-constants CFLAGS_PPC += -mlong-branch diff --git a/libkern/libkern/OSAtomic.h b/libkern/libkern/OSAtomic.h index c86f099c6..cb0338156 100644 --- a/libkern/libkern/OSAtomic.h +++ b/libkern/libkern/OSAtomic.h @@ -43,7 +43,7 @@ extern "C" { @param address The 4-byte aligned address of the data to update atomically. @result true if newValue was written to the address. */ -extern Boolean OSCompareAndSwap( UInt32 oldValue, UInt32 newValue, UInt32 * address ); +extern Boolean OSCompareAndSwap( UInt32 oldValue, UInt32 newValue, UInt32 * address ); /*! @function OSAddAtomic @abstract 32-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @@ -58,7 +58,7 @@ extern SInt32 OSAddAtomic(SInt32 amount, SInt32 * address); @abstract 16-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSAddAtomic16 function adds the specified amount to the value at the specified address and returns the result. @param amount The amount to add. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The result of the addition. */ extern SInt16 OSAddAtomic16(SInt32 amount, SInt16 * address); @@ -67,7 +67,7 @@ extern SInt16 OSAddAtomic16(SInt32 amount, SInt16 * address); @abstract 8-bit add operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSAddAtomic8 function adds the specified amount to the value at the specified address and returns the result. @param amount The amount to add. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The result of the addition. */ extern SInt8 OSAddAtomic8(SInt32 amount, SInt8 * address); @@ -83,7 +83,7 @@ extern SInt32 OSIncrementAtomic(SInt32 * address); /*! @function OSIncrementAtomic16 @abstract 16-bit increment operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSIncrementAtomic16 function increments the value at the specified address by one and returns the value as it was before the change. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The value before the increment. */ extern SInt16 OSIncrementAtomic16(SInt16 * address); @@ -91,7 +91,7 @@ extern SInt16 OSIncrementAtomic16(SInt16 * address); /*! @function OSIncrementAtomic8 @abstract 8-bit increment operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSIncrementAtomic8 function increments the value at the specified address by one and returns the value as it was before the change. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The value before the increment. */ extern SInt8 OSIncrementAtomic8(SInt8 * address); @@ -107,7 +107,7 @@ extern SInt32 OSDecrementAtomic(SInt32 * address); /*! @function OSDecrementAtomic16 @abstract 16-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSDecrementAtomic16 function decrements the value at the specified address by one and returns the value as it was before the change. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The value before the decrement. */ extern SInt16 OSDecrementAtomic16(SInt16 * address); @@ -115,7 +115,7 @@ extern SInt16 OSDecrementAtomic16(SInt16 * address); /*! @function OSDecrementAtomic8 @abstract 8-bit decrement operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSDecrementAtomic8 function decrements the value at the specified address by one and returns the value as it was before the change. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The value before the decrement. */ extern SInt8 OSDecrementAtomic8(SInt8 * address); @@ -133,7 +133,7 @@ extern UInt32 OSBitAndAtomic(UInt32 mask, UInt32 * address); @abstract 16-bit logical and operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitAndAtomic16 function logically ands the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically and with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The result of the logical and. */ extern UInt16 OSBitAndAtomic16(UInt32 mask, UInt16 * address); @@ -142,7 +142,7 @@ extern UInt16 OSBitAndAtomic16(UInt32 mask, UInt16 * address); @abstract 8-bit logical and operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitAndAtomic8 function logically ands the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically and with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The result of the logical and. */ extern UInt8 OSBitAndAtomic8(UInt32 mask, UInt8 * address); @@ -160,7 +160,7 @@ extern UInt32 OSBitOrAtomic(UInt32 mask, UInt32 * address); @abstract 16-bit logical or operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitOrAtomic16 function logically ors the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically or with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The result of the logical or. */ extern UInt16 OSBitOrAtomic16(UInt32 mask, UInt16 * address); @@ -169,7 +169,7 @@ extern UInt16 OSBitOrAtomic16(UInt32 mask, UInt16 * address); @abstract 8-bit logical or operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitOrAtomic8 function logically ors the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically or with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The result of the logical or. */ extern UInt8 OSBitOrAtomic8(UInt32 mask, UInt8 * address); @@ -187,7 +187,7 @@ extern UInt32 OSBitXorAtomic(UInt32 mask, UInt32 * address); @abstract 16-bit logical xor operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitXorAtomic16 function logically xors the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically or with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The 2-byte aligned address of the value to update atomically. @result The result of the logical xor. */ extern UInt16 OSBitXorAtomic16(UInt32 mask, UInt16 * address); @@ -196,7 +196,7 @@ extern UInt16 OSBitXorAtomic16(UInt32 mask, UInt16 * address); @abstract 8-bit logical xor operation, performed atomically with respect to all devices that participate in the coherency architecture of the platform. @discussion The OSBitXorAtomic8 function logically xors the bits of the specified mask into the value at the specified address and returns the result. @param mask The mask to logically or with the value. - @param address The 4-byte aligned address of the value to update atomically. + @param address The address of the value to update atomically. @result The result of the logical xor. */ extern UInt8 OSBitXorAtomic8(UInt32 mask, UInt8 * address); @@ -255,5 +255,3 @@ static __inline__ void OSSynchronizeIO(void) #endif #endif /* ! _OS_OSATOMIC_H */ - - diff --git a/libkern/libkern/OSBase.h b/libkern/libkern/OSBase.h index cfc9c01fc..2883836e9 100644 --- a/libkern/libkern/OSBase.h +++ b/libkern/libkern/OSBase.h @@ -41,5 +41,27 @@ #endif #endif +#include <stdint.h> + +__BEGIN_DECLS + +OS_INLINE +uint64_t +__OSAbsoluteTime( + AbsoluteTime abstime) +{ + return (*(uint64_t *)&abstime); +} + +OS_INLINE +uint64_t * +__OSAbsoluteTimePtr( + AbsoluteTime *abstime) +{ + return ((uint64_t *)abstime); +} + +__END_DECLS + #endif /* _OS_OSBASE_H */ diff --git a/libkern/libkern/OSTypes.h b/libkern/libkern/OSTypes.h index 120db5e11..a57a3fb63 100644 --- a/libkern/libkern/OSTypes.h +++ b/libkern/libkern/OSTypes.h @@ -80,7 +80,4 @@ typedef unsigned char Boolean; #endif /* __TYPES__ */ #endif /* __MACTYPES__ */ - #endif /* _OS_OSTYPES_H */ - - diff --git a/libkern/ppc/bcmp.s b/libkern/ppc/bcmp.s new file mode 100644 index 000000000..934ec4dcd --- /dev/null +++ b/libkern/ppc/bcmp.s @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +; +#include <ppc/asm.h> +#include <ppc/proc_reg.h> +; +; int bcmp(const void *LHS, const void *RHS, size_t len); +; +; Because bcmp returns zero if equal and nonzero otherwise, it is slightly +; faster than memcmp, which returns the difference between the first different +; bytes. +; r3 - LHS +; r4 - RHS +; r5 - len + + .align 5 + .globl EXT(bcmp) +LEXT(bcmp) + + cmpwi cr1,r5,6 ; six chars long? + mr r6,r3 ; copy LHS ptr so we can use r3 as result + mr. r3,r5 ; test length and move to r3 + bgt cr1,Llong ; more than 6 chars long + blt cr1,Lshort ; less than 6 + + ; most common operand length is 6 chars (enet addrs) + + lwz r8,0(r6) ; first 4 bytes of LHS + lwz r7,0(r4) ; and RHS + lhz r9,4(r6) ; next 2 of LHS + sub. r3,r8,r7 ; compare first 4 + bnelr ; first 4 differed (r3!=0) + lhz r10,4(r4) ; next 2 of RHS + sub r3,r9,r10 ; compare last 2 + blr ; done, result in r3 + + ; handle long strings +Llong: + srwi r0,r5,2 ; r0 = word len + mtctr r0 ; set up for loop +Llongloop: + lwz r8,0(r6) ; next 4 bytes from LHS + addi r6,r6,4 + lwz r7,0(r4) ; next 4 from RHS + addi r4,r4,4 + sub. r3,r8,r7 ; compare next 4 bytes + bdnzt+ eq,Llongloop ; loop if ctr!=0 and cr0_eq + bnelr ; done if not equal (r3!=0) + + andi. r5,r5,3 ; more to go? + + ; compare short strings (0-5 bytes long) + ; r5 = length remaining + ; cr0= set on length + ; r3 = zero if length is zero +Lshort: + beqlr ; done (r3=0) + mtctr r5 +Lshortloop: + lbz r8,0(r6) ; get next byte from LHS + addi r6,r6,1 + lbz r7,0(r4) ; and next byte from RHS + addi r4,r4,1 + sub. r3,r8,r7 ; compare + bdnzt+ eq,Lshortloop ; loop if ctr!=0 and cr0_eq + blr ; done, r3 set correctly by the subtract + diff --git a/libkern/ppc/memcmp.s b/libkern/ppc/memcmp.s new file mode 100644 index 000000000..027af6bae --- /dev/null +++ b/libkern/ppc/memcmp.s @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +; +#include <ppc/asm.h> +#include <ppc/proc_reg.h> +; +; int memcmp(const void *LHS, const void *RHS, size_t len); +; +; Memcmp returns the difference between the first two different bytes, +; or 0 if the two strings are equal. Because we compare a word at a +; time, this requires a little additional processing once we find a +; difference. +; r3 - LHS +; r4 - RHS +; r5 - len + + .align 5 + .globl EXT(memcmp) +LEXT(memcmp) + + cmpwi cr1,r5,6 ; six is the most common length + mr r6,r3 ; we want to use r3 for compare result + mr. r3,r5 ; test length for 0 + bgt cr1,Llong ; handle long strings + blt cr1,Lshort ; and short strings + + ; six char strings are special cased because they are the most common +Lsix: + lwz r8,0(r6) ; first 4 bytes of LHS + lwz r7,0(r4) ; and RHS + xor. r3,r8,r7 ; compare first 4 + bne Ldifferent ; first 4 differed + lhz r8,4(r6) ; last 2 of LHS + lhz r7,4(r4) ; last 2 of RHS + xor. r3,r8,r7 ; compare last 2 + beqlr ; done if equal + + ; strings differ, so we must compute difference between first two + ; differing bytes. + ; r8 = LHS bytes + ; r7 = RHS bytes + ; r3 = r8 xor r7 (r3!=0) +Ldifferent: + cntlzw r9,r3 ; count leading 0s in xor + rlwinm r10,r9,0,0,28 ; mask off low 3 bits, so r10 = 0, 8, 16, or 24 + subfic r6,r10,24 ; r6 := (24 - r10) + srw r4,r8,r6 ; r4 = LHS differing byte + srw r5,r7,r6 ; r5 = RHS differing byte + sub r3,r4,r5 ; r3 = difference + blr + + ; handle long strings +Llong: + srwi r0,r5,2 ; r0 = word length + mtctr r0 ; set up for loop +Llongloop: + lwz r8,0(r6) ; next 4 bytes from LHS + addi r6,r6,4 + lwz r7,0(r4) ; next 4 from RHS + addi r4,r4,4 + xor. r3,r8,r7 ; compare next 4 bytes + bdnzt+ eq,Llongloop ; loop if ctr!=0 and cr0_eq + bne Ldifferent ; these 4 bytes not equal + + andi. r5,r5,3 ; more to go? + + ; compare short strings (0-5 bytes long) + ; r5 = length (0-5) + ; cr0= set on length + ; r3 = if r5=0, then r3=0 +Lshort: + beqlr ; 0-length strings are defined to be equal (r3=0) + mtctr r5 +Lshortloop: + lbz r8,0(r6) ; get next byte from LHS + addi r6,r6,1 + lbz r7,0(r4) ; and next byte from RHS + addi r4,r4,1 + sub. r3,r8,r7 ; compare + bdnzt+ eq,Lshortloop ; lloop if ctr!=0 and cr0_eq + blr ; done, r3 set correctly by the subtract diff --git a/libkern/ppc/strlen.s b/libkern/ppc/strlen.s new file mode 100644 index 000000000..def6639f3 --- /dev/null +++ b/libkern/ppc/strlen.s @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +; +; +; Strlen, optimized for PPC. The routine we use is 2-3x faster +; then the simple loop which checks each byte for zero. +; For 0- and 1-byte strings, the simple routine is faster, but +; only by a few cycles. The algorithm used was adapted from the +; Mac OS 9 stdCLib strcopy routine, which was originally +; written by Gary Davidian. It relies on the following rather +; inobvious but very efficient test: +; +; y = dataWord + 0xFEFEFEFF +; z = ~dataWord & 0x80808080 +; if ( y & z ) = 0 then all bytes in dataWord are non-zero +; +; The test maps any non-zero byte to zeros and any zero byte to 0x80, +; with one exception: 0x01 bytes preceeding the first zero are also +; mapped to 0x80. +; +#include <ppc/asm.h> +#include <ppc/proc_reg.h> +; +; int strlen(ptr) +; +; + + .align 5 + .globl EXT(strlen) +LEXT(strlen) + + andi. r4,r3,0x03 ; test alignment first + mr r9,r3 ; store the original address for later use.... + bne LalignSource ; align the source addr if not already aligned +Llentry: + lis r5,hi16(0xFEFEFEFF) + lis r6,hi16(0x80808080) + subi r3,r3,0x04 ; pre-decrement r3 for the lwzu + ori r5,r5,lo16(0xFEFEFEFF) ; r5=0xFEFEFEFF + ori r6,r6,lo16(0x80808080) ; r6=0x80808080 + +LLoop: + lwzu r8,4(r3) ; get the first 4 bytes and increment address + add r4,r5,r8 ; r4= data + 0xFEFEFEFF + andc r7,r6,r8 ; r7= ~data & 0x80808080 + and. r4,r4,r7 ; r4= r4 & r7 + beq LLoop ; if r4 is zero, then all bytes are non-zero + +; Now we know one of the bytes in r8 is zero, +; we just have to figure out which one. +; We have mapped 0 bytes to 0x80, and nonzero bytes to 0x00, +; with one exception: +; 0x01 bytes preceeding the first zero are also mapped to 0x80. +; So we have to mask out the 0x80s caused by 0x01s before +; counting leading zeroes to get the bytes in last word. + + rlwinm r5,r8,7,0,31 ; move 0x01 bits to 0x80 position + subf r3,r9,r3 ; start to compute string length + andc r4,r4,r5 ; turn off false hits from 0x0100 worst case + cntlzw r7,r4 ; now we can count leading 0s + srwi r7,r7,3 ; convert 0,8,16,24 to 0,1,2,3 + add r3,r3,r7 ; add in nonzero bytes in last word + blr + +; We must align the source address for two reasons: to avoid spurious page +; faults, and for speed. +; r4 = low 2 bits of address (1,2, or 3) +; r3 = address +; r9 = original address (still same as r3) + +LalignSource: + lbz r5,0(r3) ; get the first byte... + subic. r4,r4,2 ; test for 1, 2 or 3 bytes + addi r3,r3,1 ; increment address + addi r6,r9,1 ; now r6==r3 + cmpwi cr1,r5,0 ; zero? + beq cr1,Lreturn ; if its zero return zero + bgt Llentry ; address is aligned now if low bits were 3 + + lbz r5,0(r3) ; get the next byte... + addi r3,r3,1 ; increment address + cmpwi cr1,r5,0 ; zero? + beq cr1,Lreturn ; if its zero return one + beq Llentry ; addr is aligned now if low bits were 2 + + lbz r5,0(r3) ; get the next byte... + addi r3,r3,1 ; increment address + cmpwi cr1,r5,0 ; zero? + bne cr1,Llentry ; not zero, continue check (now aligned) +Lreturn: + sub r3,r3,r6 ; get string length (0, 1, or 2) + blr + diff --git a/libsa/bootstrap.cpp b/libsa/bootstrap.cpp index 12c9ed6e7..3b046ab37 100644 --- a/libsa/bootstrap.cpp +++ b/libsa/bootstrap.cpp @@ -29,6 +29,8 @@ extern "C" { #include <libsa/malloc.h> }; +#include "kld_patch.h" + extern "C" { /***** * This function is used by IOCatalogue to load a kernel @@ -49,8 +51,6 @@ extern void (*remove_startup_extension_function)(const char * name); * about loading and matching drivers. */ extern int kernelLinkerPresent; - -extern IOLock * kld_lock; }; @@ -69,9 +69,6 @@ static KLDBootstrap bootstrap_obj; */ KLDBootstrap::KLDBootstrap() { - kld_lock = IOLockAlloc(); - IOLockLock(kld_lock); - kmod_load_function = &load_kernel_extension; record_startup_extensions_function = &recordStartupExtensions; @@ -79,8 +76,6 @@ KLDBootstrap::KLDBootstrap() { remove_startup_extension_function = &removeStartupExtension; kernelLinkerPresent = 1; - - IOLockUnlock(kld_lock); } /* The destructor frees all wired memory regions held @@ -88,16 +83,15 @@ KLDBootstrap::KLDBootstrap() { */ KLDBootstrap::~KLDBootstrap() { - OSDictionary * startupExtensions; + kld_file_cleanup_all_resources(); - IOLockLock(kld_lock); + /* Dump all device-tree entries for boot drivers, and all + * info on startup extensions. The IOCatalogue will now + * get personalities from kextd. + */ + clearStartupExtensionsAndLoaderInfo(); + /* Free all temporary malloc memory. + */ malloc_reset(); - - startupExtensions = getStartupExtensions(); - if (startupExtensions) startupExtensions->release(); - - IOLockUnlock(kld_lock); - IOLockFree(kld_lock); - } diff --git a/libsa/catalogue.cpp b/libsa/catalogue.cpp index 1528cc634..2de5325bd 100644 --- a/libsa/catalogue.cpp +++ b/libsa/catalogue.cpp @@ -39,7 +39,6 @@ extern "C" { #include <IOKit/assert.h> - extern "C" { extern void IODTFreeLoaderInfo( char *key, void *infoAddr, int infoSize ); extern kern_return_t host_info(host_t host, @@ -47,8 +46,6 @@ extern kern_return_t host_info(host_t host, host_info_t info, mach_msg_type_number_t *count); extern int check_cpu_subtype(cpu_subtype_t cpu_subtype); - -extern IOLock * kld_lock; }; @@ -61,6 +58,7 @@ extern IOLock * kld_lock; /********************************************************************* *********************************************************************/ static OSDictionary * gStartupExtensions = 0; +static OSArray * gBootLoaderObjects = 0; OSDictionary * getStartupExtensions(void) { if (gStartupExtensions) { @@ -75,6 +73,25 @@ OSDictionary * getStartupExtensions(void) { return gStartupExtensions; } +/* This array holds objects that are needed to be held around during + * boot before kextd starts up. Currently it contains OSData objects + * copied from OF entries for mkext archives in device ROMs. Because + * the Device Tree support code dumps these after initially handing + * them to us, we have to be able to clean them up later. + */ +OSArray * getBootLoaderObjects(void) { + if (gBootLoaderObjects) { + return gBootLoaderObjects; + } + gBootLoaderObjects = OSArray::withCapacity(1); + if (! gBootLoaderObjects) { + IOLog("Error: Couldn't allocate " + "bootstrap objects array.\n"); + LOG_DELAY(); + } + return gBootLoaderObjects; +} + /********************************************************************* * This function checks that a driver dict has all the required @@ -380,6 +397,11 @@ typedef struct BootxDriverInfo { long moduleLength; } BootxDriverInfo; +typedef struct MkextEntryInfo { + vm_address_t base_address; + mkext_file * fileinfo; +} MkextEntryInfo; + /********************************************************************* * This private function reads the data for a single extension from @@ -492,9 +514,14 @@ OSDictionary * readExtension(OSDictionary * propertyDict, /* It's perfectly okay for a KEXT to have no executable. * Check that moduleAddr is nonzero before attempting to * get one. + * + * NOTE: The driverCode object is created "no-copy", so + * it doesn't own that memory. The memory must be freed + * separately from the OSData object (see + * clearStartupExtensionsAndLoaderInfo() at the end of this file). */ if (dataBuffer->moduleAddr && dataBuffer->moduleLength) { - driverCode = OSData::withBytes(dataBuffer->moduleAddr, + driverCode = OSData::withBytesNoCopy(dataBuffer->moduleAddr, dataBuffer->moduleLength); if (!driverCode) { IOLog("Error: Couldn't allocate data object " @@ -512,12 +539,6 @@ OSDictionary * readExtension(OSDictionary * propertyDict, finish: - /* Free the memory for this extension that was set up - * by bootx. - */ - IODTFreeLoaderInfo(memory_map_name, (void *)driverInfo->paddr, - (int)driverInfo->length); - // do not release bootxDriverDataObject // do not release driverName @@ -542,14 +563,17 @@ finish: /********************************************************************* * Used to uncompress a single file entry in an mkext archive. +* +* The OSData returned does not own its memory! You must deallocate +* that memory using kmem_free() before releasing the OSData(). *********************************************************************/ -int uncompressFile(u_int8_t * base_address, - mkext_file * fileinfo, - /* out */ OSData ** file) { +static bool uncompressFile(u_int8_t *base_address, mkext_file * fileinfo, + /* out */ OSData ** file) { - int result = 1; - u_int8_t * uncompressed_file = 0; // don't free; owned by OSData obj - OSData * uncompressedFile = 0; // don't release + bool result = true; + kern_return_t kern_result; + u_int8_t * uncompressed_file = 0; // kmem_free() on error + OSData * uncompressedFile = 0; // returned size_t uncompressed_size = 0; size_t offset = OSSwapBigToHostInt32(fileinfo->offset); @@ -568,12 +592,13 @@ int uncompressFile(u_int8_t * base_address, } // Add 1 for '\0' to terminate XML string! - uncompressed_file = (u_int8_t *)kalloc(realsize + 1); - if (!uncompressed_file) { + kern_result = kmem_alloc(kernel_map, (vm_offset_t *)&uncompressed_file, + realsize + 1); + if (kern_result != KERN_SUCCESS) { IOLog("Error: Couldn't allocate data buffer " "to uncompress file.\n"); LOG_DELAY(); - result = 0; + result = false; goto finish; } @@ -583,7 +608,7 @@ int uncompressFile(u_int8_t * base_address, IOLog("Error: Couldn't allocate data object " "to uncompress file.\n"); LOG_DELAY(); - result = 0; + result = false; goto finish; } @@ -595,7 +620,7 @@ int uncompressFile(u_int8_t * base_address, IOLog("Error: Uncompressed file is not the length " "recorded.\n"); LOG_DELAY(); - result = 0; + result = false; goto finish; } } else { @@ -608,6 +633,10 @@ int uncompressFile(u_int8_t * base_address, finish: if (!result) { + if (uncompressed_file) { + kmem_free(kernel_map, (vm_address_t)uncompressed_file, + realsize + 1); + } if (uncompressedFile) { uncompressedFile->release(); *file = 0; @@ -616,6 +645,14 @@ finish: return result; } +bool uncompressModule(OSData *compData, /* out */ OSData ** file) { + + MkextEntryInfo *info = (MkextEntryInfo *) compData->getBytesNoCopy(); + + return uncompressFile((u_int8_t *) info->base_address, + info->fileinfo, file); +} + /********************************************************************* * Does the work of pulling extensions out of an mkext archive located @@ -639,6 +676,9 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info, OSString * moduleName = 0; // don't release OSString * errorString = NULL; // must release + OSData * moduleInfo = 0; // must release + MkextEntryInfo module_info; + mkext_data = (mkext_header *)mkext_file_info->paddr; if (OSSwapBigToHostInt32(mkext_data->magic) != MKEXT_MAGIC || @@ -739,18 +779,16 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info, &driverPlistDataObject)) { IOLog("Error: couldn't uncompress plist file " - "%d from multikext archive.\n", i); + "from multikext archive entry %d.\n", i); LOG_DELAY(); - result = false; - goto finish; // or just continue? + continue; } if (!driverPlistDataObject) { IOLog("Error: No property list present " "for multikext archive entry %d.\n", i); LOG_DELAY(); - result = false; - goto finish; // or just continue? + continue; } else { driverPlist = OSDynamicCast(OSDictionary, OSUnserializeXML( @@ -765,16 +803,14 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info, errorString->getCStringNoCopy()); LOG_DELAY(); } - result = false; - goto finish; // or just continue? + continue; } if (!validateExtensionDict(driverPlist)) { IOLog("Error: Failed to validate property list " "for multikext archive entry %d.\n", i); LOG_DELAY(); - result = false; - goto finish; + continue; } } @@ -815,20 +851,37 @@ bool extractExtensionsFromArchive(MemoryMapFileInfo * mkext_file_info, driverDict->setObject("plist", driverPlist); - if (!uncompressFile((u_int8_t *)mkext_data, module_file, - &driverCode)) { + /***** + * Prepare an entry to hold the mkext entry info for the + * compressed binary module, if there is one. If all four fields + * of the module entry are zero, there isn't one. + */ + if (OSSwapBigToHostInt32(module_file->offset) || + OSSwapBigToHostInt32(module_file->compsize) || + OSSwapBigToHostInt32(module_file->realsize) || + OSSwapBigToHostInt32(module_file->modifiedsecs)) { + + moduleInfo = OSData::withCapacity(sizeof(MkextEntryInfo)); + if (!moduleInfo) { + IOLog("Error: Couldn't allocate data object " + "for multikext archive entry %d.\n", i); + LOG_DELAY(); + result = false; + goto finish; + } + + module_info.base_address = (vm_address_t)mkext_data; + module_info.fileinfo = module_file; - IOLog("Error: couldn't uncompress module file " - "%d from multikext archive.\n", i); - LOG_DELAY(); - result = false; - goto finish; // or just continue? - } + if (!moduleInfo->appendBytes(&module_info, sizeof(module_info))) { + IOLog("Error: Couldn't record info " + "for multikext archive entry %d.\n", i); + LOG_DELAY(); + result = false; + goto finish; + } - /* It's okay for there to be no module - */ - if (driverCode) { - driverDict->setObject("code", driverCode); + driverDict->setObject("compressedCode", moduleInfo); } OSDictionary * incumbentExt = OSDynamicCast(OSDictionary, @@ -871,18 +924,16 @@ finish: if (driverPlistDataObject) driverPlistDataObject->release(); if (driverPlist) driverPlist->release(); - if (driverCode) driverCode->release(); - if (driverDict) driverDict->release(); + if (driverCode) driverCode->release(); + if (moduleInfo) moduleInfo->release(); + if (driverDict) driverDict->release(); if (errorString) errorString->release(); return result; } - /********************************************************************* -* Unlike with single KEXTs, a failure to read any member of a -* multi-KEXT archive is considered a failure for all. We want to -* take no chances unpacking a single, compressed archive of drivers. +* *********************************************************************/ bool readExtensions(OSDictionary * propertyDict, const char * memory_map_name, @@ -919,9 +970,6 @@ finish: extensions->flushCollection(); } - IODTFreeLoaderInfo(memory_map_name, (void *)mkext_file_info->paddr, - (int)mkext_file_info->length); - return result; } @@ -1012,18 +1060,21 @@ finish: /********************************************************************* * Called from IOCatalogue to add extensions from an mkext archive. +* This function makes a copy of the mkext object passed in because +* the device tree support code dumps it after calling us (indirectly +* through the IOCatalogue). *********************************************************************/ bool addExtensionsFromArchive(OSData * mkextDataObject) { bool result = true; OSDictionary * startupExtensions = NULL; // don't release + OSArray * bootLoaderObjects = NULL; // don't release + OSData * localMkextDataObject = NULL; // don't release OSDictionary * extensions = NULL; // must release MemoryMapFileInfo mkext_file_info; OSCollectionIterator * keyIterator = NULL; // must release OSString * key = NULL; // don't release - IOLockLock(kld_lock); - startupExtensions = getStartupExtensions(); if (!startupExtensions) { IOLog("Can't record extension archive; there is no @@ -1033,6 +1084,14 @@ bool addExtensionsFromArchive(OSData * mkextDataObject) { goto finish; } + bootLoaderObjects = getBootLoaderObjects(); + if (! bootLoaderObjects) { + IOLog("Error: Couldn't allocate array to hold temporary objects.\n"); + LOG_DELAY(); + result = false; + goto finish; + } + extensions = OSDictionary::withCapacity(2); if (!extensions) { IOLog("Error: Couldn't allocate dictionary to unpack " @@ -1042,8 +1101,25 @@ bool addExtensionsFromArchive(OSData * mkextDataObject) { goto finish; } - mkext_file_info.paddr = (UInt32)mkextDataObject->getBytesNoCopy(); - mkext_file_info.length = mkextDataObject->getLength(); + /* The mkext we've been handed (or the data it references) can go away, + * so we need to make a local copy to keep around as long as it might + * be needed. + */ + localMkextDataObject = OSData::withData(mkextDataObject); + if (!localMkextDataObject) { + IOLog("Error: Couldn't copy extension archive.\n"); + LOG_DELAY(); + result = false; + goto finish; + } + + mkext_file_info.paddr = (UInt32)localMkextDataObject->getBytesNoCopy(); + mkext_file_info.length = localMkextDataObject->getLength(); + + /* Save the local mkext data object so that we can deallocate it later. + */ + bootLoaderObjects->setObject(localMkextDataObject); + localMkextDataObject->release(); result = extractExtensionsFromArchive(&mkext_file_info, extensions); if (!result) { @@ -1092,8 +1168,6 @@ finish: if (extensions) extensions->release(); - IOLockUnlock(kld_lock); - return result; } @@ -1127,8 +1201,6 @@ bool recordStartupExtensions(void) { OSDictionary * newDriverDict = NULL; // must release OSDictionary * driverPlist = NULL; // don't release - IOLockLock(kld_lock); - IOLog("Recording startup extensions.\n"); LOG_DELAY(); @@ -1339,6 +1411,7 @@ finish: IOLog("Error: Failed to record startup extensions.\n"); LOG_DELAY(); } else { +#if DEBUG keyIterator = OSCollectionIterator::withCollection( startupExtensions); @@ -1353,6 +1426,7 @@ finish: keyIterator->release(); keyIterator = 0; } +#endif DEBUG } if (newDriverDict) newDriverDict->release(); @@ -1361,7 +1435,6 @@ finish: if (mkextExtensions) mkextExtensions->release(); if (startupExtensions) startupExtensions->release(); - IOLockUnlock(kld_lock); return result; } @@ -1382,8 +1455,6 @@ void removeStartupExtension(const char * extensionName) { OSCollectionIterator * keyIterator = NULL; // must release OSString * key = NULL; // don't release - IOLockLock(kld_lock); - startupExtensions = getStartupExtensions(); if (!startupExtensions) goto finish; @@ -1432,7 +1503,143 @@ void removeStartupExtension(const char * extensionName) { finish: if (keyIterator) keyIterator->release(); + return; +} + +/********************************************************************* +* FIXME: This function invalidates the globals gStartupExtensions and +* FIXME: ...gBootLoaderObjects without setting them to NULL. Since +* FIXME: ...the code itself is immediately unloaded, there may not be +* FIXME: ...any reason to worry about that! +*********************************************************************/ +void clearStartupExtensionsAndLoaderInfo(void) +{ + OSDictionary * startupExtensions = NULL; // must release + OSArray * bootLoaderObjects = NULL; // must release + + IORegistryEntry * bootxMemoryMap = NULL; // must release + OSDictionary * propertyDict = NULL; // must release + OSCollectionIterator * keyIterator = NULL; // must release + OSString * key = NULL; // don't release + + /***** + * Drop any temporarily held data objects. + */ + bootLoaderObjects = getBootLoaderObjects(); + if (bootLoaderObjects) { + bootLoaderObjects->release(); + } + + /**** + * If any "code" entries in driver dictionaries are accompanied + * by "compressedCode" entries, then those data objects were + * created based of of kmem_alloc()'ed memory, which must be + * freed specially. + */ + startupExtensions = getStartupExtensions(); + if (startupExtensions) { + keyIterator = + OSCollectionIterator::withCollection(startupExtensions); + if (!keyIterator) { + IOLog("Error: Couldn't allocate iterator for startup " + "extensions.\n"); + LOG_DELAY(); + goto memory_map; // bail to the memory_map label + } + + while ( (key = OSDynamicCast(OSString, + keyIterator->getNextObject())) ) { + + OSDictionary * driverDict = 0; + OSData * codeData = 0; + + driverDict = OSDynamicCast(OSDictionary, + startupExtensions->getObject(key)); + if (driverDict) { + codeData = OSDynamicCast(OSData, + driverDict->getObject("code")); + + if (codeData && + driverDict->getObject("compressedCode")) { + + kmem_free(kernel_map, + (unsigned int)codeData->getBytesNoCopy(), + codeData->getLength()); + } + } + } + + keyIterator->release(); + startupExtensions->release(); + } + +memory_map: + + /**** + * Go through the device tree's memory map and remove any driver + * data entries. + */ + bootxMemoryMap = + IORegistryEntry::fromPath( + "/chosen/memory-map", // path + gIODTPlane // plane + ); + // return value is retained so be sure to release it + + if (!bootxMemoryMap) { + IOLog("Error: Couldn't read booter memory map.\n"); + LOG_DELAY(); + goto finish; + } + + propertyDict = bootxMemoryMap->dictionaryWithProperties(); + if (!propertyDict) { + IOLog("Error: Couldn't get property dictionary " + "from memory map.\n"); + LOG_DELAY(); + goto finish; + } + + keyIterator = OSCollectionIterator::withCollection(propertyDict); + if (!keyIterator) { + IOLog("Error: Couldn't allocate iterator for driver images.\n"); + LOG_DELAY(); + goto finish; + } + + while ( (key = OSDynamicCast(OSString, + keyIterator->getNextObject())) ) { + + const char * keyValue = key->getCStringNoCopy(); + + if ( !strncmp(keyValue, BOOTX_KEXT_PREFIX, + strlen(BOOTX_KEXT_PREFIX)) || + !strncmp(keyValue, BOOTX_MULTIKEXT_PREFIX, + strlen(BOOTX_MULTIKEXT_PREFIX)) ) { + + OSData * bootxDriverDataObject = NULL; + MemoryMapFileInfo * driverInfo = 0; + + bootxDriverDataObject = OSDynamicCast(OSData, + propertyDict->getObject(keyValue)); + // don't release bootxDriverDataObject + + if (!bootxDriverDataObject) { + continue; + } + driverInfo = (MemoryMapFileInfo *) + bootxDriverDataObject->getBytesNoCopy(0, + sizeof(MemoryMapFileInfo)); + IODTFreeLoaderInfo((char *)keyValue, + (void *)driverInfo->paddr, + (int)driverInfo->length); + } + } + +finish: + if (bootxMemoryMap) bootxMemoryMap->release(); + if (propertyDict) propertyDict->release(); + if (keyIterator) keyIterator->release(); - IOLockUnlock(kld_lock); return; } diff --git a/libsa/conf/Makefile b/libsa/conf/Makefile index c744dea55..85e1a341a 100644 --- a/libsa/conf/Makefile +++ b/libsa/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(LIBKERN_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(LIBKERN_KERNEL_CONFIG) $(LIBKERN_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(LIBKERN_KERNEL_CONFIG) $(LIBKERN_KERNEL_CONFIG); \ ); .ORDER: $(COMPOBJROOT)/$(LIBKERN_KERNEL_CONFIG)/Makefile @@ -52,6 +52,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(LIBKERN_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(LIBKERN_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/libsa/conf/Makefile.template b/libsa/conf/Makefile.template index 7725d5aac..816da3ef1 100644 --- a/libsa/conf/Makefile.template +++ b/libsa/conf/Makefile.template @@ -27,7 +27,7 @@ include $(MakeInc_def) # # XXX: CFLAGS # -CFLAGS+= -DKERNEL -DLIBKERN_KERNEL_PRIVATE -DDEBUG \ +CFLAGS+= -DKERNEL -DLIBKERN_KERNEL_PRIVATE \ -Wall -Wno-four-char-constants -fno-common SFLAGS+= -DKERNEL @@ -104,9 +104,6 @@ do_build_all: do_depend %RULES --include Makedep - include $(MakeInc_rule) - include $(MakeInc_dir) diff --git a/libsa/conf/files b/libsa/conf/files index b8718a272..13ac0d965 100644 --- a/libsa/conf/files +++ b/libsa/conf/files @@ -7,11 +7,15 @@ libsa/bootstrap.cpp standard libsa/catalogue.cpp standard +libsa/kld_patch.c standard libsa/kmod.cpp standard libsa/mach.c standard -libsa/malloc.c standard libsa/misc.c standard libsa/mkext.c standard -libsa/sort.c standard -libsa/bsearch.c standard libsa/vers_rsrc.c standard + +# pseudo libc +libsa/bsearch.c standard +libsa/malloc.c standard +libsa/sort.c standard +libsa/strrchr.c standard diff --git a/libsa/conf/version.minor b/libsa/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/libsa/conf/version.minor +++ b/libsa/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/libsa/conf/version.variant b/libsa/conf/version.variant index 7f8f011eb..e69de29bb 100644 --- a/libsa/conf/version.variant +++ b/libsa/conf/version.variant @@ -1 +0,0 @@ -7 diff --git a/libsa/kld_patch.c b/libsa/kld_patch.c new file mode 100644 index 000000000..646bf14d7 --- /dev/null +++ b/libsa/kld_patch.c @@ -0,0 +1,2124 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * History: + * 2001-05-30 gvdl Initial implementation of the vtable patcher. + */ +// 45678901234567890123456789012345678901234567890123456789012345678901234567890 + +#include <mach-o/fat.h> +#include <mach-o/loader.h> +#include <mach-o/nlist.h> +#include <mach-o/reloc.h> + +#if KERNEL + +#include <stdarg.h> +#include <string.h> + +#include <sys/systm.h> + +#include <libkern/OSTypes.h> + +#include <libsa/stdlib.h> +#include <libsa/mach/mach.h> + +#include "mach_loader.h" + +#include <vm/vm_kern.h> + +enum { false = 0, true = 1 }; + +#define vm_page_size page_size + +extern load_return_t fatfile_getarch( + void * vp, // normally a (struct vnode *) + vm_offset_t data_ptr, + struct fat_arch * archret); + +#else /* !KERNEL */ +#include <unistd.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/errno.h> +#include <sys/fcntl.h> +#include <sys/stat.h> +#include <sys/mman.h> + +#include <mach/mach.h> +#include <mach/mach_error.h> + +#include <mach-o/arch.h> + +#include <CoreFoundation/CoreFoundation.h> + +#endif /* KERNEL */ + +#include "kld_patch.h" + +#if 0 +static __inline__ void DIE(void) { IODelay(2000000000); } + +#define LOG_DELAY() IODelay(200000) +#define DEBUG_LOG(x) do { IOLog x; LOG_DELAY(); } while(0) +#else + +#define DIE() +#define LOG_DELAY() +#define DEBUG_LOG(x) + +#endif + +// OSObject symbol prefixes and suffixes +#define kVTablePrefix "___vt" +#define kReservedPrefix "__RESERVED" +#define kSuperClassSuffix ".superClass" +#define kGMetaSuffix ".gMetaClass" +#define kLinkEditSegName SEG_LINKEDIT + +// GCC 2.95 drops 2 leading constants in the vtable +#define kVTablePreambleLen 2 + +// Last address that I'm willing to try find vm in +#define kTopAddr ((unsigned char *) (1024 * 1024 * 1024)) + +// Size in bytes that Data Ref object's get increased in size +// Must be a power of 2 +#define kDataCapacityIncrement 128 + +// My usual set of helper macros. I personally find these macros +// easier to read in the code rather than an explicit error condition +// check. If I don't make it easy then I may get lazy ond not check +// everything. I'm sorry if you find this code harder to read. + +// break_if will evaluate the expression and if it is true +// then it will print the msg, which is enclosed in parens +// and then break. Usually used in loops are do { } while (0) +#define break_if(expr, msg) \ + if (expr) { \ + errprintf msg; \ + break; \ + } + +// return_if will evaluate expr and if true it will log the +// msg, which is enclosed in parens, and then it will return +// with the return code of ret. +#define return_if(expr, ret, msg) do { \ + if (expr) { \ + errprintf msg; \ + return ret; \ + } \ +} while (0) + +#ifndef MIN +#define MIN(a,b) (((a)<(b))?(a):(b)) +#endif /* MIN */ +#ifndef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#endif /* MAX */ + +typedef struct Data { + unsigned long fLength, fCapacity; + unsigned char *fData; +} Data, *DataRef; + +struct sectionRecord { + const struct section *fSection; + DataRef fRelocCache; +}; + +enum patchState { + kSymbolIdentical, + kSymbolLocal, + kSymbolPadUpdate, + kSymbolSuperUpdate, + kSymbolMismatch +}; + +struct patchRecord { + struct nlist *fSymbol; + enum patchState fType; +}; + +struct relocRecord { + void *fValue; + const struct nlist *fSymbol; + struct relocation_info *fRInfo; + void *reserved; +}; + +struct metaClassRecord { + char *fSuperName; + struct fileRecord *fFile; + const struct nlist *fVTableSym; + struct patchRecord *fPatchedVTable; + char fClassName[1]; +}; + +struct fileRecord { + size_t fMapSize, fMachOSize; + const char *fPath; + unsigned char *fMap, *fMachO, *fPadEnd; + DataRef fClassList; + DataRef fSectData; + DataRef fNewSymbols, fNewStrings; + struct symtab_command *fSymtab; + struct sectionRecord *fSections; + char *fStringBase; + struct nlist *fSymbolBase; + const struct nlist *fLocalSyms; + unsigned int fNSects; + int fNLocal; + int fNewStringsLen; + Boolean fIsKernel, fNoKernelExecutable, fIsKmem; + Boolean fImageDirty, fSymbolsDirty; +}; + +static DataRef sFilesTable; +static struct fileRecord *sKernelFile; + +static DataRef sMergedFiles; +static DataRef sMergeMetaClasses; +static Boolean sMergedKernel; + +static void errprintf(const char *fmt, ...) +{ + extern void kld_error_vprintf(const char *format, va_list ap); + + va_list ap; + + va_start(ap, fmt); + kld_error_vprintf(fmt, ap); + va_end(ap); + +DIE(); +} + +static __inline__ unsigned long DataGetLength(DataRef data) +{ + return data->fLength; +} + +static __inline__ unsigned char *DataGetPtr(DataRef data) +{ + return data->fData; +} + + +static __inline__ Boolean DataContainsAddr(DataRef data, void *vAddr) +{ + unsigned char *addr = vAddr; + + return (data->fData <= addr) && (addr < data->fData + data->fLength); +} + +static __inline__ Boolean DataAddLength(DataRef data, unsigned long length) +{ + static Boolean DataSetLength(DataRef data, unsigned long length); + return DataSetLength(data, data->fLength + length); +} + +static __inline__ Boolean +DataAppendBytes(DataRef data, const void *addr, unsigned int len) +{ + unsigned long size = DataGetLength(data); + + if (!DataAddLength(data, len)) + return false; + + bcopy(addr, DataGetPtr(data) + size, len); + return true; +} + +static __inline__ Boolean DataAppendData(DataRef dst, DataRef src) +{ + return DataAppendBytes(dst, DataGetPtr(src), DataGetLength(src)); +} + +static Boolean DataSetLength(DataRef data, unsigned long length) +{ + // Don't bother to ever shrink a data object. + if (length > data->fCapacity) { + unsigned char *newData; + unsigned long newCapacity; + + newCapacity = length + kDataCapacityIncrement - 1; + newCapacity &= ~(kDataCapacityIncrement - 1); + newData = (unsigned char *) realloc(data->fData, newCapacity); + if (!newData) + return false; + + bzero(newData + data->fCapacity, newCapacity - data->fCapacity); + data->fData = newData; + data->fCapacity = newCapacity; + } + + data->fLength = length; + return true; +} + +static DataRef DataCreate(unsigned long length) +{ + DataRef data = (DataRef) malloc(sizeof(Data)); + + if (data) { + if (!length) + data->fCapacity = kDataCapacityIncrement; + else { + data->fCapacity = length + kDataCapacityIncrement - 1; + data->fCapacity &= ~(kDataCapacityIncrement - 1); + } + + data->fData = (unsigned char *) malloc(data->fCapacity); + if (!data->fData) { + free(data); + return NULL; + } + + bzero(data->fData, data->fCapacity); + data->fLength = length; + } + return data; +} + +static void DataRelease(DataRef data) +{ + if (data) { + if (data->fData) + free(data->fData); + data->fData = 0; + free(data); + } +} + +static const char * +symbolname(const struct fileRecord *file, const struct nlist *sym) +{ + unsigned long strsize; + long strx = sym->n_un.n_strx; + + if (strx >= 0) + return file->fStringBase + strx; + + strsize = file->fSymtab->strsize; + strx = -strx; + if (strx < strsize) + return file->fStringBase + strx; + + strx -= strsize; + return (char *) DataGetPtr(file->fNewStrings) + strx; +} + +static struct fileRecord *getFile(const char *path) +{ + if (sFilesTable) { + int i, nfiles; + struct fileRecord **files; + + // Check to see if we have already merged this file + nfiles = DataGetLength(sFilesTable) / sizeof(struct fileRecord *); + files = (struct fileRecord **) DataGetPtr(sFilesTable); + for (i = 0; i < nfiles; i++) { + if (!strcmp(path, files[i]->fPath)) + return files[i]; + } + } + + return NULL; +} + +static struct fileRecord * addFile(struct fileRecord *file) +{ + struct fileRecord *newFile; + + if (!sFilesTable) { + sFilesTable = DataCreate(0); + if (!sFilesTable) + return NULL; + } + + newFile = (struct fileRecord *) malloc(sizeof(struct fileRecord)); + if (!newFile) + return NULL; + + if (!DataAppendBytes(sFilesTable, &newFile, sizeof(newFile))) { + free(newFile); + return NULL; + } + + bcopy(file, newFile, sizeof(struct fileRecord)); + return newFile; +} + +// @@@ gvdl: need to clean up the sMergeMetaClasses +// @@@ gvdl: I had better fix the object file up again +static void removeFile(struct fileRecord *file) +{ + if (file->fClassList) { + DataRelease(file->fClassList); + file->fClassList = 0; + } + + if (file->fSectData) { + struct sectionRecord *section; + unsigned int i, nsect; + + nsect = file->fNSects; + section = file->fSections; + for (i = 0; i < nsect; i++, section++) { + if (section->fRelocCache) { + DataRelease(section->fRelocCache); + section->fRelocCache = 0; + } + } + + DataRelease(file->fSectData); + file->fSectData = 0; + file->fSections = 0; + file->fNSects = 0; + } + + if (file->fMap) { +#if KERNEL + if (file->fIsKmem) + kmem_free(kernel_map, (vm_address_t) file->fMap, file->fMapSize); +#else /* !KERNEL */ + if (file->fPadEnd) { + vm_address_t padVM; + vm_size_t padSize; + + padVM = round_page((vm_address_t) file->fMap + file->fMapSize); + padSize = (vm_size_t) ((vm_address_t) file->fPadEnd - padVM); + (void) vm_deallocate(mach_task_self(), padVM, padSize); + file->fPadEnd = 0; + } + + (void) munmap((caddr_t) file->fMap, file->fMapSize); +#endif /* !KERNEL */ + file->fMap = 0; + } + + file->fPath = 0; +} + +#if !KERNEL +static Boolean +mapObjectFile(struct fileRecord *file) +{ + Boolean result = false; + static unsigned char *sFileMapBaseAddr; + + int fd = 0; + + if (!sFileMapBaseAddr) { + kern_return_t ret; + vm_address_t probeAddr; + + // If we don't already have a base addr find any random chunk + // of 32 meg of VM and to use the 16 meg boundrary as a base. + ret = vm_allocate(mach_task_self(), &probeAddr, + 32 * 1024 * 1024, VM_FLAGS_ANYWHERE); + return_if(KERN_SUCCESS != ret, false, + ("Unable to allocate base memory %s\n", mach_error_string(ret))); + (void) vm_deallocate(mach_task_self(), probeAddr, 32 * 1024 * 1024); + + // Now round to the next 16 Meg boundrary + probeAddr = (probeAddr + (16 * 1024 * 1024 - 1)) + & ~(16 * 1024 * 1024 - 1); + sFileMapBaseAddr = (unsigned char *) probeAddr; + } + + fd = open(file->fPath, O_RDONLY, 0); + return_if(fd == -1, false, ("Can't open %s for reading - %s\n", + file->fPath, strerror(errno))); + + do { + kern_return_t ret; + struct stat sb; + int retaddr = -1; + + break_if(fstat(fd, &sb) == -1, + ("Can't stat %s - %s\n", file->fPath, strerror(errno))); + + file->fMapSize = sb.st_size; + file->fMap = sFileMapBaseAddr; + ret = KERN_SUCCESS; + while (file->fMap < kTopAddr) { + vm_address_t padVM; + vm_address_t padVMEnd; + vm_size_t padSize; + + padVM = round_page((vm_address_t) file->fMap + file->fMapSize); + retaddr = (int) mmap(file->fMap, file->fMapSize, + PROT_READ|PROT_WRITE, + MAP_FIXED|MAP_FILE|MAP_PRIVATE, + fd, 0); + if (-1 == retaddr) { + break_if(ENOMEM != errno, + ("mmap failed %d - %s\n", errno, strerror(errno))); + + file->fMap = (unsigned char *) padVM; + continue; + } + + + // Round up padVM to the next page after the file and assign at + // least another fMapSize more room rounded up to the next page + // boundary. + padVMEnd = round_page(padVM + file->fMapSize); + padSize = padVMEnd - padVM; + ret = vm_allocate( + mach_task_self(), &padVM, padSize, VM_FLAGS_FIXED); + if (KERN_SUCCESS == ret) { + file->fPadEnd = (unsigned char *) padVMEnd; + break; + } + else { + munmap(file->fMap, file->fMapSize); + break_if(KERN_INVALID_ADDRESS != ret, + ("Unable to allocate pad vm for %s - %s\n", + file->fPath, mach_error_string(ret))); + + file->fMap = (unsigned char *) padVMEnd; + continue; // try again wherever the vm system wants + } + } + + if (-1 == retaddr || KERN_SUCCESS != ret) + break; + + break_if(file->fMap >= kTopAddr, + ("Unable to map memory %s\n", file->fPath)); + + sFileMapBaseAddr = file->fPadEnd; + result = true; + } while(0); + + close(fd); + return result; +} +#endif /* !KERNEL */ + +static Boolean findBestArch(struct fileRecord *file) +{ + unsigned long magic; + struct fat_header *fat; + + + file->fMachOSize = file->fMapSize; + file->fMachO = file->fMap; + magic = ((const struct mach_header *) file->fMachO)->magic; + fat = (struct fat_header *) file->fMachO; + + // Try to figure out what type of file this is + return_if(file->fMapSize < sizeof(unsigned long), false, + ("%s isn't a valid object file - no magic\n", file->fPath)); + +#if KERNEL + + // CIGAM is byte-swapped MAGIC + if (magic == FAT_MAGIC || magic == FAT_CIGAM) { + + load_return_t load_return; + struct fat_arch fatinfo; + + load_return = fatfile_getarch(NULL, (vm_address_t) fat, &fatinfo); + return_if(load_return != LOAD_SUCCESS, false, + ("Extension \"%s\": has no code for this computer\n", file->fPath)); + + file->fMachO = file->fMap + fatinfo.offset; + file->fMachOSize = fatinfo.size; + magic = ((const struct mach_header *) file->fMachO)->magic; + } + +#else /* !KERNEL */ + + // Do we need to in-place swap the endianness of the fat header? + if (magic == FAT_CIGAM) { + unsigned long i; + struct fat_arch *arch; + + fat->nfat_arch = NXSwapBigLongToHost(fat->nfat_arch); + return_if(file->fMapSize < sizeof(struct fat_header) + + fat->nfat_arch * sizeof(struct fat_arch), + false, ("%s is too fat\n", file->fPath)); + + arch = (struct fat_arch *) &fat[1]; + for (i = 0; i < fat->nfat_arch; i++) { + arch[i].cputype = NXSwapBigLongToHost(arch[i].cputype); + arch[i].cpusubtype = NXSwapBigLongToHost(arch[i].cpusubtype); + arch[i].offset = NXSwapBigLongToHost(arch[i].offset); + arch[i].size = NXSwapBigLongToHost(arch[i].size); + arch[i].align = NXSwapBigLongToHost(arch[i].align); + } + + magic = NXSwapBigLongToHost(fat->magic); + } + + // Now see if we can find any valid architectures + if (magic == FAT_MAGIC) { + const NXArchInfo *myArch; + unsigned long fatsize; + struct fat_arch *arch; + + fatsize = sizeof(struct fat_header) + + fat->nfat_arch * sizeof(struct fat_arch); + return_if(file->fMapSize < fatsize, + false, ("%s isn't a valid fat file\n", file->fPath)); + + myArch = NXGetLocalArchInfo(); + arch = NXFindBestFatArch(myArch->cputype, myArch->cpusubtype, + (struct fat_arch *) &fat[1], fat->nfat_arch); + return_if(!arch, + false, ("%s hasn't got arch for %s\n", file->fPath, myArch->name)); + return_if(arch->offset + arch->size > file->fMapSize, + false, ("%s's %s arch is incomplete\n", file->fPath, myArch->name)); + file->fMachO = file->fMap + arch->offset; + file->fMachOSize = arch->size; + magic = ((const struct mach_header *) file->fMachO)->magic; + } + +#endif /* KERNEL */ + + return_if(magic != MH_MAGIC, + false, ("%s isn't a valid mach-o\n", file->fPath)); + + return true; +} + +static Boolean +parseSegments(struct fileRecord *file, struct segment_command *seg) +{ + struct sectionRecord *sections; + int i, nsects = seg->nsects; + const struct segmentMap { + struct segment_command seg; + const struct section sect[1]; + } *segMap; + + if (!nsects) { +#if KERNEL + // We don't need to look for the LinkEdit segment unless + // we are running in the kernel environment. + if (!strcmp(kLinkEditSegName, seg->segname)) { + // Grab symbol table from linkedit we will need this later + file->fSymbolBase = (void *) seg; + } +#endif + + return true; // Nothing more to do, so that was easy. + } + + if (!file->fSectData) { + file->fSectData = DataCreate(0); + if (!file->fSectData) + return false; + } + + // Increase length of section DataRef and cache data pointer + if (!DataAddLength(file->fSectData, nsects * sizeof(struct sectionRecord))) + return false; + file->fSections = (struct sectionRecord *) DataGetPtr(file->fSectData); + + // Initialise the new sections + sections = &file->fSections[file->fNSects]; + file->fNSects += nsects; + for (i = 0, segMap = (struct segmentMap *) seg; i < nsects; i++) + sections[i].fSection = &segMap->sect[i]; + + return true; +} + +// @@@ gvdl: These functions need to be hashed they are +// going to be way too slow for production code. +static const struct nlist * +findSymbolByAddress(const struct fileRecord *file, void *entry) +{ + // not quite so dumb linear search of all symbols + const struct nlist *sym; + int i, nsyms; + + // First try to find the symbol in the most likely place which is the + // extern symbols + sym = file->fLocalSyms; + for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) { + if (sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) ) + return sym; + } + + // Didn't find it in the external symbols so try to local symbols before + // giving up. + sym = file->fSymbolBase; + for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) { + if ( (sym->n_type & N_EXT) ) + return NULL; + if ( sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) ) + return sym; + } + + return NULL; +} + +struct searchContext { + const char *fSymname; + const char *fStrbase; +}; + +static int symbolSearch(const void *vKey, const void *vSym) +{ + const struct searchContext *key = (const struct searchContext *) vKey; + const struct nlist *sym = (const struct nlist *) vSym; + + return strcmp(key->fSymname, key->fStrbase + sym->n_un.n_strx); +} + +static const struct nlist * +findSymbolByName(struct fileRecord *file, const char *symname) +{ + struct searchContext context; + + context.fSymname = symname; + context.fStrbase = file->fStringBase; + return (struct nlist *) + bsearch(&context, + file->fLocalSyms, file->fNLocal, sizeof(struct nlist), + symbolSearch); +} + +static Boolean +relocateSection(const struct fileRecord *file, struct sectionRecord *sectionRec) +{ + const struct nlist *symbol; + const struct section *section; + struct relocRecord *rec; + struct relocation_info *rinfo; + unsigned long i; + unsigned long r_address, r_symbolnum, r_length; + enum reloc_type_generic r_type; + UInt8 *sectionBase; + void **entry; + + sectionRec->fRelocCache = DataCreate( + sectionRec->fSection->nreloc * sizeof(struct relocRecord)); + if (!sectionRec->fRelocCache) + return false; + + section = sectionRec->fSection; + sectionBase = file->fMachO + section->offset; + + rec = (struct relocRecord *) DataGetPtr(sectionRec->fRelocCache); + rinfo = (struct relocation_info *) (file->fMachO + section->reloff); + for (i = 0; i < section->nreloc; i++, rec++, rinfo++) { + + // Totally uninterested in scattered relocation entries + if ( (rinfo->r_address & R_SCATTERED) ) + continue; + + r_address = rinfo->r_address; + entry = (void **) (sectionBase + r_address); + + /* + * The r_address field is really an offset into the contents of the + * section and must reference something inside the section (Note + * that this is not the case for PPC_RELOC_PAIR entries but this + * can't be one with the above checks). + */ + return_if(r_address >= section->size, false, + ("Invalid relocation entry in %s - not in section\n", file->fPath)); + + // If we don't have a VANILLA entry or the Vanilla entry isn't + // a 'long' then ignore the entry and try the next. + r_type = (enum reloc_type_generic) rinfo->r_type; + r_length = rinfo->r_length; + if (r_type != GENERIC_RELOC_VANILLA || r_length != 2) + continue; + + r_symbolnum = rinfo->r_symbolnum; + + /* + * If rinfo->r_extern is set this relocation entry is an external entry + * else it is a local entry. + */ + if (rinfo->r_extern) { + /* + * This is an external relocation entry. + * r_symbolnum is an index into the input file's symbol table + * of the symbol being refered to. The symbol must be + * undefined to be used in an external relocation entry. + */ + return_if(r_symbolnum >= file->fSymtab->nsyms, false, + ("Invalid relocation entry in %s - no symbol\n", file->fPath)); + + /* + * If this is an indirect symbol resolve indirection (all chains + * of indirect symbols have been resolved so that they point at + * a symbol that is not an indirect symbol). + */ + symbol = file->fSymbolBase; + if ((symbol[r_symbolnum].n_type & N_TYPE) == N_INDR) + r_symbolnum = symbol[r_symbolnum].n_value; + symbol = &symbol[r_symbolnum]; + + return_if(symbol->n_type != (N_EXT | N_UNDF), false, + ("Invalid relocation entry in %s - extern\n", file->fPath)); + } + else { + /* + * If the symbol is not in any section then it can't be a + * pointer to a local segment and I don't care about it. + */ + if (r_symbolnum == R_ABS) + continue; + + // Note segment references are offset by 1 from 0. + return_if(r_symbolnum > file->fNSects, false, + ("Invalid relocation entry in %s - local\n", file->fPath)); + + // Find the symbol, if any, that backs this entry + symbol = findSymbolByAddress(file, *entry); + } + + rec->fValue = *entry; // Save the previous value + rec->fRInfo = rinfo; // Save a pointer to the reloc + rec->fSymbol = symbol; // Record the current symbol + + *entry = (void *) rec; // Save pointer to record in object image + } + + ((struct fileRecord *) file)->fImageDirty = true; + + return true; +} + +static const struct nlist * +findSymbolRefAtLocation(const struct fileRecord *file, + struct sectionRecord *sctn, void **loc) +{ + if (file->fIsKernel) { + if (*loc) + return findSymbolByAddress(file, *loc); + } + else if (sctn->fRelocCache || relocateSection(file, sctn)) { + struct relocRecord *reloc = (struct relocRecord *) *loc; + + if (DataContainsAddr(sctn->fRelocCache, reloc)) + return reloc->fSymbol; + } + + return NULL; +} + +static Boolean +addClass(struct fileRecord *file, + struct metaClassRecord *inClass, + const char *cname) +{ + struct metaClassRecord *newClass = NULL; + struct metaClassRecord **fileClasses = NULL; + int len; + +if (!file->fIsKernel) { // @@@ gvdl: + DEBUG_LOG(("Adding Class %s\n", cname)); +} + + if (!file->fClassList) { + file->fClassList = DataCreate(0); + if (!file->fClassList) + return false; + } + + do { + // Attempt to allocate all necessary resource first + len = strlen(cname) + 1 + + (int) (&((struct metaClassRecord *) 0)->fClassName); + newClass = (struct metaClassRecord *) malloc(len); + if (!newClass) + break; + + if (!DataAddLength(file->fClassList, sizeof(struct metaClassRecord *))) + break; + fileClasses = (struct metaClassRecord **) + (DataGetPtr(file->fClassList) + DataGetLength(file->fClassList)); + + // Copy the meta Class structure and string name into newClass + // and insert object at end of the file->fClassList and sMergeMetaClasses + *newClass = *inClass; + strcpy(newClass->fClassName, cname); + fileClasses[-1] = newClass; + + return true; + } while (0); + + if (fileClasses) + DataAddLength(file->fClassList, -sizeof(struct metaClassRecord *)); + + if (newClass) + free(newClass); + + return false; +} + +static struct metaClassRecord *getClass(DataRef classList, const char *cname) +{ + if (classList) { + int i, nclass; + struct metaClassRecord **classes, *thisClass; + + nclass = DataGetLength(classList) / sizeof(struct metaClassRecord *); + classes = (struct metaClassRecord **) DataGetPtr(classList); + for (i = 0; i < nclass; i++) { + thisClass = classes[i]; + if (!strcmp(thisClass->fClassName, cname)) + return thisClass; + } + } + + return NULL; +} + +// Add the class 'cname' to the list of known OSObject based classes +// Note 'sym' is the <cname>.superClass symbol. +static Boolean +recordClass(struct fileRecord *file, const char *cname, const struct nlist *sym) +{ + char *supername = NULL; + const char *classname = NULL; + struct metaClassRecord newClass; + char strbuffer[1024]; + + // Only do the work actual work to find the super class if we are + // not currently working on the kernel. The kernel is the end + // of all superclass chains as by definition the kernel is binary + // compatible with itself. + if (!file->fIsKernel) { + const char *dot; + const struct nlist *supersym; + const struct section *section; + struct sectionRecord *sectionRec; + unsigned char sectind = sym->n_sect; + const char *superstr; + void **location; + + // We can't resolve anything that isn't in a real section + // Note that the sectind is starts at one to make room for the + // NO_SECT flag but the fNSects field isn't offset so we have a + // '>' test. Which means this isn't an OSObject based class + if (sectind == NO_SECT || sectind > file->fNSects) + return true; + + sectionRec = file->fSections + sectind - 1; + section = sectionRec->fSection; + location = (void **) ( file->fMachO + section->offset + + sym->n_value - section->addr ); + + supersym = findSymbolRefAtLocation(file, sectionRec, location); + if (!supersym) + return true; // No superclass symbol then it isn't an OSObject. + + // Find string in file and skip leading '_' and find last '.' + superstr = symbolname(file, supersym) + 1; + dot = strrchr(superstr, '.'); + if (!dot || strcmp(dot, kGMetaSuffix)) + return true; // Not an OSObject superclass so ignore it. + + supername = (char *) malloc(dot - superstr + 1); + strncpy(supername, superstr, dot - superstr); + supername[dot - superstr] = '\0'; + } + + do { + break_if(getClass(file->fClassList, cname), + ("Duplicate class %s in %s\n", cname, file->fPath)); + + snprintf(strbuffer, sizeof(strbuffer), "%s%s", kVTablePrefix, cname); + newClass.fVTableSym = findSymbolByName(file, strbuffer); + break_if(!newClass.fVTableSym, + ("Can't find vtable %s in %s\n", cname, file->fPath)); + + newClass.fFile = file; + newClass.fSuperName = supername; + newClass.fPatchedVTable = NULL; + + // Can't use cname as it may be a stack variable + // However the vtable's string has the class name as a suffix + // so why don't we use that rather than mallocing a string. + classname = symbolname(file, newClass.fVTableSym) + + sizeof(kVTablePrefix) - 1; + break_if(!addClass(file, &newClass, classname), + ("recordClass - no memory?\n")); + + return true; + } while (0); + + if (supername) + free(supername); + + return false; +} + +static Boolean getMetaClassGraph(struct fileRecord *file) +{ + const struct nlist *sym; + const char *strbase; + int i, nsyms; + + // Search the symbol table for the local symbols that are generated + // by the metaclass system. There are three metaclass variables + // that are relevant. + // + // <ClassName>.metaClass A pointer to the meta class structure. + // <ClassName>.superClass A pointer to the super class's meta class. + // <ClassName>.gMetaClass The meta class structure itself. + // ___vt<ClassName> The VTable for the class <ClassName>. + // + // In this code I'm going to search for any symbols that + // ends in kSuperClassSuffix as this indicates this class is a conforming + // OSObject subclass and will need to be patched, and it also + // contains a pointer to the super class's meta class structure. + strbase = file->fStringBase; + sym = file->fLocalSyms; + for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) { + const char *symname; + const char *dot; + char classname[1024]; + unsigned char n_type = sym->n_type & (N_TYPE | N_EXT); + + // Check that the symbols is a global and that it has a name. + if (((N_SECT | N_EXT) != n_type && (N_ABS | N_EXT) != n_type) + || !sym->n_un.n_strx) + continue; + + // Only search from the last '.' in the symbol. + // but skip the leading '_' in all symbols first. + symname = strbase + sym->n_un.n_strx + 1; + dot = strrchr(symname, '.'); + if (!dot || strcmp(dot, kSuperClassSuffix)) + continue; + + // Got a candidate so hand it over for class processing. + return_if(dot - symname >= (int) sizeof(classname), + false, ("Symbol %s is too long\n", symname)); + + bcopy(symname, classname, dot - symname); + classname[dot - symname] = '\0'; + if (!recordClass(file, classname, sym)) + return false; + } + + return_if(!file->fClassList, false, ("Internal error, " + "getMetaClassGraph(%s) found no classes", file->fPath)); + + DEBUG_LOG(("Found %d classes in %x for %s\n", + DataGetLength(file->fClassList)/sizeof(void*), + file->fClassList, file->fPath)); + + return true; +} + +static Boolean mergeOSObjectsForFile(const struct fileRecord *file) +{ + int i, nmerged; + Boolean foundDuplicates = false; + +DEBUG_LOG(("Merging file %s\n", file->fPath)); // @@@ gvdl: + + if (!file->fClassList) + return true; + + if (!sMergedFiles) { + sMergedFiles = DataCreate(0); + return_if(!sMergedFiles, false, + ("Unable to allocate memory metaclass list\n", file->fPath)); + } + + // Check to see if we have already merged this file + nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *); + for (i = 0; i < nmerged; i++) { + if (file == ((void **) DataGetPtr(sMergedFiles))[i]) + return true; + } + + if (!sMergeMetaClasses) { + sMergeMetaClasses = DataCreate(0); + return_if(!sMergeMetaClasses, false, + ("Unable to allocate memory metaclass list\n", file->fPath)); + } + else { /* perform a duplicate check */ + int i, j, cnt1, cnt2; + struct metaClassRecord **list1, **list2; + + list1 = (struct metaClassRecord **) DataGetPtr(file->fClassList); + cnt1 = DataGetLength(file->fClassList) / sizeof(*list1); + list2 = (struct metaClassRecord **) DataGetPtr(sMergeMetaClasses); + cnt2 = DataGetLength(sMergeMetaClasses) / sizeof(*list2); + + for (i = 0; i < cnt1; i++) { + for (j = 0; j < cnt2; j++) { + if (!strcmp(list1[i]->fClassName, list2[j]->fClassName)) { + errprintf("duplicate class %s in %s & %s\n", + list1[i]->fClassName, + file->fPath, list2[j]->fFile->fPath); + } + } + } + } + if (foundDuplicates) + return false; + + return_if(!DataAppendBytes(sMergedFiles, &file, sizeof(file)), false, + ("Unable to allocate memory to merge %s\n", file->fPath)); + + return_if(!DataAppendData(sMergeMetaClasses, file->fClassList), false, + ("Unable to allocate memory to merge %s\n", file->fPath)); + + if (file == sKernelFile) + sMergedKernel = true; + + return true; +} + +// Returns a pointer to the base of the section offset by the sections +// base address. The offset is so that we can add nlist::n_values directly +// to this address and get a valid pointer in our memory. +static unsigned char * +getSectionForSymbol(const struct fileRecord *file, const struct nlist *symb, + void ***endP) +{ + const struct section *section; + unsigned char sectind; + unsigned char *base; + + sectind = symb->n_sect; // Default to symbols section + if ((symb->n_type & N_TYPE) == N_ABS && file->fIsKernel) { + // Absolute symbol so we have to iterate over our sections + for (sectind = 1; sectind <= file->fNSects; sectind++) { + unsigned long start, end; + + section = file->fSections[sectind - 1].fSection; + start = section->addr; + end = start + section->size; + if (start <= symb->n_value && symb->n_value < end) { + // Found the relevant section + break; + } + } + } + + // Is the vtable in a valid section? + return_if(sectind == NO_SECT || sectind > file->fNSects, + (unsigned char *) -1, + ("%s isn't a valid kext, bad section reference\n", file->fPath)); + + section = file->fSections[sectind - 1].fSection; + + // for when we start walking the vtable so compute offset's now. + base = file->fMachO + section->offset; + *endP = (void **) (base + section->size); + + return base - section->addr; // return with addr offset +} + +static Boolean resolveKernelVTable(struct metaClassRecord *metaClass) +{ + const struct fileRecord *file; + struct patchRecord *patchedVTable; + void **curEntry, **vtableEntries, **endSection; + unsigned char *sectionBase; + struct patchRecord *curPatch; + int classSize; + + // Should never occur but it doesn't cost us anything to check. + if (metaClass->fPatchedVTable) + return true; + +DEBUG_LOG(("Kernel vtable %s\n", metaClass->fClassName)); // @@@ gvdl: + + // Do we have a valid vtable to patch? + return_if(!metaClass->fVTableSym, + false, ("Internal error - no class vtable symbol?\n")); + + file = metaClass->fFile; + + // If the metaClass we are being to ask is in the kernel then we + // need to do a quick scan to grab the fPatchList in a reliable format + // however we don't need to check the superclass in the kernel + // as the kernel vtables are always correct wrt themselves. + // Note this ends the superclass chain recursion. + return_if(!file->fIsKernel, + false, ("Internal error - resolveKernelVTable not kernel\n")); + + if (file->fNoKernelExecutable) { + // Oh dear attempt to map the kernel's VM into my memory space + return_if(file->fNoKernelExecutable, false, + ("Internal error - fNoKernelExecutable not implemented yet\n")); + } + + // We are going to need the base and the end + sectionBase = getSectionForSymbol(file, metaClass->fVTableSym, &endSection); + if (-1 == (long) sectionBase) + return false; + + vtableEntries = (void **) (sectionBase + metaClass->fVTableSym->n_value); + curEntry = vtableEntries + kVTablePreambleLen; + for (classSize = 0; curEntry < endSection && *curEntry; classSize++) + curEntry++; + + return_if(*curEntry, false, ("Bad kernel image, short section\n")); + + patchedVTable = (struct patchRecord *) + malloc((classSize + 1) * sizeof(struct patchRecord)); + return_if(!patchedVTable, false, ("resolveKernelVTable - no memory\n")); + + // Copy the vtable of this class into the patch table + curPatch = patchedVTable; + curEntry = vtableEntries + kVTablePreambleLen; + for (; *curEntry; curEntry++, curPatch++) { + curPatch->fSymbol = (struct nlist *) + findSymbolByAddress(file, *curEntry); + curPatch->fType = kSymbolLocal; + } + + // Tag the end of the patch vtable + curPatch->fSymbol = NULL; + metaClass->fPatchedVTable = patchedVTable; + + return true; +} + +// reloc->fPatch must contain a valid pointer on entry +static struct nlist * +getNewSymbol(struct fileRecord *file, + const struct relocRecord *reloc, const char *supername) +{ + unsigned int size, i, namelen; + struct nlist **sym; + struct nlist *msym; + const char *strbase; + struct relocation_info *rinfo; + long strx; + + if (!file->fNewSymbols) { + file->fNewSymbols = DataCreate(0); + return_if(!file->fNewSymbols, NULL, + ("Unable to allocate new symbol table for %s\n", file->fPath)); + } + + // Make sure we have a string table as well for the new symbol + if (!file->fNewStrings) { + file->fNewStrings = DataCreate(0); + return_if(!file->fNewStrings, NULL, + ("Unable to allocate string table for %s\n", file->fPath)); + } + + rinfo = (struct relocation_info *) reloc->fRInfo; + size = DataGetLength(file->fNewSymbols) / sizeof(struct nlist *); + sym = (const struct nlist **) DataGetPtr(file->fNewSymbols); + // remember that the n_strx for new symbols names is negated + strbase = (const char *) + DataGetPtr(file->fNewStrings) - file->fSymtab->strsize; + for (i = 0; i < size; i++, sym++) { + const char *symname = strbase - (*sym)->n_un.n_strx; + + if (!strcmp(symname, supername)) { + rinfo->r_symbolnum = i + file->fSymtab->nsyms; + file->fSymbolsDirty = true; + return *sym; + } + } + + // Assert that this is a vaild symbol. I need this condition to be true + // for the later code to make non-zero. So the first time through I'd + // better make sure that it is 0. + return_if(reloc->fSymbol->n_sect, NULL, + ("Undefined symbol entry with non-zero section %s:%s\n", + file->fPath, symbolname(file, reloc->fSymbol))); + + msym = (struct nlist *) malloc(sizeof(struct nlist)); + return_if(!msym, + NULL, ("Unable to create symbol table entry for %s\n", file->fPath)); + + // If we are here we didn't find the symbol so create a new one now + if (!DataAppendBytes(file->fNewSymbols, &msym, sizeof(msym))) { + free(msym); + return_if(true, + NULL, ("Unable to grow symbol table for %s\n", file->fPath)); + } + + namelen = strlen(supername) + 1; + strx = DataGetLength(file->fNewStrings); + if (!DataAppendBytes(file->fNewStrings, supername, namelen)) { + free(msym); + DataAddLength(file->fNewSymbols, -sizeof(struct nlist)); // Undo harm + return_if(true, NULL, + ("Unable to grow string table for %s\n", file->fPath)); + } + + // Offset the string index by the original string table size + // and negate the address to indicate that this is a 'new' symbol + msym->n_un.n_strx = -(strx + file->fSymtab->strsize); + msym->n_type = (N_EXT | N_UNDF); + msym->n_sect = NO_SECT; + msym->n_desc = 0; + msym->n_value = 0; + + // Mark the old symbol as being potentially deletable I can use the + // n_sect field as the input symbol must be of type N_UNDF which means + // that the n_sect field must be set to NO_SECT otherwise it is an + // in valid input file. + ((struct nlist *) reloc->fSymbol)->n_un.n_strx + = -reloc->fSymbol->n_un.n_strx; + ((struct nlist *) reloc->fSymbol)->n_sect = (unsigned char) -1; + + rinfo->r_symbolnum = i + file->fSymtab->nsyms; + file->fSymbolsDirty = true; + return msym; +} + +static struct nlist * +fixOldSymbol(struct fileRecord *file, + const struct relocRecord *reloc, const char *supername) +{ + unsigned int namelen; + struct nlist *sym = (struct nlist *) reloc->fSymbol; + const char *oldname = symbolname(file, sym); + + // assert(sym->n_un.n_strx >= 0); + + namelen = strlen(supername); + if (namelen < strlen(oldname)) { + // Overwrite old string in string table + strcpy((char *) oldname, supername); + } + else { + long strx; + + // Make sure we have a string table as well for this symbol + if (!file->fNewStrings) { + file->fNewStrings = DataCreate(0); + return_if(!file->fNewStrings, NULL, + ("Unable to allocate string table for %s\n", file->fPath)); + } + + // Find the end of the fNewStrings data structure; + strx = DataGetLength(file->fNewStrings); + return_if(!DataAppendBytes(file->fNewStrings, supername, namelen + 1), + NULL, ("Unable to grow string table for %s\n", file->fPath)); + + // now add the current table size to the offset + sym->n_un.n_strx = strx + file->fSymtab->strsize; + } + + // Mark the symbol as having been processed by negating it. + // Also note that we have dirtied the file and need to repair the + // symbol table. + sym->n_un.n_strx = -sym->n_un.n_strx; + file->fSymbolsDirty = true; + return sym; +} + +static enum patchState +symbolCompare(const struct fileRecord *file, + const struct nlist *classsym, + const char *supername) +{ + const char *classname; + + + // Check to see if the target function is locally defined + // if it is then we can assume this is a local vtable override + if ((classsym->n_type & N_TYPE) != N_UNDF) + return kSymbolLocal; + + // Check to see if both symbols point to the same symbol name + // if so then we are still identical. + classname = symbolname(file, classsym); + if (!strcmp(classname, supername)) + return kSymbolIdentical; + + // Right now we know that the target's vtable entry is different from the + // superclass' vtable entry. This means that we will have to apply a + // patch to the current entry, however before returning lets check to + // see if we have a _RESERVEDnnn field 'cause we can use this as a + // registration point that must align between vtables. + if (!strncmp(supername, kReservedPrefix, sizeof(kReservedPrefix) - 1)) + return kSymbolMismatch; + + // OK, we have a superclass difference where the superclass doesn't + // reference a pad function so assume that the superclass is correct. + if (!strncmp(classname, kReservedPrefix, sizeof(kReservedPrefix) - 1)) + return kSymbolPadUpdate; + else + return kSymbolSuperUpdate; +} + +static Boolean patchVTable(struct metaClassRecord *metaClass) +{ + struct metaClassRecord *super = NULL; + struct fileRecord *file; + struct patchRecord *patchedVTable; + struct relocRecord **curReloc, **vtableRelocs, **endSection; + unsigned char *sectionBase; + int classSize; + + // Should never occur but it doesn't cost us anything to check. + if (metaClass->fPatchedVTable) + return true; + + // Do we have a valid vtable to patch? + return_if(!metaClass->fVTableSym, + false, ("Internal error - no class vtable symbol?\n")); + + file = metaClass->fFile; + + // If the metaClass we are being to ask is in the kernel then we + // need to do a quick scan to grab the fPatchList in a reliable format + // however we don't need to check the superclass in the kernel + // as the kernel vtables are always correct wrt themselves. + // Note this ends the superclass chain recursion. + return_if(file->fIsKernel, + false, ("Internal error - patchVTable shouldn't used for kernel\n")); + + if (!metaClass->fSuperName) + return false; + + // The class isn't in the kernel so make sure that the super class + // is patched before patching ouselves. + super = getClass(sMergeMetaClasses, metaClass->fSuperName); + return_if(!super, false, ("Can't find superclass for %s : %s \n", + metaClass->fClassName, metaClass->fSuperName)); + + // Superclass recursion if necessary + if (!super->fPatchedVTable) { + Boolean res; + + if (super->fFile->fIsKernel) + res = resolveKernelVTable(super); + else + res = patchVTable(super); + if (!res) + return false; + } + +DEBUG_LOG(("Patching %s\n", metaClass->fClassName)); // @@@ gvdl: + + // We are going to need the base and the end + + sectionBase = getSectionForSymbol(file, + metaClass->fVTableSym, (void ***) &endSection); + if (-1 == (long) sectionBase) + return false; + + vtableRelocs = (struct relocRecord **) + (sectionBase + metaClass->fVTableSym->n_value); + curReloc = vtableRelocs + kVTablePreambleLen; + for (classSize = 0; curReloc < endSection && *curReloc; classSize++) + curReloc++; + + return_if(*curReloc, false, + ("%s isn't a valid kext, short section\n", file->fPath)); + + patchedVTable = (struct patchRecord *) + malloc((classSize + 1) * sizeof(struct patchRecord)); + return_if(!patchedVTable, false, ("patchedVTable - no memory\n")); + + do { + struct patchRecord *curPatch; + struct nlist *symbol; + + curPatch = patchedVTable; + curReloc = vtableRelocs + kVTablePreambleLen; + + // Grab the super table patches if necessary + // Can't be patching a kernel table as we don't walk super + // class chains in the kernel symbol space. + if (super && super->fPatchedVTable) { + const struct patchRecord *spp; + + spp = super->fPatchedVTable; + + for ( ; spp->fSymbol; curReloc++, spp++, curPatch++) { + const char *supername = + symbolname(super->fFile, spp->fSymbol); + + symbol = (struct nlist *) (*curReloc)->fSymbol; + + curPatch->fType = symbolCompare(file, symbol, supername); + switch (curPatch->fType) { + case kSymbolIdentical: + case kSymbolLocal: + break; + + case kSymbolSuperUpdate: + symbol = getNewSymbol(file, (*curReloc), supername); + break; + + case kSymbolPadUpdate: + symbol = fixOldSymbol(file, (*curReloc), supername); + break; + + case kSymbolMismatch: + errprintf("%s is not compatible with its %s superclass, " + "broken superclass?\n", + metaClass->fClassName, super->fClassName); + goto abortPatch; + + default: + errprintf("Internal error - unknown patch type\n"); + goto abortPatch; + } + if (symbol) { + curPatch->fSymbol = symbol; + (*curReloc)->fSymbol = symbol; + } + else + goto abortPatch; + } + } + + // Copy the remainder of this class' vtable into the patch table + for (; *curReloc; curReloc++, curPatch++) { + // Local reloc symbols + curPatch->fType = kSymbolLocal; + curPatch->fSymbol = (struct nlist *) (*curReloc)->fSymbol; + } + + // Tag the end of the patch vtable + curPatch->fSymbol = NULL; + + metaClass->fPatchedVTable = patchedVTable; + return true; + } while(0); + +abortPatch: + if (patchedVTable) + free(patchedVTable); + + return false; +} + +static Boolean growImage(struct fileRecord *file, vm_size_t delta) +{ +#if !KERNEL + file->fMachOSize += delta; + return (file->fMachO + file->fMachOSize <= file->fPadEnd); +#else /* KERNEL */ + vm_address_t startMachO, endMachO, endMap; + vm_offset_t newMachO; + vm_size_t newsize; + unsigned long i, nsect, nclass = 0; + struct metaClassRecord **classes = NULL; + struct sectionRecord *section; + kern_return_t ret; + + startMachO = (vm_address_t) file->fMachO; + endMachO = startMachO + file->fMachOSize + delta; + endMap = (vm_address_t) file->fMap + file->fMapSize; + + // Do we have room in the current mapped image + if (endMachO < round_page(endMap)) { + file->fMachOSize += delta; + return true; + } + + newsize = endMachO - startMachO; + if (newsize < round_page(file->fMapSize)) { + // We have room in the map if we shift the macho image within the + // current map. We will have to patch up pointers into the object. + newMachO = (vm_offset_t) file->fMap; + bcopy((char *) startMachO, (char *) newMachO, file->fMachOSize); + } + else if (file->fIsKmem) { + // kmem_alloced mapping so we can try a kmem_realloc + ret = kmem_realloc(kernel_map, + (vm_address_t) file->fMap, + (vm_size_t) file->fMapSize, + &newMachO, + newsize); + if (KERN_SUCCESS != ret) + return false; + + // If the mapping didn't move then just return + if ((vm_address_t) file->fMap == newMachO) { + file->fMachOSize = file->fMapSize = newsize; + return true; + } + + // We have relocated the kmem image so we are going to have to + // move all of the pointers into the image around. + } + else { + // The image doesn't have room for us and I can't kmem_realloc + // then I just have to bite the bullet and copy the object code + // into a bigger memory segment + ret = kmem_alloc(kernel_map, &newMachO, newsize); + + if (KERN_SUCCESS != ret) + return false; + bcopy((char *) startMachO, (void *) newMachO, file->fMachOSize); + file->fIsKmem = true; + } + + + file->fMap = file->fMachO = (unsigned char *) newMachO; + file->fMapSize = newsize; + file->fMachOSize += delta; // Increment the image size + + // If we are here then we have shifted the object image in memory + // I really should change all of my pointers into the image to machO offsets + // but I have run out of time. So I'm going to very quickly go over the + // cached data structures and add adjustments to the addresses that are + // affected. I wonder how long it will take me to get them all. + // + // For every pointer into the MachO I need to add an adjustment satisfying + // the following simultanous equations + // addr_old = macho_old + fixed_offset + // addr_new = macho_new + fixed_offset therefore: + // addr_new = addr_old + (macho_new - macho_old) +#define REBASE(addr, delta) ( ((vm_address_t) (addr)) += (delta) ) + delta = newMachO - startMachO; + + // Rebase the cached in object 'struct symtab_command' pointer + REBASE(file->fSymtab, delta); + + // Rebase the cached in object 'struct nlist' pointer for all symbols + REBASE(file->fSymbolBase, delta); + + // Rebase the cached in object 'struct nlist' pointer for local symbols + REBASE(file->fLocalSyms, delta); + + // Rebase the cached in object 'char' pointer for the string table + REBASE(file->fStringBase, delta); + + // Ok now we have to go over all of the relocs one last time + // to clean up the pad updates which had their string index negated + // to indicate that we have finished with them. + section = file->fSections; + for (i = 0, nsect = file->fNSects; i < nsect; i++, section++) + REBASE(section->fSection, delta); + + // We only ever grow images that contain class lists so dont bother + // the check if file->fClassList is non-zero 'cause it can't be + // assert(file->fClassList); + nclass = DataGetLength(file->fClassList) + / sizeof(struct metaClassRecord *); + classes = (struct metaClassRecord **) DataGetPtr(file->fClassList); + for (i = 0; i < nclass; i++) { + struct patchRecord *patch; + + for (patch = classes[i]->fPatchedVTable; patch->fSymbol; patch++) { + vm_address_t symAddr = (vm_address_t) patch->fSymbol; + if (symAddr >= startMachO && symAddr < endMachO) + REBASE(patch->fSymbol, delta); + } + } + + +#undef REBASE + + return true; + +#endif /* KERNEL */ +} + +static Boolean +prepareFileForLink(struct fileRecord *file) +{ + unsigned long i, last, numnewsyms, newsymsize, newstrsize; + struct sectionRecord *section; + struct nlist **symp, *sym; + + // If we didn't even do a pseudo 'relocate' and dirty the image + // then we can just return now. + if (!file->fImageDirty) + return true; + +DEBUG_LOG(("Linking 2 %s\n", file->fPath)); // @@@ gvdl: + + // We have to go over all of the relocs to repair the damage + // that we have done to the image when we did our 'relocation' + section = file->fSections; + for (i = 0, last = file->fNSects; i < last; i++, section++) { + unsigned char *sectionBase; + struct relocRecord *rec; + unsigned long j, nreloc; + + if (section->fRelocCache) { + sectionBase = file->fMachO + section->fSection->offset; + nreloc = section->fSection->nreloc; + rec = (struct relocRecord *) DataGetPtr(section->fRelocCache); + + // We will need to repair the reloc list + for (j = 0; j < nreloc; j++, rec++) { + void **entry; + struct nlist *sym; + + // Repair Damage to object image + entry = (void **) (sectionBase + rec->fRInfo->r_address); + *entry = rec->fValue; + + // Check if the symbol that this relocation entry points + // to is marked as erasable + sym = (struct nlist *) rec->fSymbol; + if (sym && sym->n_type == (N_EXT | N_UNDF) + && sym->n_sect == (unsigned char) -1) { + // clear mark now + sym->n_un.n_strx = -sym->n_un.n_strx; + sym->n_sect = NO_SECT; + } + } + + // Clean up the fRelocCache we don't need it any more. + DataRelease(section->fRelocCache); + section->fRelocCache = 0; + } + } + file->fImageDirty = false; // Image is clean + + // If we didn't dirty the symbol table then just return + if (!file->fSymbolsDirty) + return true; + + // calculate total file size increase and check against padding + numnewsyms = (file->fNewSymbols)? DataGetLength(file->fNewSymbols) : 0; + numnewsyms /= sizeof(struct nlist *); + newsymsize = numnewsyms * sizeof(struct nlist); + newstrsize = (file->fNewStrings)? DataGetLength(file->fNewStrings) : 0; + newstrsize = (newstrsize + 3) & ~3; // Round to nearest word + + return_if(!growImage(file, newsymsize + newstrsize), + false, ("Unable to patch the extension, no memory\n", file->fPath)); + + // Push out the new symbol table if necessary + if (numnewsyms) { + caddr_t base; + + // Move the string table out of the way of the grown symbol table + // Don't forget the '\0' from end of string table. + base = (caddr_t) file->fStringBase; + bcopy(base, base + newsymsize, file->fSymtab->strsize); + file->fStringBase += newsymsize; + file->fSymtab->stroff += newsymsize; + + // Now append the new symbols to the symbol table. + base = (caddr_t) file->fSymbolBase + + file->fSymtab->nsyms * sizeof(struct nlist); + symp = (struct nlist **) DataGetPtr(file->fNewSymbols); + for (i = 0; i < numnewsyms; i++, base += sizeof(struct nlist), symp++) + bcopy(*symp, base, sizeof(struct nlist)); + file->fSymtab->nsyms += numnewsyms; + + DataRelease(file->fNewSymbols); + file->fNewSymbols = 0; + } + + // Push out the new string table if necessary + if (newstrsize) { + caddr_t base = (caddr_t) file->fStringBase + file->fSymtab->strsize; + unsigned long actuallen = DataGetLength(file->fNewStrings); + + // Set the last word in string table to zero before copying data + *((unsigned long *) ((char *) base + newstrsize - 4)) = 0; + + // Now append the new strings to the end of the file + bcopy((caddr_t) DataGetPtr(file->fNewStrings), base, actuallen); + + file->fSymtab->strsize += newstrsize; + + DataRelease(file->fNewStrings); + file->fNewStrings = 0; + } + + // Repair the symbol table string index values + // I used negative strx's to indicate symbol has been processed + sym = file->fSymbolBase; + for (i = 0, last = file->fSymtab->nsyms; i < last; i++, sym++) { + if (sym->n_un.n_strx < 0) { + if ( sym->n_type != (N_EXT | N_UNDF) + || (unsigned char) -1 != sym->n_sect) + sym->n_un.n_strx = -sym->n_un.n_strx; + else { + // This symbol isn't being used by any vtable's reloc so + // convert it into an N_ABS style of symbol, remove the + // external bit and null out the symbol name. + bzero(sym, sizeof(*sym)); + sym->n_type = N_ABS; /* type flag, see below */ + } + } + } + file->fSymbolsDirty = false; + + return true; +} + +Boolean +#if KERNEL +kld_file_map(const char *pathName, + unsigned char *map, + size_t mapSize, + Boolean isKmem) +#else +kld_file_map(const char *pathName) +#endif /* KERNEL */ +{ + struct fileRecord file, *fp = 0; + + // Already done no need to repeat + fp = getFile(pathName); + if (fp) + return true; + + bzero(&file, sizeof(file)); + file.fPath = pathName; + +#if KERNEL + file.fMap = map; + file.fMapSize = mapSize; + file.fIsKmem = isKmem; +#else + if (!mapObjectFile(&file)) + return false; +#endif /* KERNEL */ + + do { + const struct machOMapping { + struct mach_header h; + struct load_command c[1]; + } *machO; + const struct load_command *cmd; + const struct nlist *sym; + unsigned int i, firstlocal, nsyms; + unsigned long strsize; + const char *strbase; + Boolean foundOSObject; + + if (!findBestArch(&file)) + break; + + machO = (const struct machOMapping *) file.fMachO; + if (file.fMachOSize < machO->h.sizeofcmds) + break; + + // If the file type is MH_EXECUTE then this must be a kernel + // as all Kernel extensions must be of type MH_OBJECT + for (i = 0, cmd = &machO->c[0]; i < machO->h.ncmds; i++) { + if (cmd->cmd == LC_SEGMENT) { + return_if(!parseSegments(&file, (struct segment_command *) cmd), + false, ("%s isn't a valid mach-o, bad segment\n", + file.fPath)); + } + else if (cmd->cmd == LC_SYMTAB) + file.fSymtab = (struct symtab_command *) cmd; + + cmd = (struct load_command *) ((UInt8 *) cmd + cmd->cmdsize); + } + break_if(!file.fSymtab, + ("%s isn't a valid mach-o, no symbols\n", file.fPath)); + + // we found a link edit segment so recompute the bases + if (file.fSymbolBase) { + struct segment_command *link = + (struct segment_command *) file.fSymbolBase; + + file.fSymbolBase = (struct nlist *) + (link->vmaddr + (file.fSymtab->symoff - link->fileoff)); + file.fStringBase = (char *) + (link->vmaddr + (file.fSymtab->stroff - link->fileoff)); + break_if( ( (caddr_t) file.fStringBase + file.fSymtab->strsize + > (caddr_t) link->vmaddr + link->vmsize ), + ("%s isn't a valid mach-o le, bad symbols\n", file.fPath)); + } + else { + file.fSymbolBase = (struct nlist *) + (file.fMachO + file.fSymtab->symoff); + file.fStringBase = (char *) + (file.fMachO + file.fSymtab->stroff); + break_if( ( file.fSymtab->stroff + file.fSymtab->strsize + > file.fMachOSize ), + ("%s isn't a valid mach-o, bad symbols\n", file.fPath)); + } + + // If this file the kernel and do we have an executable image + file.fIsKernel = (MH_EXECUTE == machO->h.filetype); + file.fNoKernelExecutable = (vm_page_size == file.fSymtab->symoff) + && (file.fSections[0].fSection->size == 0); + + // Search for the first non-stab symbol in table + strsize = file.fSymtab->strsize; + strbase = file.fStringBase; + sym = file.fSymbolBase; + firstlocal = 0; + foundOSObject = false; + for (i = 0, nsyms = file.fSymtab->nsyms; i < nsyms; i++, sym++) { + if ((unsigned long) sym->n_un.n_strx > strsize) + break; + + // Find the first exported symbol + if ( !file.fLocalSyms && (sym->n_type & N_EXT) ) { + file.fLocalSyms = sym; + firstlocal = i; + } + + // Find the a OSObject based subclass by searching for symbols + // that have a suffix of '.superClass' + if (!foundOSObject + && ((sym->n_type & (N_TYPE | N_EXT)) == (N_SECT | N_EXT) + || (sym->n_type & (N_TYPE | N_EXT)) == (N_ABS | N_EXT)) + && sym->n_un.n_strx) { + const char *dot; + + // Only search from the last '.' in the symbol. + // but skip the leading '_' in all symbols first. + dot = strrchr(strbase + sym->n_un.n_strx + 1, '.'); + if (dot && !strcmp(dot, kSuperClassSuffix)) + foundOSObject = true; + } + + // Find the last local symbol + if ( !file.fNLocal && sym->n_type == (N_EXT | N_UNDF) ) + file.fNLocal = i - firstlocal; + + } + break_if(i < nsyms, + ("%s isn't a valid mach-o, bad symbol strings\n", file.fPath)); + + break_if(!file.fLocalSyms, ("%s has no symbols?\n", file.fPath)); + + // If we don't have any undefined symbols then all symbols + // must be local so just compute it now if necessary. + if ( !file.fNLocal ) + file.fNLocal = i - firstlocal; + + fp = addFile(&file); + if (!fp) + break; + + if (foundOSObject && !getMetaClassGraph(fp)) + break; + + if (file.fIsKernel) + sKernelFile = fp; +#if KERNEL + if (!sKernelFile) { + extern struct mach_header _mh_execute_header; + extern struct segment_command *getsegbyname(char *seg_name); + + struct segment_command *sg; + size_t kernelSize; + Boolean ret; + + sg = (struct segment_command *) getsegbyname(kLinkEditSegName); + break_if(!sg, ("Can't find kernel link edit segment\n")); + + kernelSize = sg->vmaddr + sg->vmsize - (size_t) &_mh_execute_header; + ret = kld_file_map(kld_basefile_name, + (unsigned char *) &_mh_execute_header, kernelSize, + /* isKmem */ false); + break_if(!ret, ("kld can't map kernel file")); + } +#endif /* KERNEL */ + + return true; + } while(0); + + removeFile(&file); + + return false; +} + +void *kld_file_getaddr(const char *pathName, long *size) +{ + struct fileRecord *file = getFile(pathName); + + if (!file) + return 0; + + if (size) + *size = file->fMachOSize; + + return file->fMachO; +} + +void *kld_file_lookupsymbol(const char *pathName, const char *symname) +{ + struct fileRecord *file = getFile(pathName); + const struct nlist *sym; + const struct section *section; + unsigned char *sectionBase; + unsigned char sectind; + + return_if(!file, + NULL, ("Unknown file %s\n", pathName)); + + sym = findSymbolByName(file, symname); + + // May be a non-extern symbol so look for it there + if (!sym) { + const char *strbase; + unsigned int i, nsyms; + + sym = file->fSymbolBase; + strbase = file->fStringBase; + for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) { + if ( (sym->n_type & N_EXT) ) { + sym = 0; + break; // Terminate search when we hit an extern + } + if ( (sym->n_type & N_STAB) ) + continue; + if ( !strcmp(symname, strbase + sym->n_un.n_strx) ) + break; + } + } + + return_if(!sym, + NULL, ("Unknown symbol %s in %s\n", symname, pathName)); + + // Is the vtable in a valid section? + sectind = sym->n_sect; + return_if(sectind == NO_SECT || sectind > file->fNSects, NULL, + ("Malformed object file, invalid section reference for %s in %s\n", + symname, pathName)); + + section = file->fSections[sectind - 1].fSection; + sectionBase = file->fMachO + section->offset - section->addr; + + return (void *) (sectionBase + sym->n_value); +} + +Boolean kld_file_merge_OSObjects(const char *pathName) +{ + struct fileRecord *file = getFile(pathName); + + return_if(!file, + false, ("Internal error - unable to find file %s\n", pathName)); + + return mergeOSObjectsForFile(file); +} + +Boolean kld_file_patch_OSObjects(const char *pathName) +{ + struct fileRecord *file = getFile(pathName); + struct metaClassRecord **classes; + unsigned long i, last; + + return_if(!file, + false, ("Internal error - unable to find file %s\n", pathName)); + +DEBUG_LOG(("Patch file %s\n", pathName)); // @@@ gvdl: + + // If we don't have any classes we can return now. + if (!file->fClassList) + return true; + + // If we haven't alread merged the kernel then do it now + if (!sMergedKernel && sKernelFile) + mergeOSObjectsForFile(sKernelFile); + return_if(!sMergedKernel, false, ("Internal error no kernel?\n")); + + if (!mergeOSObjectsForFile(file)) + return false; + + // Patch all of the classes in this executable + last = DataGetLength(file->fClassList) / sizeof(void *); + classes = (struct metaClassRecord **) DataGetPtr(file->fClassList); + for (i = 0; i < last; i++) { + if (!patchVTable(classes[i])) + return false; + } + + return true; +} + +Boolean kld_file_prepare_for_link() +{ + if (sMergedFiles) { + unsigned long i, nmerged = 0; + struct fileRecord **files; + + // Check to see if we have already merged this file + nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *); + files = (struct fileRecord **) DataGetPtr(sMergedFiles); + for (i = 0; i < nmerged; i++) { + if (!prepareFileForLink(files[i])) + return false; + } + } + + // Clear down the meta class table and merged file lists + DataRelease(sMergeMetaClasses); + DataRelease(sMergedFiles); + sMergedFiles = sMergeMetaClasses = NULL; + sMergedKernel = false; + + return true; +} + +void kld_file_cleanup_all_resources() +{ + unsigned long i, nfiles; + +#if KERNEL // @@@ gvdl: + // Debugger("kld_file_cleanup_all_resources"); +#endif + + if (!sFilesTable || !(nfiles = DataGetLength(sFilesTable))) + return; // Nothing to do just return now + + nfiles /= sizeof(struct fileRecord *); + for (i = 0; i < nfiles; i++) + removeFile(((void **) DataGetPtr(sFilesTable))[i]); + + // Don't really have to clean up anything more as the whole + // malloc engine is going to be released and I couldn't be bothered. +} + +#if !KERNEL +Boolean kld_file_debug_dump(const char *pathName, const char *outName) +{ + const struct fileRecord *file = getFile(pathName); + int fd; + Boolean ret = false; + + return_if(!file, false, ("Unknown file %s for dumping\n", pathName)); + + fd = open(outName, O_WRONLY|O_CREAT|O_TRUNC, 0666); + return_if(-1 == fd, false, ("Can't create output file %s - %s(%d)\n", + outName, strerror(errno), errno)); + + do { + break_if(-1 == write(fd, file->fMachO, file->fMachOSize), + ("Can't dump output file %s - %s(%d)\n", + outName, strerror(errno), errno)); + ret = true; + } while(0); + + close(fd); + + return ret; +} +#endif /* !KERNEL */ + diff --git a/libsa/kld_patch.h b/libsa/kld_patch.h new file mode 100644 index 000000000..b0e6058b3 --- /dev/null +++ b/libsa/kld_patch.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * History: + * 2001-05-30 gvdl Initial implementation of the vtable patcher. + */ + +#include <sys/cdefs.h> + +__BEGIN_DECLS + +#if KERNEL +extern Boolean kld_file_map(const char *pathName, + unsigned char *map, size_t mapSize, + Boolean isKmem); +#else +extern Boolean kld_file_map(const char *pathName); + +extern void * + kld_file_lookupsymbol(const char *pathName, const char *symbolname); + +Boolean kld_file_debug_dump(const char *pathName, const char *outName); +#endif /* KERNEL */ + +extern void *kld_file_getaddr(const char *pathName, long *size); + +extern Boolean kld_file_merge_OSObjects(const char *pathName); + +extern Boolean kld_file_patch_OSObjects(const char *pathName); + +extern Boolean kld_file_prepare_for_link(); + +extern void kld_file_cleanup_all_resources(); + +__END_DECLS diff --git a/libsa/kmod.cpp b/libsa/kmod.cpp index df62979f5..4d18d4399 100644 --- a/libsa/kmod.cpp +++ b/libsa/kmod.cpp @@ -37,13 +37,10 @@ extern "C" { #include <mach_loader.h> }; +#include "kld_patch.h" -extern "C" { -extern load_return_t fatfile_getarch( - void * vp, // normally a (struct vnode *) - vm_offset_t data_ptr, - struct fat_arch * archret); +extern "C" { extern kern_return_t kmod_create_internal( kmod_info_t *info, @@ -67,22 +64,116 @@ extern void invalidate_icache(vm_offset_t addr, unsigned cnt, int phys); }; -IOLock * kld_lock; +#define LOG_DELAY() +#define VTYELLOW "\033[33m" +#define VTRESET "\033[0m" -#define LOG_DELAY() -#define VTYELLOW "\033[33m" -#define VTRESET "\033[0m" +/********************************************************************* +* +*********************************************************************/ +bool verifyCompatibility(OSString * extName, OSString * requiredVersion) +{ + OSDictionary * extensionsDict; // don't release + OSDictionary * extDict; // don't release + OSDictionary * extPlist; // don't release + OSString * extVersion; // don't release + OSString * extCompatVersion; // don't release + UInt32 ext_version; + UInt32 ext_compat_version; + UInt32 required_version; + + /* Get the dictionary of startup extensions. + * This is keyed by module name. + */ + extensionsDict = getStartupExtensions(); + if (!extensionsDict) { + IOLog("verifyCompatibility(): No extensions dictionary.\n"); + return false; + } + + /* Get the requested extension's dictionary entry and its property + * list, containing module dependencies. + */ + extDict = OSDynamicCast(OSDictionary, + extensionsDict->getObject(extName)); + + if (!extDict) { + IOLog("verifyCompatibility(): " + "Extension \"%s\" cannot be found.\n", + extName->getCStringNoCopy()); + return false; + } + + extPlist = OSDynamicCast(OSDictionary, extDict->getObject("plist")); + if (!extPlist) { + IOLog("verifyCompatibility(): " + "Extension \"%s\" has no property list.\n", + extName->getCStringNoCopy()); + return false; + } + + + extVersion = OSDynamicCast(OSString, + extPlist->getObject("CFBundleVersion")); + if (!extVersion) { + IOLog("verifyCompatibility(): " + "Extension \"%s\" has no \"CFBundleVersion\" property.\n", + extName->getCStringNoCopy()); + return false; + } + + extCompatVersion = OSDynamicCast(OSString, + extPlist->getObject("OSBundleCompatibleVersion")); + if (!extCompatVersion) { + IOLog("verifyCompatibility(): " + "Extension \"%s\" has no \"OSBundleCompatibleVersion\" property.\n", + extName->getCStringNoCopy()); + return false; + } + + if (!VERS_parse_string(requiredVersion->getCStringNoCopy(), + &required_version)) { + IOLog("verifyCompatibility(): " + "Can't parse required version \"%s\" of dependency %s.\n", + requiredVersion->getCStringNoCopy(), + extName->getCStringNoCopy()); + return false; + } + if (!VERS_parse_string(extVersion->getCStringNoCopy(), + &ext_version)) { + IOLog("verifyCompatibility(): " + "Can't parse version \"%s\" of dependency %s.\n", + extVersion->getCStringNoCopy(), + extName->getCStringNoCopy()); + return false; + } + if (!VERS_parse_string(extCompatVersion->getCStringNoCopy(), + &ext_compat_version)) { + IOLog("verifyCompatibility(): " + "Can't parse compatible version \"%s\" of dependency %s.\n", + extCompatVersion->getCStringNoCopy(), + extName->getCStringNoCopy()); + return false; + } + + if (required_version > ext_version || required_version < ext_compat_version) { + return false; + } + + return true; +} + /********************************************************************* * This function builds a uniqued, in-order list of modules that need * to be loaded in order for kmod_name to be successfully loaded. This * list ends with kmod_name itself. *********************************************************************/ static -OSArray * getDependencyListForKmod(char * kmod_name) { +OSArray * getDependencyListForKmod(const char * kmod_name) { int error = 0; @@ -91,6 +182,9 @@ OSArray * getDependencyListForKmod(char * kmod_name) { OSDictionary * extPlist; // don't release OSString * extName; // don't release OSArray * dependencyList = NULL; // return value, caller releases + OSBoolean * isKernelResourceObj = 0; // don't release + bool isKernelResource = false; + bool declaresExecutable = false; unsigned int i; /* These are used to remove duplicates from the dependency list. @@ -161,6 +255,30 @@ OSArray * getDependencyListForKmod(char * kmod_name) { goto finish; } + /* A kext that's not a kernel extension and declares no executable has nothing + * to load, so just return an empty array. + */ + isKernelResourceObj = OSDynamicCast(OSBoolean, + extPlist->getObject("OSKernelResource")); + if (isKernelResourceObj && isKernelResourceObj->isTrue()) { + isKernelResource = true; + } else { + isKernelResource = false; + } + + if (extPlist->getObject("CFBundleExecutable")) { + declaresExecutable = true; + } else { + declaresExecutable = false; + } + + if (!isKernelResource && !declaresExecutable) { + error = 0; + goto finish; + } + + /* Okay, let's get started. + */ dependencyList->setObject(extName); @@ -219,9 +337,9 @@ OSArray * getDependencyListForKmod(char * kmod_name) { goto finish; } - curExtDepDict = OSDynamicCast(OSDictionary, - curExtPlist->getObject("OSBundleLibraries")); - if (curExtDepDict) { + curExtDepDict = OSDynamicCast(OSDictionary, + curExtPlist->getObject("OSBundleLibraries")); + if (curExtDepDict) { OSCollectionIterator * keyIterator = OSCollectionIterator::withCollection(curExtDepDict); @@ -237,6 +355,41 @@ OSArray * getDependencyListForKmod(char * kmod_name) { OSDynamicCast(OSString, keyIterator->getNextObject())) ) { + OSString * requiredVersion = OSDynamicCast(OSString, + curExtDepDict->getObject(curDepName)); + + if (!verifyCompatibility(curDepName, requiredVersion)) { + IOLog("getDependencyListForKmod(): " + "Dependency %s of %s is not compatible or is unavailable.\n", + curDepName->getCStringNoCopy(), + curName->getCStringNoCopy()); + LOG_DELAY(); + error = 1; + goto finish; + } + + /* Don't add any entries that are not kernel resources and that declare no + * executable. Such kexts have nothing to load and so don't belong in the + * dependency list. Entries that are kernel resource *do* get added, + * however, because such kexts get fake kmod entries for reference counting. + */ + isKernelResourceObj = OSDynamicCast(OSBoolean, + curExtPlist->getObject("OSKernelResource")); + if (isKernelResourceObj && isKernelResourceObj->isTrue()) { + isKernelResource = true; + } else { + isKernelResource = false; + } + if (curExtPlist->getObject("CFBundleExecutable")) { + declaresExecutable = true; + } else { + declaresExecutable = false; + } + + if (!isKernelResource && !declaresExecutable) { + continue; + } + dependencyList->setObject(curDepName); } @@ -292,7 +445,6 @@ OSArray * getDependencyListForKmod(char * kmod_name) { } - finish: if (originalList) { @@ -314,209 +466,6 @@ finish: /********************************************************************* *********************************************************************/ -static bool verifyCompatibleVersions(OSArray * dependencyList) { - bool result = true; - - OSString * requestedModuleName = NULL; - - OSDictionary * extensionsDict = NULL; - int count, i; - OSString * curName = NULL; - OSDictionary * curExt = NULL; - OSDictionary * curExtPlist = NULL; - - OSBoolean * isKernelResource = NULL; - - OSDictionary * dependencies = NULL; - OSCollectionIterator * dependencyIterator = NULL; // must release - OSString * dependencyName = NULL; - OSString * curExtDependencyVersion = NULL; - UInt32 cur_ext_required_dependency_vers; - - OSDictionary * dependency = NULL; - OSDictionary * dependencyPlist = NULL; - - OSString * dependencyVersion = NULL; - OSString * dependencyCompatibleVersion = NULL; - UInt32 dependency_vers; - UInt32 dependency_compat_vers; - - - /* Get the dictionary of startup extensions. - * This is keyed by module name. - */ - extensionsDict = getStartupExtensions(); - if (!extensionsDict) { - IOLog("verifyCompatibleVersions(): No extensions dictionary.\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - - count = dependencyList->getCount(); - if (!count) { - IOLog("verifyCompatibleVersions(): " - "Invoked with no dependency list.\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - requestedModuleName = OSDynamicCast(OSString, - dependencyList->getObject(count - 1)); - - for (i = count - 1; i >= 0; i--) { - - if (dependencyIterator) { - dependencyIterator->release(); - dependencyIterator = NULL; - } - - curName = OSDynamicCast(OSString, dependencyList->getObject(i)); - if (!curName) { - IOLog("verifyCompatibleVersions(): Internal error (1).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - curExt = OSDynamicCast(OSDictionary, - extensionsDict->getObject(curName)); - if (!curExt) { - IOLog("verifyCompatibleVersions(): Internal error (2).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - curExtPlist = OSDynamicCast(OSDictionary, - curExt->getObject("plist")); - if (!curExtPlist) { - IOLog("verifyCompatibleVersions(): Internal error (3).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - - /* In-kernel extensions don't need to check dependencies. - */ - isKernelResource = OSDynamicCast(OSBoolean, - curExtPlist->getObject("OSKernelResource")); - if (isKernelResource && isKernelResource->isTrue()) { - continue; - } - - dependencies = OSDynamicCast(OSDictionary, - curExtPlist->getObject("OSBundleLibraries")); - if (!dependencies || dependencies->getCount() < 1) { - IOLog(VTYELLOW "verifyCompatibleVersions(): Extension \"%s\" " - "declares no dependencies.\n" VTRESET, - curName->getCStringNoCopy()); - LOG_DELAY(); - result = false; - goto finish; - } - - dependencyIterator = - OSCollectionIterator::withCollection(dependencies); - if (!curExtPlist) { - IOLog("verifyCompatibleVersions(): Internal error (4).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - while ((dependencyName = OSDynamicCast(OSString, - dependencyIterator->getNextObject()))) { - - curExtDependencyVersion = OSDynamicCast(OSString, - dependencies->getObject(dependencyName)); - if (!curExtDependencyVersion) { - IOLog("verifyCompatibleVersions(): Internal error (5).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - dependency = OSDynamicCast(OSDictionary, - extensionsDict->getObject(dependencyName)); - if (!dependency) { - IOLog("verifyCompatibleVersions(): Internal error (6).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - dependencyPlist = OSDynamicCast(OSDictionary, - dependency->getObject("plist")); - if (!dependencyPlist) { - IOLog("verifyCompatibleVersions(): Internal error (7).\n"); - LOG_DELAY(); - result = false; - goto finish; - } - - dependencyVersion = OSDynamicCast(OSString, - dependencyPlist->getObject("CFBundleVersion")); - if (!curExtDependencyVersion) { - IOLog(VTYELLOW "Dependency extension \"%s\" doesn't declare a " - "version.\n" VTRESET, - dependencyName->getCStringNoCopy()); - LOG_DELAY(); - result = false; - goto finish; - } - - dependencyCompatibleVersion = OSDynamicCast(OSString, - dependencyPlist->getObject("OSBundleCompatibleVersion")); - if (!dependencyCompatibleVersion) { - IOLog(VTYELLOW "Dependency extension \"%s\" doesn't declare a " - "compatible version.\n" VTRESET, - dependencyName->getCStringNoCopy()); - LOG_DELAY(); - result = false; - goto finish; - } - -IOLog("\033[33m %s (needs %s, compat-current is %s-%s).\n" VTRESET, - dependencyName->getCStringNoCopy(), - curExtDependencyVersion->getCStringNoCopy(), - dependencyCompatibleVersion->getCStringNoCopy(), - dependencyVersion->getCStringNoCopy()); -LOG_DELAY(); - - if (!VERS_parse_string(curExtDependencyVersion->getCStringNoCopy(), - &cur_ext_required_dependency_vers)) { - } - if (!VERS_parse_string(dependencyVersion->getCStringNoCopy(), - &dependency_vers)) { - } - if (!VERS_parse_string(dependencyCompatibleVersion->getCStringNoCopy(), - &dependency_compat_vers)) { - } - - if (cur_ext_required_dependency_vers > dependency_vers || - cur_ext_required_dependency_vers < dependency_compat_vers) { - - IOLog(VTYELLOW "Cannot load extension \"%s\": dependencies " - "\"%s\" and \"%s\" are not of compatible versions.\n" VTRESET, - requestedModuleName->getCStringNoCopy(), - curName->getCStringNoCopy(), - dependencyName->getCStringNoCopy()); - LOG_DELAY(); - result = false; - goto finish; - } - } - } - -finish: - return result; -} - - /* Used in address_for_loaded_kmod. */ static kmod_info_t * g_current_kmod_info = NULL; @@ -635,35 +584,34 @@ unsigned long alloc_for_kmod( return link_load_address; } - /********************************************************************* * This function reads the startup extensions dictionary to get the * address and length of the executable data for the requested kmod. *********************************************************************/ static -int get_text_info_for_kmod(const char * kmod_name, - char ** text_address, - unsigned long * text_size) { +int map_and_patch(const char * kmod_name) { + + char *address; + + // Does the kld system already know about this kmod? + address = (char *) kld_file_getaddr(kmod_name, NULL); + if (address) + return 1; // None of these needs to be released. OSDictionary * extensionsDict; OSDictionary * kmodDict; - OSData * driverCode; - - vm_offset_t kmod_address; - typedef union { - struct mach_header mach_header; - struct fat_header fat_header; - } kmod_header_composite; - kmod_header_composite * kmod_headers; + OSData * compressedCode = 0; + // Driver Code may need to be released + OSData * driverCode; /* Get the requested kmod's info dictionary from the global * startup extensions dictionary. */ extensionsDict = getStartupExtensions(); if (!extensionsDict) { - IOLog("text_address_for_kmod(): No extensions dictionary.\n"); + IOLog("map_and_patch(): No extensions dictionary.\n"); LOG_DELAY(); return 0; } @@ -671,63 +619,72 @@ int get_text_info_for_kmod(const char * kmod_name, kmodDict = OSDynamicCast(OSDictionary, extensionsDict->getObject(kmod_name)); if (!kmodDict) { - IOLog("text_address_for_kmod(): " + IOLog("map_and_patch(): " "Extension \"%s\" cannot be found.\n", kmod_name); LOG_DELAY(); return 0; } + Boolean ret = false; + driverCode = OSDynamicCast(OSData, kmodDict->getObject("code")); - if (!driverCode) { - IOLog("text_address_for_kmod(): " - "Extension \"%s\" has no \"code\" property.\n", - kmod_name); - LOG_DELAY(); - return 0; + if (driverCode) { + ret = kld_file_map(kmod_name, + (unsigned char *) driverCode->getBytesNoCopy(), + (size_t) driverCode->getLength(), + /* isKmem */ false); + } + else { // May be an compressed extension + + // If we have a compressed segment the uncompressModule + // will return a new OSData object that points to the kmem_alloced + // memory. Note we don't take a reference to driverCode so later + // when we release it we will actually free this driver. Ownership + // of the kmem has been handed of to kld_file. + compressedCode = OSDynamicCast(OSData, + kmodDict->getObject("compressedCode")); + if (!compressedCode) { + IOLog("map_and_patch(): " + "Extension \"%s\" has no \"code\" property.\n", kmod_name); + LOG_DELAY(); + return 0; + } + if (!uncompressModule(compressedCode, &driverCode)) { + IOLog("map_and_patch(): " + "Extension \"%s\" Couldn't uncompress code.\n", kmod_name); + LOG_DELAY(); + return 0; + } + + unsigned char *driver = (unsigned char *) driverCode->getBytesNoCopy(); + size_t driverSize = driverCode->getLength(); + + ret = kld_file_map(kmod_name, driver, driverSize, /* isKmem */ true); + driverCode->release(); + if (!ret) + kmem_free(kernel_map, (vm_address_t) driver, driverSize); } - kmod_address = (vm_offset_t)driverCode->getBytesNoCopy(); - kmod_headers = (kmod_header_composite *)kmod_address; - - /* Now extract the appropriate code from the executable data. - */ - if (kmod_headers->mach_header.magic == MH_MAGIC) { - - *text_address = (char *)kmod_address; - *text_size = driverCode->getLength(); - return 1; - - } else if (kmod_headers->fat_header.magic == FAT_MAGIC || - kmod_headers->fat_header.magic == FAT_CIGAM) { - // CIGAM is byte-swapped MAGIC - - load_return_t load_return; - struct fat_arch fatinfo; - - load_return = fatfile_getarch(NULL, kmod_address, &fatinfo); - if (load_return != LOAD_SUCCESS) { - IOLog("text_address_for_kmod(): Extension \"%s\" " - "doesn't contain code for this computer.\n", kmod_name); - LOG_DELAY(); - return 0; - } - - *text_address = (char *)(kmod_address + fatinfo.offset); - *text_size = fatinfo.size; - return 1; + if (!ret) { + IOLog("map_and_patch(): " + "Extension \"%s\" Didn't successfully load.\n", kmod_name); + LOG_DELAY(); + return 0; + } - } else { - IOLog("text_address_for_kmod(): Extension \"%s\" either " - "isn't code or doesn't contain code for this computer.\n", - kmod_name); + if (!kld_file_patch_OSObjects(kmod_name)) { + IOLog("map_and_patch(): " + "Extension \"%s\" Error binding OSObjects.\n", kmod_name); LOG_DELAY(); return 0; } + // Now repair any damage that the kld patcher may have done to the image + kld_file_prepare_for_link(); + return 1; } - /********************************************************************* *********************************************************************/ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { @@ -750,8 +707,8 @@ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { if (!VERS_parse_string(kmod_info->version, &kmod_vers)) { - IOLog(VTYELLOW "verify_kmod(): kmod \"%s\" has an invalid " - "version.\n" VTRESET, kmod_info->name); + IOLog("verify_kmod(): kmod \"%s\" has an invalid " + "version.\n", kmod_info->name); LOG_DELAY(); result = false; goto finish; @@ -780,7 +737,7 @@ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { } plist = OSDynamicCast(OSDictionary, - extensionsDict->getObject("plist")); + kmodDict->getObject("plist")); if (!kmodDict) { IOLog("verify_kmod(): Kmod \"%s\" has no property list.\n", kmod_name); @@ -790,10 +747,10 @@ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { } versionString = OSDynamicCast(OSString, - extensionsDict->getObject("CFBundleVersion")); + plist->getObject("CFBundleVersion")); if (!versionString) { - IOLog(VTYELLOW "verify_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" " - "property.\n" VTRESET, + IOLog("verify_kmod(): Kmod \"%s\" has no \"CFBundleVersion\" " + "property.\n", kmod_name); LOG_DELAY(); result = false; @@ -803,16 +760,16 @@ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { if (!VERS_parse_string(versionString->getCStringNoCopy(), &plist_vers)) { - IOLog(VTYELLOW "verify_kmod(): Property list for kmod \"%s\" has " - "an invalid version.\n" VTRESET, kmod_info->name); + IOLog("verify_kmod(): Property list for kmod \"%s\" has " + "an invalid version.\n", kmod_info->name); LOG_DELAY(); result = false; goto finish; } if (kmod_vers != plist_vers) { - IOLog(VTYELLOW "verify_kmod(): Kmod \"%s\" and its property list " - "claim different versions (%s & %s).\n" VTRESET, + IOLog("verify_kmod(): Kmod \"%s\" and its property list " + "claim different versions (%s & %s).\n", kmod_info->name, kmod_info->version, versionString->getCStringNoCopy()); @@ -821,12 +778,10 @@ bool verify_kmod(const char * kmod_name, kmod_info_t * kmod_info) { goto finish; } + result = true; finish: - // FIXME: make this really return the result after conversion - return true; - return result; } @@ -946,8 +901,17 @@ kern_return_t load_kmod(OSArray * dependencyList) { if (!g_current_kmod_info->size) continue; - if (!get_text_info_for_kmod(current_kmod_name, - &kmod_address, &kmod_size)) { + if (!kld_file_merge_OSObjects(current_kmod_name)) { + IOLog("get_text_info_for_kmod(): Can't merge OSObjects \"%s\".\n", + current_kmod_name); + LOG_DELAY(); + result = KERN_FAILURE; + goto finish; + } + + kmod_address = (char *) + kld_file_getaddr(current_kmod_name, (long *) &kmod_size); + if (!kmod_address) { IOLog("get_text_info_for_kmod() failed for dependency kmod " "\"%s\".\n", current_kmod_name); @@ -957,9 +921,7 @@ kern_return_t load_kmod(OSArray * dependencyList) { } kld_result = kld_load_from_memory(&kmod_header, - current_kmod_name, - (char *)kmod_address, - kmod_size); + current_kmod_name, kmod_address, kmod_size); if (kld_result) { do_kld_unload = 1; @@ -986,19 +948,26 @@ kern_return_t load_kmod(OSArray * dependencyList) { g_current_kmod_name = requested_kmod_name; g_current_kmod_info = 0; // there is no kmod yet - if (!get_text_info_for_kmod(requested_kmod_name, - &kmod_address, &kmod_size)) { - IOLog("load_kmod: get_text_info_for_kmod() failed for " - "kmod \"%s\".\n", requested_kmod_name); + if (!map_and_patch(requested_kmod_name)) { + IOLog("load_kmod: map_and_patch() failed for " + "kmod \"%s\".\n", requested_kmod_name); + LOG_DELAY(); + result = KERN_FAILURE; + goto finish; + } + + kmod_address = (char *) + kld_file_getaddr(requested_kmod_name, (long *) &kmod_size); + if (!kmod_address) { + IOLog("load_kmod: kld_file_getaddr() failed internal error " + "on \"%s\".\n", requested_kmod_name); LOG_DELAY(); result = KERN_FAILURE; goto finish; } kld_result = kld_load_from_memory(&kmod_header, - requested_kmod_name, - (char *)kmod_address, - kmod_size); + requested_kmod_name, kmod_address, kmod_size); if (kld_result) { do_kld_unload = 1; @@ -1068,9 +1037,11 @@ kern_return_t load_kmod(OSArray * dependencyList) { goto finish; } +#if DEBUG IOLog("kmod id %d successfully created at 0x%lx, size %ld.\n", (unsigned int)kmod_id, link_buffer_address, link_buffer_size); LOG_DELAY(); +#endif DEBUG /* Record dependencies for the newly-loaded kmod. */ @@ -1149,12 +1120,7 @@ kern_return_t load_kernel_extension(char * kmod_name) { kmod_info_t * kmod_info; OSArray * dependencyList = NULL; // must release OSArray * curDependencyList = NULL; // must release - - - /* This must be the very first thing done by this function. - */ - IOLockLock(kld_lock); - + bool isKernelResource = false; /* See if the kmod is already loaded. */ @@ -1164,8 +1130,6 @@ kern_return_t load_kernel_extension(char * kmod_name) { goto finish; } - // FIXME: Need to check whether kmod is built into the kernel! - /* It isn't loaded; build a dependency list and * load those. */ @@ -1181,21 +1145,6 @@ kern_return_t load_kernel_extension(char * kmod_name) { goto finish; } - if (!verifyCompatibleVersions(dependencyList)) { - IOLog(VTYELLOW "load_kernel_extension(): " - "Version mismatch for kernel extension \"%s\".\n" VTRESET, - kmod_name); - LOG_DELAY(); -#if 0 -// FIXME: This is currently a warning only; when kexts are updated -// this will become an error. - result = KERN_FAILURE; - goto finish; -#else - IOLog(VTYELLOW "Loading anyway.\n" VTRESET); -#endif 0 - } - count = dependencyList->getCount(); for (i = 0; i < count; i++) { kern_return_t load_result; @@ -1206,18 +1155,26 @@ kern_return_t load_kernel_extension(char * kmod_name) { dependencyList->getObject(i)); cur_kmod_name = curKmodName->getCStringNoCopy(); curDependencyList = getDependencyListForKmod(cur_kmod_name); - - load_result = load_kmod(curDependencyList); - if (load_result != KERN_SUCCESS) { + if (!curDependencyList) { IOLog("load_kernel_extension(): " - "load_kmod() failed for kmod \"%s\".\n", + "Can't get dependencies for kernel extension \"%s\".\n", cur_kmod_name); LOG_DELAY(); - result = load_result; + result = KERN_FAILURE; goto finish; + } else { + load_result = load_kmod(curDependencyList); + if (load_result != KERN_SUCCESS) { + IOLog("load_kernel_extension(): " + "load_kmod() failed for kmod \"%s\".\n", + cur_kmod_name); + LOG_DELAY(); + result = load_result; + goto finish; + } + curDependencyList->release(); + curDependencyList = NULL; } - curDependencyList->release(); - curDependencyList = NULL; } @@ -1232,9 +1189,5 @@ finish: curDependencyList = NULL; } - /* This must be the very last thing done before returning. - */ - IOLockUnlock(kld_lock); - return result; } diff --git a/libsa/libsa/catalogue.h b/libsa/libsa/catalogue.h index 75efe4441..e21a0d22d 100644 --- a/libsa/libsa/catalogue.h +++ b/libsa/libsa/catalogue.h @@ -1,5 +1,9 @@ -bool recordStartupExtensions(void); -bool addExtensionsFromArchive(OSData * mkext); -void removeStartupExtension(const char * extensionName); +extern bool recordStartupExtensions(void); +extern bool addExtensionsFromArchive(OSData * mkext); +extern void removeStartupExtension(const char * extensionName); -OSDictionary * getStartupExtensions(void); +extern OSDictionary * getStartupExtensions(void); + +extern void clearStartupExtensionsAndLoaderInfo(void); + +extern bool uncompressModule(OSData *compressed, /* out */ OSData ** file); diff --git a/libsa/libsa/stdlib.h b/libsa/libsa/stdlib.h index 441b121ed..cecd0a5ff 100644 --- a/libsa/libsa/stdlib.h +++ b/libsa/libsa/stdlib.h @@ -21,7 +21,7 @@ __private_extern__ void free_all(void); // "Free" all memory blocks __private_extern__ void malloc_reset(void); // Destroy all memory regions __private_extern__ void * realloc(void * address, size_t new_size); - +__private_extern__ char * strrchr(const char *cp, int ch); __private_extern__ void qsort( void * array, diff --git a/libsa/libsa/vers_rsrc.h b/libsa/libsa/vers_rsrc.h index 71ba9051e..fb4901867 100644 --- a/libsa/libsa/vers_rsrc.h +++ b/libsa/libsa/vers_rsrc.h @@ -23,7 +23,7 @@ typedef enum { #define BCD_illegal (0xff) // full byte, 11111111 -int VERS_parse_string(char * vers_string, UInt32 * version_num); +int VERS_parse_string(const char * vers_string, UInt32 * version_num); int VERS_string(char * buffer, UInt32 length, UInt32 vers); #endif _LIBSA_VERS_H_ diff --git a/libsa/mach_loader.h b/libsa/mach_loader.h index 8e9715bcc..415f03e93 100644 --- a/libsa/mach_loader.h +++ b/libsa/mach_loader.h @@ -51,12 +51,6 @@ typedef struct _load_result { :0; } load_result_t; -load_return_t load_machfile( - struct vnode *vp, - struct mach_header *header, - unsigned long file_offset, - unsigned long macho_size, - load_result_t *result); #define LOAD_SUCCESS 0 #define LOAD_BADARCH 1 /* CPU type/subtype not found */ diff --git a/libsa/strrchr.c b/libsa/strrchr.c new file mode 100644 index 000000000..8c57859e6 --- /dev/null +++ b/libsa/strrchr.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * History: + * 2001-05-30 gvdl Duplicated from bsd/libkern/rindex.c + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/* static char sccsid[] = "@(#)rindex.c 8.1 (Berkeley) 6/4/93"; */ +#endif /* LIBC_SCCS and not lint */ + +__private_extern__ char * strrchr(const char *cp, int ch) +{ + char *save; + char c; + + for (save = (char *) 0; (c = *cp); cp++) { + if (c == ch) + save = (char *) cp; + } + + return save; +} + diff --git a/libsa/vers_rsrc.c b/libsa/vers_rsrc.c index d3b4b4a6c..65dc005a1 100644 --- a/libsa/vers_rsrc.c +++ b/libsa/vers_rsrc.c @@ -110,7 +110,7 @@ VERS_revision VERS_revision_for_string(char ** string_p) { } -int VERS_parse_string(char * vers_string, UInt32 * version_num) { +int VERS_parse_string(const char * vers_string, UInt32 * version_num) { int result = 1; VERS_version vers; char * current_char_p; diff --git a/makedefs/MakeInc.cmd b/makedefs/MakeInc.cmd index 6e8595691..9f2a856e1 100644 --- a/makedefs/MakeInc.cmd +++ b/makedefs/MakeInc.cmd @@ -17,6 +17,7 @@ LIPO = /usr/bin/lipo BASENAME = /usr/bin/basename RELPATH = $(NEXT_ROOT)/usr/local/bin/relpath +TR = /usr/bin/tr SEG_HACK = $(NEXT_ROOT)/usr/local/bin/seg_hack UNIFDEF = /usr/bin/unifdef diff --git a/makedefs/MakeInc.def b/makedefs/MakeInc.def index dec553993..c6b1b3f76 100644 --- a/makedefs/MakeInc.def +++ b/makedefs/MakeInc.def @@ -28,23 +28,36 @@ endif # # Component List # +ifndef COMPONENT_LIST export COMPONENT_LIST = osfmk bsd iokit pexpert libkern libsa -export COMPONENT = $(firstword $(subst /, ,$(shell $(RELPATH) $(SRCROOT) $(SOURCE)))) -export COMPONENT_IMPORT_LIST = $(filter-out $(COMPONENT),$(COMPONENT_LIST)) +export COMPONENT_LIST_UC := $(shell echo -n $(COMPONENT_LIST) | $(TR) a-z A-Z) +endif +ifndef COMPONENT +export COMPONENT := $(firstword $(subst /, ,$(shell $(RELPATH) $(SRCROOT) $(SOURCE)))) +export COMPONENT_IMPORT_LIST := $(filter-out $(COMPONENT),$(COMPONENT_LIST)) +else +ifeq ($(COMPONENT), .) +export COMPONENT := $(firstword $(subst /, ,$(shell $(RELPATH) $(SRCROOT) $(SOURCE)))) +export COMPONENT_IMPORT_LIST := $(filter-out $(COMPONENT),$(COMPONENT_LIST)) +endif +endif # Architecture options # # supported configurations : PPC I386 # +ifndef ARCH_CONFIGS ifdef RC_ARCHS -export ARCH_CONFIGS = $(shell echo -n $(RC_ARCHS) | tr a-z A-Z) +export ARCH_CONFIGS := $(shell echo -n $(RC_ARCHS) | $(TR) a-z A-Z) else -ifndef ARCH_CONFIGS -export ARCH_CONFIGS = $(shell arch | tr a-z A-Z) +export ARCH_CONFIGS := $(shell arch | $(TR) a-z A-Z) +endif +endif +ifdef ARCH_CONFIG +ifndef ARCH_CONFIG_LC +export ARCH_CONFIG_LC := $(shell echo -n $(ARCH_CONFIG) | $(TR) A-Z a-z) endif endif -export ARCH_CONFIG = $(firstword $(ARCH_CONFIGS)) -export arch_config = $(shell echo -n $(ARCH_CONFIG) | tr A-Z a-z) # Kernel Configuration options @@ -54,7 +67,9 @@ export arch_config = $(shell echo -n $(ARCH_CONFIG) | tr A-Z a-z) ifndef KERNEL_CONFIGS export KERNEL_CONFIGS = RELEASE endif +ifndef KERNEL_CONFIG export KERNEL_CONFIG = $(firstword $(KERNEL_CONFIGS)) +endif # # Kernel Configuration to install @@ -62,12 +77,14 @@ export KERNEL_CONFIG = $(firstword $(KERNEL_CONFIGS)) # supported install architecture : PPC I386 # export INSTALL_TYPE = RELEASE +ifndef INSTALL_ARCHS ifdef RC_ARCHS export INSTALL_ARCHS = $(ARCH_CONFIGS) else export INSTALL_ARCHS = $(ARCH_CONFIGS) endif -export INSTALL_ARCH = $(ARCH_CONFIG) +export INSTALL_ARCHS_LC := $(shell echo -n $(ARCH_CONFIGS) | $(TR) A-Z a-z) +endif export INSTALL_ARCH_DEFAULT = PPC @@ -98,9 +115,9 @@ export CFLAGS_PROFILE = export CFLAGS_PPC = -arch ppc -Dppc -DPPC -D__PPC__ -D_BIG_ENDIAN=__BIG_ENDIAN__ export CFLAGS_I386 = -arch i386 -Di386 -DI386 -D__I386__ -D_BIG_ENDIAN=__LITTLE_ENDIAN__ -export CFLAGS_RELEASEPPC = -O2 -mcpu=750 -fschedule-insns -export CFLAGS_RELEASE_TRACEPPC = -O2 -mcpu=750 -fschedule-insns -export CFLAGS_DEBUGPPC = -O1 -mcpu=750 -fschedule-insns +export CFLAGS_RELEASEPPC = -O2 -mcpu=750 -mmultiple -fschedule-insns +export CFLAGS_RELEASE_TRACEPPC = -O2 -mcpu=750 -mmultiple -fschedule-insns +export CFLAGS_DEBUGPPC = -O1 -mcpu=750 -mmultiple -fschedule-insns export CFLAGS_RELEASEI386 = -O2 export CFLAGS_DEBUGI386 = -O2 @@ -175,7 +192,7 @@ export LDFLAGS_KERNEL_DEBUG = export LDFLAGS_KERNEL_PROFILE = export LDFLAGS_KERNEL_PPC = -arch ppc -segaddr __VECTORS 0x0 -segaddr __TEXT 0x11000 -e __start -sectalign __DATA __common 0x1000 -sectalign __DATA __bss 0x1000 -export LDFLAGS_KERNEL_I386 = -arch i386 -segaddr __TEXT 0x100000 -segaddr __LINKEDIT 0x780000 -e _pstart +export LDFLAGS_KERNEL_I386 = -arch i386 -segaddr __TEXT 0x100000 -e _pstart export LDFLAGS_KERNEL = $(LDFLAGS_KERNEL_GEN) \ $($(addsuffix $(ARCH_CONFIG),LDFLAGS_KERNEL_)) \ @@ -235,6 +252,7 @@ endif KINCVERS = A KINCFRAME = $(FRAMEDIR)/Kernel.framework KINCDIR = $(KINCFRAME)/Versions/$(KINCVERS)/Headers +KPINCDIR = $(KINCFRAME)/Versions/$(KINCVERS)/PrivateHeaders # # Compononent Header file destinations diff --git a/makedefs/MakeInc.dir b/makedefs/MakeInc.dir index efa1cd788..77239fec7 100644 --- a/makedefs/MakeInc.dir +++ b/makedefs/MakeInc.dir @@ -1,7 +1,7 @@ # # Install kernel header files # -installhdrs: exporthdrs installhdrs_mi installhdrs_md +installhdrs: SRCROOT DSTROOT OBJROOT exporthdrs installhdrs_mi installhdrs_md @echo "[ $(SRCROOT) ] make installhdrs installing Kernel.framework"; \ kincpath=$(DSTROOT)/$(KINCDIR); \ kframepath=$(DSTROOT)/$(KINCFRAME); \ @@ -19,6 +19,9 @@ installhdrs: exporthdrs installhdrs_mi installhdrs_md [ -L Current ] || $(LN) $(KINCVERS) Current; \ cd $$kframepath; \ [ -L Headers ] || $(LN) Versions/Current/Headers Headers; \ + $(MKDIR) $(DSTROOT)/$(KPINCDIR); \ + cd $$kframepath; [ -L PrivateHeaders ] || \ + $(LN) Versions/Current/PrivateHeaders PrivateHeaders; \ find $$kframepath -type f | xargs -s 32000 chmod a-w # @@ -29,7 +32,7 @@ installhdrs: exporthdrs installhdrs_mi installhdrs_md # # Install machine independent header files # -installhdrs_mi: SRCROOT DSTROOT OBJROOT +installhdrs_mi: @echo "[ $(SOURCE) ] make installhdrs_mi "; \ rel_path=$(shell $(RELPATH) $(SRCROOT) $(SOURCE)); \ kernel_config=$(INSTALL_TYPE); \ @@ -48,7 +51,7 @@ installhdrs_mi: SRCROOT DSTROOT OBJROOT # # Install machine dependent kernel header files # -installhdrs_md: SRCROOT DSTROOT OBJROOT +installhdrs_md: @echo "[ $(SOURCE) ] make installhdrs_md "; \ rel_path=$(shell $(RELPATH) $(SRCROOT) $(SOURCE)); \ kernel_config=$(INSTALL_TYPE); \ @@ -72,15 +75,11 @@ do_installhdrs_mi: build_installhdrs_mi:: @echo "[ $(SOURCE) ] make build_installhdrs_mi $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(INSTALL_TYPE); \ - arch_config=$(ARCH_CONFIG); \ for installinc_subdir in $(INSTINC_SUBDIRS); \ do \ $(MKDIR) $${installinc_subdir}; \ (cd $${installinc_subdir}; \ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=$(SOURCE)$${installinc_subdir}/Makefile \ + ${MAKE} MAKEFILES=$(SOURCE)$${installinc_subdir}/Makefile \ SOURCE=$(SOURCE)$${installinc_subdir}/ \ TARGET=$(TARGET)$${installinc_subdir}/ \ build_installhdrs_mi \ @@ -95,15 +94,11 @@ do_installhdrs_md: build_installhdrs_md:: @echo "[ $(SOURCE) ] make installhdrs_md $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(KERNEL_CONFIG); \ - arch_config=$(ARCH_CONFIG); \ for installinc_subdir in $($(addprefix INSTINC_SUBDIRS_, $(ARCH_CONFIG))); \ do \ $(MKDIR) $${installinc_subdir}; \ (cd $${installinc_subdir}; \ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=$(SOURCE)$${installinc_subdir}/Makefile \ + ${MAKE} MAKEFILES=$(SOURCE)$${installinc_subdir}/Makefile \ SOURCE=$(SOURCE)$${installinc_subdir}/ \ TARGET=$(TARGET)$${installinc_subdir}/ \ build_installhdrs_md \ @@ -114,7 +109,7 @@ build_installhdrs_md:: # # Install kernel header files # -exporthdrs: exporthdrs_mi exporthdrs_md +exporthdrs: SRCROOT DSTROOT OBJROOT exporthdrs_mi exporthdrs_md # # Install header files order @@ -126,7 +121,7 @@ exporthdrs: exporthdrs_mi exporthdrs_md # do_exporthdrs_mi: -exporthdrs_mi: SRCROOT DSTROOT OBJROOT +exporthdrs_mi: @echo "[ ${SOURCE} ] make exporthdrs_mi "; \ rel_path=$(shell $(RELPATH) $(SRCROOT) $(SOURCE)); \ kernel_config=$(INSTALL_TYPE); \ @@ -145,7 +140,7 @@ exporthdrs_mi: SRCROOT DSTROOT OBJROOT # # Install machine dependent kernel header files # -exporthdrs_md: SRCROOT DSTROOT OBJROOT +exporthdrs_md: @echo "[ $(SOURCE) ] make exporthdrs_md "; \ rel_path=$(shell $(RELPATH) $(SRCROOT) $(SOURCE)); \ kernel_config=$(INSTALL_TYPE); \ @@ -170,15 +165,11 @@ do_exporthdrs_mi: build_exporthdrs_mi: @echo "[ $(SOURCE) ] make build_exporthdrs_mi $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(INSTALL_TYPE); \ - arch_config=$(ARCH_CONFIG); \ for exportinc_subdir in $(EXPINC_SUBDIRS); \ do \ $(MKDIR) $${exportinc_subdir}; \ (cd $${exportinc_subdir}; \ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=$(SOURCE)$${exportinc_subdir}/Makefile \ + ${MAKE} MAKEFILES=$(SOURCE)$${exportinc_subdir}/Makefile \ SOURCE=$(SOURCE)$${exportinc_subdir}/ \ TARGET=$(TARGET)$${exportinc_subdir}/ \ build_exporthdrs_mi \ @@ -193,15 +184,11 @@ do_exporthdrs_md: build_exporthdrs_md: @echo "[ $(SOURCE) ] make exporthdrs_md $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(KERNEL_CONFIG); \ - arch_config=$(ARCH_CONFIG); \ for exportinc_subdir in $($(addprefix EXPINC_SUBDIRS_, $(ARCH_CONFIG))); \ do \ $(MKDIR) $${exportinc_subdir}; \ (cd $${exportinc_subdir}; \ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=$(SOURCE)$${exportinc_subdir}/Makefile \ + ${MAKE} MAKEFILES=$(SOURCE)$${exportinc_subdir}/Makefile \ SOURCE=$(SOURCE)$${exportinc_subdir}/ \ TARGET=$(TARGET)$${exportinc_subdir}/ \ build_exporthdrs_md \ @@ -236,15 +223,11 @@ do_build_setup: build_setup: @echo "[ $(SOURCE) ] make build_setup $(COMPONENT) $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(KERNEL_CONFIG); \ - arch_config=$(ARCH_CONFIG); \ for setup_subdir in $(SETUP_SUBDIRS) $($(addprefix SETUP_SUBDIRS_, $(ARCH_CONFIG))); \ do \ $(MKDIR) $${setup_subdir}; \ (cd $${setup_subdir}; \ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=${SOURCE}/$${setup_subdir}/Makefile \ + ${MAKE} MAKEFILES=${SOURCE}/$${setup_subdir}/Makefile \ SOURCE=${SOURCE}/$${setup_subdir}/ \ TARGET=${TARGET}/$${setup_subdir}/ \ build_setup \ @@ -266,13 +249,10 @@ all: SRCROOT DSTROOT OBJROOT build_subdir=${OBJROOT}/$${kernel_config}_$${arch_config}/$${rel_path}; \ $(MKDIR) $${build_subdir}; \ (cd $${build_subdir}; \ - new_component=$(firstword $(subst /, ,$(subst $(shell $(RELPATH) -d / $(SRCROOT) $(SRCROOT)),,$(addprefix $(shell $(RELPATH) -d / $(SOURCE) $(SOURCE))/,$${rel_path}))));\ - target_subdir=${OBJROOT}/$${kernel_config}_$${arch_config}/$${new_component}; \ ${MAKE} KERNEL_CONFIG=$${kernel_config} \ ARCH_CONFIG=$${arch_config} \ MAKEFILES=${SOURCE}/Makefile \ SOURCE=${SOURCE}/ \ - TARGET=$${target_subdir}/ \ build_all \ ); \ done; \ @@ -284,23 +264,19 @@ all: SRCROOT DSTROOT OBJROOT do_build_all: build_all: - @echo "[ $(SOURCE) ] make build_all $(COMPONENT) $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - kernel_config=$(KERNEL_CONFIG); \ - arch_config=$(ARCH_CONFIG); \ + @TARGET=${OBJROOT}/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT); \ + echo "[ $(SOURCE) ] make build_all $(COMPONENT) $(KERNEL_CONFIG) $(ARCH_CONFIG) $${TARGET}"; \ for comp_subdir in $(COMP_SUBDIRS) $($(addprefix COMP_SUBDIRS_, $(ARCH_CONFIG))); \ do \ $(MKDIR) $${comp_subdir}; \ (cd $${comp_subdir}; \ - new_component=$(firstword $(subst /, ,$(subst $(shell $(RELPATH) -d / $(SRCROOT) $(SRCROOT)),,$(addprefix $(shell $(RELPATH) -d / $(SOURCE) $(SOURCE))/, $${comp_subdir}))));\ - ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ - MAKEFILES=${SOURCE}/$${comp_subdir}/Makefile \ + ${MAKE} MAKEFILES=${SOURCE}/$${comp_subdir}/Makefile \ SOURCE=${SOURCE}$${comp_subdir}/ \ - TARGET=${OBJROOT}/$${kernel_config}_$${arch_config}/$${new_component} \ + TARGET=$${TARGET} \ build_all \ ); \ done; \ - ${MAKE} do_build_all; + ${MAKE} INCL_MAKEDEP=TRUE TARGET=$${TARGET} do_build_all; # # Build all architectures for all Configuration/Architecture options @@ -353,13 +329,10 @@ install: SRCROOT DSTROOT OBJROOT SYMROOT installhdrs all install_subdir=${OBJROOT}/$${kernel_config}_$${arch_config}/$${rel_path}; \ $(MKDIR) $${install_subdir}; \ (cd $${install_subdir}; \ - new_component=$(firstword $(subst /, ,$(subst $(shell $(RELPATH) -d / $(SRCROOT) $(SRCROOT)),,$(addprefix $(shell $(RELPATH) -d / $(SOURCE) $(SOURCE))/,$${rel_path}))));\ - target_subdir=${OBJROOT}/$${kernel_config}_$${arch_config}/$${new_component}; \ ${MAKE} KERNEL_CONFIG=$${kernel_config} \ ARCH_CONFIG=$${arch_config} \ MAKEFILES=${SOURCE}/Makefile \ SOURCE=${SOURCE}/ \ - TARGET=$${target_subdir}/ \ build_install \ ); \ done; \ @@ -373,24 +346,22 @@ setup_build_install: do_build_install: build_install: - @echo "[ $(SOURCE) ] make build_install $(COMPONENT) $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; \ - ${MAKE} setup_build_install; \ + @TARGET=${OBJROOT}/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT); \ + echo "[ $(SOURCE) ] make build_install $(COMPONENT) $(KERNEL_CONFIG) $(ARCH_CONFIG) $${TARGET}"; \ + ${MAKE} TARGET=$${TARGET} setup_build_install; \ kernel_config=$(KERNEL_CONFIG); \ - arch_config=$(ARCH_CONFIG); \ for install_subdir in $(INST_SUBDIRS); \ do \ $(MKDIR) $${install_subdir}; \ (cd $${install_subdir}; \ - new_component=$(firstword $(subst /, ,$(subst $(shell $(RELPATH) -d / $(SRCROOT) $(SRCROOT)),,$(addprefix $(shell $(RELPATH) -d / $(SOURCE) $(SOURCE))/, $${comp_subdir}))));\ ${MAKE} KERNEL_CONFIG=$${kernel_config} \ - ARCH_CONFIG=$${arch_config} \ MAKEFILES=${SOURCE}/$${install_subdir}/Makefile \ SOURCE=${SOURCE}$${install_subdir}/ \ - TARGET=${OBJROOT}/$${kernel_config}_$${arch_config}/$${new_component} \ + TARGET=$${TARGET} \ build_install \ ); \ done; \ - ${MAKE} do_build_install; + ${MAKE} TARGET=$${TARGET} do_build_install; # diff --git a/makedefs/MakeInc.rule b/makedefs/MakeInc.rule index ed02f4b6d..fc63338f6 100644 --- a/makedefs/MakeInc.rule +++ b/makedefs/MakeInc.rule @@ -344,7 +344,7 @@ COMP_SOBJ_FILES = $(addprefix $(TARGET)$(COMP_OBJ_DIR), $(COMP_SOBJ_LIST)) $(COMP_SOBJ_FILES): $(TARGET)$(COMP_OBJ_DIR)%.o : %.s ${S_KCC} -E -MD ${SFLAGS} -DASSEMBLER $(INCFLAGS) $< > $(patsubst %.o, %.pp, ${@}); sed '/^\#/d' $(patsubst %.o, %.pp, ${@}) > $(patsubst %.o, %.s, ${@}); - ${S_KCC} ${SFLAGS} -m${arch_config} ${_HOST_AS_FLAGS} -c $(patsubst %.o, %.s, ${@}); + ${S_KCC} ${SFLAGS} -m${ARCH_CONFIG_LC} ${_HOST_AS_FLAGS} -c $(patsubst %.o, %.s, ${@}); ${RM} ${_RMFLAGS_} $(patsubst %.o, %.pp, ${@}) $(patsubst %.o,%.s,${@}); S_RULE_1A=@ls / @@ -352,7 +352,7 @@ S_RULE_1B= ${patsubst %.o,%.s,${@}} > /dev/null S_RULE_2= ${S_KCC} -E -MD ${SFLAGS} -DASSEMBLER $(INCFLAGS) $< \ > $(patsubst %.o, %.pp, ${@}); \ sed '/^\#/d' $(patsubst %.o, %.pp, ${@}) > $(patsubst %.o, %.s, ${@}); -S_RULE_3= ${S_KCC} ${SFLAGS} -m${arch_config} ${_HOST_AS_FLAGS} -c $(patsubst %.o, %.s, ${@});\ +S_RULE_3= ${S_KCC} ${SFLAGS} -m${ARCH_CONFIG_LC} ${_HOST_AS_FLAGS} -c $(patsubst %.o, %.s, ${@});\ ${RM} ${_RMFLAGS_} $(patsubst %.o, %.pp, ${@}) $(patsubst %.o,%.s,${@}) # @@ -419,24 +419,22 @@ setup_build_all: do_build_all: $(COMP_FILES) $(COMP_COBJ_FILES) $(COMP_SOBJ_FILES) $(COMPONENT_IMAGE_FILE) @echo "[ $(SOURCE) ] make do_build_all $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)" -ifeq ($(shell $(RELPATH) $(SRCROOT) $(SOURCE)), .) +ifeq ($(COMPONENT), .) do_build_all: do_build_mach_kernel endif # # mach_kernel building rules # -MK_COMPONENT_OBJ_FILES = $(addprefix $(TARGET),$(foreach component,$(COMPONENT_LIST), $(addprefix $(component)/$(firstword $($(addsuffix _KERNEL_CONFIG, $(shell echo -n $(component) | tr a-z A-Z))) $(KERNEL_CONFIG))/, $(addsuffix .o, $(component))))) - do_build_mach_kernel: - @echo "[ building mach_kernel ]" + @echo "[ building mach_kernel ]"; $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/kernel_newvers \ "`${CAT} $(SRCROOT)/osfmk/conf/kernelversion.major`" \ "`${CAT} $(SRCROOT)/osfmk/conf/kernelversion.minor`" \ - "`${CAT} $(SRCROOT)/osfmk/conf/kernelversion.variant`" - ${KCC} $(CFLAGS) $(INCLUDES) -c kernel_vers.c - $(LD) $(LDFLAGS_KERNEL) $(MK_COMPONENT_OBJ_FILES) kernel_vers.o -o $(TARGET)mach_kernel.sys $(LD_KERNEL_LIBS) - $(STRIP) $(STRIP_FLAGS) $(TARGET)mach_kernel.sys -o $(TARGET)mach_kernel + "`${CAT} $(SRCROOT)/osfmk/conf/kernelversion.variant`"; \ + ${KCC} $(CFLAGS) $(INCLUDES) -c kernel_vers.c; \ + $(LD) $(LDFLAGS_KERNEL) $(addprefix $(TARGET)/,$(foreach component,$(COMPONENT_LIST), $(addprefix $(component)/$(firstword $($(addsuffix _KERNEL_CONFIG, $(component))) $(KERNEL_CONFIG))/, $(addsuffix .o, $(component))))) kernel_vers.o -o $(TARGET)/mach_kernel.sys $(LD_KERNEL_LIBS); \ + $(STRIP) $(STRIP_FLAGS) $(TARGET)/mach_kernel.sys -o $(TARGET)/mach_kernel; # # Generic Install rules # @@ -444,40 +442,40 @@ INSTALL_FILE_FILES = $(addprefix $(DSTROOT)$(INSTALL_FILE_DIR), $(INSTALL_FILE_L force_file_install: -$(INSTALL_FILE_FILES): $(DSTROOT)$(INSTALL_FILE_DIR)% : $(TARGET)% force_file_install +$(INSTALL_FILE_FILES): $(DSTROOT)$(INSTALL_FILE_DIR)% : $(TARGET)/% force_file_install @echo Installing $< in $@; @$(MKDIR) $(DSTROOT)$(INSTALL_FILE_DIR); \ - if [ "`echo $(INSTALL_ARCHS) | wc -w`" -eq 1 ]; then \ + if [ "`echo $(INSTALL_ARCHS_LC) | wc -w`" -eq 1 ]; then \ $(RM) $(RMFLAGS) $@; \ install $(INSTALL_FLAGS) $< $(dir $@); \ else \ if [ ! -e $@ ]; then \ echo >empty_file; \ - lipo_arg="$(subst _empty_file, empty_file,$(foreach lipo_arch,$(shell echo -n $(INSTALL_ARCHS) | tr A-Z a-z), $(addprefix -arch , $(addsuffix _empty_file, $(lipo_arch)))))"; \ + lipo_arg="$(subst _empty_file, empty_file,$(foreach lipo_arch,$(INSTALL_ARCHS_LC), $(addprefix -arch , $(addsuffix _empty_file, $(lipo_arch)))))"; \ $(LIPO) $${lipo_arg} -create -output $@; \ $(RM) $(RMFLAGS) empty_file; \ fi; \ - $(LIPO) $@ -replace $(shell echo -n $(ARCH_CONFIG) | tr A-Z a-z) $< -o $@; \ + $(LIPO) $@ -replace $(ARCH_CONFIG_LC) $< -o $@; \ fi INSTALL_FILESYS_FILES = $(addprefix $(SYMROOT)$(INSTALL_FILE_DIR), $(INSTALL_FILE_LIST)) force_filesys_install: -$(INSTALL_FILESYS_FILES): $(SYMROOT)$(INSTALL_FILE_DIR)% : $(TARGET)%.sys force_filesys_install +$(INSTALL_FILESYS_FILES): $(SYMROOT)$(INSTALL_FILE_DIR)% : $(TARGET)/%.sys force_filesys_install @echo Installing $< in $@; @$(MKDIR) $(SYMROOT)$(INSTALL_FILE_DIR); \ - if [ "`echo $(INSTALL_ARCHS) | wc -w`" -eq 1 ]; then \ + if [ "`echo $(INSTALL_ARCHS_LC) | wc -w`" -eq 1 ]; then \ $(RM) $(RMFLAGS) $@; \ install $(INSTALL_FLAGS) $< $(dir $@); \ else \ if [ ! -e $@ ]; then \ echo >empty_file; \ - lipo_arg="$(subst _empty_file, empty_file,$(foreach lipo_arch,$(shell echo -n $(INSTALL_ARCHS) | tr A-Z a-z), $(addprefix -arch , $(addsuffix _empty_file, $(lipo_arch)))))"; \ + lipo_arg="$(subst _empty_file, empty_file,$(foreach lipo_arch,$(INSTALL_ARCHS_LC), $(addprefix -arch , $(addsuffix _empty_file, $(lipo_arch)))))"; \ $(LIPO) $${lipo_arg} -create -output $@; \ $(RM) $(RMFLAGS) empty_file; \ fi; \ - $(LIPO) $@ -replace $(shell echo -n $(ARCH_CONFIG) | tr A-Z a-z) $< -o $@; \ + $(LIPO) $@ -replace $(ARCH_CONFIG_LC) $< -o $@; \ fi setup_build_install: @@ -486,5 +484,7 @@ setup_build_install: do_build_install: $(INSTALL_FILESYS_FILES) $(INSTALL_FILE_FILES) @echo "[ $(SOURCE) ] make do_build_install $(KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)" +ifeq ($(INCL_MAKEDEP), TRUE) -include Makedep +endif diff --git a/osfmk/.gdbinit b/osfmk/.gdbinit index 144e2b894..127a23ae2 100644 --- a/osfmk/.gdbinit +++ b/osfmk/.gdbinit @@ -202,7 +202,7 @@ define showactint while ($mysp != 0) && (($mysp & 0xf) == 0) && ($mysp < 0xb0000000) && ($mysp > $prevsp) printf "\n\t\t0x%08x ", $mysp set $kgm_return = *($mysp + 8) - if ($kgm_return > end) + if (($kgm_return > end) && ($kgm_return < 0x40000000)) showkmodaddr $kgm_return else output /a * ($mysp + 8) diff --git a/osfmk/conf/Makefile b/osfmk/conf/Makefile index c7a6db857..a1d04575e 100644 --- a/osfmk/conf/Makefile +++ b/osfmk/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(OSFMK_KERNEL_CONFIG)/Makefile: $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(OSFMK_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(OSFMK_KERNEL_CONFIG)/Makefile: $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(OSFMK_KERNEL_CONFIG) $(OSFMK_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(OSFMK_KERNEL_CONFIG) $(OSFMK_KERNEL_CONFIG); \ ); $(COMPOBJROOT)/$(OSFMK_KERNEL_CONFIG)/platforms.h: $(COMPOBJROOT)/$(OSFMK_KERNEL_CONFIG)/Makefile @@ -57,6 +57,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(OSFMK_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(OSFMK_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/osfmk/conf/Makefile.template b/osfmk/conf/Makefile.template index 2d2c9abd0..70ae5e94f 100644 --- a/osfmk/conf/Makefile.template +++ b/osfmk/conf/Makefile.template @@ -109,7 +109,7 @@ do_build_all: do_depend # we name it genassym.o to help with the automatic # dependency generation -genassym.o: $(SOURCE_DIR)/$(COMPONENT)/$(arch_config)/genassym.c +genassym.o: $(SOURCE_DIR)/$(COMPONENT)/$(ARCH_CONFIG_LC)/genassym.c ${KCC} ${CFLAGS} -MD ${_HOST_EXTRA_CFLAGS} -S -o ${@} -c ${INCFLAGS} $< assym.s: genassym.o @@ -120,8 +120,6 @@ ${SOBJS}: assym.s %RULES --include Makedep - include $(MakeInc_rule) include $(MakeInc_dir) diff --git a/osfmk/conf/files b/osfmk/conf/files index 8fedad362..dc72c4e15 100644 --- a/osfmk/conf/files +++ b/osfmk/conf/files @@ -170,8 +170,6 @@ osfmk/kern/priority.c standard osfmk/kern/processor.c standard osfmk/kern/queue.c standard osfmk/kern/sched_prim.c standard -osfmk/kern/sf.c standard -osfmk/kern/spl.c standard osfmk/kern/sscanf.c standard osfmk/kern/startup.c standard osfmk/kern/subsystem.c standard @@ -206,9 +204,7 @@ osfmk/kern/bsd_kern.c optional mach_bsd ./mach/lock_set_server.c standard ./mach/mach_host_server.c standard ./mach/mach_port_server.c standard -./mach/memory_object_user.c standard ./mach/memory_object_server.c standard -./mach/memory_object_default_user.c standard ./mach/memory_object_control_server.c standard ./mach/memory_object_default_server.c standard ./mach/memory_object_name_server.c standard @@ -219,6 +215,8 @@ osfmk/kern/bsd_kern.c optional mach_bsd # when we can (i.e. when we can get the send-always behavior covered # even with MIG-generated code). # ./mach/notify_user.c standard +# ./mach/memory_object_user.c standard +# ./mach/memory_object_default_user.c standard # ./mach/processor_server.c standard ./mach/processor_set_server.c standard @@ -228,7 +226,9 @@ osfmk/kern/bsd_kern.c optional mach_bsd ./mach/thread_act_server.c standard ./mach/vm_map_server.c standard osfmk/mach-o/mach_header.c standard +osfmk/vm/device_vm.c standard osfmk/vm/memory_object.c standard +osfmk/vm/task_working_set.c standard osfmk/vm/vm_debug.c standard osfmk/vm/vm_external.c optional mach_pagemap osfmk/vm/vm_fault.c standard diff --git a/osfmk/conf/kernelversion.minor b/osfmk/conf/kernelversion.minor index 00750edc0..b8626c4cf 100644 --- a/osfmk/conf/kernelversion.minor +++ b/osfmk/conf/kernelversion.minor @@ -1 +1 @@ -3 +4 diff --git a/osfmk/conf/kernelversion.variant b/osfmk/conf/kernelversion.variant index 7f8f011eb..8b1378917 100644 --- a/osfmk/conf/kernelversion.variant +++ b/osfmk/conf/kernelversion.variant @@ -1 +1 @@ -7 + diff --git a/osfmk/conf/version.minor b/osfmk/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/osfmk/conf/version.minor +++ b/osfmk/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/osfmk/conf/version.variant b/osfmk/conf/version.variant index 7f8f011eb..8b1378917 100644 --- a/osfmk/conf/version.variant +++ b/osfmk/conf/version.variant @@ -1 +1 @@ -7 + diff --git a/osfmk/ddb/db_print.c b/osfmk/ddb/db_print.c index 775ce439b..0dcca6f3a 100644 --- a/osfmk/ddb/db_print.c +++ b/osfmk/ddb/db_print.c @@ -82,9 +82,6 @@ #include <ddb/db_output.h> /* For db_printf() */ #include <ddb/db_print.h> -#include <kern/sf.h> -#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ - #if TASK_SWAPPER #include <kern/task_swap.h> #endif /* TASK_SWAPPER */ @@ -245,7 +242,7 @@ db_act_stat( *p++ = (athread->state & TH_RUN) ? 'R' : '.'; *p++ = (athread->state & TH_WAIT) ? 'W' : '.'; *p++ = (athread->state & TH_SUSP) ? 'S' : '.'; - *p++ = (athread->state & TH_SWAPPED_OUT) ? 'O' : '.'; + *p++ = (athread->state & TH_STACK_HANDOFF) ? 'O' : '.'; *p++ = (athread->state & TH_UNINT) ? 'N' : '.'; /* show if the FPU has been used */ *p++ = db_act_fp_used(thr_act) ? 'F' : '.'; @@ -322,7 +319,7 @@ db_print_act( db_printf("%s ID: ACT STAT SW STACK SHUTTLE", indent); db_printf(" SUS PRI WAIT_FUNC\n"); } - policy = (athread ? athread->policy : 2); + policy = ((athread && (athread->sched_mode&TH_MODE_TIMESHARE))? 1: 2); db_printf("%s%3d%c %0*X %s %s %0*X %0*X %3d %3d/%s ", indent, act_id, (thr_act == current_act())? '#': ':', diff --git a/osfmk/default_pager/default_pager.c b/osfmk/default_pager/default_pager.c index cbd50979e..864b9eabd 100644 --- a/osfmk/default_pager/default_pager.c +++ b/osfmk/default_pager/default_pager.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001, 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,586 +22,6 @@ /* * @OSF_COPYRIGHT@ */ -/* - * HISTORY - * $Log: default_pager.c,v $ - * Revision 1.7 2001/01/15 20:03:32 lindak - * Merged PR-2523198-116-3 into Cheetah from magee which fixes all of the - * following: - * 2430517 2445360 2511207 2513779 2523198 2581705 2585290 2595323 2596060 - * 2597427 2601360 - * - * Revision 1.6.260.1 2001/01/14 10:02:17 jmagee - * A conglomeration of fixes related to races in the termination of processes - * - * Bug #2430517 - Race condition between port death and BSD causes wait4() to fail - * Bug #2445360 - Process hung in sigsuspend waiting for SIGCHLD - * Bug #2511207 - IPC thread_act disable too "loose" - * Bug #2513779 - thread_continue is NOT a continuation routine - * Bug #2523198 - shuttleless activation during thread creation - * Bug #2581705 - 4F8: panic in task_info - * Bug #2585290 - PANIC: thread_deallocate: released last reference on map - * Bug #2595323 - Cheetah4K9: Lost user context - * Bug #2596060 - can't get mutex interlock in vm_map_deallocate / load_machfile - * Bug #2601360 - killing CrashReporter causes process hangs - * Submitted by: jmagee - * Reviewed by: Youngworth Umesh Ramesh - * - * Revision 1.6 2000/10/13 06:21:06 lindak - * Merged PR-2425995-2 into Cheetah (youngworth Need Pager and VM support for - * 64 bit address space) - * - * Revision 1.5.804.1 2000/10/12 17:29:25 youngwor - * Changes for base 64 bit data path support - * - * Revision 1.5.782.1 2000/10/12 14:02:32 youngwor - * Changes to support 64 bit data path throughout the kernel. - * Bug #: 2425995 - * Submitted by: Chris Youngworth - * Reviewed by: - * - * Revision 1.5 2000/01/26 05:56:22 wsanchez - * Add APSL - * - * Revision 1.4 1999/07/20 02:55:34 lindak - * Merged PR-2291281-1 into Beaker (magee Kernel Components kobject groupings) - * - * Revision 1.3.674.1 1999/07/20 00:33:02 jmagee - * Workaround for partial EMMI components work - * - * Revision 1.3 1999/02/24 16:55:12 wsanchez - * PR-2308031 - * - * Revision 1.2.168.1 1999/02/23 20:43:52 semeria - * Component Header files phase 1 - * - * Revision 1.2 1998/12/01 00:24:41 wsanchez - * Merged in CDY_DP1 (chris: default pager) - * - * Revision 1.1.2.2 1998/11/25 21:32:17 youngwor - * fix errant comment format - * - * Revision 1.1.2.1 1998/11/24 22:39:57 youngwor - * Check-in of support for the in-kernel default pager - * - * Revision 1.1.1.1 1998/03/07 02:26:31 wsanchez - * Import of OSF Mach kernel (~mburg) - * - * Revision 1.2.84.2 1997/03/27 18:45:15 barbou - * submit adidtional picco changes - * [1996/09/12 22:09:29 robert] - * AXP pool merge. - * [97/02/25 barbou] - * - * Revision 1.2.84.1 1996/11/29 16:54:38 stephen - * nmklinux_1.0b3_shared into pmk1.1 - * Added -v option (verbose flag) and tests before warning printfs - * [1996/07/29 12:25:54 stephen] - * - * Revision 1.2.34.16 1996/07/31 06:41:45 paire - * Merged with nmk20b7_shared (1.2.77.1) - * [96/05/30 paire] - * - * Revision 1.2.77.1 1996/04/12 06:30:58 paire - * Changed signature of default_pager_thread to (void ()(void *)). - * Replaced bzero() by memset(). - * [96/01/30 paire] - * - * Revision 1.2.34.15 1995/08/21 20:52:09 devrcs - * Initialize dpt_initialized_p element of - * default_pager_thread_tb and set it to true after thread starts - * up. Wait until all threads have signalled ready before - * telling the bootstrap process that it's ok to go ahead. - * [95/07/10 randys] - * - * Revision 1.2.34.14 1995/06/12 18:44:00 dwm - * ri-osc CR1394 - allow argument from bootstrap to set cluster size, - * Usage: default_pager clsize=4 sd0b, for example - * [1995/06/12 18:40:21 dwm] - * - * Revision 1.2.34.13 1995/05/31 07:55:10 emcmanus - * Use mach_msg instead of mach_msg_overwrite_trap so that message - * operations can be interrupted without provoking a default-pager - * panic. Remote gdb does this. - * [1995/05/31 07:54:21 emcmanus] - * - * Revision 1.2.34.12 1995/05/25 20:36:39 mmp - * Removed TEMPORARILY_USE_OLD_INIT and the !TEMPORARILY_USE_OLD_INIT - * code. The change to use m_o_init was not temporary. - * [1995/05/25 19:59:17 mmp] - * - * Revision 1.2.34.11 1995/04/07 18:50:57 barbou - * Merged into mainline: - * Revision 1.2.34.10 1995/02/27 18:24:08 mmp - * Replaced m_o_notify with m_o_init; used m_o_change_attributes - * instead of m_o_establish; removed m_o_rejected. - * [1995/02/27 18:22:40 mmp] - * Revision 1.2.34.9 1995/02/23 21:15:48 alanl - * Use system_priority instead of server_priority. Fix locking - * with regards to pager_extend! - * Merged with DIPC2_SHARED. - * [1995/02/23 21:14:55 alanl] - * [95/03/08 barbou] - * - * VM-MK6 Merge. - * Started from the modified b26 file. - * Integrated the following MK6 changes: - * - * Fix ri-osc CR846: Avoid use of fixed BASEPRI_SYSTEM; use new - * host_info() interface to determine priority dynamically. - * [1994/12/23 15:39:32 bolinger] - * mk6 CR668 - 1.3b26 merge - * Correct local btodb() def; change port_to_ds() et al. to work - * with port names returned by current merged kernel. - * [1994/12/03 02:10:30 bolinger] - * mk6 CR668 - 1.3b26 merge - * Did not bring forward PAGING_MEMORY support. Did bring forward - * NORMA support -- can be deleted when proven no longer needed. - * [1994/11/10 15:32:12 bolinger] - * [95/01/10 barbou] - * [95/03/08 barbou] - * - * Revision 1.2.56.2 1995/02/13 14:40:41 barbou - * VM-MK6 Merge. - * Started from the modified b26 file. - * Integrated the following MK6 changes: - * - * Fix ri-osc CR846: Avoid use of fixed BASEPRI_SYSTEM; use new - * host_info() interface to determine priority dynamically. - * [1994/12/23 15:39:32 bolinger] - * mk6 CR668 - 1.3b26 merge - * Correct local btodb() def; change port_to_ds() et al. to work - * with port names returned by current merged kernel. - * [1994/12/03 02:10:30 bolinger] - * mk6 CR668 - 1.3b26 merge - * Did not bring forward PAGING_MEMORY support. Did bring forward - * NORMA support -- can be deleted when proven no longer needed. - * [1994/11/10 15:32:12 bolinger] - * [95/01/10 barbou] - * - * Revision 1.2.46.3 1994/11/02 14:57:23 barbou - * Use new task_swappable() interface to make our task unswappable. - * [94/11/02 barbou] - * - * Revision 1.2.46.2 1994/10/10 15:28:48 barbou - * VM Merge - Default Pager Clustering. - * - * Also split this file in three: - * default_pager.c contains code that deals with threads and - * incoming messages. - * dp_memory_object.c contains memory object management code. - * dp_backing_store.c contains backing store management code. - * [94/10/10 barbou] - * - * Revision 1.2.6.23 1994/05/16 16:43:50 jph - * CR8809 -- Fix messages when paging space is exhausted. - * CR10905 -- Disallow overlapped paging areas. - * [1994/05/16 16:43:04 jph] - * - * Revision 1.2.6.22 1994/04/01 18:42:34 jph - * CR10550 -- Add backing store info interfaces. - * CR10718 -- Fix pagein error path. - * [1994/04/01 18:40:13 jph] - * - * Revision 1.2.6.21 1994/03/04 18:34:49 jeffc - * CR10636 -- delete all NMK15_COMPAT support. - * [1994/03/04 14:50:44 jeffc] - * - * Revision 1.2.6.20 1994/02/16 14:22:24 jph - * CR10554 -- Multi-page requests now handled, albeit crudely. - * Fixed leak in data_request for partial page reads. - * Tidied up code to be at least consistent. - * Fixed ASSERTIONS option and bad assert (name_refs in terminate). - * [1994/02/16 14:20:47 jph] - * - * Revision 1.2.6.19 1994/02/07 22:41:25 jph - * Merged with changes from 1.2.6.18 - * [1994/02/07 22:40:25 jph] - * - * CR10433 -- Upgrade default pager. - * Add device argument capability. - * Removed defunct file_io.h reference. - * Replaced pager_{lock_init,lock,unlock,lock_try} macros. - * Moved cthreads globals to top of file from middle. - * Removed "id" field of "partition_t" - not needed. - * Added "device", "offset", "count" and "record_shift" fields - * to "partition_t" to record backing store device info. - * Removed "p_read", "p_write" and "p_private" fields from - * "partition_t" - Unneeded filesystem abstraction. - * Merge "struct dstruct" fields into the "struct dpager", - * delete "struct dstruct" and "default_pager_t". - * Added "struct bstruct" and "all_backing_store" to hold list - * of all backing store ports. - * Simplify arguments to create_paging_partition(). - * Delete part_id(), add_paging_file() and default_pager_setup() routines. - * Added backing_store_port_alloc(), log2() routine. - * Added vm_page_mask and vm_page_shift to augment vm_page_size. - * [1994/02/07 22:28:15 jph] - * - * Revision 1.2.6.18 1994/02/01 19:44:38 collins - * CR9926: Set the default pager scheduling policy to round-robin with - * a priority of BASEPRI_SYSTEM. - * [1994/02/01 14:56:05 collins] - * - * Revision 1.2.6.17 1994/01/27 17:04:21 chasb - * Expand Copyright markers - * [1994/01/27 16:32:40 chasb] - * - * Revision 1.2.6.16 1994/01/26 18:42:03 collins - * CR10474: Change any_t to void *. - * [1994/01/26 18:39:47 collins] - * - * Revision 1.2.6.15 1994/01/25 17:02:40 jeffc - * CR10107 -- Mach spec compliance - eliminate copy_call - * [1994/01/24 21:23:43 jeffc] - * - * Revision 1.2.6.14 1994/01/20 16:58:18 meissner - * CR 10468 - Make initialization have proper number of {}'s. - * [1994/01/19 19:02:57 meissner] - * - * Revision 1.2.6.13 1993/12/03 20:53:51 jvs - * Trusted pager throttling changes. CR 10108 - * [1993/12/03 20:53:09 jvs] - * - * Revision 1.2.6.12 1993/12/02 17:22:34 jph - * CR10254 -- Fix warning about unused ledger/ security ports. - * [1993/12/02 15:59:30 jph] - * - * Revision 1.2.6.11 1993/11/24 20:30:31 jph - * CR9801 brezak merge, ledgers, security and NMK15_COMPAT - * [1993/11/23 22:52:33 jph] - * - * New bootstrap_ports() signature. - * [1993/11/23 20:58:25 jph] - * - * Revision 1.2.6.10 1993/11/23 18:05:47 watkins - * Increment send right for object in mo_notify. - * [1993/11/23 18:04:35 watkins] - * - * Revision 1.2.6.9 1993/11/16 21:49:42 watkins - * Remove pager_name argument from memory_object_terminate - * and memory_object_create, as per spec. Remove mo_init - * and flesh out mo_notify. Extend maps for reads beyond the - * end. Add xpr traces. - * [1993/11/16 21:29:43 watkins] - * - * Revision 1.2.6.8 1993/10/20 18:50:13 gm - * CR9928: Remove bootstrap_port lookup. - * CR9990: Remove code that deletes initial stack. - * [1993/10/20 12:34:40 gm] - * - * Revision 1.2.6.7 1993/10/08 17:32:08 jeffc - * CR9508 - Delete typed IPC code - * [1993/09/28 17:27:02 jeffc] - * - * Revision 1.2.6.6 1993/10/08 16:08:14 jeffc - * CR9792 - delete obsolete memory_object_data_write message. - * [1993/10/08 15:59:49 jeffc] - * - * Revision 1.2.6.5 1993/10/05 21:57:08 watkins - * New memory object attribute interfaces comply with spec. - * [1993/10/05 21:53:27 watkins] - * - * Revision 1.2.6.4 1993/09/16 18:38:39 jeffc - * CR9792 - delete defunct EMMI interfaces - * [1993/09/15 20:02:07 jeffc] - * - * Revision 1.2.6.3 1993/08/05 17:57:08 gm - * CR9627: Moved def_pager_setup and bootstrap code here. Removed - * EXT_PAGER code. Fixed up code problems with more agressive warning - * in gcc. Added full prototype support. Changed internal interfaces - * that had unions as return values to take pointer arguments instead. - * Delete bootstrap code since their is now a separate bootstrap task. - * Removed set_ras_address() since it should be provided by a machine - * dependent file on machines that need it. Changed to get priv - * ports using mach interfaces instead of argv. - * [1993/07/09 19:11:36 gm] - * - * Revision 1.2.6.2 1993/06/09 02:08:56 gm - * Conditionalize no_senders_check for untyped IPC. CR #9058. - * [1993/05/11 18:19:30 rod] - * - * Add header files to pick up definitions of Mach traps and - * wiring interfaces. - * [1993/05/14 15:37:15 jeffc] - * - * Fix ANSI C violations and warnings. - * [1993/05/13 21:05:22 jeffc] - * - * Remove dependency on own pathname. - * [1993/05/12 17:53:18 jeffc] - * - * Revision 1.2 1993/04/19 15:07:02 devrcs - * Added trailer support to untyped ipc. [travos@osf.org, fdr@osf.org] - * [1993/04/06 18:14:54 travos] - * - * Merge untyped ipc: - * Added untyped support to bootstrap_compat(). - * [1993/04/02 17:37:59 rod] - * - * Share more code when building the in kernel version - * of the pager. - * [93/03/19 bernadat] - * - * Fix memory_object_synchronize hang. - * [1993/03/15 13:21:59 david] - * - * memory_object_synchronize define twice - * [1993/03/03 15:09:30 david] - * - * remerge with 1.1.2.3 - * [1993/03/03 14:26:14 david] - * - * Add memory_object_synchronize stub - * [1993/03/03 11:04:05 david] - * - * Fixed a deadlock bug in internal pager configuration. - * [93/02/25 bernadat] - * - * moved out of mach_kernel directory - * [1993/02/27 13:56:35 david] - * - * Modified to use the same new interface (default_pager_object.defs) for both - * configurations. - * [1993/02/17 13:40:18 bruel] - * - * Added stubs for new exception interface. - * [93/02/11 bruel] - * - * Modified from mk78. - * Added the ufs_pager_option. - * [93/01/29 bruel] - * - * Yup, it works. Undefine CHECKSUM, debug and - * DEBUG_READER_CONFLICTS again. - * [92/12/03 ian] - * - * Update CHECKSUM to work with current dp_map union. - * [92/12/03 ian] - * - * Define debug CHECKSUM and DEBUG_READER_CONFLICTS. - * [92/11/28 ian] - * - * Eliminated use of old memory object calls (set_attributes, data_write, data_provided). - * [92/09/25 jsb] - * - * $EndLog$ - */ -/* CMU_HIST */ -/* - * Revision 2.12 92/07/20 13:32:18 cmaeda - * Added private version of set_ras_address for fast_tas support. - * [92/05/11 14:31:52 cmaeda] - * - * Revision 2.11 92/05/05 10:03:46 danner - * For merge purposes, backed-out the unstable stuff. - * [92/05/04 11:12:01 af] - * - * Now we can page an object across partitions. - * Initial rough ideas about automatically extending - * paging space. - * [92/03/11 02:23:58 af] - * - * Revision 2.10 92/03/06 13:58:48 rpd - * Fixed pager_dealloc_page calls in pager_dealloc (from af). - * Removed chatty printfs. - * [92/03/06 rpd] - * - * Revision 2.9 92/03/05 15:58:35 rpd - * Changed PAGEMAP_ENTRIES from 128 to 64. From af. - * [92/03/05 rpd] - * - * Revision 2.8 92/03/03 12:12:04 rpd - * Changed to catch exception messages and handle bootstrap requests. - * Added partition_init. - * [92/03/03 rpd] - * - * Revision 2.7 92/02/25 11:22:38 elf - * Accept creation of objects bigger than any one partition, in - * anticipation of the code that will page across partitions. - * Since we are at it, also proceed with no paging partitions: - * rely on killing unlucky objects on pageouts. - * [92/02/25 af] - * - * Revision 2.6 92/02/23 23:00:31 elf - * Copyright updated, corrected history. - * [92/02/23 elf] - * - * Revision 2.5 92/02/23 22:25:35 elf - * Improved handling of big objects, fixed a deadlock in - * object relocation, improved printouts. - * Now only crash if out of memory, otherwise use the old - * code that just marked the object as in-error. - * [92/02/23 13:25:49 af] - * - * As per jsb instructions, removed all NORMA conditionals. - * Rename port names to odd values, a trivial heuristic that - * makes name conflicts even more unlikely. - * [92/02/22 af] - * - * Refined the port name conflict problem. Instead of renaming - * ports that we send to, just set aside the memory that we cannot - * use. When objects get deleted put back the memory in the system. - * [92/02/21 af] - * - * Added renaming of request and name ports (from af). - * [92/02/21 danner] - * - * Many changes. Now supports adding/removing paging files, it does - * not immediately panic if a paging file fills up but relocates the - * object elsewhere, it uses the precious attribute in data_supply - * to reduce paging space usage (under USE_PRECIOUS conditional, - * enabled). - * [92/02/19 17:29:54 af] - * - * Two mods: changed bitmap ops to work one int at a time rather - * than one byte at a time. This helps under load, e.g. when the - * paging file is large and busy. Second mod to use port-to-pointer - * casting in lookups, rather than hash+list searching. This not - * only helps under load (I see >600 objects on my pmax) but also - * increases parallelism a little. - * Shrunk the code size by one page in the process. - * [92/02/14 01:44:23 af] - * - * Revision 2.4 92/01/23 15:19:41 rpd - * Changed to not include mig server interfaces. - * [92/01/23 rpd] - * - * Revision 2.3 92/01/14 16:43:14 rpd - * Moved mach/default_pager_object.defs to mach/default_pager.defs. - * Revised default_pager_info etc. for their new definitions. - * Removed (now) unnecessary #define's to rename kernel functions. - * [92/01/13 rpd] - * Added page_size to default_pager_info. - * Added default_pager_object_pages. - * [92/01/03 rpd] - * - * Updated to handle name ports from memory_object_create. - * Changed to remember the name ports associated with objects. - * Changed default_pager_objects to return the name ports. - * [91/12/28 rpd] - * - * Added default_pager_objects. - * [91/12/15 rpd] - * - * Revision 2.2 92/01/03 19:56:21 dbg - * Simplify locking. - * [91/10/02 dbg] - * - * Convert to run outside of kernel. - * [91/09/04 dbg] - * - * Revision 2.17 91/08/29 13:44:27 jsb - * A couple quick changes for NORMA_VM. Will be fixed later. - * - * Revision 2.16 91/08/28 16:59:29 jsb - * Fixed the default values of default_pager_internal_count and - * default_pager_external_count. - * [91/08/28 rpd] - * - * Revision 2.15 91/08/28 11:09:32 jsb - * Added seqnos_memory_object_change_completed. - * From dlb: use memory_object_data_supply for pagein when buffer is - * going to be deallocated. - * From me: don't use data_supply under NORMA_VM (will be fixed). - * [91/08/26 14:30:07 jsb] - * - * Changed to process requests in parallel when possible. - * - * Don't bother keeping track of mscount. - * [91/08/16 rpd] - * Added default_pager_info. - * [91/08/15 rpd] - * - * Added sequence numbers to the memory object interface. - * Changed to use no-senders notifications. - * Changed to keep track of port rights and not use mach_port_destroy. - * Added dummy supply-completed and data-return stubs. - * [91/08/13 rpd] - * - * Revision 2.14 91/05/18 14:28:32 rpd - * Don't give privileges to threads handling external objects. - * [91/04/06 rpd] - * Enhanced to use multiple threads, for performance and to avoid - * a deadlock caused by default_pager_object_create. - * Added locking to partitions. - * Added locking to pager_port_hashtable. - * Changed pager_port_hash to something reasonable. - * [91/04/03 rpd] - * - * Revision 2.13 91/05/14 15:21:41 mrt - * Correcting copyright - * - * Revision 2.12 91/03/16 14:41:26 rpd - * Updated for new kmem_alloc interface. - * Fixed memory_object_create to zero the new pager structure. - * [91/03/03 rpd] - * Removed thread_swappable. - * [91/01/18 rpd] - * - * Revision 2.11 91/02/05 17:00:49 mrt - * Changed to new copyright - * [91/01/28 14:54:31 mrt] - * - * Revision 2.10 90/09/09 14:31:01 rpd - * Use decl_simple_lock_data. - * [90/08/30 rpd] - * - * Revision 2.9 90/08/27 21:44:51 dbg - * Add definitions of NBBY, howmany. - * [90/07/16 dbg] - * - * Revision 2.8 90/06/02 14:45:22 rpd - * Changed default_pager_object_create so the out argument - * is a poly send right. - * [90/05/03 rpd] - * Removed references to keep_wired_memory. - * [90/04/29 rpd] - * Converted to new IPC. - * Removed data-request queue. - * [90/03/26 21:30:57 rpd] - * - * Revision 2.7 90/03/14 21:09:58 rwd - * Call default_pager_object_server and add - * default_pager_object_create - * [90/01/22 rwd] - * - * Revision 2.6 90/01/11 11:41:08 dbg - * Use bootstrap-task print routines. - * [89/12/20 dbg] - * - * De-lint. - * [89/12/06 dbg] - * - * Revision 2.5 89/12/08 19:52:03 rwd - * Turn off CHECKSUM - * [89/12/06 rwd] - * - * Revision 2.4 89/10/23 12:01:54 dbg - * Change pager_read_offset and pager_write_offset to return block - * number as function result. default_read()'s caller must now - * deallocate data if not the same as the data buffer passed in. - * Add register declarations and clean up loops a bit. - * [89/10/19 dbg] - * - * Oops - nothing like having your debugging code introduce bugs... - * [89/10/17 dbg] - * - * Revision 2.3 89/10/16 15:21:59 rwd - * debugging: checksum pages in each object. - * [89/10/04 dbg] - * - * Revision 2.2 89/09/08 11:22:06 dbg - * Wait for default_partition to be set. - * [89/09/01 dbg] - * - * Modified to call outside routines for read and write. - * Removed disk structure. Added part_create. - * Reorganized code. - * [89/07/11 dbg] - * - */ -/* CMU_ENDHIST */ /* * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University @@ -666,8 +86,9 @@ boolean_t verbose; mutex_t dpt_lock; /* lock for the dpt array struct */ default_pager_thread_t **dpt_array; +memory_object_default_t default_pager_object; /* for memory_object_create. */ + MACH_PORT_FACE default_pager_default_set; /* Port set for "default" thread. */ -MACH_PORT_FACE default_pager_default_port;/* Port for memory_object_create. */ MACH_PORT_FACE default_pager_internal_set; /* Port set for internal objects. */ MACH_PORT_FACE default_pager_external_set; /* Port set for external objects. */ @@ -898,12 +319,12 @@ strprefix(register const char *s1, register const char *s2) kern_return_t default_pager_info( - MACH_PORT_FACE pager, + memory_object_default_t pager, default_pager_info_t *infop) { vm_size_t pages_total, pages_free; - if (pager != default_pager_default_port) + if (pager != default_pager_object) return KERN_INVALID_ARGUMENT; bs_global_info(&pages_total, &pages_free); @@ -923,10 +344,30 @@ default_pager_initialize() static char here[] = "default_pager_initialize"; + /* + * Vm variables. + */ + vm_page_mask = vm_page_size - 1; + vm_page_shift = local_log2(vm_page_size); + + /* + * List of all vstructs. + */ + vstruct_zone = zinit(sizeof(struct vstruct), + 10000 * sizeof(struct vstruct), + 8192, "vstruct zone"); + VSL_LOCK_INIT(); + queue_init(&vstruct_list.vsl_queue); + vstruct_list.vsl_count = 0; + + VSTATS_LOCK_INIT(&global_stats.gs_lock); + + bs_initialize(); + /* * Exported DMM port. */ - default_pager_default_port = ipc_port_alloc_kernel(); + default_pager_object = ipc_port_alloc_kernel(); /* @@ -935,7 +376,7 @@ default_pager_initialize() #ifdef USER_PAGER if ((kr = netname_check_in(name_server_port, "UserPager", default_pager_self, - default_pager_default_port)) + default_pager_object)) != KERN_SUCCESS) { dprintf(("netname_check_in returned 0x%x\n", kr)); exit(1); @@ -943,34 +384,18 @@ default_pager_initialize() #else /* USER_PAGER */ { int clsize; - ipc_port_t DMM; + memory_object_default_t dmm; - DMM = ipc_port_make_send(default_pager_default_port); + dmm = default_pager_object; clsize = (vm_page_size << vstruct_def_clshift); - kr = host_default_memory_manager(host_priv_self(), &DMM, clsize); - if ((kr != KERN_SUCCESS) || (DMM != MACH_PORT_NULL)) + kr = host_default_memory_manager(host_priv_self(), &dmm, clsize); + if ((kr != KERN_SUCCESS) || + (dmm != MEMORY_OBJECT_DEFAULT_NULL)) Panic("default memory manager"); } #endif /* USER_PAGER */ - /* - * Vm variables. - */ - vm_page_mask = vm_page_size - 1; - vm_page_shift = local_log2(vm_page_size); - - /* - * List of all vstructs. - */ - VSL_LOCK_INIT(); - queue_init(&vstruct_list.vsl_queue); - queue_init(&vstruct_list.vsl_leak_queue); - vstruct_list.vsl_count = 0; - - VSTATS_LOCK_INIT(&global_stats.gs_lock); - - bs_initialize(); } diff --git a/osfmk/default_pager/default_pager_internal.h b/osfmk/default_pager/default_pager_internal.h index a2ac7d610..85699351d 100644 --- a/osfmk/default_pager/default_pager_internal.h +++ b/osfmk/default_pager/default_pager_internal.h @@ -81,9 +81,11 @@ #define MACH_PORT_FACE mach_port_t +#if 0 #ifndef USE_PRECIOUS #define USE_PRECIOUS TRUE #endif +#endif #ifdef USER_PAGER #define UP(stuff) stuff @@ -91,8 +93,6 @@ #define UP(stuff) #endif /* USER_PAGER */ -extern int norma_mk; /* is the kernel configured with NORMA ? */ - #ifndef MACH_KERNEL extern struct mutex dprintf_lock; #define PRINTF_LOCK_INIT() mutex_init(&dprintf_lock) @@ -104,14 +104,14 @@ extern struct mutex dprintf_lock; #define dprintf(args) \ do { \ PRINTF_LOCK(); \ - printf("%s[%d]%s: ", my_name, dp_thread_id(), here); \ + printf("%s[%d]: ", my_name, dp_thread_id()); \ printf args; \ PRINTF_UNLOCK(); \ } while (0) #else #define dprintf(args) \ do { \ - printf("%s[KERNEL:]%s: ", my_name, here); \ + printf("%s[KERNEL]: ", my_name); \ printf args; \ } while (0) #endif @@ -119,7 +119,7 @@ extern struct mutex dprintf_lock; /* * Debug. */ -extern char my_name[]; +__private_extern__ char my_name[]; #define DEFAULT_PAGER_DEBUG 0 @@ -149,15 +149,15 @@ extern int debug_mask; my_name, dp_thread_id(), here, \ __FILE__, __LINE__, # expr); \ #else - panic("%s[KERNEL]%s: assertion failed in %s line %d: %s",\ - my_name, here, __FILE__, __LINE__, # expr); \ + panic("%s[KERNEL]: assertion failed in %s line %d: %s",\ + my_name, __FILE__, __LINE__, # expr); \ #endif } while (0) #else /* DEFAULT_PAGER_DEBUG */ -#define DEBUG(level, args) here[0] = here[0] -#define ASSERT(clause) here[0] = here[0] +#define DEBUG(level, args) +#define ASSERT(clause) #endif /* DEFAULT_PAGER_DEBUG */ @@ -189,6 +189,8 @@ extern int vm_page_shift; #endif #define howmany(a,b) (((a) + (b) - 1)/(b)) +extern memory_object_default_t default_pager_object; + #ifdef MACH_KERNEL extern mutex_t dpt_lock; /* Lock for the dpt array */ extern unsigned int default_pager_internal_count; @@ -196,14 +198,12 @@ extern MACH_PORT_FACE default_pager_host_port; /* extern task_t default_pager_self; */ /* dont need or want */ extern MACH_PORT_FACE default_pager_internal_set; extern MACH_PORT_FACE default_pager_external_set; -extern MACH_PORT_FACE default_pager_default_port; extern MACH_PORT_FACE default_pager_default_set; #else extern mach_port_t default_pager_host_port; extern task_port_t default_pager_self; extern mach_port_t default_pager_internal_set; extern mach_port_t default_pager_external_set; -extern mach_port_t default_pager_default_port; extern mach_port_t default_pager_default_set; #endif @@ -315,6 +315,7 @@ struct backing_store_list_head { #endif }; extern struct backing_store_list_head backing_store_list; +extern int backing_store_release_trigger_disable; #ifdef MACH_KERNEL #define BSL_LOCK_INIT() mutex_init(&backing_store_list.bsl_lock, ETAP_DPAGE_BSL) @@ -537,53 +538,80 @@ struct clmap { (clm)->cl_alloc.clb_map >>= (VSCLSIZE(vs) - (clm)->cl_numpages) typedef struct vstruct_alias { - vm_offset_t name; + int *name; struct vstruct *vs; } vstruct_alias_t; -/* - * VM Object Structure: This is the structure used to manage pagers associated - * to VM objects.Mapping between pager port and paging object. - */ - -typedef struct vstruct { - queue_chain_t vs_links; /* Link in pager-port list */ #ifdef MACH_KERNEL - hw_lock_data_t vs_lock; /* Lock for the structure */ +#define DPT_LOCK_INIT(lock) mutex_init(&(lock), ETAP_DPAGE_VSTRUCT) +#define DPT_LOCK(lock) mutex_lock(&(lock)) +#define DPT_UNLOCK(lock) mutex_unlock(&(lock)) +#define VS_LOCK_TYPE hw_lock_data_t +#define VS_LOCK_INIT(vs) hw_lock_init(&(vs)->vs_lock) +#define VS_TRY_LOCK(vs) (VS_LOCK(vs),TRUE) +#define VS_LOCK(vs) hw_lock_lock(&(vs)->vs_lock) +#define VS_UNLOCK(vs) hw_lock_unlock(&(vs)->vs_lock) +#define VS_MAP_LOCK_TYPE mutex_t +#define VS_MAP_LOCK_INIT(vs) mutex_init(&(vs)->vs_map_lock, ETAP_DPAGE_VSMAP) +#define VS_MAP_LOCK(vs) mutex_lock(&(vs)->vs_map_lock) +#define VS_MAP_TRY_LOCK(vs) mutex_try(&(vs)->vs_map_lock) +#define VS_MAP_UNLOCK(vs) mutex_unlock(&(vs)->vs_map_lock) #else - struct mutex vs_lock; /* Lock for the structure */ +#define VS_LOCK_TYPE struct mutex +#define VS_LOCK_INIT(vs) mutex_init(&(vs)->vs_lock, ETAP_DPAGE_VSTRUCT) +#define VS_TRY_LOCK(vs) mutex_try(&(vs)->vs_lock) +#define VS_LOCK(vs) mutex_lock(&(vs)->vs_lock) +#define VS_UNLOCK(vs) mutex_unlock(&(vs)->vs_lock) +#define VS_MAP_LOCK_TYPE struct mutex +#define VS_MAP_LOCK_INIT(vs) mutex_init(&(vs)->vs_map_lock) +#define VS_MAP_LOCK(vs) mutex_lock(&(vs)->vs_map_lock) +#define VS_MAP_TRY_LOCK(vs) mutex_try(&(vs)->vs_map_lock) +#define VS_MAP_UNLOCK(vs) mutex_unlock(&(vs)->vs_map_lock) #endif - MACH_PORT_FACE vs_mem_obj_port; /* Memory object port */ - mach_port_seqno_t vs_next_seqno; /* next sequence number to issue */ - mach_port_seqno_t vs_seqno; /* Pager port sequence number */ - MACH_PORT_FACE vs_control_port;/* Memory object's control port */ - mach_port_urefs_t vs_control_refs; /* Mem object's control port refs */ - MACH_PORT_FACE vs_object_name; /* Name port */ - mach_port_urefs_t vs_name_refs; /* Name port user-refs */ + + +/* + * VM Object Structure: This is the structure used to manage + * default pager object associations with their control counter- + * parts (VM objects). + */ +typedef struct vstruct { + int *vs_mem_obj; /* our memory obj - temp */ + int vs_mem_obj_ikot;/* JMM:fake ip_kotype() */ + memory_object_control_t vs_control; /* our mem obj control ref */ + VS_LOCK_TYPE vs_lock; /* data for the lock */ + + /* JMM - Could combine these first two in a single pending count now */ + unsigned int vs_next_seqno; /* next sequence num to issue */ + unsigned int vs_seqno; /* Pager port sequence number */ + unsigned int vs_readers; /* Reads in progress */ + unsigned int vs_writers; /* Writes in progress */ #ifdef MACH_KERNEL - boolean_t vs_waiting_seqno;/* to wait on seqno */ - boolean_t vs_waiting_read; /* to wait on readers */ - boolean_t vs_waiting_write;/* to wait on writers */ - boolean_t vs_waiting_refs; /* to wait on refs */ - boolean_t vs_waiting_async;/* to wait on async_pending */ + int + /* boolean_t */ vs_waiting_seqno:1, /* to wait on seqno */ + /* boolean_t */ vs_waiting_read:1, /* waiting on reader? */ + /* boolean_t */ vs_waiting_write:1, /* waiting on writer? */ + /* boolean_t */ vs_waiting_async:1, /* waiting on async? */ + /* boolean_t */ vs_indirect:1, /* map indirect? */ + /* boolean_t */ vs_xfer_pending:1; /* xfer out of seg? */ #else - event_t vs_waiting_seqno;/* to wait on seqno */ - event_t vs_waiting_read; /* to wait on readers */ - event_t vs_waiting_write;/* to wait on writers */ - event_t vs_waiting_refs; /* to wait on refs */ - event_t vs_waiting_async;/* to wait on async_pending */ + event_t vs_waiting_seqno;/* to wait on seqno */ + event_t vs_waiting_read; /* to wait on readers */ + event_t vs_waiting_write;/* to wait on writers */ + event_t vs_waiting_async;/* to wait on async_pending */ + int vs_indirect:1, /* Is the map indirect ? */ + vs_xfer_pending:1; /* xfering out of a seg ? */ #endif - unsigned int vs_readers; /* Reads in progress */ - unsigned int vs_writers; /* Writes in progress */ - unsigned int vs_errors; /* Pageout error count */ + unsigned int vs_async_pending;/* pending async write count */ + unsigned int vs_errors; /* Pageout error count */ + unsigned int vs_references; /* references */ - int vs_clshift; /* Bit shift: clusters to pages */ - int vs_size; /* Object size in clusters */ - int vs_indirect:1, /* Is the map indirect ? */ - vs_xfer_pending:1; /* xfering out of a seg ? */ - int vs_async_pending; /* Count of pending async writes */ + queue_chain_t vs_links; /* Link in pager-wide list */ + + int vs_clshift; /* Bit shift: clusters->pages */ + int vs_size; /* Object size in clusters */ #ifdef MACH_KERNEL mutex_t vs_map_lock; /* to protect map below */ #else @@ -597,37 +625,31 @@ typedef struct vstruct { #define vs_dmap vs_un.vsu_dmap #define vs_imap vs_un.vsu_imap -#define MEM_OBJ_CTL(vs) ((vs)->vs_control_port) #define VSTRUCT_NULL ((vstruct_t) 0) -#ifdef MACH_KERNEL -#define DPT_LOCK_INIT(lock) mutex_init(&(lock), ETAP_DPAGE_VSTRUCT) -#define DPT_LOCK(lock) mutex_lock(&(lock)) -#define DPT_UNLOCK(lock) mutex_unlock(&(lock)) -#define VS_LOCK_INIT(vs) hw_lock_init(&(vs)->vs_lock) -#define VS_TRY_LOCK(vs) (VS_LOCK(vs),TRUE) -#define VS_LOCK(vs) hw_lock_lock(&(vs)->vs_lock) -#define VS_UNLOCK(vs) hw_lock_unlock(&(vs)->vs_lock) -#else -#define VS_LOCK_INIT(vs) mutex_init(&(vs)->vs_lock, ETAP_DPAGE_VSTRUCT) -#define VS_TRY_LOCK(vs) mutex_try_lock(&(vs)->vs_lock) -#define VS_LOCK(vs) mutex_lock(&(vs)->vs_lock) -#define VS_UNLOCK(vs) mutex_unlock(&(vs)->vs_lock) -#endif - -#ifdef MACH_KERNEL -#define VS_MAP_LOCK_INIT(vs) mutex_init(&(vs)->vs_map_lock, ETAP_DPAGE_VSMAP) -#else -#define VS_MAP_LOCK_INIT(vs) mutex_init(&(vs)->vs_map_lock) -#endif -#define VS_MAP_LOCK(vs) mutex_lock(&(vs)->vs_map_lock) -#ifndef MACH_KERNEL -#define VS_MAP_TRY_LOCK(vs) mutex_try_lock(&(vs)->vs_map_lock) -#else -#define VS_MAP_TRY_LOCK(vs) mutex_try(&(vs)->vs_map_lock) -#endif -#define VS_MAP_UNLOCK(vs) mutex_unlock(&(vs)->vs_map_lock) +__private_extern__ void vs_async_wait(vstruct_t); + +#if PARALLEL +__private_extern__ void vs_lock(vstruct_t); +__private_extern__ void vs_unlock(vstruct_t); +__private_extern__ void vs_start_read(vstruct_t); +__private_extern__ void vs_finish_read(vstruct_t); +__private_extern__ void vs_wait_for_readers(vstruct_t); +__private_extern__ void vs_start_write(vstruct_t); +__private_extern__ void vs_finish_write(vstruct_t); +__private_extern__ void vs_wait_for_writers(vstruct_t); +#else /* PARALLEL */ +#define vs_lock(vs) +#define vs_unlock(vs) +#define vs_start_read(vs) +#define vs_wait_for_readers(vs) +#define vs_finish_read(vs) +#define vs_start_write(vs) +#define vs_wait_for_writers(vs) +#define vs_wait_for_sync_writers(vs) +#define vs_finish_write(vs) +#endif /* PARALLEL */ /* * Data structures and variables dealing with asynchronous @@ -673,9 +695,13 @@ struct vstruct_list_head { struct mutex vsl_lock; #endif int vsl_count; /* saves code */ - queue_head_t vsl_leak_queue; }; -extern struct vstruct_list_head vstruct_list; + +__private_extern__ struct vstruct_list_head vstruct_list; + +__private_extern__ void vstruct_list_insert(vstruct_t vs); +__private_extern__ void vstruct_list_delete(vstruct_t vs); + #ifdef MACH_KERNEL #define VSL_LOCK_INIT() mutex_init(&vstruct_list.vsl_lock, ETAP_DPAGE_VSLIST) @@ -686,6 +712,10 @@ extern struct vstruct_list_head vstruct_list; #define VSL_LOCK_TRY() mutex_try(&vstruct_list.vsl_lock) #define VSL_UNLOCK() mutex_unlock(&vstruct_list.vsl_lock) +#ifdef MACH_KERNEL +__private_extern__ zone_t vstruct_zone; +#endif + /* * Create port alias for vstruct address. * @@ -694,21 +724,28 @@ extern struct vstruct_list_head vstruct_list; * check. */ #ifdef MACH_KERNEL -#define ISVS 123456 -#define port_is_vs(_port_) \ - ((((struct vstruct_alias *)((_port_)->alias)) != NULL) && \ - (((struct vstruct_alias *)(_port_)->alias)->name==ISVS)) -#define port_to_vs(_port_) \ - ((struct vstruct_alias *)(_port_)->alias)->vs -#define vs_to_port(_vs_) (_vs_->vs_mem_obj_port) -#define vs_lookup(_port_, _vs_) \ + +#define ISVS ((int *)123456) +#define mem_obj_is_vs(_mem_obj_) \ + (((_mem_obj_) != NULL) && ((_mem_obj_)->pager == ISVS)) +#define mem_obj_to_vs(_mem_obj_) \ + ((vstruct_t)(_mem_obj_)) +#define vs_to_mem_obj(_vs_) ((memory_object_t)(_vs_)) +#define vs_lookup(_mem_obj_, _vs_) \ + do { \ + if (!mem_obj_is_vs(_mem_obj_)) \ + panic("bad dp memory object"); \ + _vs_ = mem_obj_to_vs(_mem_obj_); \ + } while (0) +#define vs_lookup_safe(_mem_obj_, _vs_) \ do { \ - if ((((struct vstruct_alias *)(_port_)->alias) == NULL) || \ - (((struct vstruct_alias *)(_port_)->alias)->name!=ISVS)) \ - panic("bad pager port"); \ - _vs_ = port_to_vs(_port_); \ + if (!mem_obj_is_vs(_mem_obj_)) \ + _vs_ = VSTRUCT_NULL; \ + else \ + _vs_ = mem_obj_to_vs(_mem_obj_); \ } while (0) #else + #define vs_to_port(_vs_) (((vm_offset_t)(_vs_))+1) #define port_to_vs(_port_) ((vstruct_t)(((vm_offset_t)(_port_))&~3)) #define port_is_vs(_port_) ((((vm_offset_t)(_port_))&3) == 1) @@ -716,7 +753,7 @@ extern struct vstruct_list_head vstruct_list; #define vs_lookup(_port_, _vs_) \ do { \ if (!MACH_PORT_VALID(_port_) || !port_is_vs(_port_) \ - || port_to_vs(_port_)->vs_mem_obj_port != (_port_)) \ + || port_to_vs(_port_)->vs_mem_obj != (_port_)) \ Panic("bad pager port"); \ _vs_ = port_to_vs(_port_); \ } while (0) @@ -731,14 +768,14 @@ extern int dp_thread_id(void); extern boolean_t device_reply_server(mach_msg_header_t *, mach_msg_header_t *); #ifdef MACH_KERNEL -extern void default_pager_no_senders(MACH_PORT_FACE, - mach_port_seqno_t, +extern boolean_t default_pager_no_senders(memory_object_t, mach_port_mscount_t); #else extern void default_pager_no_senders(memory_object_t, mach_port_seqno_t, mach_port_mscount_t); #endif + extern int local_log2(unsigned int); extern void bs_initialize(void); extern void bs_global_info(vm_size_t *, diff --git a/osfmk/default_pager/default_pager_object.defs b/osfmk/default_pager/default_pager_object.defs index 43595fe6d..77e4ae75e 100644 --- a/osfmk/default_pager/default_pager_object.defs +++ b/osfmk/default_pager/default_pager_object.defs @@ -71,9 +71,8 @@ type vnode_ptr_t = array[1] of int; routine default_pager_object_create( default_pager : mach_port_t; - out memory_object : memory_object_t = - MACH_MSG_TYPE_MAKE_SEND; - object_size : vm_size_t); + object_size : vm_size_t; + out memory_object : memory_object_t); routine default_pager_info( default_pager : mach_port_t; diff --git a/osfmk/default_pager/default_pager_types.h b/osfmk/default_pager/default_pager_types.h index 96b9206fb..745d22ad2 100644 --- a/osfmk/default_pager/default_pager_types.h +++ b/osfmk/default_pager/default_pager_types.h @@ -27,8 +27,11 @@ #ifndef _MACH_DEFAULT_PAGER_TYPES_H_ #define _MACH_DEFAULT_PAGER_TYPES_H_ - +#include <mach/mach_types.h> #include <mach/machine/vm_types.h> +#include <mach/memory_object_types.h> + +typedef memory_object_default_t default_pager_t; #ifdef MACH_KERNEL_PRIVATE diff --git a/osfmk/default_pager/diag.h b/osfmk/default_pager/diag.h index e197e2aa8..c4c58a688 100644 --- a/osfmk/default_pager/diag.h +++ b/osfmk/default_pager/diag.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2001, 2000 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -22,50 +22,6 @@ /* * @OSF_COPYRIGHT@ */ -/* - * HISTORY - * $Log: diag.h,v $ - * Revision 1.3 2000/01/26 05:56:23 wsanchez - * Add APSL - * - * Revision 1.2 1998/12/01 00:24:42 wsanchez - * Merged in CDY_DP1 (chris: default pager) - * - * Revision 1.1.2.2 1998/11/25 21:32:17 youngwor - * fix errant comment format - * - * Revision 1.1.2.1 1998/11/24 22:39:59 youngwor - * Check-in of support for the in-kernel default pager - * - * Revision 1.1.1.1 1998/03/07 02:26:31 wsanchez - * Import of OSF Mach kernel (~mburg) - * - * Revision 1.1.6.3 1995/04/07 18:51:32 barbou - * Changed panic messages format. - * [94/10/10 barbou] - * [95/03/08 barbou] - * - * Revision 1.1.6.2 1995/01/11 19:30:28 devrcs - * mk6 CR668 - 1.3b26 merge - * [1994/11/10 15:31:34 bolinger] - * - * Insert 1.3 log. - * - * BEGIN OSC1_3 HISTORY - * - * Revision 1.1.2.2 1994/04/01 18:45:25 jph - * CR10550 -- Add stats macros for info interfaces. - * [1994/04/01 18:45:06 jph] - * - * Revision 1.1.2.1 1994/02/16 14:22:46 jph - * CR10554 -- Simple assert and panic macros for diagnostics. - * [1994/02/16 14:22:02 jph] - * - * END OSC1_3 HISTORY - * [1994/11/10 15:30:44 bolinger] - * - * $EndLog$ - */ #ifndef MACH_KERNEL #ifdef ASSERTIONS @@ -78,9 +34,9 @@ #endif #ifndef MACH_KERNEL -#define Panic(aargh) panic("%s[%d]%s: %s", my_name, dp_thread_id(), here, aargh) +#define Panic(aargh) panic("%s[%d]: %s", my_name, dp_thread_id(), aargh) #else -#define Panic(aargh) panic("%s[KERNEL]%s: %s", my_name, here, aargh) +#define Panic(aargh) panic("%s[KERNEL]: %s", my_name, aargh) #endif extern char my_name[]; diff --git a/osfmk/default_pager/dp_backing_store.c b/osfmk/default_pager/dp_backing_store.c index ce90036af..effec727c 100644 --- a/osfmk/default_pager/dp_backing_store.c +++ b/osfmk/default_pager/dp_backing_store.c @@ -1,3 +1,4 @@ + /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * @@ -53,6 +54,7 @@ * Paging File Management. */ +#include <mach/memory_object_control.h> #include <mach/memory_object_server.h> #include "default_pager_internal.h" #include <default_pager/default_pager_alerts.h> @@ -66,14 +68,22 @@ /* CDY CDY */ #include <vm/vm_map.h> -/* MAXPHYS derived from bsd/bsd/ppc/param.h, we need a */ -/* universal originating in the kernel, or a formal means of exporting */ -/* from the bsd component */ +/* + * ALLOC_STRIDE... the maximum number of bytes allocated from + * a swap file before moving on to the next swap file... if + * all swap files reside on a single disk, this value should + * be very large (this is the default assumption)... if the + * swap files are spread across multiple disks, than this value + * should be small (128 * 1024)... + * + * This should be determined dynamically in the future + */ -#define MAXPHYS (64 * 1024) +#define ALLOC_STRIDE (1024 * 1024 * 1024) int physical_transfer_cluster_count = 0; -#define VM_SUPER_CLUSTER 0x10000 +#define VM_SUPER_CLUSTER 0x20000 +#define VM_SUPER_PAGES 32 /* * 0 means no shift to pages, so == 1 page/cluster. 1 would mean @@ -84,8 +94,8 @@ int vstruct_def_clshift = VSTRUCT_DEF_CLSHIFT; int default_pager_clsize = 0; /* statistics */ -unsigned int clustered_writes[MAX_CLUSTER_SIZE+1]; -unsigned int clustered_reads[MAX_CLUSTER_SIZE+1]; +unsigned int clustered_writes[VM_SUPER_PAGES+1]; +unsigned int clustered_reads[VM_SUPER_PAGES+1]; /* * Globals used for asynchronous paging operations: @@ -133,6 +143,7 @@ ipc_port_t min_pages_trigger_port = NULL; ipc_port_t max_pages_trigger_port = NULL; boolean_t bs_low = FALSE; +int backing_store_release_trigger_disable = 0; @@ -163,6 +174,8 @@ unsigned int dp_pages_free = 0; unsigned int cluster_transfer_minimum = 100; kern_return_t ps_write_file(paging_segment_t, upl_t, vm_offset_t, vm_offset_t, unsigned int, int); /* forward */ +kern_return_t ps_read_file (paging_segment_t, upl_t, vm_offset_t, vm_offset_t, unsigned int, unsigned int *, int); /* forward */ + default_pager_thread_t * get_read_buffer() @@ -201,7 +214,7 @@ bs_initialize(void) vs_async_free_list = NULL; #endif /* VS_ASYNC_REUSE */ - for (i = 0; i < MAX_CLUSTER_SIZE+1; i++) { + for (i = 0; i < VM_SUPER_PAGES + 1; i++) { clustered_writes[i] = 0; clustered_reads[i] = 0; } @@ -217,7 +230,6 @@ void bs_no_paging_space( boolean_t out_of_memory) { - static char here[] = "bs_no_paging_space"; if (out_of_memory) dprintf(("*** OUT OF MEMORY ***\n")); @@ -307,7 +319,6 @@ bs_global_info( vm_size_t pages_total, pages_free; paging_segment_t ps; int i; - static char here[] = "bs_global_info"; PSL_LOCK(); pages_total = pages_free = 0; @@ -346,7 +357,6 @@ backing_store_t backing_store_alloc(void) { backing_store_t bs; - static char here[] = "backing_store_alloc"; bs = (backing_store_t) kalloc(sizeof (struct backing_store)); if (bs == BACKING_STORE_NULL) @@ -410,7 +420,6 @@ backing_store_add( MACH_PORT_FACE port = bs->bs_port; MACH_PORT_FACE pset = default_pager_default_set; kern_return_t kr = KERN_SUCCESS; - static char here[] = "backing_store_add"; if (kr != KERN_SUCCESS) panic("backing_store_add: add to set"); @@ -443,9 +452,8 @@ bs_get_global_clsize( int clsize) { int i; - MACH_PORT_FACE DMM; + memory_object_default_t dmm; kern_return_t kr; - static char here[] = "bs_get_global_clsize"; /* * Only allow setting of cluster size once. If called @@ -454,13 +462,6 @@ bs_get_global_clsize( * paging segments. */ if (default_pager_clsize == 0) { - if (norma_mk) { - /* - * On NORMA, don't use clustered paging because - * XMM can't handle it. - */ - vstruct_def_clshift = 0; - } /* * Keep cluster size in bit shift because it's quicker * arithmetic, and easier to keep at a power of 2. @@ -480,19 +481,22 @@ bs_get_global_clsize( printf("%scluster size = %d page%s\n", my_name, default_pager_clsize, (default_pager_clsize == 1) ? "" : "s"); + /* * Let the kernel know too, in case it hasn't used the * default value provided in main() yet. */ - DMM = default_pager_default_port; + dmm = default_pager_object; clsize = default_pager_clsize * vm_page_size; /* in bytes */ kr = host_default_memory_manager(host_priv_self(), - &DMM, + &dmm, clsize); + memory_object_default_deallocate(dmm); + if (kr != KERN_SUCCESS) { panic("bs_get_global_cl_size:host_default_memory_manager"); } - if (DMM != default_pager_default_port) { + if (dmm != default_pager_object) { panic("bs_get_global_cl_size:there is another default pager"); } } @@ -504,18 +508,17 @@ bs_get_global_clsize( kern_return_t default_pager_backing_store_create( - MACH_PORT_FACE pager, - int priority, - int clsize, /* in bytes */ - MACH_PORT_FACE *backing_store) + memory_object_default_t pager, + int priority, + int clsize, /* in bytes */ + MACH_PORT_FACE *backing_store) { backing_store_t bs; MACH_PORT_FACE port; kern_return_t kr; struct vstruct_alias *alias_struct; - static char here[] = "default_pager_backing_store_create"; - if (pager != default_pager_default_port) + if (pager != default_pager_object) return KERN_INVALID_ARGUMENT; bs = backing_store_alloc(); @@ -645,6 +648,16 @@ ps_delete( /* lock and the vs locks are not being held by bumping the */ /* vs_async_pending count. */ + + while(backing_store_release_trigger_disable != 0) { + assert_wait((event_t) + &backing_store_release_trigger_disable, + THREAD_UNINT); + VSL_UNLOCK(); + thread_block((void (*)(void)) 0); + VSL_LOCK(); + } + /* we will choose instead to hold a send right */ vs_count = vstruct_list.vsl_count; vs = (vstruct_t) queue_first((queue_entry_t)&(vstruct_list.vsl_queue)); @@ -677,23 +690,27 @@ ps_delete( error = KERN_FAILURE; else { vm_object_t transfer_object; + int count; upl_t upl; transfer_object = vm_object_allocate(VM_SUPER_CLUSTER); - error = vm_fault_list_request(transfer_object, - (vm_object_offset_t)0, - VM_SUPER_CLUSTER, &upl, NULL, - 0, UPL_NO_SYNC | UPL_CLEAN_IN_PLACE - | UPL_SET_INTERNAL); + count = 0; + error = vm_object_upl_request(transfer_object, + (vm_object_offset_t)0, VM_SUPER_CLUSTER, + &upl, NULL, &count, + UPL_NO_SYNC | UPL_CLEAN_IN_PLACE + | UPL_SET_INTERNAL); if(error == KERN_SUCCESS) { #ifndef ubc_sync_working - uc_upl_commit(upl, NULL); + upl_commit(upl, NULL); + upl_deallocate(upl); error = ps_vstruct_transfer_from_segment( vs, ps, transfer_object); #else error = ps_vstruct_transfer_from_segment( vs, ps, upl); - uc_upl_commit(upl, NULL); + upl_commit(upl, NULL); + upl_deallocate(upl); #endif vm_object_deallocate(transfer_object); } else { @@ -704,9 +721,10 @@ ps_delete( if(error) { VS_LOCK(vs); vs->vs_async_pending -= 1; /* release vs_async_wait */ - if (vs->vs_async_pending == 0) { + if (vs->vs_async_pending == 0 && vs->vs_waiting_async) { + vs->vs_waiting_async = FALSE; VS_UNLOCK(vs); - thread_wakeup(&vs->vs_waiting_async); + thread_wakeup(&vs->vs_async_pending); } else { VS_UNLOCK(vs); } @@ -714,6 +732,16 @@ ps_delete( } VSL_LOCK(); + + while(backing_store_release_trigger_disable != 0) { + assert_wait((event_t) + &backing_store_release_trigger_disable, + THREAD_UNINT); + VSL_UNLOCK(); + thread_block((void (*)(void)) 0); + VSL_LOCK(); + } + next_vs = (vstruct_t) queue_next(&(vs->vs_links)); if((next_vs != (vstruct_t)&vstruct_list) && (vs != next_vs) && (vs_count != 1)) { @@ -727,9 +755,10 @@ ps_delete( VSL_UNLOCK(); VS_LOCK(vs); vs->vs_async_pending -= 1; - if (vs->vs_async_pending == 0) { + if (vs->vs_async_pending == 0 && vs->vs_waiting_async) { + vs->vs_waiting_async = FALSE; VS_UNLOCK(vs); - thread_wakeup(&vs->vs_waiting_async); + thread_wakeup(&vs->vs_async_pending); } else { VS_UNLOCK(vs); } @@ -753,7 +782,6 @@ default_pager_backing_store_delete( int error; int interim_pages_removed = 0; kern_return_t kr; - static char here[] = "default_pager_backing_store_delete"; if ((bs = backing_store_lookup(backing_store)) == BACKING_STORE_NULL) return KERN_INVALID_ARGUMENT; @@ -863,7 +891,6 @@ default_pager_backing_store_delete( if((void *)bs->bs_port->alias != NULL) kfree((vm_offset_t) bs->bs_port->alias, sizeof (struct vstruct_alias)); - pager_mux_hash_delete((ipc_port_t) (bs->bs_port)); ipc_port_dealloc_kernel((ipc_port_t) (bs->bs_port)); bs->bs_port = MACH_PORT_NULL; BS_UNLOCK(bs); @@ -930,7 +957,6 @@ default_pager_add_segment( paging_segment_t ps; int i; int error; - static char here[] = "default_pager_add_segment"; if ((bs = backing_store_lookup(backing_store)) == BACKING_STORE_NULL) @@ -1042,7 +1068,7 @@ bs_add_device( count = info[DEV_GET_SIZE_DEVICE_SIZE] / rec_size; clsize = bs_get_global_clsize(0); if (!default_pager_backing_store_create( - default_pager_default_port, + default_pager_object, DEFAULT_PAGER_BACKING_STORE_MAXPRI, (clsize * vm_page_size), &bs)) { @@ -1159,14 +1185,12 @@ void vs_free_async( struct vs_async *vsa) { - static char here[] = "vs_free_async"; MACH_PORT_FACE reply_port; kern_return_t kr; reply_port = vsa->reply_port; kfree((vm_offset_t) reply_port->alias, sizeof (struct vstuct_alias)); kfree((vm_offset_t) vsa, sizeof (struct vs_async)); - pager_mux_hash_delete(reply_port); ipc_port_dealloc_kernel((MACH_PORT_FACE) (reply_port)); #if 0 VS_ASYNC_LOCK(); @@ -1177,15 +1201,16 @@ vs_free_async( #endif /* VS_ASYNC_REUSE */ +zone_t vstruct_zone; + vstruct_t ps_vstruct_create( vm_size_t size) { vstruct_t vs; int i; - static char here[] = "ps_vstruct_create"; - vs = (vstruct_t) kalloc(sizeof (struct vstruct)); + vs = (vstruct_t) zalloc(vstruct_zone); if (vs == VSTRUCT_NULL) { return VSTRUCT_NULL; } @@ -1195,18 +1220,15 @@ ps_vstruct_create( /* * The following fields will be provided later. */ - vs->vs_mem_obj_port = MACH_PORT_NULL; + vs->vs_mem_obj = NULL; + vs->vs_control = MEMORY_OBJECT_CONTROL_NULL; + vs->vs_references = 1; vs->vs_seqno = 0; - vs->vs_control_port = MACH_PORT_NULL; - vs->vs_control_refs = 0; - vs->vs_object_name = MACH_PORT_NULL; - vs->vs_name_refs = 0; #ifdef MACH_KERNEL vs->vs_waiting_seqno = FALSE; vs->vs_waiting_read = FALSE; vs->vs_waiting_write = FALSE; - vs->vs_waiting_refs = FALSE; vs->vs_waiting_async = FALSE; #else mutex_init(&vs->vs_waiting_seqno, ETAP_DPAGE_VSSEQNO); @@ -1277,7 +1299,6 @@ ps_select_segment( paging_segment_t ps; int i; int j; - static char here[] = "ps_select_segment"; /* * Optimize case where there's only one segment. @@ -1287,6 +1308,7 @@ ps_select_segment( PSL_LOCK(); if (paging_segment_count == 1) { paging_segment_t lps; /* used to avoid extra PS_UNLOCK */ + ipc_port_t trigger = IP_NULL; ps = paging_segments[paging_segment_max]; *psindex = paging_segment_max; @@ -1301,9 +1323,7 @@ ps_select_segment( dp_pages_free -= 1 << ps->ps_clshift; if(min_pages_trigger_port && (dp_pages_free < minimum_pages_remaining)) { - default_pager_space_alert( - min_pages_trigger_port, - HI_WAT_ALERT); + trigger = min_pages_trigger_port; min_pages_trigger_port = NULL; bs_low = TRUE; } @@ -1313,6 +1333,11 @@ ps_select_segment( } PS_UNLOCK(ps); PSL_UNLOCK(); + + if (trigger != IP_NULL) { + default_pager_space_alert(trigger, HI_WAT_ALERT); + ipc_port_release_send(trigger); + } return lps; } @@ -1334,9 +1359,9 @@ ps_select_segment( j = start_index+1; physical_transfer_cluster_count = 0; } - else if ((physical_transfer_cluster_count+1) == (MAXPHYS >> + else if ((physical_transfer_cluster_count+1) == (ALLOC_STRIDE >> (((paging_segments[start_index])->ps_clshift) - + page_shift))) { + + vm_page_shift))) { physical_transfer_cluster_count = 0; j = start_index + 1; } else { @@ -1362,14 +1387,14 @@ ps_select_segment( /* this segment is being turned off */ } else if ((ps->ps_clcount) && (ps->ps_clshift >= shift)) { + ipc_port_t trigger = IP_NULL; + ps->ps_clcount--; dp_pages_free -= 1 << ps->ps_clshift; if(min_pages_trigger_port && (dp_pages_free < minimum_pages_remaining)) { - default_pager_space_alert( - min_pages_trigger_port, - HI_WAT_ALERT); + trigger = min_pages_trigger_port; min_pages_trigger_port = NULL; } PS_UNLOCK(ps); @@ -1378,6 +1403,13 @@ ps_select_segment( */ ps_select_array[i] = j; PSL_UNLOCK(); + + if (trigger != IP_NULL) { + default_pager_space_alert( + trigger, + HI_WAT_ALERT); + ipc_port_release_send(trigger); + } *psindex = j; return ps; } @@ -1409,7 +1441,7 @@ ps_allocate_cluster( int bit_num = 0; paging_segment_t ps; vm_offset_t cluster; - static char here[] = "ps_allocate_cluster"; + ipc_port_t trigger = IP_NULL; /* * Find best paging segment. @@ -1440,15 +1472,18 @@ ps_allocate_cluster( PS_LOCK(ps); ps->ps_clcount--; dp_pages_free -= 1 << ps->ps_clshift; - PSL_UNLOCK(); if(min_pages_trigger_port && (dp_pages_free < minimum_pages_remaining)) { - default_pager_space_alert( - min_pages_trigger_port, - HI_WAT_ALERT); + trigger = min_pages_trigger_port; min_pages_trigger_port = NULL; } + PSL_UNLOCK(); PS_UNLOCK(ps); + if (trigger != IP_NULL) { + default_pager_space_alert(trigger, HI_WAT_ALERT); + ipc_port_release_send(trigger); + } + } else if ((ps = ps_select_segment(vs->vs_clshift, psindex)) == PAGING_SEGMENT_NULL) { #if 0 @@ -1460,13 +1495,18 @@ ps_allocate_cluster( dprintf(("no space in available paging segments; " "swapon suggested\n")); /* the count got off maybe, reset to zero */ + PSL_LOCK(); dp_pages_free = 0; if(min_pages_trigger_port) { - default_pager_space_alert( - min_pages_trigger_port, HI_WAT_ALERT); + trigger = min_pages_trigger_port; min_pages_trigger_port = NULL; bs_low = TRUE; } + PSL_UNLOCK(); + if (trigger != IP_NULL) { + default_pager_space_alert(trigger, HI_WAT_ALERT); + ipc_port_release_send(trigger); + } return (vm_offset_t) -1; } ASSERT(ps->ps_clcount != 0); @@ -1507,6 +1547,7 @@ ps_deallocate_cluster( paging_segment_t ps, vm_offset_t cluster) { + ipc_port_t trigger = IP_NULL; if (cluster >= (vm_offset_t) ps->ps_ncls) panic("ps_deallocate_cluster: Invalid cluster number"); @@ -1520,11 +1561,13 @@ ps_deallocate_cluster( clrbit(ps->ps_bmap, cluster); ++ps->ps_clcount; dp_pages_free += 1 << ps->ps_clshift; - PSL_UNLOCK(); - if(max_pages_trigger_port && (dp_pages_free > maximum_pages_free)) { - default_pager_space_alert(max_pages_trigger_port, LO_WAT_ALERT); + if(max_pages_trigger_port + && (backing_store_release_trigger_disable == 0) + && (dp_pages_free > maximum_pages_free)) { + trigger = max_pages_trigger_port; max_pages_trigger_port = NULL; } + PSL_UNLOCK(); /* * Move the hint down to the freed cluster if it is @@ -1544,6 +1587,21 @@ ps_deallocate_cluster( ps_select_array[ps->ps_bs->bs_priority] = 0; PSL_UNLOCK(); + if (trigger != IP_NULL) { + VSL_LOCK(); + if(backing_store_release_trigger_disable != 0) { + assert_wait((event_t) + &backing_store_release_trigger_disable, + THREAD_UNINT); + VSL_UNLOCK(); + thread_block((void (*)(void)) 0); + } else { + VSL_UNLOCK(); + } + default_pager_space_alert(trigger, LO_WAT_ALERT); + ipc_port_release_send(trigger); + } + return; } @@ -1567,7 +1625,6 @@ ps_vstruct_dealloc( { int i; spl_t s; - static char here[] = "ps_vstruct_dealloc"; VS_MAP_LOCK(vs); @@ -1601,24 +1658,7 @@ ps_vstruct_dealloc( bs_commit(- vs->vs_size); - ip_lock(vs_to_port(vs)); - (vs_to_port(vs))->ip_destination = 0; - (vs_to_port(vs))->ip_receiver_name = MACH_PORT_NULL; - - s= splsched(); - imq_lock(&vs_to_port(vs)->ip_messages); - (vs_to_port(vs))->ip_mscount = 0; - (vs_to_port(vs))->ip_messages.imq_seqno = 0; - imq_unlock(&vs_to_port(vs)->ip_messages); - splx(s); - - ip_unlock(vs_to_port(vs)); - pager_mux_hash_delete((ipc_port_t) vs_to_port(vs)); - ipc_port_release_receive(vs_to_port(vs)); - /* - * Do this *after* deallocating the port name - */ - kfree((vm_offset_t)vs, sizeof *vs); + zfree(vstruct_zone, (vm_offset_t)vs); } int ps_map_extend(vstruct_t, int); /* forward */ @@ -1746,7 +1786,6 @@ ps_clmap( vm_offset_t newoff; int i; struct vs_map *vsmap; - static char here[] = "ps_clmap"; VS_MAP_LOCK(vs); @@ -1952,7 +1991,6 @@ ps_clunmap( { vm_offset_t cluster; /* The cluster number of offset */ struct vs_map *vsmap; - static char here[] = "ps_clunmap"; VS_MAP_LOCK(vs); @@ -2049,7 +2087,6 @@ vs_cl_write_complete( boolean_t async, int error) { - static char here[] = "vs_cl_write_complete"; kern_return_t kr; if (error) { @@ -2071,10 +2108,11 @@ vs_cl_write_complete( VS_LOCK(vs); ASSERT(vs->vs_async_pending > 0); vs->vs_async_pending -= size; - if (vs->vs_async_pending == 0) { + if (vs->vs_async_pending == 0 && vs->vs_waiting_async) { + vs->vs_waiting_async = FALSE; VS_UNLOCK(vs); /* mutex_unlock(&vs->vs_waiting_async); */ - thread_wakeup(&vs->vs_waiting_async); + thread_wakeup(&vs->vs_async_pending); } else { VS_UNLOCK(vs); } @@ -2091,7 +2129,6 @@ device_write_reply( io_buf_len_t bytes_written) { struct vs_async *vsa; - static char here[] = "device_write_reply"; vsa = (struct vs_async *) ((struct vstruct_alias *)(reply_port->alias))->vs; @@ -2209,7 +2246,6 @@ ps_read_device( vm_offset_t dev_buffer; vm_offset_t buf_ptr; unsigned int records_read; - static char here[] = "ps_read_device"; struct vs_async *vsa; mutex_t vs_waiting_read_reply; @@ -2347,7 +2383,6 @@ ps_write_device( recnum_t records_written; kern_return_t kr; MACH_PORT_FACE reply_port; - static char here[] = "ps_write_device"; @@ -2470,7 +2505,6 @@ pvs_object_data_provided( vm_offset_t offset, vm_size_t size) { - static char here[] = "pvs_object_data_provided"; DEBUG(DEBUG_VS_INTERNAL, ("buffer=0x%x,offset=0x%x,size=0x%x\n", @@ -2489,32 +2523,40 @@ pvs_object_data_provided( kern_return_t pvs_cluster_read( vstruct_t vs, - vm_offset_t offset, + vm_offset_t vs_offset, vm_size_t cnt) { - vm_offset_t actual_offset; - vm_offset_t buffer; - paging_segment_t ps; - struct clmap clmap; upl_t upl; kern_return_t error = KERN_SUCCESS; - int size, size_wanted, i; + int size; unsigned int residual; unsigned int request_flags; - int unavail_size; - default_pager_thread_t *dpt; - boolean_t dealloc; - static char here[] = "pvs_cluster_read"; + int seg_index; + int pages_in_cl; + int cl_size; + int cl_mask; + int cl_index; + int xfer_size; + vm_offset_t ps_offset[(VM_SUPER_CLUSTER / PAGE_SIZE) >> VSTRUCT_DEF_CLSHIFT]; + paging_segment_t psp[(VM_SUPER_CLUSTER / PAGE_SIZE) >> VSTRUCT_DEF_CLSHIFT]; + struct clmap clmap; + + pages_in_cl = 1 << vs->vs_clshift; + cl_size = pages_in_cl * vm_page_size; + cl_mask = cl_size - 1; /* - * This loop will be executed once per cluster referenced. - * Typically this means once, since it's unlikely that the - * VM system will ask for anything spanning cluster boundaries. + * This loop will be executed multiple times until the entire + * request has been satisfied... if the request spans cluster + * boundaries, the clusters will be checked for logical continunity, + * if contiguous the I/O request will span multiple clusters, otherwise + * it will be broken up into the minimal set of I/O's * - * If there are holes in a cluster (in a paging segment), we stop + * If there are holes in a request (either unallocated pages in a paging + * segment or an unallocated paging segment), we stop * reading at the hole, inform the VM of any data read, inform * the VM of an unavailable range, then loop again, hoping to - * find valid pages later in the cluster. This continues until + * find valid pages later in the requested range. This continues until * the entire range has been examined, and read, if present. */ @@ -2524,165 +2566,249 @@ pvs_cluster_read( request_flags = UPL_NO_SYNC | UPL_CLEAN_IN_PLACE ; #endif while (cnt && (error == KERN_SUCCESS)) { - actual_offset = ps_clmap(vs, offset, &clmap, CL_FIND, 0, 0); + int ps_info_valid; + int page_list_count; - if (actual_offset == (vm_offset_t) -1) { + if (cnt > VM_SUPER_CLUSTER) + size = VM_SUPER_CLUSTER; + else + size = cnt; + cnt -= size; - /* - * Either a failure due to an error on a previous - * write or a zero fill on demand page. In either case, - * optimize to do one reply for all pages up to next - * cluster boundary. - */ - unsigned int local_size, clmask, clsize; + ps_info_valid = 0; + seg_index = 0; - clmask = (vm_page_size << vs->vs_clshift) - 1; - clsize = vm_page_size << vs->vs_clshift; - clmask = clsize - 1; - local_size = clsize - (offset & clmask); - ASSERT(local_size); - local_size = MIN(local_size, cnt); + while (size > 0 && error == KERN_SUCCESS) { + int abort_size; + int failed_size; + int beg_pseg; + int beg_indx; + vm_offset_t cur_offset; - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, local_size, local_size, - &upl, NULL, 0, request_flags); - if (clmap.cl_error) { - uc_upl_abort(upl, UPL_ABORT_ERROR); - } else { - uc_upl_abort(upl, UPL_ABORT_UNAVAILABLE); + + if ( !ps_info_valid) { + ps_offset[seg_index] = ps_clmap(vs, vs_offset & ~cl_mask, &clmap, CL_FIND, 0, 0); + psp[seg_index] = CLMAP_PS(clmap); + ps_info_valid = 1; } + /* + * skip over unallocated physical segments + */ + if (ps_offset[seg_index] == (vm_offset_t) -1) { + abort_size = cl_size - (vs_offset & cl_mask); + abort_size = MIN(abort_size, size); + + page_list_count = 0; + memory_object_super_upl_request( + vs->vs_control, + (memory_object_offset_t)vs_offset, + abort_size, abort_size, + &upl, NULL, &page_list_count, + request_flags); - cnt -= local_size; - offset += local_size; - continue; - } + if (clmap.cl_error) { + upl_abort(upl, UPL_ABORT_ERROR); + } else { + upl_abort(upl, UPL_ABORT_UNAVAILABLE); + } + upl_deallocate(upl); - /* - * Count up contiguous available or unavailable - * pages. - */ - ps = CLMAP_PS(clmap); - ASSERT(ps); - size = 0; - unavail_size = 0; + size -= abort_size; + vs_offset += abort_size; - for (i = 0; - (size < cnt) && (unavail_size < cnt) && - (i < CLMAP_NPGS(clmap)); i++) { - if (CLMAP_ISSET(clmap, i)) { - if (unavail_size != 0) - break; - size += vm_page_size; - BS_STAT(ps->ps_bs, - ps->ps_bs->bs_pages_in++); - } else { - if (size != 0) - break; - unavail_size += vm_page_size; + seg_index++; + ps_info_valid = 0; + continue; } - } - /* - * Let VM system know about holes in clusters. - */ - if (size == 0) { - ASSERT(unavail_size); - GSTAT(global_stats.gs_pages_unavail += - atop(unavail_size)); - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, unavail_size, - unavail_size, &upl, NULL, 0, + cl_index = (vs_offset & cl_mask) / vm_page_size; + + for (abort_size = 0; cl_index < pages_in_cl && abort_size < size; cl_index++) { + /* + * skip over unallocated pages + */ + if (CLMAP_ISSET(clmap, cl_index)) + break; + abort_size += vm_page_size; + } + if (abort_size) { + /* + * Let VM system know about holes in clusters. + */ + GSTAT(global_stats.gs_pages_unavail += atop(abort_size)); + + page_list_count = 0; + memory_object_super_upl_request( + vs->vs_control, + (memory_object_offset_t)vs_offset, + abort_size, abort_size, + &upl, NULL, &page_list_count, request_flags); - uc_upl_abort(upl, UPL_ABORT_UNAVAILABLE); - cnt -= unavail_size; - offset += unavail_size; - continue; - } - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, size, size, &upl, - NULL, 0, request_flags | UPL_SET_INTERNAL); - if(ps->ps_segtype == PS_PARTITION) { -/* - error = ps_read_device(ps, actual_offset, upl, - size, &residual, 0); -*/ - } else { - error = ps_read_file(ps, upl, actual_offset, - size, &residual, 0); - } + upl_abort(upl, UPL_ABORT_UNAVAILABLE); + upl_deallocate(upl); - /* - * Adjust counts and send response to VM. Optimize for the - * common case, i.e. no error and/or partial data. - * If there was an error, then we need to error the entire - * range, even if some data was successfully read. - * If there was a partial read we may supply some - * data and may error some as well. In all cases the - * VM must receive some notification for every page in the - * range. - */ - if ((error == KERN_SUCCESS) && (residual == 0)) { + size -= abort_size; + vs_offset += abort_size; + + if (cl_index == pages_in_cl) { + /* + * if we're at the end of this physical cluster + * then bump to the next one and continue looking + */ + seg_index++; + ps_info_valid = 0; + continue; + } + if (size == 0) + break; + } /* - * Got everything we asked for, supply the data to - * the VM. Note that as a side effect of supplying - * the data, the buffer holding the supplied data is - * deallocated from the pager's address space. + * remember the starting point of the first allocated page + * for the I/O we're about to issue */ - pvs_object_data_provided(vs, upl, offset, size); - } else { - size_wanted = size; - if (error == KERN_SUCCESS) { - if (residual == size) { - /* - * If a read operation returns no error - * and no data moved, we turn it into - * an error, assuming we're reading at - * or beyong EOF. - * Fall through and error the entire - * range. + beg_pseg = seg_index; + beg_indx = cl_index; + cur_offset = vs_offset; + + /* + * calculate the size of the I/O that we can do... + * this may span multiple physical segments if + * they are contiguous + */ + for (xfer_size = 0; xfer_size < size; ) { + + while (cl_index < pages_in_cl && xfer_size < size) { + /* + * accumulate allocated pages within a physical segment */ - error = KERN_FAILURE; - } else { - /* - * Otherwise, we have partial read. If - * the part read is a integral number - * of pages supply it. Otherwise round - * it up to a page boundary, zero fill - * the unread part, and supply it. - * Fall through and error the remainder - * of the range, if any. + if (CLMAP_ISSET(clmap, cl_index)) { + xfer_size += vm_page_size; + cur_offset += vm_page_size; + cl_index++; + + BS_STAT(psp[seg_index]->ps_bs, + psp[seg_index]->ps_bs->bs_pages_in++); + } else + break; + } + if (cl_index < pages_in_cl || xfer_size >= size) { + /* + * we've hit an unallocated page or the + * end of this request... go fire the I/O */ - int fill, lsize; - - fill = residual & ~vm_page_size; - lsize = (size - residual) + fill; - pvs_object_data_provided(vs, upl, - offset, lsize); - cnt -= lsize; - offset += lsize; - if (size -= lsize) { - error = KERN_FAILURE; - } + break; + } + /* + * we've hit the end of the current physical segment + * and there's more to do, so try moving to the next one + */ + seg_index++; + + ps_offset[seg_index] = ps_clmap(vs, cur_offset & ~cl_mask, &clmap, CL_FIND, 0, 0); + psp[seg_index] = CLMAP_PS(clmap); + ps_info_valid = 1; + + if ((ps_offset[seg_index - 1] != (ps_offset[seg_index] - cl_size)) || (psp[seg_index - 1] != psp[seg_index])) { + /* + * if the physical segment we're about to step into + * is not contiguous to the one we're currently + * in, or it's in a different paging file, or + * it hasn't been allocated.... + * we stop here and generate the I/O + */ + break; } + /* + * start with first page of the next physical segment + */ + cl_index = 0; } + if (xfer_size) { + /* + * we have a contiguous range of allocated pages + * to read from + */ + page_list_count = 0; + memory_object_super_upl_request(vs->vs_control, + (memory_object_offset_t)vs_offset, + xfer_size, xfer_size, + &upl, NULL, &page_list_count, + request_flags | UPL_SET_INTERNAL); + + error = ps_read_file(psp[beg_pseg], upl, (vm_offset_t) 0, + ps_offset[beg_pseg] + (beg_indx * vm_page_size), xfer_size, &residual, 0); + } else + continue; + failed_size = 0; + + /* + * Adjust counts and send response to VM. Optimize for the + * common case, i.e. no error and/or partial data. + * If there was an error, then we need to error the entire + * range, even if some data was successfully read. + * If there was a partial read we may supply some + * data and may error some as well. In all cases the + * VM must receive some notification for every page in the + * range. + */ + if ((error == KERN_SUCCESS) && (residual == 0)) { + /* + * Got everything we asked for, supply the data to + * the VM. Note that as a side effect of supplying + * the data, the buffer holding the supplied data is + * deallocated from the pager's address space. + */ + pvs_object_data_provided(vs, upl, vs_offset, xfer_size); + } else { + failed_size = xfer_size; + + if (error == KERN_SUCCESS) { + if (residual == xfer_size) { + /* + * If a read operation returns no error + * and no data moved, we turn it into + * an error, assuming we're reading at + * or beyong EOF. + * Fall through and error the entire + * range. + */ + error = KERN_FAILURE; + } else { + /* + * Otherwise, we have partial read. If + * the part read is a integral number + * of pages supply it. Otherwise round + * it up to a page boundary, zero fill + * the unread part, and supply it. + * Fall through and error the remainder + * of the range, if any. + */ + int fill, lsize; + + fill = residual & ~vm_page_size; + lsize = (xfer_size - residual) + fill; + pvs_object_data_provided(vs, upl, vs_offset, lsize); + + if (lsize < xfer_size) { + failed_size = xfer_size - lsize; + error = KERN_FAILURE; + } + } + } + } /* * If there was an error in any part of the range, tell - * the VM. Deallocate the remainder of the buffer. - * Note that error is explicitly checked again since + * the VM. Note that error is explicitly checked again since * it can be modified above. */ if (error != KERN_SUCCESS) { - BS_STAT(ps->ps_bs, - ps->ps_bs->bs_pages_in_fail += - atop(size)); + BS_STAT(psp[beg_pseg]->ps_bs, + psp[beg_pseg]->ps_bs->bs_pages_in_fail += atop(failed_size)); } + size -= xfer_size; + vs_offset += xfer_size; } - cnt -= size; - offset += size; } /* END while (cnt && (error == 0)) */ return error; @@ -2699,166 +2825,200 @@ vs_cluster_write( boolean_t dp_internal, int flags) { - vm_offset_t actual_offset; /* Offset within paging segment */ vm_offset_t size; vm_offset_t transfer_size; - vm_offset_t subx_size; int error = 0; struct clmap clmap; + + vm_offset_t actual_offset; /* Offset within paging segment */ paging_segment_t ps; + vm_offset_t subx_size; + vm_offset_t mobj_base_addr; + vm_offset_t mobj_target_addr; + int mobj_size; + struct vs_async *vsa; vm_map_copy_t copy; - static char here[] = "vs_cluster_write"; upl_t upl; - upl_page_info_t *page_list; - upl_page_info_t pl[20]; - vm_offset_t mobj_base_addr; - vm_offset_t mobj_target_addr; - int mobj_size; + upl_page_info_t *pl; int page_index; int list_size; int cl_size; - - ps = PAGING_SEGMENT_NULL; - if (!dp_internal) { + int page_list_count; int request_flags; int super_size; + int first_dirty; + int num_dirty; + int num_of_pages; + int seg_index; + int pages_in_cl; + int must_abort; vm_offset_t upl_offset; + vm_offset_t seg_offset; + vm_offset_t ps_offset[(VM_SUPER_CLUSTER / PAGE_SIZE) >> VSTRUCT_DEF_CLSHIFT]; + paging_segment_t psp[(VM_SUPER_CLUSTER / PAGE_SIZE) >> VSTRUCT_DEF_CLSHIFT]; + - cl_size = (1 << vs->vs_clshift) * vm_page_size; + pages_in_cl = 1 << vs->vs_clshift; + cl_size = pages_in_cl * vm_page_size; if (bs_low) { super_size = cl_size; + request_flags = UPL_NOBLOCK | UPL_RET_ONLY_DIRTY | UPL_COPYOUT_FROM | UPL_NO_SYNC | UPL_SET_INTERNAL; } else { super_size = VM_SUPER_CLUSTER; + request_flags = UPL_NOBLOCK | UPL_CLEAN_IN_PLACE | UPL_RET_ONLY_DIRTY | UPL_COPYOUT_FROM | UPL_NO_SYNC | UPL_SET_INTERNAL; } + page_list_count = 0; + memory_object_super_upl_request(vs->vs_control, + (memory_object_offset_t)offset, + cnt, super_size, + &upl, NULL, &page_list_count, + request_flags | UPL_PAGEOUT); - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, cnt, super_size, - &upl, NULL, - 0, request_flags); + pl = UPL_GET_INTERNAL_PAGE_LIST(upl); - mobj_base_addr = upl->offset; - list_size = upl->size; + for (seg_index = 0, transfer_size = upl->size; transfer_size > 0; ) { - page_list = UPL_GET_INTERNAL_PAGE_LIST(upl); - memcpy(pl, page_list, - sizeof(upl_page_info_t) * (list_size/page_size)); + ps_offset[seg_index] = ps_clmap(vs, upl->offset + (seg_index * cl_size), + &clmap, CL_ALLOC, + transfer_size < cl_size ? + transfer_size : cl_size, 0); - /* Now parcel up the 64k transfer, do at most cluster size */ - /* at a time. */ - upl_offset = 0; - page_index = 0; - mobj_target_addr = mobj_base_addr; + if (ps_offset[seg_index] == (vm_offset_t) -1) { + upl_abort(upl, 0); + upl_deallocate(upl); + + return KERN_FAILURE; - for (transfer_size = list_size; transfer_size != 0;) { - actual_offset = ps_clmap(vs, mobj_target_addr, - &clmap, CL_ALLOC, - transfer_size < cl_size ? - transfer_size : cl_size, 0); + } + psp[seg_index] = CLMAP_PS(clmap); - if (actual_offset == (vm_offset_t) -1) { - for(;transfer_size != 0;) { - if(UPL_PAGE_PRESENT(pl, page_index)) { - uc_upl_abort_range(upl, - upl_offset, - transfer_size, - UPL_ABORT_FREE_ON_EMPTY); - break; - } - transfer_size-=page_size; - upl_offset += vm_page_size; - page_index++; + if (transfer_size > cl_size) { + transfer_size -= cl_size; + seg_index++; + } else + transfer_size = 0; + } + for (page_index = 0, num_of_pages = upl->size / vm_page_size; page_index < num_of_pages; ) { + /* + * skip over non-dirty pages + */ + for ( ; page_index < num_of_pages; page_index++) { + if (UPL_DIRTY_PAGE(pl, page_index) || UPL_PRECIOUS_PAGE(pl, page_index)) + /* + * this is a page we need to write + * go see if we can buddy it up with others + * that are contiguous to it + */ + break; + /* + * if the page is not-dirty, but present we need to commit it... + * this is an unusual case since we only asked for dirty pages + */ + if (UPL_PAGE_PRESENT(pl, page_index)) { + boolean_t empty = FALSE; + upl_commit_range(upl, + page_index * vm_page_size, + vm_page_size, + UPL_COMMIT_NOTIFY_EMPTY, + pl, + MAX_UPL_TRANSFER, + &empty); + if (empty) + upl_deallocate(upl); } - error = 1; - break; } - cnt = MIN(transfer_size, - CLMAP_NPGS(clmap) * vm_page_size); - ps = CLMAP_PS(clmap); + if (page_index == num_of_pages) + /* + * no more pages to look at, we're out of here + */ + break; - while (cnt > 0) { - /* attempt to send entire cluster */ - subx_size = 0; - - while (cnt > 0) { - /* do the biggest contiguous transfer of dirty */ - /* pages */ - if (UPL_DIRTY_PAGE(pl, page_index) || - UPL_PRECIOUS_PAGE(pl, page_index)){ - page_index++; - subx_size += vm_page_size; - cnt -= vm_page_size; - } else { - if (subx_size == 0) { - actual_offset += vm_page_size; - mobj_target_addr += vm_page_size; - - if(UPL_PAGE_PRESENT(pl, page_index)) { - uc_upl_commit_range(upl, - upl_offset, - vm_page_size, - TRUE, pl); + /* + * gather up contiguous dirty pages... we have at least 1 + * otherwise we would have bailed above + * make sure that each physical segment that we step + * into is contiguous to the one we're currently in + * if it's not, we have to stop and write what we have + */ + for (first_dirty = page_index; page_index < num_of_pages; ) { + if ( !UPL_DIRTY_PAGE(pl, page_index) && !UPL_PRECIOUS_PAGE(pl, page_index)) + break; + page_index++; + /* + * if we just looked at the last page in the UPL + * we don't need to check for physical segment + * continuity + */ + if (page_index < num_of_pages) { + int cur_seg; + int nxt_seg; + + cur_seg = (page_index - 1) / pages_in_cl; + nxt_seg = page_index / pages_in_cl; + + if (cur_seg != nxt_seg) { + if ((ps_offset[cur_seg] != (ps_offset[nxt_seg] - cl_size)) || (psp[cur_seg] != psp[nxt_seg])) + /* + * if the segment we're about to step into + * is not contiguous to the one we're currently + * in, or it's in a different paging file.... + * we stop here and generate the I/O + */ + break; } - - upl_offset += vm_page_size; - transfer_size -= vm_page_size; - page_index++; - cnt -= vm_page_size; - } else { - break; - } - } - } - if (subx_size) { - - error = ps_write_file(ps, upl, upl_offset, - actual_offset, subx_size, flags); - if (error) { - actual_offset += subx_size; - mobj_target_addr += subx_size; - upl_offset += subx_size; - transfer_size -= subx_size; - - for(;transfer_size != 0;) { - if(UPL_PAGE_PRESENT(pl, page_index)) { - uc_upl_abort_range(upl, - upl_offset, - transfer_size, - UPL_ABORT_FREE_ON_EMPTY); - break; - } - transfer_size-=page_size; - upl_offset += vm_page_size; - page_index++; - } - break; } + } + num_dirty = page_index - first_dirty; + must_abort = 1; - ps_vs_write_complete(vs, mobj_target_addr, - subx_size, error); - } - actual_offset += subx_size; - mobj_target_addr += subx_size; - upl_offset += subx_size; + if (num_dirty) { + upl_offset = first_dirty * vm_page_size; + seg_index = first_dirty / pages_in_cl; + seg_offset = upl_offset - (seg_index * cl_size); + transfer_size = num_dirty * vm_page_size; + + error = ps_write_file(psp[seg_index], upl, upl_offset, + ps_offset[seg_index] + seg_offset, transfer_size, flags); + + if (error == 0) { + while (transfer_size) { + int seg_size; - transfer_size -= subx_size; - subx_size = 0; + if ((seg_size = cl_size - (upl_offset % cl_size)) > transfer_size) + seg_size = transfer_size; + + ps_vs_write_complete(vs, upl->offset + upl_offset, seg_size, error); + + transfer_size -= seg_size; + upl_offset += seg_size; + } + must_abort = 0; + } + } + if (must_abort) { + boolean_t empty = FALSE; + upl_abort_range(upl, + first_dirty * vm_page_size, + num_dirty * vm_page_size, + UPL_ABORT_NOTIFY_EMPTY, + &empty); + if (empty) + upl_deallocate(upl); } - if (error) - break; } + } else { assert(cnt <= (vm_page_size << vs->vs_clshift)); list_size = cnt; @@ -3105,10 +3265,10 @@ vs_changed: vs_finish_write(vs); VS_LOCK(vs); vs->vs_xfer_pending = TRUE; - VS_UNLOCK(vs); vs_wait_for_sync_writers(vs); vs_start_write(vs); vs_wait_for_readers(vs); + VS_UNLOCK(vs); if (!(vs->vs_indirect)) { goto vs_changed; } @@ -3222,8 +3382,6 @@ vs_cluster_transfer( vm_offset_t ioaddr; - static char here[] = "vs_cluster_transfer"; - /* vs_cluster_transfer reads in the pages of a cluster and * then writes these pages back to new backing store. The * segment the pages are being read from is assumed to have @@ -3246,8 +3404,6 @@ vs_cluster_transfer( * in effect. */ - /* uc_upl_map(kernel_map, upl, &ioaddr); */ - VSM_CLR(write_vsmap); VSM_CLR(original_read_vsmap); /* grab the actual object's pages to sync with I/O */ @@ -3333,21 +3489,24 @@ vs_cluster_transfer( */ } else { #ifndef ubc_sync_working - error = vm_fault_list_request(transfer_object, + int page_list_count = 0; + + error = vm_object_upl_request(transfer_object, (vm_object_offset_t) (actual_offset & ((vm_page_size << vs->vs_clshift) - 1)), - size, &upl, NULL, - 0, UPL_NO_SYNC | UPL_CLEAN_IN_PLACE - | UPL_SET_INTERNAL); + size, &upl, NULL, &page_list_count, + UPL_NO_SYNC | UPL_CLEAN_IN_PLACE + | UPL_SET_INTERNAL); if (error == KERN_SUCCESS) { - error = ps_read_file(ps, upl, actual_offset, + error = ps_read_file(ps, upl, (vm_offset_t) 0, actual_offset, size, &residual, 0); if(error) - uc_upl_commit(upl, NULL); + upl_commit(upl, NULL); + upl_deallocate(upl); } #else /* NEED TO BE WITH SYNC & NO COMMIT & NO RDAHEAD*/ - error = ps_read_file(ps, upl, actual_offset, + error = ps_read_file(ps, upl, (vm_offset_t) 0, actual_offset, size, &residual, (UPL_IOSYNC | UPL_NOCOMMIT | UPL_NORDAHEAD)); #endif @@ -3364,6 +3523,8 @@ vs_cluster_transfer( * */ if ((error == KERN_SUCCESS) && (residual == 0)) { + int page_list_count = 0; + /* * Got everything we asked for, supply the data to * the new BS. Note that as a side effect of supplying @@ -3378,14 +3539,15 @@ vs_cluster_transfer( *vsmap_ptr = write_vsmap; #ifndef ubc_sync_working - error = vm_fault_list_request(transfer_object, -(vm_object_offset_t) (actual_offset & ((vm_page_size << vs->vs_clshift) - 1)), - size, &upl, NULL, - 0, UPL_NO_SYNC | UPL_CLEAN_IN_PLACE - | UPL_SET_INTERNAL); + error = vm_object_upl_request(transfer_object, + (vm_object_offset_t) + (actual_offset & ((vm_page_size << vs->vs_clshift) - 1)), + size, &upl, NULL, &page_list_count, + UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL); if(vs_cluster_write(vs, upl, offset, size, TRUE, 0) != KERN_SUCCESS) { - uc_upl_commit(upl, NULL); + upl_commit(upl, NULL); + upl_deallocate(upl); #else if(vs_cluster_write(vs, upl, offset, size, TRUE, UPL_IOSYNC | UPL_NOCOMMIT ) != KERN_SUCCESS) { @@ -3464,7 +3626,6 @@ vs_cluster_transfer( if(!VSM_ISCLR(write_vsmap)) *vsmap_ptr = write_vsmap; - /* uc_upl_un_map(kernel_map, upl); */ return error; } @@ -3478,7 +3639,6 @@ default_pager_add_file(MACH_PORT_FACE backing_store, paging_segment_t ps; int i; int error; - static char here[] = "default_pager_add_file"; if ((bs = backing_store_lookup(backing_store)) == BACKING_STORE_NULL) @@ -3565,12 +3725,11 @@ default_pager_add_file(MACH_PORT_FACE backing_store, -kern_return_t ps_read_file(paging_segment_t, upl_t, vm_offset_t, unsigned int, unsigned int *, int); /* forward */ - kern_return_t ps_read_file( paging_segment_t ps, upl_t upl, + vm_offset_t upl_offset, vm_offset_t offset, unsigned int size, unsigned int *residualp, @@ -3579,7 +3738,6 @@ ps_read_file( vm_object_offset_t f_offset; int error = 0; int result; - static char here[] = "ps_read_file"; clustered_reads[atop(size)]++; @@ -3588,7 +3746,7 @@ ps_read_file( /* for transfer case we need to pass uploffset and flags */ error = vnode_pagein(ps->ps_vnode, - upl, (vm_offset_t)0, f_offset, (vm_size_t)size, flags, NULL); + upl, upl_offset, f_offset, (vm_size_t)size, flags | UPL_NORDAHEAD, NULL); /* The vnode_pagein semantic is somewhat at odds with the existing */ /* device_read semantic. Partial reads are not experienced at this */ @@ -3604,7 +3762,6 @@ ps_read_file( result = KERN_SUCCESS; } return result; - } kern_return_t @@ -3618,7 +3775,6 @@ ps_write_file( { vm_object_offset_t f_offset; kern_return_t result; - static char here[] = "ps_write_file"; int error = 0; @@ -3641,18 +3797,29 @@ default_pager_triggers(MACH_PORT_FACE default_pager, int flags, MACH_PORT_FACE trigger_port) { + MACH_PORT_FACE release; + kern_return_t kr; - if(flags & HI_WAT_ALERT) { - if(min_pages_trigger_port) - ipc_port_release_send(min_pages_trigger_port); + PSL_LOCK(); + if (flags == HI_WAT_ALERT) { + release = min_pages_trigger_port; min_pages_trigger_port = trigger_port; minimum_pages_remaining = hi_wat/vm_page_size; bs_low = FALSE; - } - if(flags & LO_WAT_ALERT) { - if(max_pages_trigger_port) - ipc_port_release_send(max_pages_trigger_port); + kr = KERN_SUCCESS; + } else if (flags == LO_WAT_ALERT) { + release = max_pages_trigger_port; max_pages_trigger_port = trigger_port; maximum_pages_free = lo_wat/vm_page_size; + kr = KERN_SUCCESS; + } else { + release = trigger_port; + kr = KERN_INVALID_ARGUMENT; } + PSL_UNLOCK(); + + if (IP_VALID(release)) + ipc_port_release_send(release); + + return kr; } diff --git a/osfmk/default_pager/dp_memory_object.c b/osfmk/default_pager/dp_memory_object.c index 6ab4c91f9..d9ecaafeb 100644 --- a/osfmk/default_pager/dp_memory_object.c +++ b/osfmk/default_pager/dp_memory_object.c @@ -54,8 +54,10 @@ */ #include "default_pager_internal.h" +#include <mach/memory_object_types.h> #include <mach/memory_object_server.h> -#include <vm/vm_pageout.h> /* include for upl_t */ +#include <vm/memory_object.h> +#include <vm/vm_pageout.h> /* @@ -69,9 +71,7 @@ */ struct vstruct_list_head vstruct_list; -void vstruct_list_insert(vstruct_t vs); /* forward */ - -void +__private_extern__ void vstruct_list_insert( vstruct_t vs) { @@ -81,9 +81,8 @@ vstruct_list_insert( VSL_UNLOCK(); } -void vstruct_list_delete(vstruct_t vs); /* forward */ -void +__private_extern__ void vstruct_list_delete( vstruct_t vs) { @@ -101,24 +100,21 @@ vstruct_list_delete( * terminate requests wait for proceeding reads and writes to finish. */ -unsigned int default_pager_total = 0; /* debugging */ -unsigned int default_pager_wait_seqno = 0; /* debugging */ -unsigned int default_pager_wait_read = 0; /* debugging */ -unsigned int default_pager_wait_write = 0; /* debugging */ -unsigned int default_pager_wait_refs = 0; /* debugging */ +static unsigned int default_pager_total = 0; /* debugging */ +static unsigned int default_pager_wait_seqno = 0; /* debugging */ +static unsigned int default_pager_wait_read = 0; /* debugging */ +static unsigned int default_pager_wait_write = 0; /* debugging */ +static unsigned int default_pager_wait_refs = 0; /* debugging */ -void vs_async_wait(vstruct_t); /* forward */ - -void +__private_extern__ void vs_async_wait( vstruct_t vs) { - static char here[] = "vs_async_wait"; ASSERT(vs->vs_async_pending >= 0); while (vs->vs_async_pending > 0) { vs->vs_waiting_async = TRUE; - assert_wait(&vs->vs_waiting_async, THREAD_UNINT); + assert_wait(&vs->vs_async_pending, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); @@ -126,32 +122,27 @@ vs_async_wait( ASSERT(vs->vs_async_pending == 0); } -#if PARALLEL -void vs_lock(vstruct_t, mach_port_seqno_t); -void vs_unlock(vstruct_t); -void vs_start_read(vstruct_t); -void vs_wait_for_readers(vstruct_t); -void vs_finish_read(vstruct_t); -void vs_start_write(vstruct_t); -void vs_wait_for_writers(vstruct_t); -void vs_finish_write(vstruct_t); -void vs_wait_for_refs(vstruct_t); -void vs_finish_refs(vstruct_t); +#if PARALLEL /* * Waits for correct sequence number. Leaves pager locked. - * JMM - Sequence numbers guarantee ordering, but in a preemptible - * kernel, they are generated without locks, and so their - * generation order is undefined (and therefore unreliable). - * Since we ned to fix this anyway, and I needed to get rid - * rid of asymmetry in the interface definitions, I have - * punted this to here. + * + * JMM - Sequence numbers guarantee ordering of requests generated + * by a single thread if the receiver is multithreaded and + * the interfaces are asynchronous (i.e. sender can generate + * more than one request before the first is received in the + * pager). Normally, IPC would generate these number in that + * case. But we are trying to avoid using IPC for the in-kernel + * scenario. Since these are actually invoked synchronously + * anyway (in-kernel), we can just fake the sequence number + * generation here (thus avoiding the dependence on IPC). */ -void +__private_extern__ void vs_lock( - vstruct_t vs, - mach_port_seqno_t seqno) + vstruct_t vs) { + mach_port_seqno_t seqno; + default_pager_total++; VS_LOCK(vs); @@ -160,7 +151,7 @@ vs_lock( while (vs->vs_seqno != seqno) { default_pager_wait_seqno++; vs->vs_waiting_seqno = TRUE; - assert_wait(&vs->vs_waiting_seqno, THREAD_UNINT); + assert_wait(&vs->vs_seqno, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); @@ -170,22 +161,23 @@ vs_lock( /* * Increments sequence number and unlocks pager. */ -void +__private_extern__ void vs_unlock(vstruct_t vs) { - boolean_t need_wakeups = vs->vs_waiting_seqno; - - vs->vs_waiting_seqno = FALSE; vs->vs_seqno++; + if (vs->vs_waiting_seqno) { + vs->vs_waiting_seqno = FALSE; + VS_UNLOCK(vs); + thread_wakeup(&vs->vs_seqno); + return; + } VS_UNLOCK(vs); - if (need_wakeups) - thread_wakeup(&vs->vs_waiting_seqno); } /* * Start a read - one more reader. Pager must be locked. */ -void +__private_extern__ void vs_start_read( vstruct_t vs) { @@ -195,14 +187,14 @@ vs_start_read( /* * Wait for readers. Unlocks and relocks pager if wait needed. */ -void +__private_extern__ void vs_wait_for_readers( vstruct_t vs) { while (vs->vs_readers != 0) { default_pager_wait_read++; vs->vs_waiting_read = TRUE; - assert_wait(&vs->vs_waiting_read, THREAD_UNINT); + assert_wait(&vs->vs_readers, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); @@ -212,26 +204,24 @@ vs_wait_for_readers( /* * Finish a read. Pager is unlocked and returns unlocked. */ -void +__private_extern__ void vs_finish_read( vstruct_t vs) { VS_LOCK(vs); - if (--vs->vs_readers == 0) { - boolean_t need_wakeups = vs->vs_waiting_read; - + if (--vs->vs_readers == 0 && vs->vs_waiting_read) { vs->vs_waiting_read = FALSE; VS_UNLOCK(vs); - if (need_wakeups) - thread_wakeup(&vs->vs_waiting_read); - } else - VS_UNLOCK(vs); + thread_wakeup(&vs->vs_readers); + return; + } + VS_UNLOCK(vs); } /* * Start a write - one more writer. Pager must be locked. */ -void +__private_extern__ void vs_start_write( vstruct_t vs) { @@ -241,14 +231,14 @@ vs_start_write( /* * Wait for writers. Unlocks and relocks pager if wait needed. */ -void +__private_extern__ void vs_wait_for_writers( vstruct_t vs) { while (vs->vs_writers != 0) { default_pager_wait_write++; vs->vs_waiting_write = TRUE; - assert_wait(&vs->vs_waiting_write, THREAD_UNINT); + assert_wait(&vs->vs_writers, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); @@ -261,14 +251,15 @@ vs_wait_for_writers( /* vs_async_wait count non-zero. It will not ocnflict with */ /* other writers on an async basis because it only writes on */ /* a cluster basis into fresh (as of sync time) cluster locations */ -void + +__private_extern__ void vs_wait_for_sync_writers( vstruct_t vs) { while (vs->vs_writers != 0) { default_pager_wait_write++; vs->vs_waiting_write = TRUE; - assert_wait(&vs->vs_waiting_write, THREAD_UNINT); + assert_wait(&vs->vs_writers, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); @@ -279,77 +270,26 @@ vs_wait_for_sync_writers( /* * Finish a write. Pager is unlocked and returns unlocked. */ -void +__private_extern__ void vs_finish_write( vstruct_t vs) { VS_LOCK(vs); - if (--vs->vs_writers == 0) { - boolean_t need_wakeups = vs->vs_waiting_write; - + if (--vs->vs_writers == 0 && vs->vs_waiting_write) { vs->vs_waiting_write = FALSE; VS_UNLOCK(vs); - if (need_wakeups) - thread_wakeup(&vs->vs_waiting_write); - } else - VS_UNLOCK(vs); -} - -/* - * Wait for concurrent default_pager_objects. - * Unlocks and relocks pager if wait needed. - */ -void -vs_wait_for_refs( - vstruct_t vs) -{ - while (vs->vs_name_refs == 0) { - default_pager_wait_refs++; - vs->vs_waiting_refs = TRUE; - assert_wait(&vs->vs_waiting_refs, THREAD_UNINT); - VS_UNLOCK(vs); - thread_block((void (*)(void))0); - VS_LOCK(vs); + thread_wakeup(&vs->vs_writers); + return; } + VS_UNLOCK(vs); } - -/* - * Finished creating name refs - wake up waiters. - */ -void -vs_finish_refs( - vstruct_t vs) -{ - boolean_t need_wakeups = vs->vs_waiting_refs; - vs->vs_waiting_refs = FALSE; - if (need_wakeups) - thread_wakeup(&vs->vs_waiting_refs); -} - -#else /* PARALLEL */ - -#define vs_lock(vs,seqno) -#define vs_unlock(vs) -#define vs_start_read(vs) -#define vs_wait_for_readers(vs) -#define vs_finish_read(vs) -#define vs_start_write(vs) -#define vs_wait_for_writers(vs) -#define vs_wait_for_sync_writers(vs) -#define vs_finish_write(vs) -#define vs_wait_for_refs(vs) -#define vs_finish_refs(vs) - #endif /* PARALLEL */ -vstruct_t vs_object_create(vm_size_t); /* forward */ - vstruct_t vs_object_create( vm_size_t size) { vstruct_t vs; - static char here[] = "vs_object_create"; /* * Allocate a vstruct. If there are any problems, then report them @@ -365,46 +305,7 @@ vs_object_create( return vs; } -mach_port_urefs_t default_pager_max_urefs = 10000; - -/* - * Check user reference count on memory object control port. - * Vstruct must be locked. - * Unlocks and re-locks vstruct if needs to call kernel. - */ -void vs_check_request(vstruct_t, MACH_PORT_FACE); /* forward */ - -void -vs_check_request( - vstruct_t vs, - MACH_PORT_FACE control_port) -{ - mach_port_delta_t delta; - kern_return_t kr; - static char here[] = "vs_check_request"; - - if (++vs->vs_control_refs > default_pager_max_urefs) { - delta = 1 - vs->vs_control_refs; - vs->vs_control_refs = 1; - - VS_UNLOCK(vs); - - /* - * Deallocate excess user references. - */ - - { -/* find a better interface for this, what will we use as a component */ - int i; - delta = -delta; - for(i=0; i<delta; i++) - ipc_port_release_send(control_port); - } - - VS_LOCK(vs); - } -} - +#if 0 void default_pager_add(vstruct_t, boolean_t); /* forward */ void @@ -412,10 +313,10 @@ default_pager_add( vstruct_t vs, boolean_t internal) { - MACH_PORT_FACE mem_obj = vs->vs_mem_obj_port; - MACH_PORT_FACE pset; + memory_object_t mem_obj = vs->vs_mem_obj; + mach_port_t pset; mach_port_mscount_t sync; - MACH_PORT_FACE previous; + mach_port_t previous; kern_return_t kr; static char here[] = "default_pager_add"; @@ -440,97 +341,27 @@ default_pager_add( ipc_port_nsrequest(mem_obj, sync, mem_obj, &previous); } - -/* - * Routine: dp_memory_object_create - * Purpose: - * Handle requests for memory objects from the - * kernel. - * Notes: - * Because we only give out the default memory - * manager port to the kernel, we don't have to - * be so paranoid about the contents. - */ -kern_return_t -dp_memory_object_create( - MACH_PORT_FACE dmm, - MACH_PORT_FACE *new_mem_obj, - vm_size_t new_size) -{ - mach_port_seqno_t seqno; - vstruct_t vs; - MACH_PORT_FACE pager; - static char here[] = "memory_object_create"; - - assert(dmm == default_pager_default_port); - - vs = vs_object_create(new_size); - if (vs == VSTRUCT_NULL) - return KERN_RESOURCE_SHORTAGE; - - pager = *new_mem_obj = ipc_port_alloc_kernel(); - assert (pager != IP_NULL); - (void) ipc_port_make_send(pager); - - { - struct vstruct_alias *alias_struct; - - alias_struct = (struct vstruct_alias *) - kalloc(sizeof(struct vstruct_alias)); - if(alias_struct != NULL) { - alias_struct->vs = vs; - alias_struct->name = ISVS; - pager->alias = (int) alias_struct; - } - else Panic("Out of kernel memory"); - - /* JMM - Add binding to this pager under components */ - pager_mux_hash_insert(pager, &dp_memory_object_subsystem); - vs->vs_next_seqno = 0; - pager->ip_receiver = ipc_space_kernel; - } - - /* - * Set up associations between this port - * and this default_pager structure - */ - - vs->vs_mem_obj_port = pager; - - /* - * After this, other threads might receive requests - * for this memory object or find it in the port list. - */ - - vstruct_list_insert(vs); - default_pager_add(vs, TRUE); - - return KERN_SUCCESS; -} +#endif kern_return_t dp_memory_object_init( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE control_port, + memory_object_t mem_obj, + memory_object_control_t control, vm_size_t pager_page_size) { - mach_port_seqno_t seqno; vstruct_t vs; - static char here[] = "memory_object_init"; assert(pager_page_size == vm_page_size); + memory_object_control_reference(control); + vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); + vs_lock(vs); - if (vs->vs_control_port != MACH_PORT_NULL) + if (vs->vs_control != MEMORY_OBJECT_CONTROL_NULL) Panic("bad request"); - vs->vs_control_port = control_port; - vs->vs_control_refs = 1; - vs->vs_object_name = MACH_PORT_NULL; - vs->vs_name_refs = 1; - + vs->vs_control = control; vs_unlock(vs); return KERN_SUCCESS; @@ -538,45 +369,45 @@ dp_memory_object_init( kern_return_t dp_memory_object_synchronize( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - vm_offset_t length, + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t length, vm_sync_t flags) { - mach_port_seqno_t seqno; vstruct_t vs; - static char here[] = "memory_object_synchronize"; vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); - vs_check_request(vs, control_port); + vs_lock(vs); vs_unlock(vs); - memory_object_synchronize_completed( - vm_object_lookup(control_port), - offset, length); + memory_object_synchronize_completed(vs->vs_control, offset, length); return KERN_SUCCESS; } +kern_return_t +dp_memory_object_unmap( + memory_object_t mem_obj) +{ + panic("dp_memory_object_unmap"); + + return KERN_FAILURE; +} + kern_return_t dp_memory_object_terminate( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE control_port) + memory_object_t mem_obj) { - mach_port_seqno_t seqno; + memory_object_control_t control; vstruct_t vs; - mach_port_urefs_t request_refs; kern_return_t kr; - static char here[] = "memory_object_terminate"; /* * control port is a receive right, not a send right. */ vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); + vs_lock(vs); /* * Wait for read and write requests to terminate. @@ -588,17 +419,12 @@ dp_memory_object_terminate( /* * After memory_object_terminate both memory_object_init * and a no-senders notification are possible, so we need - * to clean up the request and name ports but leave - * the mem_obj port. - * - * A concurrent default_pager_objects might be allocating - * more references for the name port. In this case, - * we must first wait for it to finish. + * to clean up our reference to the memory_object_control + * to prepare for a new init. */ - vs_wait_for_refs(vs); - - vs->vs_control_port = MACH_PORT_NULL; + control = vs->vs_control; + vs->vs_control = MEMORY_OBJECT_CONTROL_NULL; /* a bit of special case ugliness here. Wakeup any waiting reads */ /* these data requests had to be removed from the seqno traffic */ @@ -607,54 +433,72 @@ dp_memory_object_terminate( /* synchronous interface. The new async will be able to return */ /* failure during its sync phase. In the mean time ... */ - thread_wakeup(&vs->vs_waiting_write); - thread_wakeup(&vs->vs_waiting_async); - - request_refs = vs->vs_control_refs; - vs->vs_control_refs = 0; - - vs->vs_object_name = MACH_PORT_NULL; - - assert(vs->vs_name_refs != 0); - vs->vs_name_refs = 0; + thread_wakeup(&vs->vs_writers); + thread_wakeup(&vs->vs_async_pending); vs_unlock(vs); /* - * Now we deallocate our various port rights. + * Now we deallocate our reference on the control. */ - - { - int i; - for(i=0; i<request_refs; i++) - ipc_port_release_send(control_port); - } - if(control_port->alias != (int)NULL) - kfree((vm_offset_t) (control_port->alias), - sizeof(struct vstruct_alias)); - ipc_port_release_receive(control_port); + memory_object_control_deallocate(control); return KERN_SUCCESS; } void -default_pager_no_senders( - MACH_PORT_FACE mem_obj, - mach_port_seqno_t seqno, - mach_port_mscount_t mscount) +dp_memory_object_reference( + memory_object_t mem_obj) +{ + vstruct_t vs; + + vs_lookup_safe(mem_obj, vs); + if (vs == VSTRUCT_NULL) + return; + + VS_LOCK(vs); + assert(vs->vs_references > 0); + vs->vs_references++; + VS_UNLOCK(vs); +} + +extern ipc_port_t max_pages_trigger_port; +extern int dp_pages_free; +extern int maximum_pages_free; +void +dp_memory_object_deallocate( + memory_object_t mem_obj) { vstruct_t vs; - static char here[] = "default_pager_no_senders"; + mach_port_seqno_t seqno; + ipc_port_t trigger; /* - * Because we don't give out multiple send rights + * Because we don't give out multiple first references * for a memory object, there can't be a race - * between getting a no-senders notification - * and creating a new send right for the object. - * Hence we don't keep track of mscount. + * between getting a deallocate call and creating + * a new reference for the object. */ - vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); + vs_lookup_safe(mem_obj, vs); + if (vs == VSTRUCT_NULL) + return; + + VS_LOCK(vs); + if (--vs->vs_references > 0) { + VS_UNLOCK(vs); + return; + } + + seqno = vs->vs_next_seqno++; + while (vs->vs_seqno != seqno) { + default_pager_wait_seqno++; + vs->vs_waiting_seqno = TRUE; + assert_wait(&vs->vs_seqno, THREAD_UNINT); + VS_UNLOCK(vs); + thread_block((void (*)(void))0); + VS_LOCK(vs); + } + vs_async_wait(vs); /* wait for pending async IO */ /* do not delete the vs structure until the referencing pointers */ @@ -668,11 +512,13 @@ default_pager_no_senders( VS_LOCK(vs); vs_async_wait(vs); /* wait for pending async IO */ } + + /* - * We shouldn't get a no-senders notification + * We shouldn't get a deallocation call * when the kernel has the object cached. */ - if (vs->vs_control_port != MACH_PORT_NULL) + if (vs->vs_control != MEMORY_OBJECT_CONTROL_NULL) Panic("bad request"); /* @@ -681,6 +527,14 @@ default_pager_no_senders( */ VS_UNLOCK(vs); + /* Lock out paging segment removal for the duration of this */ + /* call. We are vulnerable to losing a paging segment we rely */ + /* on as soon as we remove ourselves from the VSL and unlock */ + + /* Keep our thread from blocking on attempt to trigger backing */ + /* store release */ + backing_store_release_trigger_disable += 1; + /* * Remove the memory object port association, and then * the destroy the port itself. We must remove the object @@ -688,32 +542,42 @@ default_pager_no_senders( * because of default_pager_objects. */ vstruct_list_delete(vs); + VSL_UNLOCK(); + ps_vstruct_dealloc(vs); - /* - * Recover memory that we might have wasted because - * of name conflicts - */ - while (!queue_empty(&vstruct_list.vsl_leak_queue)) { - vs = (vstruct_t) queue_first(&vstruct_list.vsl_leak_queue); - queue_remove_first(&vstruct_list.vsl_leak_queue, vs, vstruct_t, - vs_links); - kfree((vm_offset_t) vs, sizeof *vs); + VSL_LOCK(); + backing_store_release_trigger_disable -= 1; + if(backing_store_release_trigger_disable == 0) { + thread_wakeup((event_t)&vm_page_laundry_count); } VSL_UNLOCK(); + + PSL_LOCK(); + if(max_pages_trigger_port + && (backing_store_release_trigger_disable == 0) + && (dp_pages_free > maximum_pages_free)) { + trigger = max_pages_trigger_port; + max_pages_trigger_port = NULL; + } else + trigger = IP_NULL; + PSL_UNLOCK(); + + if (trigger != IP_NULL) { + default_pager_space_alert(trigger, LO_WAT_ALERT); + ipc_port_release_send(trigger); + } + } kern_return_t dp_memory_object_data_request( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE reply_to, - vm_object_offset_t offset, + memory_object_t mem_obj, + memory_object_offset_t offset, vm_size_t length, vm_prot_t protection_required) { - mach_port_seqno_t seqno; vstruct_t vs; - static char here[] = "memory_object_data_request"; GSTAT(global_stats.gs_pagein_calls++); @@ -722,8 +586,7 @@ dp_memory_object_data_request( /* port. As we are expanding this pager to support user interfaces */ /* this should be changed to return kern_failure */ vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); - vs_check_request(vs, reply_to); + vs_lock(vs); /* We are going to relax the strict sequencing here for performance */ /* reasons. We can do this because we know that the read and */ @@ -731,6 +594,7 @@ dp_memory_object_data_request( /* of read and write requests at the cache memory_object level */ /* break out wait_for_writers, all of this goes away when */ /* we get real control of seqno with the new component interface */ + if (vs->vs_writers != 0) { /* you can't hold on to the seqno and go */ /* to sleep like that */ @@ -739,13 +603,13 @@ dp_memory_object_data_request( while (vs->vs_writers != 0) { default_pager_wait_write++; vs->vs_waiting_write = TRUE; - assert_wait(&vs->vs_waiting_write, THREAD_UNINT); + assert_wait(&vs->vs_writers, THREAD_UNINT); VS_UNLOCK(vs); thread_block((void (*)(void))0); VS_LOCK(vs); vs_async_wait(vs); } - if(vs->vs_control_port == MACH_PORT_NULL) { + if(vs->vs_control == MEMORY_OBJECT_CONTROL_NULL) { VS_UNLOCK(vs); return KERN_FAILURE; } @@ -783,28 +647,19 @@ dp_memory_object_data_request( kern_return_t dp_memory_object_data_initialize( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - pointer_t addr, - vm_size_t data_cnt) + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t size) { - mach_port_seqno_t seqno; vstruct_t vs; - static char here[] = "memory_object_data_initialize"; - -#ifdef lint - control_port++; -#endif /* lint */ DEBUG(DEBUG_MO_EXTERNAL, ("mem_obj=0x%x,offset=0x%x,cnt=0x%x\n", - (int)mem_obj, (int)offset, (int)data_cnt)); - GSTAT(global_stats.gs_pages_init += atop(data_cnt)); + (int)mem_obj, (int)offset, (int)size)); + GSTAT(global_stats.gs_pages_init += atop(size)); vs_lookup(mem_obj, vs); - vs_lock(vs, seqno); - vs_check_request(vs, control_port); + vs_lock(vs); vs_start_write(vs); vs_unlock(vs); @@ -813,88 +668,38 @@ dp_memory_object_data_initialize( * loop if the address range specified crosses cluster * boundaries. */ - vs_cluster_write(vs, 0, (vm_offset_t)offset, data_cnt, FALSE, 0); + vs_cluster_write(vs, 0, (vm_offset_t)offset, size, FALSE, 0); vs_finish_write(vs); return KERN_SUCCESS; } -kern_return_t -dp_memory_object_lock_completed( - memory_object_t mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - vm_size_t length) -{ - mach_port_seqno_t seqno; - static char here[] = "memory_object_lock_completed"; - -#ifdef lint - mem_obj++; - seqno++; - control_port++; - offset++; - length++; -#endif /* lint */ - - Panic("illegal"); - return KERN_FAILURE; -} - kern_return_t dp_memory_object_data_unlock( memory_object_t mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - vm_size_t data_cnt, + memory_object_offset_t offset, + vm_size_t size, vm_prot_t desired_access) { - static char here[] = "memory_object_data_unlock"; - - Panic("illegal"); + Panic("dp_memory_object_data_unlock: illegal"); return KERN_FAILURE; } -kern_return_t -dp_memory_object_supply_completed( - memory_object_t mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - vm_size_t length, - kern_return_t result, - vm_offset_t error_offset) -{ - static char here[] = "memory_object_supply_completed"; - - Panic("illegal"); - return KERN_FAILURE; -} - kern_return_t dp_memory_object_data_return( - MACH_PORT_FACE mem_obj, - MACH_PORT_FACE control_port, - vm_object_offset_t offset, - pointer_t addr, - vm_size_t data_cnt, + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t size, boolean_t dirty, boolean_t kernel_copy) { - mach_port_seqno_t seqno; vstruct_t vs; - static char here[] = "memory_object_data_return"; - -#ifdef lint - control_port++; - dirty++; - kernel_copy++; -#endif /* lint */ DEBUG(DEBUG_MO_EXTERNAL, - ("mem_obj=0x%x,offset=0x%x,addr=0x%xcnt=0x%x\n", - (int)mem_obj, (int)offset, (int)addr, (int)data_cnt)); + ("mem_obj=0x%x,offset=0x%x,size=0x%x\n", + (int)mem_obj, (int)offset, (int)size)); GSTAT(global_stats.gs_pageout_calls++); /* This routine is called by the pageout thread. The pageout thread */ @@ -913,74 +718,54 @@ dp_memory_object_data_return( /* a synchronous interface */ /* return KERN_LOCK_OWNED; */ upl_t upl; - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, data_cnt, data_cnt, &upl, NULL, 0, - UPL_NOBLOCK | UPL_CLEAN_IN_PLACE + int page_list_count = 0; + memory_object_super_upl_request(vs->vs_control, + (memory_object_offset_t)offset, + size, size, + &upl, NULL, &page_list_count, + UPL_NOBLOCK | UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_COPYOUT_FROM); - uc_upl_abort(upl,0); - ipc_port_release_send(control_port); + upl_abort(upl,0); + upl_deallocate(upl); return KERN_SUCCESS; } - - if ((vs->vs_seqno != vs->vs_next_seqno++) || (vs->vs_xfer_pending)) { upl_t upl; + int page_list_count = 0; + vs->vs_next_seqno--; VS_UNLOCK(vs); + /* the call below will not be done by caller when we have */ /* a synchronous interface */ /* return KERN_LOCK_OWNED; */ - upl_system_list_request((vm_object_t) - vs->vs_control_port->ip_kobject, - offset, data_cnt, data_cnt, &upl, NULL, 0, + memory_object_super_upl_request(vs->vs_control, + (memory_object_offset_t)offset, + size, size, + &upl, NULL, &page_list_count, UPL_NOBLOCK | UPL_CLEAN_IN_PLACE | UPL_NO_SYNC | UPL_COPYOUT_FROM); - uc_upl_abort(upl,0); - ipc_port_release_send(control_port); + upl_abort(upl,0); + upl_deallocate(upl); return KERN_SUCCESS; } - if ((data_cnt % vm_page_size) != 0) + if ((size % vm_page_size) != 0) Panic("bad alignment"); vs_start_write(vs); vs->vs_async_pending += 1; /* protect from backing store contraction */ - - /* unroll vs_check_request to avoid re-locking vs */ - - if (++vs->vs_control_refs > default_pager_max_urefs) { - mach_port_delta_t delta; - - delta = 1 - vs->vs_control_refs; - vs->vs_control_refs = 1; - - vs_unlock(vs); - - /* - * Deallocate excess user references. - */ - - { - int i; - delta = -delta; - for(i=0; i<delta; i++) - ipc_port_release_send(control_port); - } - - } else { - vs_unlock(vs); - } + vs_unlock(vs); /* * Write the data via clustered writes. vs_cluster_write will * loop if the address range specified crosses cluster * boundaries. */ - vs_cluster_write(vs, 0, (vm_offset_t)offset, data_cnt, FALSE, 0); + vs_cluster_write(vs, 0, (vm_offset_t)offset, size, FALSE, 0); vs_finish_write(vs); @@ -988,9 +773,10 @@ dp_memory_object_data_return( VS_LOCK(vs); vs->vs_async_pending -= 1; /* release vs_async_wait */ - if (vs->vs_async_pending == 0) { + if (vs->vs_async_pending == 0 && vs->vs_waiting_async) { + vs->vs_waiting_async = FALSE; VS_UNLOCK(vs); - thread_wakeup(&vs->vs_waiting_async); + thread_wakeup(&vs->vs_async_pending); } else { VS_UNLOCK(vs); } @@ -999,16 +785,48 @@ dp_memory_object_data_return( return KERN_SUCCESS; } +/* + * Routine: default_pager_memory_object_create + * Purpose: + * Handle requests for memory objects from the + * kernel. + * Notes: + * Because we only give out the default memory + * manager port to the kernel, we don't have to + * be so paranoid about the contents. + */ kern_return_t -dp_memory_object_change_completed( - memory_object_t mem_obj, - memory_object_control_t memory_control, - memory_object_flavor_t flavor) +default_pager_memory_object_create( + memory_object_default_t dmm, + vm_size_t new_size, + memory_object_t *new_mem_obj) { - static char here[] = "memory_object_change_completed"; + vstruct_t vs; - Panic("illegal"); - return KERN_FAILURE; + assert(dmm == default_pager_object); + + vs = vs_object_create(new_size); + if (vs == VSTRUCT_NULL) + return KERN_RESOURCE_SHORTAGE; + + vs->vs_next_seqno = 0; + + /* + * Set up associations between this memory object + * and this default_pager structure + */ + + vs->vs_mem_obj = ISVS; + vs->vs_mem_obj_ikot = IKOT_MEMORY_OBJECT; + + /* + * After this, other threads might receive requests + * for this memory object or find it in the port list. + */ + + vstruct_list_insert(vs); + *new_mem_obj = vs_to_mem_obj(vs); + return KERN_SUCCESS; } /* @@ -1016,55 +834,38 @@ dp_memory_object_change_completed( */ kern_return_t default_pager_object_create( - MACH_PORT_FACE pager, - MACH_PORT_FACE *mem_obj, - vm_size_t size) + default_pager_t pager, + vm_size_t size, + memory_object_t *mem_objp) { vstruct_t vs; - MACH_PORT_FACE port; kern_return_t result; struct vstruct_alias *alias_struct; - static char here[] = "default_pager_object_create"; - if (pager != default_pager_default_port) + if (pager != default_pager_object) return KERN_INVALID_ARGUMENT; vs = vs_object_create(size); + if (vs == VSTRUCT_NULL) + return KERN_RESOURCE_SHORTAGE; - port = ipc_port_alloc_kernel(); - ipc_port_make_send(port); - /* register abstract memory object port with pager mux routine */ - /* (directs kernel internal calls to the right pager). */ - alias_struct = (struct vstruct_alias *) - kalloc(sizeof(struct vstruct_alias)); - if(alias_struct != NULL) { - alias_struct->vs = vs; - alias_struct->name = ISVS; - port->alias = (int) alias_struct; - } - else Panic("Out of kernel memory"); - /* - * Set up associations between these ports + * Set up associations between the default pager * and this vstruct structure */ - - vs->vs_mem_obj_port = port; + vs->vs_mem_obj = ISVS; vstruct_list_insert(vs); - default_pager_add(vs, FALSE); - - *mem_obj = port; - + *mem_objp = vs_to_mem_obj(vs); return KERN_SUCCESS; } kern_return_t default_pager_objects( - MACH_PORT_FACE pager, + default_pager_t pager, default_pager_object_array_t *objectsp, mach_msg_type_number_t *ocountp, - mach_port_array_t *portsp, + memory_object_array_t *pagersp, mach_msg_type_number_t *pcountp) { vm_offset_t oaddr = 0; /* memory for objects */ @@ -1072,16 +873,15 @@ default_pager_objects( default_pager_object_t * objects; unsigned int opotential; - vm_offset_t paddr = 0; /* memory for ports */ + vm_offset_t paddr = 0; /* memory for pagers */ vm_size_t psize = 0; /* current size */ - MACH_PORT_FACE * ports; + memory_object_t * pagers; unsigned int ppotential; unsigned int actual; unsigned int num_objects; kern_return_t kr; vstruct_t entry; - static char here[] = "default_pager_objects"; /* if (pager != default_pager_default_port) return KERN_INVALID_ARGUMENT; @@ -1109,7 +909,7 @@ default_pager_objects( num_objects = 0; opotential = *ocountp; - ports = (MACH_PORT_FACE *) *portsp; + pagers = (memory_object_t *) *pagersp; ppotential = *pcountp; VSL_LOCK(); @@ -1140,7 +940,7 @@ default_pager_objects( vm_offset_t newaddr; vm_size_t newsize; - newsize = 2 * round_page(actual * sizeof * ports); + newsize = 2 * round_page(actual * sizeof * pagers); kr = vm_allocate(kernel_map, &newaddr, newsize, TRUE); if (kr != KERN_SUCCESS) @@ -1148,8 +948,8 @@ default_pager_objects( paddr = newaddr; psize = newsize; - ppotential = psize / sizeof * ports; - ports = (MACH_PORT_FACE *)paddr; + ppotential = psize / sizeof * pagers; + pagers = (memory_object_t *)paddr; } /* @@ -1161,7 +961,7 @@ default_pager_objects( num_objects = 0; queue_iterate(&vstruct_list.vsl_queue, entry, vstruct_t, vs_links) { - MACH_PORT_FACE port; + memory_object_t pager; vm_size_t size; if ((num_objects >= opotential) || @@ -1185,47 +985,25 @@ default_pager_objects( VS_LOCK(entry); - port = entry->vs_object_name; - if (port == MACH_PORT_NULL) { - - /* - * The object is waiting for no-senders - * or memory_object_init. - */ - VS_UNLOCK(entry); - goto not_this_one; - } - /* - * We need a reference for the reply message. - * While we are unlocked, the bucket queue - * can change and the object might be terminated. - * memory_object_terminate will wait for us, - * preventing deallocation of the entry. + * We need a reference for our caller. Adding this + * reference through the linked list could race with + * destruction of the object. If we find the object + * has no references, just give up on it. */ - - if (--entry->vs_name_refs == 0) { + VS_LOCK(entry); + if (entry->vs_references == 0) { VS_UNLOCK(entry); - - /* keep the list locked, wont take long */ - - { - int i; - for(i=0; i<default_pager_max_urefs; i++) - ipc_port_make_send(port); - } - VS_LOCK(entry); - - entry->vs_name_refs += default_pager_max_urefs; - vs_finish_refs(entry); + goto not_this_one; } + dp_memory_object_reference(vs_to_mem_obj(entry)); VS_UNLOCK(entry); /* the arrays are wired, so no deadlock worries */ objects[num_objects].dpo_object = (vm_offset_t) entry; objects[num_objects].dpo_size = size; - ports [num_objects++] = port; + pagers [num_objects++] = pager; continue; not_this_one: @@ -1234,7 +1012,7 @@ default_pager_objects( */ objects[num_objects].dpo_object = (vm_offset_t) 0; objects[num_objects].dpo_size = 0; - ports [num_objects++] = MACH_PORT_NULL; + pagers[num_objects++] = MEMORY_OBJECT_NULL; } @@ -1270,7 +1048,7 @@ default_pager_objects( *ocountp = num_objects; } - if (ports == (MACH_PORT_FACE *)*portsp) { + if (pagers == (memory_object_t *)*pagersp) { /* * Our returned information fit inline. @@ -1286,13 +1064,13 @@ default_pager_objects( } else { vm_offset_t used; - used = round_page(actual * sizeof * ports); + used = round_page(actual * sizeof * pagers); if (used != psize) (void) vm_deallocate(kernel_map, paddr + used, psize - used); - *portsp = (mach_port_array_t)ports; + *pagersp = (memory_object_array_t)pagers; *pcountp = num_objects; } (void) vm_map_unwire(kernel_map, (vm_offset_t)objects, @@ -1306,13 +1084,14 @@ default_pager_objects( { register int i; for (i = 0; i < num_objects; i++) - ipc_port_dealloc_kernel(ports[i]); + if (pagers[i] != MEMORY_OBJECT_NULL) + memory_object_deallocate(pagers[i]); } if (objects != *objectsp) (void) vm_deallocate(kernel_map, oaddr, osize); - if (ports != (MACH_PORT_FACE *)*portsp) + if (pagers != (memory_object_t *)*pagersp) (void) vm_deallocate(kernel_map, paddr, psize); return KERN_RESOURCE_SHORTAGE; @@ -1320,8 +1099,8 @@ default_pager_objects( kern_return_t default_pager_object_pages( - MACH_PORT_FACE pager, - MACH_PORT_FACE object, + default_pager_t pager, + memory_object_t object, default_pager_page_array_t *pagesp, mach_msg_type_number_t *countp) { @@ -1331,10 +1110,10 @@ default_pager_object_pages( unsigned int potential, actual; kern_return_t kr; -/* - if (pager != default_pager_default_port) + + if (pager != default_pager_object) return KERN_INVALID_ARGUMENT; -*/ + kr = vm_map_copyout(ipc_kernel_map, (vm_offset_t *)&pages, (vm_map_copy_t) *pagesp); @@ -1361,7 +1140,7 @@ default_pager_object_pages( queue_iterate(&vstruct_list.vsl_queue, entry, vstruct_t, vs_links) { VS_LOCK(entry); - if (entry->vs_object_name == object) { + if (vs_to_mem_obj(entry) == object) { VSL_UNLOCK(); goto found_object; } diff --git a/osfmk/device/device.defs b/osfmk/device/device.defs index 1a91b69a9..137cca057 100644 --- a/osfmk/device/device.defs +++ b/osfmk/device/device.defs @@ -127,13 +127,10 @@ routine io_service_get_matching_services( out existing : io_object_t ); -routine io_service_add_notification_old( - master_port : mach_port_t; - in notification_type : io_name_t; - in matching : io_string_t; - in wake_port : mach_port_make_send_t; - in reference : natural_t; - out notification : io_object_t +routine io_registry_entry_get_property( + registry_entry : io_object_t; + in property_name : io_name_t; + out properties : io_buf_ptr_t, physicalcopy ); routine io_registry_create_iterator( @@ -167,7 +164,7 @@ routine io_registry_entry_get_properties( out properties : io_buf_ptr_t, physicalcopy ); -routine io_registry_entry_get_property( +routine io_registry_entry_get_property_bytes( registry_entry : io_object_t; in property_name : io_name_t; out data : io_struct_inband_t, CountInOut @@ -431,7 +428,6 @@ routine io_connect_get_notification_semaphore( out semaphore : semaphore_t ); - routine io_connect_unmap_memory( connection : io_connect_t; in memory_type : int; @@ -439,6 +435,20 @@ routine io_connect_unmap_memory( in address : vm_address_t ); +routine io_registry_entry_get_location_in_plane( + registry_entry : io_object_t; + in plane : io_name_t; + out location : io_name_t + ); + +routine io_registry_entry_get_property_recursively( + registry_entry : io_object_t; + in plane : io_name_t; + in property_name : io_name_t; + in options : int; + out properties : io_buf_ptr_t, physicalcopy + ); + #endif diff --git a/osfmk/device/device_port.h b/osfmk/device/device_port.h index df76f3f0a..ba0eda573 100644 --- a/osfmk/device/device_port.h +++ b/osfmk/device/device_port.h @@ -64,4 +64,7 @@ */ extern mach_port_t master_device_port; +#define DEVICE_PAGER_CONTIGUOUS 1 +#define DEVICE_PAGER_NOPHYSCACHE 2 + #endif /* _DEVICE_DEVICE_PORT_H_ */ diff --git a/osfmk/device/iokit_rpc.c b/osfmk/device/iokit_rpc.c index 7bc5041d4..d80e8094a 100644 --- a/osfmk/device/iokit_rpc.c +++ b/osfmk/device/iokit_rpc.c @@ -416,3 +416,4 @@ void IOGetTime( mach_timespec_t * clock_time) { *clock_time = clock_get_system_value(); } + diff --git a/osfmk/device/subrs.c b/osfmk/device/subrs.c index ad8b9c34f..1282fd398 100644 --- a/osfmk/device/subrs.c +++ b/osfmk/device/subrs.c @@ -214,27 +214,6 @@ strncpy( return (os1); } - -#if !defined(__alpha) - -/* - * Abstract: - * strlen returns the number of characters in "string" preceeding - * the terminating null character. - */ - -size_t -strlen( - register const char *string) -{ - register const char *ret = string; - - while (*string++ != '\0') - continue; - return string - 1 - ret; -} -#endif /* !defined(__alpha) */ - /* * atoi: * diff --git a/osfmk/i386/AT386/bbclock.c b/osfmk/i386/AT386/bbclock.c index 4f69e0ba2..9bad06a13 100644 --- a/osfmk/i386/AT386/bbclock.c +++ b/osfmk/i386/AT386/bbclock.c @@ -286,6 +286,7 @@ int yeartoday( int year) { + year += 1900; return((year % 4) ? 365 : ((year % 100) ? 366 : ((year % 400) ? 365: 366))); } diff --git a/osfmk/i386/AT386/kernBootStruct.h b/osfmk/i386/AT386/kernBootStruct.h index 0978b9fe7..6ac55d39d 100644 --- a/osfmk/i386/AT386/kernBootStruct.h +++ b/osfmk/i386/AT386/kernBootStruct.h @@ -24,91 +24,63 @@ * What the booter leaves behind for the kernel. */ -/* The config table has room for 13 drivers if their config files - * are the maximum size allowed. +/* + * Maximum number of boot drivers that can be loaded. */ -#define CONFIG_SIZE (13 * 4096) +#define NDRIVERS 500 -/* Maximum number of boot drivers supported, assuming their - * config files fit in the bootstruct. +/* + * Types of boot driver that may be loaded by the booter. */ -#define NDRIVERS 64 +enum { + kBootDriverTypeInvalid = 0, + kBootDriverTypeKEXT = 1, + kBootDriverTypeMKEXT = 2 +}; typedef struct { - char *address; // address where driver was loaded - int size; // entry point for driver + unsigned long address; // address where driver was loaded + unsigned long size; // number of bytes + unsigned long type; // driver type } driver_config_t; +/* + * APM BIOS information. + */ typedef struct { - unsigned short major_vers; // == 0 if not present - unsigned short minor_vers; - unsigned long cs32_base; - unsigned long cs16_base; - unsigned long ds_base; - unsigned long cs_length; - unsigned long ds_length; - unsigned long entry_offset; + unsigned short major_vers; // == 0 if not present + unsigned short minor_vers; + unsigned long cs32_base; + unsigned long cs16_base; + unsigned long ds_base; + unsigned long cs_length; + unsigned long ds_length; + unsigned long entry_offset; union { - struct { - unsigned long mode_16 :1; - unsigned long mode_32 :1; - unsigned long idle_slows_cpu :1; - unsigned long reserved :29; - } f; - unsigned long data; + struct { + unsigned long mode_16 :1; + unsigned long mode_32 :1; + unsigned long idle_slows_cpu :1; + unsigned long reserved :29; + } f; + unsigned long data; } flags; - unsigned long connected; + unsigned long connected; } APM_config_t; -typedef struct _EISA_slot_info_t { - union { - struct { - unsigned char duplicateID :4; - unsigned char slotType :1; - unsigned char prodIDPresent :1; - unsigned char dupIDPresent :1; - } s; - unsigned char d; - } u_ID; - unsigned char configMajor; - unsigned char configMinor; - unsigned short checksum; - unsigned char numFunctions; - union { - struct { - unsigned char fnTypesPresent :1; - unsigned char memoryPresent :1; - unsigned char irqPresent :1; - unsigned char dmaPresent :1; - unsigned char portRangePresent:1; - unsigned char portInitPresent :1; - unsigned char freeFormPresent :1; - unsigned char reserved:1; - } s; - unsigned char d; - } u_resources; - unsigned char id[8]; -} EISA_slot_info_t; - -typedef struct _EISA_func_info_t { - unsigned char slot; - unsigned char function; - unsigned char reserved[2]; - unsigned char data[320]; -} EISA_func_info_t; - -#define NUM_EISA_SLOTS 64 - +/* + * PCI bus information. + */ typedef struct _PCI_bus_info_t { union { - struct { - unsigned char configMethod1 :1; - unsigned char configMethod2 :1; - unsigned char :2; - unsigned char specialCycle1 :1; - unsigned char specialCycle2 :1; - } s; - unsigned char d; + struct { + unsigned char configMethod1 :1; + unsigned char configMethod2 :1; + unsigned char :2; + unsigned char specialCycle1 :1; + unsigned char specialCycle2 :1; + } s; + unsigned char d; } u_bus; unsigned char maxBusNum; unsigned char majorVersion; @@ -117,67 +89,53 @@ typedef struct _PCI_bus_info_t { } PCI_bus_info_t; /* - * Video information.. + * Video information. */ - struct boot_video { - unsigned long v_baseAddr; /* Base address of video memory */ - unsigned long v_display; /* Display Code (if Applicable */ - unsigned long v_rowBytes; /* Number of bytes per pixel row */ - unsigned long v_width; /* Width */ - unsigned long v_height; /* Height */ - unsigned long v_depth; /* Pixel Depth */ + unsigned long v_baseAddr; // Base address of video memory + unsigned long v_display; // Display Code (if Applicable + unsigned long v_rowBytes; // Number of bytes per pixel row + unsigned long v_width; // Width + unsigned long v_height; // Height + unsigned long v_depth; // Pixel Depth }; -typedef struct boot_video boot_video; - -#define BOOT_STRING_LEN 160 - -typedef struct { - short version; - char bootString[BOOT_STRING_LEN];// string we booted with - int magicCookie; // KERNBOOTMAGIC if struct valid - int numIDEs; // how many IDE drives - int rootdev; // booters guess as to rootdev - int convmem; // conventional memory - int extmem; // extended memory - char boot_file[128]; // name of the kernel we booted - int first_addr0; // first address for kern convmem - int diskInfo[4]; // bios info for bios dev 80-83 - int graphicsMode; // did we boot in graphics mode? - int kernDev; // device kernel was fetched from - int numBootDrivers; // number of drivers loaded by booter - char *configEnd; // pointer to end of config files - int kaddr; // kernel load address - int ksize; // size of kernel - void *rld_entry; // entry point for standalone rld - - driver_config_t driverConfig[NDRIVERS]; - APM_config_t apm_config; - - char _reserved[7500]; +typedef struct boot_video boot_video; - boot_video video; +#define GRAPHICS_MODE 1 +#define TEXT_MODE 0 - PCI_bus_info_t pciInfo; - - int eisaConfigFunctions; - EISA_slot_info_t eisaSlotInfo[NUM_EISA_SLOTS];// EISA slot information +#define BOOT_STRING_LEN 160 +#define CONFIG_SIZE (12 * 4096) - char config[CONFIG_SIZE]; // the config file contents +typedef struct { + short version; + char bootString[BOOT_STRING_LEN]; // boot arguments + int magicCookie; // KERNBOOTMAGIC + int numIDEs; // number of IDE drives + int rootdev; // root device + int convmem; // conventional memory + int extmem; // extended memory + char bootFile[128]; // kernel file name + int firstAddr0; // first address for kern convmem + int diskInfo[4]; // info for bios dev 80-83 + int graphicsMode; // booted in graphics mode? + int kernDev; // device kernel was fetched from + int numBootDrivers; // number of drivers loaded + char * configEnd; // pointer to end of config files + int kaddr; // kernel load address + int ksize; // size of kernel + driver_config_t driverConfig[NDRIVERS]; + char _reserved[2052]; + boot_video video; + PCI_bus_info_t pciInfo; + APM_config_t apmConfig; + char config[CONFIG_SIZE]; } KERNBOOTSTRUCT; -#define GRAPHICS_MODE 1 -#define TEXT_MODE 0 - -#define KERNSTRUCT_ADDR ((KERNBOOTSTRUCT *)0x11000) -#define KERNBOOTMAGIC 0xa7a7a7a7 - -#ifndef EISA_CONFIG_ADDR -#define EISA_CONFIG_ADDR 0x20000 -#define EISA_CONFIG_LEN 0x10000 -#endif +#define KERNSTRUCT_ADDR ((KERNBOOTSTRUCT *) 0x11000) +#define KERNBOOTMAGIC 0xa7a7a7a7 #ifndef KERNEL -extern KERNBOOTSTRUCT *kernBootStruct; +extern KERNBOOTSTRUCT * kernBootStruct; #endif diff --git a/osfmk/i386/AT386/model_dep.c b/osfmk/i386/AT386/model_dep.c index 1e43a8458..ebd42a223 100644 --- a/osfmk/i386/AT386/model_dep.c +++ b/osfmk/i386/AT386/model_dep.c @@ -188,18 +188,12 @@ i386_preinit() } } - bcopy((char *) KERNSTRUCT_ADDR, (char *) &kernBootStructData, sizeof(kernBootStructData)); kernBootStruct = &kernBootStructData; - end = getlastaddr(); - - for (i = 0; i < kernBootStruct->numBootDrivers; i++) - end += kernBootStruct->driverConfig[i].size; - - end = round_page(end); + end = round_page( kernBootStruct->kaddr + kernBootStruct->ksize ); return end; } @@ -326,32 +320,28 @@ parse_arguments(void) if (kern_args_start == 0) return; - while (p < endp) { - if (*p++ != '-') { - while (*p++ != '\0') - ; - continue; - } - while (ch = *p++) { - switch (ch) { - case 'h': - halt_in_debugger = 1; - break; - case 'm': /* -m??: memory size Mbytes*/ - mem_size = atoi_term(p, &p)*1024*1024; - break; - case 'k': /* -k??: memory size Kbytes */ - mem_size = atoi_term(p, &p)*1024; - break; - default: -#if NCPUS > 1 && AT386 - if (ch > '0' && ch <= '9') - wncpu = ch - '0'; -#endif /* NCPUS > 1 && AT386 */ - break; - } - } + + /* + * handle switches in exact format of -h or -m64 + */ + while ( (p < endp) && (*p != '\0')) { + if (*p++ != '-') + continue; + switch (*p++) { + case 'h': + halt_in_debugger = 1; + break; + case 'm': + mem_size = atoi_term(p,&p)*1024*1024; + break; + case 'k': + mem_size = atoi_term(p,&p)*1024; + break; + default: + break; + } } + } const char * diff --git a/osfmk/i386/AT386/video_console.c b/osfmk/i386/AT386/video_console.c index c795dadf6..6bcc89710 100644 --- a/osfmk/i386/AT386/video_console.c +++ b/osfmk/i386/AT386/video_console.c @@ -871,12 +871,7 @@ putc_normal(unsigned char ch) switch (ch) { case '\a': /* Beep */ { - extern int asc_ringbell(); //In IOBSDConsole.cpp - int rang; - - rang = asc_ringbell(); - - if ( !rang && !IS_TEXT_MODE ) { + if ( FALSE && !IS_TEXT_MODE ) { /* * No sound hardware, invert the screen twice instead */ diff --git a/osfmk/i386/bsd_i386.c b/osfmk/i386/bsd_i386.c index 50c24d204..d7caa5a15 100644 --- a/osfmk/i386/bsd_i386.c +++ b/osfmk/i386/bsd_i386.c @@ -62,7 +62,8 @@ thread_userstack( int, thread_state_t, unsigned int, - vm_offset_t * + vm_offset_t *, + int * ); kern_return_t @@ -102,7 +103,8 @@ thread_userstack( int flavor, thread_state_t tstate, unsigned int count, - vm_offset_t *user_stack + vm_offset_t *user_stack, + int *customstack ) { struct i386_saved_state *state; @@ -115,10 +117,16 @@ thread_userstack( if (*user_stack == 0) *user_stack = USRSTACK; + if (customstack) + *customstack = 0; switch (flavor) { case i386_THREAD_STATE: /* FIXME */ state25 = (i386_thread_state_t *) tstate; *user_stack = state25->esp ? state25->esp : USRSTACK; + if (customstack && state25->esp) + *customstack = 1; + else + *customstack = 0; break; case i386_NEW_THREAD_STATE: @@ -133,6 +141,10 @@ thread_userstack( * If a valid user stack is specified, use it. */ *user_stack = uesp ? uesp : USRSTACK; + if (customstack && uesp) + *customstack = 1; + else + *customstack = 0; break; default : return (KERN_INVALID_ARGUMENT); @@ -251,6 +263,14 @@ thread_set_child(thread_act_t child, int pid) child->mact.pcb->iss.edx = 1; child->mact.pcb->iss.efl &= ~EFL_CF; } +void thread_set_parent(thread_act_t parent, int pid); +void +thread_set_parent(thread_act_t parent, int pid) +{ + parent->mact.pcb->iss.eax = pid; + parent->mact.pcb->iss.edx = 0; + parent->mact.pcb->iss.efl &= ~EFL_CF; +} @@ -290,8 +310,6 @@ extern funnel_t * network_flock; extern struct sysent sysent[]; -void *get_bsdtask_info( - task_t); int set_bsduthreadargs (thread_act_t, struct i386_saved_state *, void *); @@ -299,10 +317,37 @@ void * get_bsduthreadarg(thread_act_t); void unix_syscall(struct i386_saved_state *); +/* USED ONLY FROM VFORK/EXIT */ void unix_syscall_return(int error) { - panic("unix_syscall_return not implemented yet!!"); + thread_act_t thread; + volatile int *rval; + struct i386_saved_state *regs; + + thread = current_act(); + rval = (int *)get_bsduthreadrval(thread); + + regs = USER_REGS(thread); + + if (error == ERESTART) { + regs->eip -= 7; + } + else if (error != EJUSTRETURN) { + if (error) { + regs->eax = error; + regs->efl |= EFL_CF; /* carry bit */ + } else { /* (not error) */ + regs->eax = rval[0]; + regs->edx = rval[1]; + regs->efl &= ~EFL_CF; + } + } + + (void) thread_funnel_set(current_thread()->funnel_lock, FALSE); + + thread_exception_return(); + /* NOTREACHED */ } @@ -314,13 +359,13 @@ unix_syscall(struct i386_saved_state *regs) unsigned short code; struct sysent *callp; int nargs, error; - int *rval; + volatile int *rval; int funnel_type; vm_offset_t params; extern int nsysent; thread = current_act(); - p = get_bsdtask_info(current_task()); + p = current_proc(); rval = (int *)get_bsduthreadrval(thread); //printf("[scall : eax %x]", regs->eax); @@ -360,6 +405,10 @@ unix_syscall(struct i386_saved_state *regs) error = (*(callp->sy_call))(p, (void *) vt, rval); +#if 0 + /* May be needed with vfork changes */ + regs = USER_REGS(thread); +#endif if (error == ERESTART) { regs->eip -= 7; } diff --git a/osfmk/i386/i386_lock.s b/osfmk/i386/i386_lock.s index db7420db5..6e58d507e 100644 --- a/osfmk/i386/i386_lock.s +++ b/osfmk/i386/i386_lock.s @@ -474,7 +474,7 @@ ENTRY(mutex_init) EMARF ret -ENTRY(_mutex_lock) +ENTRY2(mutex_lock,_mutex_lock) FRAME #if ETAP_LOCK_TRACE @@ -560,7 +560,7 @@ ml_block: movl L_ARG0,%edx /* refetch lock pointer */ jmp ml_retry /* and try again */ -ENTRY(_mutex_try) +ENTRY2(mutex_try,_mutex_try) FRAME #if ETAP_LOCK_TRACE diff --git a/osfmk/i386/lock.h b/osfmk/i386/lock.h index f68004bfb..f3cdd5241 100644 --- a/osfmk/i386/lock.h +++ b/osfmk/i386/lock.h @@ -300,43 +300,8 @@ extern void bit_unlock( #define USIMPLE_LOCK_CALLS #endif /* !(USLOCK_DEBUG || USLOCK_STATS) */ - -#if MACH_RT || (NCPUS > 1) || MACH_LDEBUG -#if MACH_LDEBUG || !MACH_RT -#define mutex_try(m) (!(m)->interlock && _mutex_try(m)) -#define mutex_lock(m) \ -MACRO_BEGIN \ - assert(assert_wait_possible()); \ - _mutex_lock((m)); \ -MACRO_END - -#else /* MACH_LDEBUG || !MACH_RT */ -#define mutex_try(m) (!(m)->interlock && \ - !xchgb ((volatile char *)&((m)->locked), 1)) -#define mutex_lock(m) \ -MACRO_BEGIN \ - assert(assert_wait_possible()); \ - _mutex_lock (m); \ -MACRO_END - -#endif /* MACH_LDEBUG || !MACH_RT */ -#else /* MACH_RT || (NCPUS > 1) || MACH_LDEBUG */ -#define mutex_try _mutex_try -#define mutex_lock _mutex_lock -#endif /* MACH_RT || (NCPUS > 1) || MACH_LDEBUG */ - -#else /* !MACH_KERNEL_PRIVATE */ - -#define mutex_try _mutex_try -#define mutex_lock(m) \ -MACRO_BEGIN \ - assert(assert_wait_possible()); \ - _mutex_lock((m)); \ -MACRO_END - -#endif /* !MACH_KERNEL_PRIVATE */ +#endif /* MACH_KERNEL_PRIVATE */ extern void kernel_preempt_check (void); #endif /* _I386_LOCK_H_ */ - diff --git a/osfmk/i386/loose_ends.c b/osfmk/i386/loose_ends.c index 305bc37ea..abf2750be 100644 --- a/osfmk/i386/loose_ends.c +++ b/osfmk/i386/loose_ends.c @@ -54,6 +54,7 @@ #include <string.h> #include <mach/boolean.h> #include <mach/i386/vm_types.h> +#include <mach/i386/vm_param.h> #include <kern/kern_types.h> #include <kern/misc_protos.h> #include <i386/misc_protos.h> @@ -61,6 +62,20 @@ /* * Should be rewritten in asm anyway. */ + +/* + * bcopy_phys - like bcopy but copies from/to physical addresses. + * this is trivial since all phys mem is mapped into + * kernel virtual space + */ + +void +bcopy_phys(const char *from, char *to, vm_size_t bytes) +{ + bcopy((char *)phystokv(from), (char *)phystokv(to), bytes); +} + + /* * ovbcopy - like bcopy, but recognizes overlapping ranges and handles * them correctly. @@ -111,6 +126,34 @@ int bcmp( return len; } +int +memcmp(s1, s2, n) + register char *s1, *s2; + register n; +{ + while (--n >= 0) + if (*s1++ != *s2++) + return (*--s1 - *--s2); + return (0); +} + +/* + * Abstract: + * strlen returns the number of characters in "string" preceeding + * the terminating null character. + */ + +size_t +strlen( + register const char *string) +{ + register const char *ret = string; + + while (*string++ != '\0') + continue; + return string - 1 - ret; +} + #if MACH_ASSERT /* diff --git a/osfmk/i386/misc_protos.h b/osfmk/i386/misc_protos.h index b666379d2..d869fc2d6 100644 --- a/osfmk/i386/misc_protos.h +++ b/osfmk/i386/misc_protos.h @@ -65,3 +65,9 @@ extern unsigned int mul_scale( unsigned int multiplicand, unsigned int multiplier, unsigned int *scale); + +/* Move arbitrarily-aligned data from one physical address to another */ +extern void bcopy_phys( + const char *from, + char *to, + vm_size_t nbytes); diff --git a/osfmk/i386/pcb.c b/osfmk/i386/pcb.c index b75cf689c..5f1e65e55 100644 --- a/osfmk/i386/pcb.c +++ b/osfmk/i386/pcb.c @@ -1052,7 +1052,7 @@ thread_set_syscall_return( kern_return_t thread_machine_create(thread_t thread, thread_act_t thr_act, void (*start_pos)(thread_t)) { - MachineThrAct_t mact = &thr_act->mact; + MachineThrAct_t mact = &thr_act->mact; #if MACH_ASSERT if (watchacts & WA_PCB) @@ -1060,23 +1060,21 @@ thread_machine_create(thread_t thread, thread_act_t thr_act, void (*start_pos)(t thread, thr_act, start_pos); #endif /* MACH_ASSERT */ - assert(thread != NULL); - assert(thr_act != NULL); - - /* - * Allocate a kernel stack per shuttle - */ - thread->kernel_stack = (int)stack_alloc(thread,start_pos); - assert(thread->kernel_stack != 0); + assert(thread != NULL); + assert(thr_act != NULL); - /* - * Point top of kernel stack to user`s registers. - */ - STACK_IEL(thread->kernel_stack)->saved_state = &mact->pcb->iss; + /* + * Allocate a kernel stack per shuttle + */ + thread->kernel_stack = (int)stack_alloc(thread,start_pos); + thread->stack_privilege = thread->kernel_stack; + assert(thread->kernel_stack != 0); /* - * Utah code fiddles with pcb here - (we don't need to) + * Point top of kernel stack to user`s registers. */ + STACK_IEL(thread->kernel_stack)->saved_state = &mact->pcb->iss; + return(KERN_SUCCESS); } @@ -1418,7 +1416,6 @@ stack_attach(struct thread_shuttle *thread, void (*start_pos)(thread_t)) { struct i386_kernel_state *statep; - thread_act_t thr_act; KERNEL_DEBUG(MACHDBG_CODE(DBG_MACH_SCHED,MACH_STACK_ATTACH), thread, thread->priority, @@ -1432,8 +1429,8 @@ stack_attach(struct thread_shuttle *thread, statep->k_eip = (unsigned long) Thread_continue; statep->k_ebx = (unsigned long) start_pos; statep->k_esp = (unsigned long) STACK_IEL(stack); - - STACK_IEL(stack)->saved_state = &thr_act->mact.pcb->iss; + assert(thread->top_act); + STACK_IEL(stack)->saved_state = &thread->top_act->mact.pcb->iss; return; } @@ -1471,3 +1468,63 @@ stack_handoff(thread_t old, return; } + +struct i386_act_context { + struct i386_saved_state ss; + struct i386_float_state fs; +}; + +void * +act_thread_csave(void) +{ +struct i386_act_context *ic; +kern_return_t kret; +int val; + + ic = (struct i386_act_context *)kalloc(sizeof(struct i386_act_context)); + + if (ic == (struct i386_act_context *)NULL) + return((void *)0); + + val = i386_SAVED_STATE_COUNT; + kret = act_machine_get_state(current_act(), i386_SAVED_STATE, &ic->ss, &val); + if (kret != KERN_SUCCESS) { + kfree((vm_offset_t)ic,sizeof(struct i386_act_context)); + return((void *)0); + } + val = i386_FLOAT_STATE_COUNT; + kret = act_machine_get_state(current_act(), i386_FLOAT_STATE, &ic->fs, &val); + if (kret != KERN_SUCCESS) { + kfree((vm_offset_t)ic,sizeof(struct i386_act_context)); + return((void *)0); + } + return(ic); +} +void +act_thread_catt(void *ctx) +{ +struct i386_act_context *ic; +kern_return_t kret; +int val; + + ic = (struct i386_act_context *)ctx; + + if (ic == (struct i386_act_context *)NULL) + return; + + kret = act_machine_set_state(current_act(), i386_SAVED_STATE, &ic->ss, i386_SAVED_STATE_COUNT); + if (kret != KERN_SUCCESS) + goto out; + + kret = act_machine_set_state(current_act(), i386_FLOAT_STATE, &ic->fs, i386_FLOAT_STATE_COUNT); + if (kret != KERN_SUCCESS) + goto out; +out: + kfree((vm_offset_t)ic,sizeof(struct i386_act_context)); +} + +void act_thread_cfree(void *ctx) +{ + kfree((vm_offset_t)ctx,sizeof(struct i386_act_context)); +} + diff --git a/osfmk/i386/pmap.c b/osfmk/i386/pmap.c index a4d2b70b3..ea5d93ebe 100644 --- a/osfmk/i386/pmap.c +++ b/osfmk/i386/pmap.c @@ -1261,6 +1261,21 @@ pmap_remove_range( pmap->stats.wired_count -= num_unwired; } +/* + * Remove phys addr if mapped in specified map + * + */ +void +pmap_remove_some_phys( + pmap_t map, + vm_offset_t phys_addr) +{ + +/* Implement to support working set code */ + +} + + /* * Remove the given range of addresses * from the specified map. diff --git a/osfmk/i386/read_fault.c b/osfmk/i386/read_fault.c index 3cd758ac5..2049a1ff1 100644 --- a/osfmk/i386/read_fault.c +++ b/osfmk/i386/read_fault.c @@ -131,7 +131,7 @@ intel_read_fault( THREAD_ABORTSAFE, lo_offset, hi_offset, behavior, &prot, &result_page, &top_page, (int *)0, - 0, map->no_zero_fill, FALSE); + 0, map->no_zero_fill, FALSE, map, vaddr); if (result != VM_FAULT_SUCCESS) { vm_object_deallocate(object); diff --git a/osfmk/i386/rtclock.c b/osfmk/i386/rtclock.c index f7cd98e50..3fd52fb11 100644 --- a/osfmk/i386/rtclock.c +++ b/osfmk/i386/rtclock.c @@ -112,7 +112,7 @@ clock_res_t RtcDelt; /* global data declarations */ struct { - AbsoluteTime abstime; + uint64_t abstime; mach_timespec_t time; mach_timespec_t alarm_time; /* time of next alarm */ @@ -120,7 +120,7 @@ struct { mach_timespec_t calend_offset; boolean_t calend_is_set; - AbsoluteTime timer_deadline; + uint64_t timer_deadline; boolean_t timer_is_set; clock_timer_func_t timer_expire; @@ -214,7 +214,7 @@ MACRO_END /* * Calibration delay counts. */ -unsigned int delaycount = 10; +unsigned int delaycount = 100; unsigned int microdata = 50; /* @@ -783,7 +783,7 @@ clock_timebase_info( void clock_set_timer_deadline( - AbsoluteTime deadline) + uint64_t deadline) { spl_t s; @@ -849,7 +849,7 @@ rtclock_reset(void) int rtclock_intr(void) { - AbsoluteTime abstime; + uint64_t abstime; mach_timespec_t clock_time; int i; spl_t s; @@ -870,10 +870,10 @@ rtclock_intr(void) /* note time now up to date */ last_ival = 0; - ADD_ABSOLUTETIME_TICKS(&rtclock.abstime, NSEC_PER_SEC/HZ); + rtclock.abstime += (NSEC_PER_SEC/HZ); abstime = rtclock.abstime; - if (rtclock.timer_is_set && - CMP_ABSOLUTETIME(&rtclock.timer_deadline, &abstime) <= 0) { + if ( rtclock.timer_is_set && + rtclock.timer_deadline <= abstime ) { rtclock.timer_is_set = FALSE; UNLOCK_RTC(s); @@ -926,9 +926,9 @@ rtclock_intr(void) void clock_get_uptime( - AbsoluteTime *result) + uint64_t *result) { - natural_t ticks; + uint32_t ticks; spl_t s; LOCK_RTC(s); @@ -936,57 +936,57 @@ clock_get_uptime( *result = rtclock.abstime; UNLOCK_RTC(s); - ADD_ABSOLUTETIME_TICKS(result, ticks); + *result += ticks; } void clock_interval_to_deadline( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result) + uint32_t interval, + uint32_t scale_factor, + uint64_t *result) { - AbsoluteTime abstime; + uint64_t abstime; clock_get_uptime(result); clock_interval_to_absolutetime_interval(interval, scale_factor, &abstime); - ADD_ABSOLUTETIME(result, &abstime); + *result += abstime; } void clock_interval_to_absolutetime_interval( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result) + uint32_t interval, + uint32_t scale_factor, + uint64_t *result) { - AbsoluteTime_to_scalar(result) = (uint64_t)interval * scale_factor; + *result = (uint64_t)interval * scale_factor; } void clock_absolutetime_interval_to_deadline( - AbsoluteTime abstime, - AbsoluteTime *result) + uint64_t abstime, + uint64_t *result) { clock_get_uptime(result); - ADD_ABSOLUTETIME(result, &abstime); + *result += abstime; } void absolutetime_to_nanoseconds( - AbsoluteTime abstime, - UInt64 *result) + uint64_t abstime, + uint64_t *result) { - *result = AbsoluteTime_to_scalar(&abstime); + *result = abstime; } void nanoseconds_to_absolutetime( - UInt64 nanoseconds, - AbsoluteTime *result) + uint64_t nanoseconds, + uint64_t *result) { - AbsoluteTime_to_scalar(result) = nanoseconds; + *result = nanoseconds; } /* @@ -1038,14 +1038,18 @@ calibrate_delay(void) for (i=0; i<10; i++) { prev = delaycount; /* - * microdata must not be to large since measure_timer + * microdata must not be too large since measure_timer * will not return accurate values if the counter (short) * rolls over */ val = measure_delay(microdata); + if (val == 0) { + delaycount *= 2; + } else { delaycount *= microdata; delaycount += val-1; /* round up to upper us */ delaycount /= val; + } if (delaycount <= 0) delaycount = 1; if (delaycount != prev) diff --git a/osfmk/i386/thread_act.h b/osfmk/i386/thread_act.h index 66e5af0c3..2ce689328 100644 --- a/osfmk/i386/thread_act.h +++ b/osfmk/i386/thread_act.h @@ -168,4 +168,8 @@ typedef struct MachineThrAct { } MachineThrAct, *MachineThrAct_t; +extern void *act_thread_csave(void); +extern void act_thread_catt(void *ctx); +extern void act_thread_cfree(void *ctx); + #endif /* _I386_THREAD_ACT_H_ */ diff --git a/osfmk/i386/trap.c b/osfmk/i386/trap.c index cd7925ee7..a845341d8 100644 --- a/osfmk/i386/trap.c +++ b/osfmk/i386/trap.c @@ -173,7 +173,7 @@ user_page_fault_continue( register thread_t cur_thr = current_thread(); register struct i386_saved_state *regs = USER_REGS(thr_act); - if ((kr == KERN_SUCCESS) && (kr == KERN_ABORTED)) { + if ((kr == KERN_SUCCESS) || (kr == KERN_ABORTED)) { #if MACH_KDB if (!db_breakpoints_inserted) { db_set_breakpoints(); @@ -1123,7 +1123,7 @@ i386_astintr(int preemption) mp_enable_preemption(); #endif - ast_taken(preemption, mask, s + ast_taken(mask, s #if FAST_IDLE ,NO_IDLE_THREAD #endif /* FAST_IDLE */ diff --git a/osfmk/ipc/ipc_kmsg.c b/osfmk/ipc/ipc_kmsg.c index 04932517e..3afee2bd4 100644 --- a/osfmk/ipc/ipc_kmsg.c +++ b/osfmk/ipc/ipc_kmsg.c @@ -1337,7 +1337,6 @@ ipc_kmsg_copyin_body( mach_msg_descriptor_t *saddr, *eaddr; boolean_t complex; mach_msg_return_t mr; - boolean_t use_page_lists, steal_pages; int i; kern_return_t kr; vm_size_t space_needed = 0; @@ -1350,8 +1349,6 @@ ipc_kmsg_copyin_body( */ dest = (ipc_object_t) kmsg->ikm_header.msgh_remote_port; complex = FALSE; - use_page_lists = ipc_kobject_vm_page_list(ip_kotype((ipc_port_t)dest)); - steal_pages = ipc_kobject_vm_page_steal(ip_kotype((ipc_port_t)dest)); body = (mach_msg_body_t *) (&kmsg->ikm_header + 1); saddr = (mach_msg_descriptor_t *) (body + 1); @@ -1377,9 +1374,6 @@ ipc_kmsg_copyin_body( if (sstart->type.type == MACH_MSG_OOL_DESCRIPTOR || sstart->type.type == MACH_MSG_OOL_VOLATILE_DESCRIPTOR) { - assert(!(sstart->out_of_line.copy == MACH_MSG_PHYSICAL_COPY && - (use_page_lists || steal_pages))); - if (sstart->out_of_line.copy != MACH_MSG_PHYSICAL_COPY && sstart->out_of_line.copy != MACH_MSG_VIRTUAL_COPY) { /* @@ -1477,51 +1471,6 @@ ipc_kmsg_copyin_body( if (length == 0) { dsc->address = 0; - } else if (use_page_lists) { - int options; - - /* - * Use page list copy mechanism if specified. - */ - if (steal_pages == FALSE) { - /* - * XXX Temporary Hackaround. - * XXX Because the same page - * XXX might be in more than one - * XXX out of line region, steal - * XXX (busy) pages from previous - * XXX region so that this copyin - * XXX won't block (permanently). - */ - if (copy != VM_MAP_COPY_NULL) - vm_map_copy_steal_pages(copy); - } - - /* - * Set up options for copying in page list. - * If deallocating, steal pages to prevent - * vm code from lazy evaluating deallocation. - */ - options = VM_PROT_READ; - if (dealloc) { - options |= VM_MAP_COPYIN_OPT_SRC_DESTROY | - VM_MAP_COPYIN_OPT_STEAL_PAGES; - } - else if (steal_pages) { - options |= VM_MAP_COPYIN_OPT_STEAL_PAGES; - } - - if (vm_map_copyin_page_list(map, addr, length, options, - ©, FALSE) - != KERN_SUCCESS) { - - ipc_kmsg_clean_partial(kmsg, i, paddr, space_needed); - return MACH_SEND_INVALID_MEMORY; - } - - dsc->address = (void *) copy; - dsc->copy = MACH_MSG_PAGE_LIST_COPY_T; - } else if ((length >= MSG_OOL_SIZE_SMALL) && (dsc->copy == MACH_MSG_PHYSICAL_COPY) && !dealloc) { @@ -2333,7 +2282,6 @@ ipc_kmsg_copyout_body( dsc = &saddr->out_of_line; assert(dsc->copy != MACH_MSG_KALLOC_COPY_T); - assert(dsc->copy != MACH_MSG_PAGE_LIST_COPY_T); copy_option = dsc->copy; @@ -3017,9 +2965,6 @@ mm_copy_options_string( case MACH_MSG_KALLOC_COPY_T: name = "KALLOC_COPY_T"; break; - case MACH_MSG_PAGE_LIST_COPY_T: - name = "PAGE_LIST_COPY_T"; - break; default: name = "unknown"; break; diff --git a/osfmk/ipc/ipc_mqueue.c b/osfmk/ipc/ipc_mqueue.c index 0c7502e6a..97f13b62c 100644 --- a/osfmk/ipc/ipc_mqueue.c +++ b/osfmk/ipc/ipc_mqueue.c @@ -342,7 +342,7 @@ ipc_mqueue_send( return MACH_SEND_TIMED_OUT; } mqueue->imq_fullwaiters = TRUE; - wait_queue_assert_wait_locked(&mqueue->imq_wait_queue, + (void)wait_queue_assert_wait_locked(&mqueue->imq_wait_queue, IPC_MQUEUE_FULL, THREAD_ABORTSAFE, TRUE); /* unlock? */ @@ -715,7 +715,7 @@ ipc_mqueue_receive( self->ith_option = option; self->ith_msize = max_size; - wait_queue_assert_wait_locked(&mqueue->imq_wait_queue, + (void)wait_queue_assert_wait_locked(&mqueue->imq_wait_queue, IPC_MQUEUE_RECEIVE, interruptible, TRUE); /* unlock? */ diff --git a/osfmk/ipc/ipc_port.c b/osfmk/ipc/ipc_port.c index 7cd8a39f7..989d73b81 100644 --- a/osfmk/ipc/ipc_port.c +++ b/osfmk/ipc/ipc_port.c @@ -888,29 +888,51 @@ ipc_port_lookup_notify( } /* - * Routine: ipc_port_make_send + * Routine: ipc_port_make_send_locked * Purpose: * Make a naked send right from a receive right. + * * Conditions: - * The port is not locked but it is active. + * port locked and active. */ - ipc_port_t -ipc_port_make_send( +ipc_port_make_send_locked( ipc_port_t port) { - assert(IP_VALID(port)); - - ip_lock(port); assert(ip_active(port)); port->ip_mscount++; port->ip_srights++; ip_reference(port); ip_unlock(port); - return port; } +/* + * Routine: ipc_port_make_send + * Purpose: + * Make a naked send right from a receive right. + */ + +ipc_port_t +ipc_port_make_send( + ipc_port_t port) +{ + + if (!IP_VALID(port)) + return port; + + ip_lock(port); + if (ip_active(port)) { + port->ip_mscount++; + port->ip_srights++; + ip_reference(port); + ip_unlock(port); + return port; + } + ip_unlock(port); + return IP_DEAD; +} + /* * Routine: ipc_port_copy_send * Purpose: @@ -1535,8 +1557,8 @@ print_ports(void) PRINT_ONE_PORT_TYPE(PSET); PRINT_ONE_PORT_TYPE(PSET_NAME); PRINT_ONE_PORT_TYPE(PAGING_REQUEST); - PRINT_ONE_PORT_TYPE(XMM_OBJECT); - PRINT_ONE_PORT_TYPE(DEVICE); + PRINT_ONE_PORT_TYPE(MEMORY_OBJECT); + PRINT_ONE_PORT_TYPE(MIG); PRINT_ONE_PORT_TYPE(XMM_PAGER); PRINT_ONE_PORT_TYPE(XMM_KERNEL); PRINT_ONE_PORT_TYPE(XMM_REPLY); diff --git a/osfmk/ipc/ipc_port.h b/osfmk/ipc/ipc_port.h index 5bd9e5857..4231bd026 100644 --- a/osfmk/ipc/ipc_port.h +++ b/osfmk/ipc/ipc_port.h @@ -115,7 +115,7 @@ struct ipc_port { } data; ipc_kobject_t ip_kobject; - struct rpc_subsystem * ip_subsystem; + struct rpc_subsystem * ip_subsystem; mach_port_mscount_t ip_mscount; mach_port_rights_t ip_srights; mach_port_rights_t ip_sorights; @@ -377,6 +377,10 @@ extern ipc_port_t ipc_port_lookup_notify( ipc_space_t space, mach_port_name_t name); +/* Make a naked send right from a receive right - port locked and active */ +extern ipc_port_t ipc_port_make_send_locked( + ipc_port_t port); + /* Make a naked send right from a receive right */ extern ipc_port_t ipc_port_make_send( ipc_port_t port); diff --git a/osfmk/ipc/mach_msg.c b/osfmk/ipc/mach_msg.c index 5c5364323..4af874090 100644 --- a/osfmk/ipc/mach_msg.c +++ b/osfmk/ipc/mach_msg.c @@ -85,8 +85,8 @@ #include <kern/thread_swap.h> #include <kern/processor.h> -#include <kern/sf.h> -#include <kern/mk_sp.h> /* JMM - to support handoff hack */ +#include <kern/mk_sp.h> + #include <machine/machine_routines.h> #include <sys/kdebug.h> @@ -344,6 +344,8 @@ mach_msg_receive( self->ith_continuation = continuation; ipc_mqueue_receive(mqueue, option, rcv_size, timeout, THREAD_ABORTSAFE); + if ((option & MACH_RCV_TIMEOUT) && timeout == 0) + _mk_sp_thread_perhaps_yield(self); return mach_msg_receive_results(); } @@ -1215,11 +1217,11 @@ mach_msg_overwrite_trap( * that doesn't try to put thread on a runq. */ { - receiver->sp_state = MK_SP_RUNNABLE; + receiver->state &= ~(TH_WAIT|TH_UNINT); + receiver->state |= TH_RUN; + receiver->wait_result = THREAD_AWAKENED; - receiver->state &= ~(TH_WAIT|TH_UNINT); - receiver->state |= TH_RUN; - receiver->wait_result = THREAD_AWAKENED; + receiver->metered_computation = 0; } thread_unlock(receiver); @@ -1246,7 +1248,7 @@ mach_msg_overwrite_trap( self->ith_continuation = thread_syscall_return; waitq = &rcv_mqueue->imq_wait_queue; - wait_queue_assert_wait_locked(waitq, + (void)wait_queue_assert_wait_locked(waitq, IPC_MQUEUE_RECEIVE, THREAD_ABORTSAFE, TRUE); /* unlock? */ diff --git a/osfmk/kdp/ml/ppc/kdp_asm.s b/osfmk/kdp/ml/ppc/kdp_asm.s index 4e53ce0b7..4f1ecd207 100644 --- a/osfmk/kdp/ml/ppc/kdp_asm.s +++ b/osfmk/kdp/ml/ppc/kdp_asm.s @@ -51,7 +51,7 @@ ENTRY(kdp_call_with_ctx, TAG_NO_FRAME_USED) #ifdef LET_KDP_REENTER mr r9, r1 /* get current stack pointer */ - subi r9, r9, FM_REDZONE + SS_SIZE + subi r9, r9, FM_REDZONE + FM_SIZE #else bl EXT(kdp_print_backtrace) #endif diff --git a/osfmk/kdp/ml/ppc/kdp_machdep.c b/osfmk/kdp/ml/ppc/kdp_machdep.c index f6cef9205..f84e6a832 100644 --- a/osfmk/kdp/ml/ppc/kdp_machdep.c +++ b/osfmk/kdp/ml/ppc/kdp_machdep.c @@ -285,6 +285,7 @@ kdp_machine_hostinfo( int i; hostinfo->cpus_mask = 0; + hostinfo->cpu_type = 0; for (i = 0; i < machine_info.max_cpus; i++) { m = &machine_slot[i]; diff --git a/osfmk/kdp/ml/ppc/kdp_vm.c b/osfmk/kdp/ml/ppc/kdp_vm.c index dad44c78c..066204a66 100644 --- a/osfmk/kdp/ml/ppc/kdp_vm.c +++ b/osfmk/kdp/ml/ppc/kdp_vm.c @@ -45,7 +45,7 @@ unsigned kdp_vm_read( caddr_t, caddr_t, unsigned); unsigned kdp_vm_write( caddr_t, caddr_t, unsigned); extern vm_offset_t kvtophys(vm_offset_t); - +extern vm_offset_t mem_actual; /* * @@ -57,7 +57,7 @@ vm_offset_t kdp_vtophys( register mapping *mp; register vm_offset_t pa; - pa = LRA(pmap->space,(void *)va); + pa = (vm_offset_t)LRA(pmap->space,(void *)va); if (pa != 0) return(pa); @@ -113,9 +113,10 @@ unsigned kdp_vm_read( kprintf("kdp_vm_read1: src %x dst %x len %x - %08X %08X\n", src, dst, len, ((unsigned long *)src)[0], ((unsigned long *)src)[1]); #endif if (kdp_trans_off) { - cur_virt_src = (vm_offset_t) ((int)src & 0x0fffffff); - cur_virt_dst = (vm_offset_t)dst; - resid = len; + cur_virt_src = (vm_offset_t)src; + if((vm_offset_t)src >= mem_actual) return 0; /* Can't read where there's not any memory */ + cur_virt_dst = (vm_offset_t)dst; + resid = (mem_actual - (vm_offset_t)src) > len ? len : (mem_actual - (vm_offset_t)src); while (resid != 0) { cur_phys_src = cur_virt_src; diff --git a/osfmk/kern/ast.c b/osfmk/kern/ast.c index f454fe9a3..df5409005 100644 --- a/osfmk/kern/ast.c +++ b/osfmk/kern/ast.c @@ -62,14 +62,12 @@ #include <cputypes.h> #include <cpus.h> #include <platforms.h> -#include <task_swapper.h> #include <kern/ast.h> #include <kern/counters.h> #include <kern/cpu_number.h> #include <kern/misc_protos.h> #include <kern/queue.h> -#include <kern/sched.h> #include <kern/sched_prim.h> #include <kern/thread.h> #include <kern/thread_act.h> @@ -77,9 +75,6 @@ #include <kern/processor.h> #include <kern/spl.h> #include <mach/policy.h> -#if TASK_SWAPPER -#include <kern/task_swap.h> -#endif /* TASK_SWAPPER */ volatile ast_t need_ast[NCPUS]; @@ -97,89 +92,65 @@ ast_init(void) void ast_taken( - boolean_t preemption, - ast_t mask, - boolean_t interrupt + ast_t reasons, + boolean_t enable ) { - register thread_t self = current_thread(); - register processor_t mypr; - register ast_t reasons; - register int mycpu; - thread_act_t act = self->top_act; -#ifdef MACH_BSD - extern void bsd_ast(thread_act_t); - extern void bsdinit_task(void); -#endif + register int mycpu; + register processor_t myprocessor; + register thread_t self = current_thread(); + boolean_t preempt_trap = (reasons == AST_PREEMPT); - mp_disable_preemption(); + disable_preemption(); mycpu = cpu_number(); - reasons = need_ast[mycpu] & mask; + reasons &= need_ast[mycpu]; need_ast[mycpu] &= ~reasons; - mp_enable_preemption(); - - ml_set_interrupts_enabled(interrupt); + enable_preemption(); /* * No ast for an idle thread */ if (self->state & TH_IDLE) - return; + goto enable_and_return; /* - * Check for preemption + * Check for urgent preemption */ - if ((reasons & AST_URGENT) && (wait_queue_assert_possible(self))) { - reasons &= ~AST_URGENT; - if ((reasons & (AST_BLOCK|AST_QUANTUM)) == 0) { - mp_disable_preemption(); - mypr = current_processor(); - if (csw_needed(self, mypr)) { - reasons |= (mypr->first_quantum ? AST_BLOCK : AST_QUANTUM); - } - mp_enable_preemption(); - } - if (reasons & (AST_BLOCK | AST_QUANTUM)) { + if ((reasons & AST_URGENT) && wait_queue_assert_possible(self)) { + if (reasons & AST_BLOCK) { counter(c_ast_taken_block++); - thread_block_reason((void (*)(void))0, - (reasons & (AST_BLOCK | AST_QUANTUM))); + thread_block_reason((void (*)(void))0, AST_BLOCK); } + + reasons &= ~AST_PREEMPT; if (reasons == 0) - return; + goto enable_and_return; } + if (preempt_trap) + goto enable_and_return; + + ml_set_interrupts_enabled(enable); + #ifdef MACH_BSD /* * Check for BSD hardcoded hooks */ if (reasons & AST_BSD) { - thread_ast_clear(act,AST_BSD); + extern void bsd_ast(thread_act_t act); + thread_act_t act = self->top_act; + + thread_ast_clear(act, AST_BSD); bsd_ast(act); } if (reasons & AST_BSD_INIT) { - thread_ast_clear(act,AST_BSD_INIT); + extern void bsdinit_task(void); + + thread_ast_clear(self->top_act, AST_BSD_INIT); bsdinit_task(); } #endif -#if TASK_SWAPPER - /* must be before AST_APC */ - if (reasons & AST_SWAPOUT) { - spl_t s; - swapout_ast(); - s = splsched(); - mp_disable_preemption(); - mycpu = cpu_number(); - if (need_ast[mycpu] & AST_APC) { - /* generated in swapout_ast() to get suspended */ - reasons |= AST_APC; /* process now ... */ - need_ast[mycpu] &= ~AST_APC; /* ... and not later */ - } - mp_enable_preemption(); - splx(s); - } -#endif /* TASK_SWAPPER */ - /* * migration APC hook */ @@ -188,93 +159,81 @@ ast_taken( } /* - * thread_block needs to know if the thread's quantum - * expired so the thread can be put on the tail of - * run queue. One of the previous actions might well - * have woken a high-priority thread, so we also use - * csw_needed check. + * Check for normal preemption */ - reasons &= (AST_BLOCK | AST_QUANTUM); - if (reasons == 0) { - mp_disable_preemption(); - mypr = current_processor(); - if (csw_needed(self, mypr)) { - reasons = (mypr->first_quantum ? AST_BLOCK : AST_QUANTUM); - } - mp_enable_preemption(); - } - if ((reasons & (AST_BLOCK | AST_QUANTUM)) && - (wait_queue_assert_possible(self))) { + reasons &= AST_BLOCK; + if (reasons == 0) { + disable_preemption(); + myprocessor = current_processor(); + if (csw_needed(self, myprocessor)) + reasons = AST_BLOCK; + enable_preemption(); + } + if ( (reasons & AST_BLOCK) && + wait_queue_assert_possible(self) ) { counter(c_ast_taken_block++); - /* - * JMM - SMP machines don't like blocking at a continuation - * here - why not? Could be a combination of set_state and - * suspension on the thread_create_running API? - * - * thread_block_reason(thread_exception_return, reasons); - */ - thread_block_reason((void (*)(void))0, reasons); + thread_block_reason(thread_exception_return, AST_BLOCK); } + + goto just_return; + +enable_and_return: + ml_set_interrupts_enabled(enable); + +just_return: + return; } void ast_check(void) { - register int mycpu; + register int mycpu; register processor_t myprocessor; - register thread_t thread = current_thread(); - spl_t s = splsched(); + register thread_t self = current_thread(); + spl_t s; - mp_disable_preemption(); + s = splsched(); mycpu = cpu_number(); /* * Check processor state for ast conditions. */ myprocessor = cpu_to_processor(mycpu); - switch(myprocessor->state) { - case PROCESSOR_OFF_LINE: - case PROCESSOR_IDLE: - case PROCESSOR_DISPATCHING: + switch (myprocessor->state) { + + case PROCESSOR_OFF_LINE: + case PROCESSOR_IDLE: + case PROCESSOR_DISPATCHING: /* * No ast. */ - break; + break; -#if NCPUS > 1 - case PROCESSOR_ASSIGN: - /* + case PROCESSOR_ASSIGN: + /* * Need ast to force action thread onto processor. - * - * XXX Should check if action thread is already there. */ ast_on(AST_BLOCK); break; -#endif /* NCPUS > 1 */ - case PROCESSOR_RUNNING: - case PROCESSOR_SHUTDOWN: + case PROCESSOR_RUNNING: + case PROCESSOR_SHUTDOWN: /* - * Propagate thread ast to processor. If we already - * need an ast, don't look for more reasons. + * Propagate thread ast to processor. */ - ast_propagate(current_act()->ast); - if (ast_needed(mycpu)) - break; + ast_propagate(self->top_act->ast); /* * Context switch check. */ - if (csw_needed(thread, myprocessor)) { - ast_on((myprocessor->first_quantum ? - AST_BLOCK : AST_QUANTUM)); - } + if (csw_needed(self, myprocessor)) + ast_on(AST_BLOCK); break; - default: - panic("ast_check: Bad processor state"); + default: + panic("ast_check: Bad processor state"); } - mp_enable_preemption(); + splx(s); } @@ -287,11 +246,11 @@ ast_check(void) void ast_on(ast_t reason) { - boolean_t intr; + boolean_t enable; - intr = ml_set_interrupts_enabled(FALSE); + enable = ml_set_interrupts_enabled(FALSE); ast_on_fast(reason); - (void *)ml_set_interrupts_enabled(intr); + (void)ml_set_interrupts_enabled(enable); } void diff --git a/osfmk/kern/ast.h b/osfmk/kern/ast.h index efda6b3a1..3512b4593 100644 --- a/osfmk/kern/ast.h +++ b/osfmk/kern/ast.h @@ -73,37 +73,32 @@ * Machine-dependent code is responsible for maintaining * a set of reasons for an AST, and passing this set to ast_taken. */ - -typedef unsigned int ast_t; +typedef unsigned int ast_t; /* * Bits for reasons */ -#define AST_NONE 0x00 -#define AST_HALT 0x01 +#define AST_HALT 0x01 #define AST_TERMINATE 0x02 #define AST_BLOCK 0x04 -#define AST_UNUSED 0x08 -#define AST_QUANTUM 0x10 -#define AST_APC 0x20 /* migration APC hook */ -#define AST_URGENT 0x40 - +#define AST_QUANTUM 0x08 +#define AST_URGENT 0x10 +#define AST_APC 0x20 /* migration APC hook */ /* * JMM - This is here temporarily. AST_BSD is used to simulate a * general purpose mechanism for setting asynchronous procedure calls * from the outside. */ -#define AST_BSD 0x80 +#define AST_BSD 0x80 #define AST_BSD_INIT 0x100 -#define AST_SWAPOUT 0x20000 - -#define AST_ALL (~AST_NONE) +#define AST_NONE 0x00 +#define AST_ALL (~AST_NONE) -#define AST_SCHEDULING (AST_HALT | AST_TERMINATE | AST_BLOCK | AST_SWAPOUT) -#define AST_PREEMPT (AST_BLOCK | AST_QUANTUM | AST_URGENT) +#define AST_SCHEDULING (AST_HALT | AST_TERMINATE | AST_BLOCK) +#define AST_PREEMPT (AST_BLOCK | AST_QUANTUM | AST_URGENT) -extern volatile ast_t need_ast[NCPUS]; +extern volatile ast_t need_ast[NCPUS]; #ifdef MACHINE_AST /* @@ -117,13 +112,12 @@ extern volatile ast_t need_ast[NCPUS]; #endif /* MACHINE_AST */ /* Initialize module */ -extern void ast_init(void); +extern void ast_init(void); /* Handle ASTs */ -extern void ast_taken( - boolean_t preemption, - ast_t mask, - boolean_t interrupt); +extern void ast_taken( + ast_t mask, + boolean_t enable); /* Check for pending ASTs */ extern void ast_check(void); @@ -135,57 +129,55 @@ extern void ast_check(void); #define MACHINE_AST_PER_THREAD 0 #endif -#define AST_PER_THREAD (MACHINE_AST_PER_THREAD|AST_HALT|AST_TERMINATE|AST_APC|AST_BSD) - +#define AST_PER_THREAD ( AST_HALT | AST_TERMINATE | AST_APC | AST_BSD | \ + MACHINE_AST_PER_THREAD ) /* - * ast_needed, ast_on, ast_off, ast_context, and ast_propagate - * assume splsched. + * ast_needed(), ast_on(), ast_off(), ast_context(), and ast_propagate() + * assume splsched. */ +#define ast_needed(mycpu) need_ast[mycpu] -#define ast_needed(mycpu) need_ast[mycpu] - -#define ast_on_fast(reasons) \ -MACRO_BEGIN \ - int mycpu = cpu_number(); \ - if ((need_ast[mycpu] |= (reasons)) != AST_NONE) \ - { aston(mycpu); } \ +#define ast_on_fast(reasons) \ +MACRO_BEGIN \ + int mycpu = cpu_number(); \ + if ((need_ast[mycpu] |= (reasons)) != AST_NONE) \ + { aston(mycpu); } \ MACRO_END -#define ast_off_fast(reasons) \ -MACRO_BEGIN \ - int mycpu = cpu_number(); \ - if ((need_ast[mycpu] &= ~(reasons)) == AST_NONE) \ - { astoff(mycpu); } \ +#define ast_off_fast(reasons) \ +MACRO_BEGIN \ + int mycpu = cpu_number(); \ + if ((need_ast[mycpu] &= ~(reasons)) == AST_NONE) \ + { astoff(mycpu); } \ MACRO_END #define ast_propagate(reasons) ast_on(reasons) -#define ast_context(act, mycpu) \ -MACRO_BEGIN \ - assert(mycpu == cpu_number()); \ - if ((need_ast[mycpu] = \ - (need_ast[mycpu] &~ AST_PER_THREAD) | (act)->ast) \ - != AST_NONE) \ - { aston(mycpu); } \ - else \ - { astoff(mycpu); } \ +#define ast_context(act, mycpu) \ +MACRO_BEGIN \ + assert((mycpu) == cpu_number()); \ + if ((need_ast[mycpu] = \ + ((need_ast[mycpu] &~ AST_PER_THREAD) | (act)->ast)) != AST_NONE) \ + { aston(mycpu); } \ + else \ + { astoff(mycpu); } \ MACRO_END #define ast_on(reason) ast_on_fast(reason) #define ast_off(reason) ast_off_fast(reason) -#define thread_ast_set(act, reason) (act)->ast |= (reason) -#define thread_ast_clear(act, reason) (act)->ast &= ~(reason) -#define thread_ast_clear_all(act) (act)->ast = AST_NONE +#define thread_ast_set(act, reason) ((act)->ast |= (reason)) +#define thread_ast_clear(act, reason) ((act)->ast &= ~(reason)) +#define thread_ast_clear_all(act) ((act)->ast = AST_NONE) /* - * NOTE: if thread is the current thread, thread_ast_set should - * be followed by ast_propagate(). + * NOTE: if thread is the current thread, thread_ast_set() should + * be followed by ast_propagate(). */ #ifdef MACH_KERNEL_PRIVATE -#define ast_urgency() (need_ast[cpu_number()] & AST_URGENT) +#define ast_urgency() (need_ast[cpu_number()] & AST_URGENT) #endif /* MACH_KERNEL_PRIVATE */ diff --git a/osfmk/kern/bsd_kern.c b/osfmk/kern/bsd_kern.c index 0c03a9193..5648cb387 100644 --- a/osfmk/kern/bsd_kern.c +++ b/osfmk/kern/bsd_kern.c @@ -73,9 +73,6 @@ int get_task_numacts(task_t); thread_act_t get_firstthread(task_t task); kern_return_t get_signalact(task_t , thread_act_t *, thread_t *, int); -kern_return_t bsd_refvm_object(vm_object_t object); - - /* * */ @@ -166,6 +163,60 @@ out: return(KERN_FAILURE); } + +kern_return_t check_actforsig(task_t task, thread_act_t * thact, thread_t * thshut, int setast) +{ + + thread_act_t inc; + thread_act_t ninc; + thread_act_t thr_act; + thread_t th; + int found=0; + + task_lock(task); + if (!task->active) { + task_unlock(task); + return(KERN_FAILURE); + } + + thr_act = THR_ACT_NULL; + for (inc = (thread_act_t)queue_first(&task->thr_acts); + inc != (thread_act_t)&task->thr_acts; + inc = ninc) { + + if (inc != thact) { + ninc = (thread_act_t)queue_next(&inc->thr_acts); + continue; + } + th = act_lock_thread(inc); + if ((inc->active) && ((th->state & TH_ABORT) != TH_ABORT)) { + found = 1; + thr_act = inc; + break; + } + act_unlock_thread(inc); + /* ninc = (thread_act_t)queue_next(&inc->thr_acts); */ + break; + } +out: + if (found) { + if (thshut) + *thshut = thr_act? thr_act->thread: THREAD_NULL ; + if (setast) { + thread_ast_set(thr_act, AST_BSD); + if (current_act() == thr_act) + ast_on(AST_BSD); + } + act_unlock_thread(thr_act); + } + task_unlock(task); + + if (found) + return(KERN_SUCCESS); + else + return(KERN_FAILURE); +} + /* * */ @@ -495,10 +546,4 @@ get_thread_waitresult( return(th->wait_result); } -kern_return_t -bsd_refvm_object(vm_object_t object) -{ - vm_object_reference(object); - return(KERN_SUCCESS); -} diff --git a/osfmk/kern/call_entry.h b/osfmk/kern/call_entry.h index df0f3b916..ad846bf5c 100644 --- a/osfmk/kern/call_entry.h +++ b/osfmk/kern/call_entry.h @@ -48,7 +48,7 @@ typedef struct call_entry { call_entry_func_t func; call_entry_param_t param0; call_entry_param_t param1; - AbsoluteTime deadline; + uint64_t deadline; enum { IDLE, PENDING, diff --git a/osfmk/kern/clock.c b/osfmk/kern/clock.c index 32cac4eba..1aab8196c 100644 --- a/osfmk/kern/clock.c +++ b/osfmk/kern/clock.c @@ -41,15 +41,12 @@ #include <kern/misc_protos.h> #include <kern/lock.h> #include <kern/host.h> -#include <kern/processor.h> -#include <kern/sched.h> #include <kern/spl.h> #include <kern/thread.h> #include <kern/thread_swap.h> #include <kern/ipc_host.h> #include <kern/clock.h> #include <kern/zalloc.h> -#include <kern/sf.h> #include <ipc/ipc_port.h> #include <mach/mach_syscalls.h> @@ -794,24 +791,22 @@ clock_set_calendar_value( void clock_deadline_for_periodic_event( - AbsoluteTime interval, - AbsoluteTime abstime, - AbsoluteTime *deadline) + uint64_t interval, + uint64_t abstime, + uint64_t *deadline) { - assert(AbsoluteTime_to_scalar(&interval) != 0); + assert(interval != 0); - ADD_ABSOLUTETIME(deadline, &interval); + *deadline += interval; - if ( AbsoluteTime_to_scalar(deadline) <= - AbsoluteTime_to_scalar(&abstime) ) { + if (*deadline <= abstime) { *deadline = abstime; clock_get_uptime(&abstime); - ADD_ABSOLUTETIME(deadline, &interval); + *deadline += interval; - if ( AbsoluteTime_to_scalar(deadline) <= - AbsoluteTime_to_scalar(&abstime) ) { + if (*deadline <= abstime) { *deadline = abstime; - ADD_ABSOLUTETIME(deadline, &interval); + *deadline += interval; } } } @@ -858,7 +853,7 @@ mach_wait_until( int wait_result; assert_wait((event_t)&mach_wait_until, THREAD_ABORTSAFE); - thread_set_timer_deadline(scalar_to_AbsoluteTime(&deadline)); + thread_set_timer_deadline(deadline); wait_result = thread_block((void (*)) 0); if (wait_result != THREAD_TIMED_OUT) thread_cancel_timer(); diff --git a/osfmk/kern/clock.h b/osfmk/kern/clock.h index 0ed37d707..58c78efd5 100644 --- a/osfmk/kern/clock.h +++ b/osfmk/kern/clock.h @@ -32,8 +32,6 @@ #ifndef _KERN_CLOCK_H_ #define _KERN_CLOCK_H_ -#include <libkern/OSBase.h> - #include <mach/message.h> #include <mach/clock_types.h> #include <mach/mach_time.h> @@ -151,13 +149,13 @@ extern kern_return_t clock_sleep_internal( mach_timespec_t *sleep_time); typedef void (*clock_timer_func_t)( - AbsoluteTime timestamp); + uint64_t timestamp); extern void clock_set_timer_func( clock_timer_func_t func); extern void clock_set_timer_deadline( - AbsoluteTime deadline); + uint64_t deadline); extern void mk_timebase_info( uint32_t *delta, @@ -166,8 +164,6 @@ extern void mk_timebase_info( uint32_t *proc_to_abs_numer, uint32_t *proc_to_abs_denom); -#define scalar_to_AbsoluteTime(x) (*(AbsoluteTime *)(x)) - #endif /* MACH_KERNEL_PRIVATE */ #define MACH_TIMESPEC_SEC_MAX (0 - 1) @@ -207,6 +203,74 @@ extern void clock_initialize_calendar(void); extern mach_timespec_t clock_get_calendar_offset(void); +extern void clock_timebase_info( + mach_timebase_info_t info); + +extern void clock_get_uptime( + uint64_t *result); + +extern void clock_interval_to_deadline( + uint32_t interval, + uint32_t scale_factor, + uint64_t *result); + +extern void clock_interval_to_absolutetime_interval( + uint32_t interval, + uint32_t scale_factor, + uint64_t *result); + +extern void clock_absolutetime_interval_to_deadline( + uint64_t abstime, + uint64_t *result); + +extern void clock_deadline_for_periodic_event( + uint64_t interval, + uint64_t abstime, + uint64_t *deadline); + +extern void clock_delay_for_interval( + uint32_t interval, + uint32_t scale_factor); + +extern void clock_delay_until( + uint64_t deadline); + +extern void absolutetime_to_nanoseconds( + uint64_t abstime, + uint64_t *result); + +extern void nanoseconds_to_absolutetime( + uint64_t nanoseconds, + uint64_t *result); + +#if !defined(MACH_KERNEL_PRIVATE) && !defined(ABSOLUTETIME_SCALAR_TYPE) + +#include <libkern/OSBase.h> + +#define clock_get_uptime(a) \ + clock_get_uptime(__OSAbsoluteTimePtr(a)) + +#define clock_interval_to_deadline(a, b, c) \ + clock_interval_to_deadline((a), (b), __OSAbsoluteTimePtr(c)) + +#define clock_interval_to_absolutetime_interval(a, b, c) \ + clock_interval_to_absolutetime_interval((a), (b), __OSAbsoluteTimePtr(c)) + +#define clock_absolutetime_interval_to_deadline(a, b) \ + clock_absolutetime_interval_to_deadline(__OSAbsoluteTime(a), __OSAbsoluteTimePtr(b)) + +#define clock_deadline_for_periodic_event(a, b, c) \ + clock_deadline_for_periodic_event(__OSAbsoluteTime(a), __OSAbsoluteTime(b), __OSAbsoluteTimePtr(c)) + +#define clock_delay_until(a) \ + clock_delay_until(__OSAbsoluteTime(a)) + +#define absolutetime_to_nanoseconds(a, b) \ + absolutetime_to_nanoseconds(__OSAbsoluteTime(a), (b)) + +#define nanoseconds_to_absolutetime(a, b) \ + nanoseconds_to_absolutetime((a), __OSAbsoluteTimePtr(b)) + #define AbsoluteTime_to_scalar(x) (*(uint64_t *)(x)) /* t1 < = > t2 */ @@ -228,46 +292,8 @@ extern mach_timespec_t clock_get_calendar_offset(void); #define ADD_ABSOLUTETIME_TICKS(t1, ticks) \ (AbsoluteTime_to_scalar(t1) += \ - (integer_t)(ticks)) - -extern void clock_timebase_info( - mach_timebase_info_t info); - -extern void clock_get_uptime( - AbsoluteTime *result); - -extern void clock_interval_to_deadline( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result); + (int32_t)(ticks)) -extern void clock_interval_to_absolutetime_interval( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result); - -extern void clock_absolutetime_interval_to_deadline( - AbsoluteTime abstime, - AbsoluteTime *result); - -extern void clock_deadline_for_periodic_event( - AbsoluteTime interval, - AbsoluteTime abstime, - AbsoluteTime *deadline); - -extern void clock_delay_for_interval( - natural_t interval, - natural_t scale_factor); - -extern void clock_delay_until( - AbsoluteTime deadline); - -extern void absolutetime_to_nanoseconds( - AbsoluteTime abstime, - UInt64 *result); - -extern void nanoseconds_to_absolutetime( - UInt64 nanoseconds, - AbsoluteTime *result); +#endif #endif /* _KERN_CLOCK_H_ */ diff --git a/osfmk/kern/host.c b/osfmk/kern/host.c index 9b8f7d7a4..283dfa4cf 100644 --- a/osfmk/kern/host.c +++ b/osfmk/kern/host.c @@ -214,14 +214,14 @@ host_info( priority_info = (host_priority_info_t) info; - priority_info->kernel_priority = MINPRI_KERNBAND; - priority_info->system_priority = MINPRI_KERNBAND; - priority_info->server_priority = MINPRI_HIGHBAND; + priority_info->kernel_priority = MINPRI_KERNEL; + priority_info->system_priority = MINPRI_KERNEL; + priority_info->server_priority = MINPRI_SYSTEM; priority_info->user_priority = BASEPRI_DEFAULT; priority_info->depress_priority = DEPRESSPRI; priority_info->idle_priority = IDLEPRI; priority_info->minimum_priority = MINPRI_STANDARD; - priority_info->maximum_priority = MAXPRI_HIGHBAND; + priority_info->maximum_priority = MAXPRI_SYSTEM; *count = HOST_PRIORITY_INFO_COUNT; diff --git a/osfmk/kern/ipc_host.c b/osfmk/kern/ipc_host.c index 6cb65051b..4c3aa3b45 100644 --- a/osfmk/kern/ipc_host.c +++ b/osfmk/kern/ipc_host.c @@ -57,9 +57,11 @@ */ #include <mach/message.h> #include <mach/mach_traps.h> +#include <mach/etap_events.h> #include <mach/mach_host_server.h> #include <kern/host.h> #include <kern/processor.h> +#include <kern/lock.h> #include <kern/task.h> #include <kern/thread.h> #include <kern/ipc_host.h> @@ -94,6 +96,8 @@ void ipc_host_init(void) ipc_port_t port; int i; + mutex_init(&realhost.lock, ETAP_MISC_MASTER); + /* * Allocate and set up the two host ports. */ diff --git a/osfmk/kern/ipc_kobject.c b/osfmk/kern/ipc_kobject.c index 5eaef10b7..4aeba476a 100644 --- a/osfmk/kern/ipc_kobject.c +++ b/osfmk/kern/ipc_kobject.c @@ -81,12 +81,6 @@ #include <kern/counters.h> -void - def_pager_hash_insert( - ipc_port_t name_port); -void pager_mux_hash_insert( - ipc_port_t port, - rpc_subsystem_t rec); void pager_mux_hash_delete( ipc_port_t port); rpc_subsystem_t pager_mux_hash_lookup( @@ -166,10 +160,7 @@ rpc_subsystem_t mig_e[] = { (rpc_subsystem_t)&processor_subsystem, (rpc_subsystem_t)&processor_set_subsystem, (rpc_subsystem_t)&is_iokit_subsystem, - (rpc_subsystem_t)&dp_memory_object_subsystem, - (rpc_subsystem_t)&dp_memory_object_default_subsystem, (rpc_subsystem_t)&memory_object_name_subsystem, - (rpc_subsystem_t)&default_pager_object_subsystem, (rpc_subsystem_t)&lock_set_subsystem, (rpc_subsystem_t)&ledger_subsystem, (rpc_subsystem_t)&semaphore_subsystem, @@ -228,112 +219,7 @@ mig_init(void) } } } -} - - -#define PAGER_MUX_HASH_COUNT 127 - - -struct pager_mux_entry { - queue_chain_t links; - ipc_port_t name; - rpc_subsystem_t pager_object; -}; -typedef struct pager_mux_entry *pager_mux_entry_t; - -queue_head_t pager_mux_hashtable[PAGER_MUX_HASH_COUNT]; -zone_t pager_mux_hash_zone; - -decl_mutex_data(,pager_mux_hash_lock) - -#define pager_mux_hash(name_port) \ - (((natural_t)(name_port) & 0xffffff) % PAGER_MUX_HASH_COUNT) - - -rpc_subsystem_t -pager_mux_hash_lookup( - ipc_port_t name_port) -{ - register queue_t bucket; - register pager_mux_entry_t entry; - register rpc_subsystem_t pager_object; - - bucket = &pager_mux_hashtable[pager_mux_hash(name_port)]; - - mutex_lock(&pager_mux_hash_lock); - for (entry = (pager_mux_entry_t)queue_first(bucket); - !queue_end(bucket, &entry->links); - entry = (pager_mux_entry_t)queue_next(&entry->links)) { - if (entry->name == name_port) { - pager_object = entry->pager_object; - /* don't need to reference the object, it can't disappear */ - /* pager_mux_reference(pager_object); */ - mutex_unlock(&pager_mux_hash_lock); - return (pager_object); - } - } - mutex_unlock(&pager_mux_hash_lock); - return (rpc_subsystem_t)0; -} - - -void -pager_mux_hash_init(void) -{ - register int i; - register vm_size_t size; - - size = sizeof(struct pager_mux_entry); - pager_mux_hash_zone = zinit( - size, - size * 2000, - PAGE_SIZE, - "pager mux port hash"); - for (i = 0; i < PAGER_MUX_HASH_COUNT; i++) - queue_init(&pager_mux_hashtable[i]); - mutex_init(&pager_mux_hash_lock, ETAP_IO_DEV_PAGEH); -} - - -void -pager_mux_hash_insert( - ipc_port_t name_port, - rpc_subsystem_t pager_object) -{ - register pager_mux_entry_t new_entry; - - new_entry = (pager_mux_entry_t) zalloc(pager_mux_hash_zone); - new_entry->links.prev = (queue_entry_t) 0; - new_entry->links.next = (queue_entry_t) 0; - new_entry->name = name_port; - new_entry->pager_object = pager_object; - - mutex_lock(&pager_mux_hash_lock); - queue_enter((&pager_mux_hashtable[pager_mux_hash(name_port)]), - new_entry, pager_mux_entry_t, links); - mutex_unlock(&pager_mux_hash_lock); -} - -void -pager_mux_hash_delete( - ipc_port_t name_port) -{ - register queue_t bucket; - register pager_mux_entry_t entry; - - bucket = &pager_mux_hashtable[pager_mux_hash(name_port)]; - - mutex_lock(&pager_mux_hash_lock); - for (entry = (pager_mux_entry_t)queue_first(bucket); - !queue_end(bucket, &entry->links); - entry = (pager_mux_entry_t)queue_next(&entry->links)) { - if (entry->name == name_port) { - queue_remove(bucket, entry, pager_mux_entry_t, links); - zfree(pager_mux_hash_zone, (vm_offset_t)entry); - break; - } - } - mutex_unlock(&pager_mux_hash_lock); + printf("mig_table_max_displ = %d\n", mig_table_max_displ); } @@ -609,12 +495,7 @@ ipc_kobject_destroy( mach_destroy_memory_entry(port); break; - case IKOT_UPL: - mach_destroy_upl(port); - break; - default: /* XXX (bogon) */ - vm_object_destroy(port); break; } } @@ -646,32 +527,19 @@ ipc_kobject_notify( ipc_port_destroy(port); /* releases lock */ return TRUE; } - paging_subsystem_object = pager_mux_hash_lookup( - (ipc_port_t)request_header->msgh_remote_port); - if(paging_subsystem_object == (rpc_subsystem_t) - &dp_memory_object_subsystem) { - default_pager_no_senders( - (ipc_port_t)request_header->msgh_remote_port, - seqno, - (mach_port_mscount_t) - ((mach_no_senders_notification_t *) - request_header)->not_count); - (ipc_port_t)reply_header->msgh_remote_port - = MACH_PORT_NULL; - return TRUE; - } - if(paging_subsystem_object == (rpc_subsystem_t) - &vnode_pager_workaround) { - vnode_pager_no_senders( - (ipc_port_t)request_header->msgh_remote_port, - (mach_port_mscount_t) - ((mach_no_senders_notification_t *) - request_header)->not_count); - (ipc_port_t)reply_header->msgh_remote_port - = MACH_PORT_NULL; - return TRUE; + if (ip_kotype(port) == IKOT_UPL) { + upl_no_senders( + (ipc_port_t)request_header->msgh_remote_port, + (mach_port_mscount_t) + ((mach_no_senders_notification_t *) + request_header)->not_count); + (ipc_port_t)reply_header->msgh_remote_port + = MACH_PORT_NULL; + return TRUE; } + break; + case MACH_NOTIFY_PORT_DELETED: case MACH_NOTIFY_PORT_DESTROYED: case MACH_NOTIFY_SEND_ONCE: diff --git a/osfmk/kern/ipc_kobject.h b/osfmk/kern/ipc_kobject.h index d2a517c55..39365d613 100644 --- a/osfmk/kern/ipc_kobject.h +++ b/osfmk/kern/ipc_kobject.h @@ -85,8 +85,8 @@ typedef natural_t ipc_kobject_type_t; #define IKOT_PSET_NAME 7 #define IKOT_TIMER 8 #define IKOT_PAGING_REQUEST 9 -#define IKOT_DEVICE 10 -#define IKOT_XMM_OBJECT 11 +#define IKOT_MIG 10 +#define IKOT_MEMORY_OBJECT 11 #define IKOT_XMM_PAGER 12 #define IKOT_XMM_KERNEL 13 #define IKOT_XMM_REPLY 14 @@ -120,11 +120,6 @@ typedef natural_t ipc_kobject_type_t; * of entry lists for copyin of out of line memory. */ -#define ipc_kobject_vm_page_list(ikot) \ - ((ikot) == IKOT_PAGING_REQUEST || (ikot) == IKOT_DEVICE) - -#define ipc_kobject_vm_page_steal(ikot) ((ikot) == IKOT_PAGING_REQUEST) - /* Initialize kernel server dispatch table */ extern void mig_init(void); diff --git a/osfmk/kern/ipc_mig.c b/osfmk/kern/ipc_mig.c index 928832f10..2b22fcf1f 100644 --- a/osfmk/kern/ipc_mig.c +++ b/osfmk/kern/ipc_mig.c @@ -50,15 +50,16 @@ /* */ -#include <norma_vm.h> -#include <mach_rt.h> +#include <libkern/OSTypes.h> +#include <libkern/OSAtomic.h> #include <mach/boolean.h> #include <mach/port.h> -#include <mach/thread_status.h> +#include <mach/mig.h> #include <mach/mig_errors.h> #include <mach/mach_types.h> #include <mach/mach_traps.h> + #include <kern/ast.h> #include <kern/ipc_tt.h> #include <kern/ipc_mig.h> @@ -66,7 +67,6 @@ #include <kern/thread.h> #include <kern/ipc_kobject.h> #include <kern/misc_protos.h> -#include <vm/vm_map.h> #include <ipc/port.h> #include <ipc/ipc_kmsg.h> #include <ipc/ipc_entry.h> @@ -75,10 +75,7 @@ #include <ipc/ipc_space.h> #include <ipc/ipc_port.h> #include <ipc/ipc_pset.h> - -/* Default (zeroed) template for qos */ - -static mach_port_qos_t qos_template; +#include <vm/vm_map.h> /* * Routine: mach_msg_send_from_kernel @@ -474,3 +471,248 @@ mig_user_deallocate( kfree((vm_offset_t)data, size); } +/* + * Routine: mig_object_init + * Purpose: + * Initialize the base class portion of a MIG object. We + * will lazy init the port, so just clear it for now. + */ +kern_return_t +mig_object_init( + mig_object_t mig_object, + const IMIGObject *interface) +{ + assert(mig_object != MIG_OBJECT_NULL); + mig_object->pVtbl = (IMIGObjectVtbl *)interface; + mig_object->port = MACH_PORT_NULL; +} + +/* + * Routine: mig_object_destroy + * Purpose: + * The object is being freed. This call lets us clean + * up any state we have have built up over the object's + * lifetime. + * Conditions: + * Since notifications and the port hold references on + * on the object, neither can exist when this is called. + * This is a good place to assert() that condition. + */ +void +mig_object_destroy( + mig_object_t mig_object) +{ + assert(mig_object->port == MACH_PORT_NULL); + return; +} + +/* + * Routine: mig_object_reference + * Purpose: + * Pure virtual helper to invoke the MIG object's AddRef + * method. + * Conditions: + * MIG object port may be locked. + */ +void +mig_object_reference( + mig_object_t mig_object) +{ + assert(mig_object != MIG_OBJECT_NULL); + mig_object->pVtbl->AddRef((IMIGObject *)mig_object); +} + +/* + * Routine: mig_object_deallocate + * Purpose: + * Pure virtual helper to invoke the MIG object's Release + * method. + * Conditions: + * Nothing locked. + */ +void +mig_object_deallocate( + mig_object_t mig_object) +{ + assert(mig_object != MIG_OBJECT_NULL); + mig_object->pVtbl->Release((IMIGObject *)mig_object); +} + +/* + * Routine: convert_mig_object_to_port [interface] + * Purpose: + * Base implementation of MIG outtrans routine to convert from + * a mig object reference to a new send right on the object's + * port. The object reference is consumed. + * Returns: + * IP_NULL - Null MIG object supplied + * Otherwise, a newly made send right for the port + * Conditions: + * Nothing locked. + */ +ipc_port_t +convert_mig_object_to_port( + mig_object_t mig_object) +{ + ipc_port_t port; + boolean_t deallocate = TRUE; + + if (mig_object == MIG_OBJECT_NULL) + return IP_NULL; + + port = mig_object->port; + while ((port == IP_NULL) || + ((port = ipc_port_make_send(port)) == IP_NULL)) { + ipc_port_t previous; + + /* + * Either the port was never set up, or it was just + * deallocated out from under us by the no-senders + * processing. In either case, we must: + * Attempt to make one + * Arrange for no senders + * Try to atomically register it with the object + * Destroy it if we are raced. + */ + port = ipc_port_alloc_kernel(); + ip_lock(port); + ipc_kobject_set_atomically(port, + (ipc_kobject_t) mig_object, + IKOT_MIG); + + /* make a sonce right for the notification */ + port->ip_sorights++; + ip_reference(port); + + ipc_port_nsrequest(port, 1, port, &previous); + /* port unlocked */ + + assert(previous == IP_NULL); + + if (OSCompareAndSwap((UInt32)IP_NULL, + (UInt32)port, + (UInt32 *)&mig_object->port)) { + deallocate = FALSE; + } else { + ipc_port_dealloc_kernel(port); + port = mig_object->port; + } + } + + if (deallocate) + mig_object->pVtbl->Release((IMIGObject *)mig_object); + + return (port); +} + + +/* + * Routine: convert_port_to_mig_object [interface] + * Purpose: + * Base implementation of MIG intrans routine to convert from + * an incoming port reference to a new reference on the + * underlying object. A new reference must be created, because + * the port's reference could go away asynchronously. + * Returns: + * NULL - Not an active MIG object port or iid not supported + * Otherwise, a reference to the underlying MIG interface + * Conditions: + * Nothing locked. + */ +mig_object_t +convert_port_to_mig_object( + ipc_port_t port, + const MIGIID *iid) +{ + mig_object_t mig_object; + void *ppv; + + if (!IP_VALID(port)) + return NULL; + + ip_lock(port); + if (!ip_active(port) || (ip_kotype(port) != IKOT_MIG)) { + ip_unlock(port); + return NULL; + } + + /* + * Our port points to some MIG object interface. Now + * query it to get a reference to the desired interface. + */ + ppv = NULL; + mig_object = (mig_object_t)port->ip_kobject; + mig_object->pVtbl->QueryInterface((IMIGObject *)mig_object, iid, &ppv); + ip_unlock(port); + return (mig_object_t)ppv; +} + +/* + * Routine: mig_object_no_senders [interface] + * Purpose: + * Base implementation of a no-senders notification handler + * for MIG objects. If there truly are no more senders, must + * destroy the port and drop its reference on the object. + * Returns: + * TRUE - port deallocate and reference dropped + * FALSE - more senders arrived, re-registered for notification + * Conditions: + * Nothing locked. + */ + +boolean_t +mig_object_no_senders( + ipc_port_t port, + mach_port_mscount_t mscount) +{ + mig_object_t mig_object; + + ip_lock(port); + if (port->ip_mscount > mscount) { + ipc_port_t previous; + + /* + * Somebody created new send rights while the + * notification was in-flight. Just create a + * new send-once right and re-register with + * the new (higher) mscount threshold. + */ + /* make a sonce right for the notification */ + port->ip_sorights++; + ip_reference(port); + ipc_port_nsrequest(port, mscount, port, &previous); + /* port unlocked */ + + assert(previous == IP_NULL); + return (FALSE); + } + + /* + * Clear the port pointer while we have it locked. + */ + mig_object = (mig_object_t)port->ip_kobject; + mig_object->port = IP_NULL; + + /* + * Bring the sequence number and mscount in + * line with ipc_port_destroy assertion. + */ + port->ip_mscount = 0; + port->ip_messages.imq_seqno = 0; + ipc_port_destroy(port); /* releases lock */ + + /* + * Release the port's reference on the object. + */ + mig_object->pVtbl->Release((IMIGObject *)mig_object); + return (TRUE); +} + +/* + * Kernel implementation of the notification chain for MIG object + * is kept separate from the actual objects, since there are expected + * to be much fewer of them than actual objects. + * + * The implementation of this part of MIG objects is coming + * "Real Soon Now"(TM). + */ diff --git a/osfmk/kern/ipc_mig.h b/osfmk/kern/ipc_mig.h index 2759aa5e6..72a7afa13 100644 --- a/osfmk/kern/ipc_mig.h +++ b/osfmk/kern/ipc_mig.h @@ -26,6 +26,7 @@ #ifndef _IPC_MIG_H_ #define _IPC_MIG_H_ +#include <mach/mig.h> #include <mach/message.h> #include <sys/kdebug.h> @@ -125,4 +126,30 @@ extern mach_msg_return_t mach_msg_rpc_from_kernel( extern void mach_msg_receive_continue(void); +/* + * Kernel implementation of the MIG object base class + * + * Conforms to the MIGObjectInterface defined in <mach/mig.h> + * Ports are automatically allocated for the duration of outstanding + * cross-task references and then released. + */ + +typedef struct mig_object { + IMIGObjectVtbl *pVtbl; /* our interface def */ + mach_port_t port; /* our port pointer */ +} mig_object_data_t; + + +/* + * MIG notify base class definition + * These are chained off the mig object to which the are registered. + * When that object triggers a notification delivery, we walk this + * chain and deliver the appropriate notification. + */ +typedef struct mig_notify_object { + IMIGNotifyObjectVtbl *pVtbl; /* our interface def */ + mach_port_t port; /* our port pointer */ +} mig_notify_object_data_t; + + #endif /* _IPC_MIG_H_ */ diff --git a/osfmk/kern/ipc_tt.c b/osfmk/kern/ipc_tt.c index a32975e15..4fc95a8bc 100644 --- a/osfmk/kern/ipc_tt.c +++ b/osfmk/kern/ipc_tt.c @@ -881,6 +881,21 @@ convert_port_to_upl( return upl; } +mach_port_t +convert_upl_to_port( + upl_t upl) +{ + return MACH_PORT_NULL; +} + +__private_extern__ void +upl_no_senders( + upl_t upl, + mach_port_mscount_t mscount) +{ + return; +} + /* * Routine: convert_port_entry_to_map * Purpose: diff --git a/osfmk/kern/ipc_tt.h b/osfmk/kern/ipc_tt.h index c34731aed..ded87c88c 100644 --- a/osfmk/kern/ipc_tt.h +++ b/osfmk/kern/ipc_tt.h @@ -150,6 +150,9 @@ extern ipc_port_t convert_task_to_port( /* Convert from a thread to a port */ extern ipc_port_t convert_act_to_port( thread_act_t ); +/* Convert from a upl to a port */ +extern ipc_port_t convert_upl_to_port( upl_t ); + /* Deallocate a space ref produced by convert_port_to_space */ extern void space_deallocate( ipc_space_t space); diff --git a/osfmk/kern/kalloc.c b/osfmk/kern/kalloc.c index 3fa65de18..a67c71d14 100644 --- a/osfmk/kern/kalloc.c +++ b/osfmk/kern/kalloc.c @@ -231,7 +231,7 @@ zone_t kalloc_zone(vm_size_t); #endif vm_map_t kalloc_map; -vm_size_t kalloc_map_size = 8 * 1024 * 1024; +vm_size_t kalloc_map_size = 16 * 1024 * 1024; vm_size_t kalloc_max; vm_size_t kalloc_max_prerounded; diff --git a/osfmk/kern/kern_types.h b/osfmk/kern/kern_types.h index 44d86bd49..8d0ab03d2 100644 --- a/osfmk/kern/kern_types.h +++ b/osfmk/kern/kern_types.h @@ -28,6 +28,8 @@ #ifdef KERNEL_PRIVATE +#include <stdint.h> + #include <mach/machine/vm_types.h> #include <ipc/ipc_types.h> @@ -52,7 +54,8 @@ struct ledger ; struct alarm ; struct clock ; struct zone ; -struct wait_queue ; +struct wait_queue_sub ; +struct wait_queue_link; #else /* MACH_KERNEL_PRIVATE */ @@ -61,6 +64,8 @@ typedef struct clock *clock_t; /* Internal use only */ #endif /* MACH_KERNEL_PRIVATE */ +typedef struct mig_object *mig_object_t; +typedef struct mig_notify *mig_notify_t; typedef struct thread_shuttle *thread_t; typedef struct thread_shuttle *thread_shuttle_t; typedef struct task *task_t; @@ -77,6 +82,8 @@ typedef struct clock *clock_serv_t; typedef struct clock *clock_ctrl_t; typedef struct zone *zone_t; typedef struct wait_queue *wait_queue_t; +typedef struct wait_queue_sub *wait_queue_sub_t; +typedef struct wait_queue_link *wait_queue_link_t; typedef host_t host_priv_t; typedef host_t host_security_t; @@ -87,10 +94,13 @@ typedef void *event_t; /* wait event */ typedef void (*continuation_t)(void); /* continuation */ #define ZONE_NULL ((zone_t) 0) -#define IKO_NULL ((ipc_kobject_t) 0) + +#define NO_EVENT ((event_t) 0) #define WAIT_QUEUE_NULL ((wait_queue_t) 0) -#define NO_EVENT ((event_t)0) +#define IKO_NULL ((ipc_kobject_t) 0) +#define MIG_OBJECT_NULL ((mig_object_t) 0) +#define MIG_NOTIFY_NULL ((mig_notify_t) 0) #endif /* KERNEL_PRIVATE */ diff --git a/osfmk/kern/kmod.c b/osfmk/kern/kmod.c index 406028fd2..4aa0f1037 100644 --- a/osfmk/kern/kmod.c +++ b/osfmk/kern/kmod.c @@ -73,7 +73,7 @@ kmod_lookupbyid(kmod_t id) } kmod_info_t * -kmod_lookupbyname(char * name) +kmod_lookupbyname(const char * name) { kmod_info_t *k = 0; @@ -211,8 +211,10 @@ kmod_create_internal(kmod_info_t *info, kmod_t *id) simple_unlock(&kmod_lock); +#if DEBUG printf("kmod_create: %s (id %d), %d pages loaded at 0x%x, header size 0x%x\n", info->name, info->id, info->size / PAGE_SIZE, info->address, info->hdr_size); +#endif DEBUG return KERN_SUCCESS; } @@ -232,6 +234,13 @@ kmod_create_fake(char *name, char *version) { kmod_info_t *info; + if (!name || ! version || + (1 + strlen(name) > KMOD_MAX_NAME) || + (1 + strlen(version) > KMOD_MAX_NAME)) { + + return KERN_INVALID_ARGUMENT; + } + info = (kmod_info_t *)kalloc(sizeof(kmod_info_t)); if (!info) { return KERN_RESOURCE_SHORTAGE; @@ -239,8 +248,8 @@ kmod_create_fake(char *name, char *version) // make de fake info->info_version = KMOD_INFO_VERSION; - bcopy(name, info->name, KMOD_MAX_NAME); - bcopy(version, info->version, KMOD_MAX_NAME); + bcopy(name, info->name, 1 + strlen(name)); + bcopy(version, info->version, 1 + strlen(version)); //NIK fixed this part info->reference_count = 1; // keep it from unloading, starting, stopping info->reference_list = 0; info->address = info->size = info->hdr_size = 0; @@ -298,8 +307,10 @@ kmod_destroy_internal(kmod_t id) kfree((vm_offset_t)t, sizeof(struct kmod_reference)); } +#if DEBUG printf("kmod_destroy: %s (id %d), deallocating %d pages starting at 0x%x\n", k->name, k->id, k->size / PAGE_SIZE, k->address); +#endif DEBUG rc = vm_map_unwire(kernel_map, k->address + k->hdr_size, k->address + k->size, FALSE); @@ -717,7 +728,7 @@ kmod_dump(vm_offset_t *addr, unsigned int cnt) while (k) { // XXX - validate page(s) that k points to if(pmap_extract(kernel_pmap, (vm_offset_t)k) == 0) { /* Exit loop if page not mapped */ - printf("kmod scan stopped due to missing page: %08X\n", k); + printf(" kmod scan stopped due to missing page: %08X\n", k); break; } if ((*addr >= k->address) && (*addr < (k->address + k->size))) { @@ -731,25 +742,24 @@ kmod_dump(vm_offset_t *addr, unsigned int cnt) } if (!found_one) return; - printf("kernel modules in backtrace: "); + printf(" Kernel loadable modules in backtrace:\n"); k = kmod; while (k) { if(pmap_extract(kernel_pmap, (vm_offset_t)k) == 0) { /* Exit loop if page not mapped */ - printf("kmod scan stopped due to missing page: %08X\n", k); + printf(" kmod scan stopped due to missing page: %08X\n", k); break; } if (k->info_version == IS_IN_BACKTRACE) { - printf("%s(%s)@0x%x ", k->name, k->version, k->address); + printf(" %s(%s)@0x%x\n", k->name, k->version, k->address); } k = k->next; } - printf("\n"); // look for dependencies k = kmod; found_one = 0; while (k) { if(pmap_extract(kernel_pmap, (vm_offset_t)k) == 0) { /* Exit loop if page not mapped */ - printf("kmod dependency scan stopped due to missing page: %08X\n", k); + printf(" kmod dependency scan stopped due to missing page: %08X\n", k); break; } if (k->info_version == IS_IN_BACKTRACE) { @@ -757,7 +767,7 @@ kmod_dump(vm_offset_t *addr, unsigned int cnt) while (r) { // XXX - validate page(s) that r and r->info point to if(pmap_extract(kernel_pmap, (vm_offset_t)r) == 0) { /* Exit loop if page not mapped */ - printf("kmod validation scan stopped due to missing page: %08X\n", r); + printf(" kmod validation scan stopped due to missing page: %08X\n", r); break; } if (r->info->info_version != IS_IN_BACKTRACE) { @@ -771,26 +781,25 @@ kmod_dump(vm_offset_t *addr, unsigned int cnt) } if (!found_one) goto cleanup; - printf("kernel module dependencies: "); + printf(" Kernel loadable module dependencies:\n"); k = kmod; while (k) { if(pmap_extract(kernel_pmap, (vm_offset_t)k) == 0) { /* Exit loop if page not mapped */ - printf("kmod dependency print stopped due to missing page: %08X\n", k); + printf(" kmod dependency print stopped due to missing page: %08X\n", k); break; } if (k->info_version == IS_A_DEPENDENCY) { - printf("%s(%s)@0x%x ", k->name, k->version, k->address); + printf(" %s(%s)@0x%x\n", k->name, k->version, k->address); } k = k->next; } - printf("\n"); cleanup: // in case we double panic k = kmod; while (k) { if(pmap_extract(kernel_pmap, (vm_offset_t)k) == 0) { /* Exit loop if page not mapped */ - printf("kmod dump cleanup stopped due to missing page: %08X\n", k); + printf(" kmod dump cleanup stopped due to missing page: %08X\n", k); break; } k->info_version = KMOD_INFO_VERSION; diff --git a/osfmk/kern/lock.h b/osfmk/kern/lock.h index 65cd1f18f..e1143bf86 100644 --- a/osfmk/kern/lock.h +++ b/osfmk/kern/lock.h @@ -150,32 +150,28 @@ typedef struct { #define decl_mutex_data(class,name) class mutex_t name; #define mutex_addr(m) (&(m)) -#if MACH_LDEBUG -#define mutex_held(m) (hw_lock_held(&((m)->locked)) && \ - ((m)->thread == (int)current_thread())) -#else /* MACH_LDEBUG */ -#define mutex_held(m) hw_lock_held(&((m)->locked)) -#endif /* MACH_LDEBUG */ +extern void mutex_init (mutex_t*, etap_event_t); +extern void mutex_lock_wait (mutex_t*); +extern void mutex_unlock_wakeup (mutex_t*); +extern void interlock_unlock (hw_lock_t); #else /* MACH_KERNEL_PRIVATE */ typedef struct __mutex__ mutex_t; -extern boolean_t mutex_held(mutex_t*); + +/* going away */ +extern void _mutex_lock (mutex_t*); +extern boolean_t _mutex_try (mutex_t*); #endif /* !MACH_KERNEL_PRIVATE */ extern mutex_t *mutex_alloc (etap_event_t); extern void mutex_free (mutex_t*); - -extern void mutex_init (mutex_t*, etap_event_t); -extern void _mutex_lock (mutex_t*); +extern void mutex_lock (mutex_t*); extern void mutex_unlock (mutex_t*); -extern boolean_t _mutex_try (mutex_t*); +extern boolean_t mutex_try (mutex_t*); -extern void mutex_lock_wait (mutex_t*); -extern void mutex_unlock_wakeup (mutex_t*); extern void mutex_pause (void); -extern void interlock_unlock (hw_lock_t); /* * The general lock structure. Provides for multiple readers, diff --git a/osfmk/kern/mach_clock.c b/osfmk/kern/mach_clock.c index 09cba548c..b7c7d8835 100644 --- a/osfmk/kern/mach_clock.c +++ b/osfmk/kern/mach_clock.c @@ -133,7 +133,6 @@ hertz_tick( pc++; #endif /* lint */ - mp_disable_preemption(); my_cpu = cpu_number(); /* @@ -142,10 +141,8 @@ hertz_tick( * especially when debugging, to wind up here with * no thread to bill against. So ignore the tick. */ - if (thread == THREAD_NULL) { - mp_enable_preemption(); + if (thread == THREAD_NULL) return; - } #if MACH_PROF inkernel = !usermode && (pc < (unsigned int)ETEXT); @@ -211,7 +208,6 @@ hertz_tick( } machine_slot[my_cpu].cpu_ticks[state]++; - thread_quantum_update(my_cpu, thread, 1, state); /* * Hertz processing performed by the master-cpu @@ -260,5 +256,4 @@ hertz_tick( profile(pc, kernel_task->profil_buffer); } #endif /* MACH_PROF */ - mp_enable_preemption(); } diff --git a/osfmk/kern/mach_factor.c b/osfmk/kern/mach_factor.c index eca59d7c6..14eba5e2b 100644 --- a/osfmk/kern/mach_factor.c +++ b/osfmk/kern/mach_factor.c @@ -76,11 +76,16 @@ integer_t mach_factor[3] = {0, 0, 0}; /* * Values are scaled by LOAD_SCALE, defined in processor_info.h */ +#define base(n) ((n) << SCHED_TICK_SHIFT) +#define frac(n) (((base(n) - 1) * LOAD_SCALE) / base(n)) + static long fract[3] = { - 800, /* (4.0/5.0) 5 second average */ - 966, /* (29.0/30.0) 30 second average */ - 983, /* (59.0/60.) 1 minute average */ + frac(5), /* 5 second average */ + frac(30), /* 30 second average */ + frac(60), /* 1 minute average */ }; +#undef base +#undef frac void compute_mach_factor(void) diff --git a/osfmk/kern/machine.c b/osfmk/kern/machine.c index 35dcb1522..b1a1ee73a 100644 --- a/osfmk/kern/machine.c +++ b/osfmk/kern/machine.c @@ -80,8 +80,7 @@ #include <kern/thread_swap.h> #include <kern/misc_protos.h> -#include <kern/sf.h> -#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ +#include <kern/mk_sp.h> /* * Exported variables: @@ -400,7 +399,6 @@ processor_doaction( if (pset->processor_count == 1) { thread_t thread; - sched_policy_t *policy; extern void start_cpu_thread(void); simple_unlock(&pset->processors_lock); @@ -408,16 +406,16 @@ processor_doaction( /* * Create the thread, and point it at the routine. */ - thread = kernel_thread_with_priority(kernel_task, MAXPRI_KERNBAND, - start_cpu_thread, FALSE); + thread = kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL, + start_cpu_thread, TRUE, FALSE); disable_preemption(); s = splsched(); thread_lock(thread); thread->state |= TH_RUN; - policy = &sched_policy[thread->policy]; - (void)policy->sp_ops.sp_thread_unblock(policy, thread); + _mk_sp_thread_unblock(thread); (void)rem_runq(thread); machine_wake_thread = thread; thread_unlock(thread); @@ -464,6 +462,7 @@ processor_doshutdown( { register int cpu = processor->slot_num; + timer_call_cancel(&processor->quantum_timer); thread_dispatch(current_thread()); timer_switch(&kernel_timer[cpu]); diff --git a/osfmk/kern/mk_sp.c b/osfmk/kern/mk_sp.c index 2ba137750..18c326ab0 100644 --- a/osfmk/kern/mk_sp.c +++ b/osfmk/kern/mk_sp.c @@ -54,7 +54,6 @@ *** into this file from `kern/syscall_subr.c.' ***/ -#include <kern/sf.h> #include <kern/mk_sp.h> #include <kern/misc_protos.h> #include <kern/spl.h> @@ -64,11 +63,6 @@ #include <kern/thread.h> #include <mach/mach_host_server.h> -/* Forwards */ -void _mk_sp_thread_depress_priority( - sf_object_t policy, - mach_msg_timeout_t depress_time); - /*** *** ??? The next two files supply the prototypes for `thread_set_policy()' *** and `thread_policy.' These routines cannot stay here if they are @@ -76,306 +70,113 @@ void _mk_sp_thread_depress_priority( ***/ #include <mach/thread_act_server.h> #include <mach/host_priv_server.h> +#include <sys/kdebug.h> -/* - * Vector containing standard scheduling policy operations - */ -sp_ops_t mk_sp_ops = { - _mk_sp_thread_update_mpri, - _mk_sp_thread_unblock, - _mk_sp_thread_done, - _mk_sp_thread_begin, - _mk_sp_thread_dispatch, - _mk_sp_thread_attach, - _mk_sp_thread_detach, - _mk_sp_thread_processor, - _mk_sp_thread_processor_set, - _mk_sp_thread_setup, - _mk_sp_swtch_pri, - _mk_sp_thread_switch, - _mk_sp_thread_depress_abort, - _mk_sp_thread_depress_timeout, - _mk_sp_thread_runnable, -}; - -/* Forwards */ -kern_return_t thread_policy_common( - thread_t thread, - int policy, - int data, - processor_set_t pset); - -/* - * Standard operations for MK Scheduling Policy - */ - -sf_return_t -_mk_sp_thread_update_mpri( - sf_object_t policy, - thread_t thread) -{ - if (thread->sched_stamp != sched_tick) - update_priority(thread); - - return(SF_SUCCESS); -} - -sf_return_t +void _mk_sp_thread_unblock( - sf_object_t policy, thread_t thread) { - /* indicate thread is now runnable */ - thread->sp_state = MK_SP_RUNNABLE; - - /* place thread at end of appropriate run queue */ - if (!(thread->state&TH_IDLE)) + if (!(thread->state & TH_IDLE)) thread_setrun(thread, TRUE, TAIL_Q); - return(SF_SUCCESS); + thread->current_quantum = 0; + thread->metered_computation = 0; + thread->reason = AST_NONE; + + KERNEL_DEBUG_CONSTANT( + MACHDBG_CODE(DBG_MACH_SCHED,MACH_MAKE_RUNNABLE) | DBG_FUNC_NONE, + (int)thread, (int)thread->sched_pri, 0, 0, 0); } -sf_return_t +void _mk_sp_thread_done( - sf_object_t policy, - thread_t old_thread) + thread_t thread) { processor_t myprocessor = cpu_to_processor(cpu_number()); /* * A running thread is being taken off a processor: - * - * - update the thread's `unconsumed_quantum' field - * - update the thread's state field */ + clock_get_uptime(&myprocessor->last_dispatch); + if (!(thread->state & TH_IDLE)) { + if ( first_quantum(myprocessor) && + myprocessor->quantum_end > myprocessor->last_dispatch ) + thread->current_quantum = + (myprocessor->quantum_end - myprocessor->last_dispatch); + else + thread->current_quantum = 0; - old_thread->unconsumed_quantum = myprocessor->quantum; - - if (old_thread->state & TH_WAIT) - old_thread->sp_state = MK_SP_BLOCKED; + if (!(thread->sched_mode & TH_MODE_REALTIME)) { + if (thread->current_quantum < min_std_quantum) { + thread->reason |= AST_QUANTUM; + thread->current_quantum += std_quantum; + } + } + else + if (thread->current_quantum == 0) + thread->reason |= AST_QUANTUM; - return(SF_SUCCESS); + thread->metered_computation += + (myprocessor->last_dispatch - thread->computation_epoch); + } } -sf_return_t +void _mk_sp_thread_begin( - sf_object_t policy, thread_t thread) { - processor_t myprocessor = cpu_to_processor(cpu_number()); - processor_set_t pset; - pset = myprocessor->processor_set; /* - * The designated thread is about to begin execution: - * - * - update the processor's `quantum' field + * The designated thread is beginning execution: */ - /* check for legal thread state */ - assert(thread->sp_state == MK_SP_RUNNABLE); - - if (thread->policy & (POLICY_RR|POLICY_FIFO)) - myprocessor->quantum = thread->unconsumed_quantum; - else - myprocessor->quantum = (thread->bound_processor ? - min_quantum : pset->set_quantum); + if (!(thread->state & TH_IDLE)) { + if (thread->current_quantum == 0) + thread->current_quantum = + (thread->sched_mode & TH_MODE_REALTIME)? + thread->realtime.computation: std_quantum; + + myprocessor->quantum_end = + (myprocessor->last_dispatch + thread->current_quantum); + timer_call_enter1(&myprocessor->quantum_timer, + thread, myprocessor->quantum_end); + + myprocessor->slice_quanta = + (thread->sched_mode & TH_MODE_TIMESHARE)? + myprocessor->processor_set->set_quanta: 1; + + thread->computation_epoch = myprocessor->last_dispatch; + } + else { + timer_call_cancel(&myprocessor->quantum_timer); - return(SF_SUCCESS); + myprocessor->slice_quanta = 1; + } } -sf_return_t +void _mk_sp_thread_dispatch( - sf_object_t policy, thread_t old_thread) { - if (old_thread->sp_state & MK_SP_RUNNABLE) { - if (old_thread->reason & AST_QUANTUM) { - thread_setrun(old_thread, FALSE, TAIL_Q); - old_thread->unconsumed_quantum = min_quantum; - } - else - thread_setrun(old_thread, FALSE, HEAD_Q); - } - - if (old_thread->sp_state & MK_SP_ATTACHED) { - /* indicate thread is now runnable */ - old_thread->sp_state = MK_SP_RUNNABLE; - - /* place thread at end of appropriate run queue */ + if (old_thread->reason & AST_QUANTUM) thread_setrun(old_thread, FALSE, TAIL_Q); - } - - return(SF_SUCCESS); -} - -/* - * Thread must already be locked. - */ -sf_return_t -_mk_sp_thread_attach( - sf_object_t policy, - thread_t thread) -{ - thread->sp_state = MK_SP_ATTACHED; - - thread->max_priority = thread->priority = BASEPRI_DEFAULT; - thread->depress_priority = -1; - - thread->cpu_usage = 0; - thread->sched_usage = 0; - thread->sched_stamp = 0; - - thread->unconsumed_quantum = min_quantum; - - /* Reflect this policy in thread data structure */ - thread->policy = policy->policy_id; - - return(SF_SUCCESS); -} - -/* - * Check to make sure that thread is removed from run - * queues and active execution; and clear pending - * priority depression. - * - * Thread must already be locked. - */ -sf_return_t -_mk_sp_thread_detach( - sf_object_t policy, - thread_t thread) -{ - struct run_queue *rq; - - assert(thread->policy == policy->policy_id); - - /* make sure that the thread is no longer on any run queue */ - if (thread->runq != RUN_QUEUE_NULL) { - rq = rem_runq(thread); - if (rq == RUN_QUEUE_NULL) { - panic("mk_sp_thread_detach: missed thread"); - } - } - - /* clear pending priority depression */ - - if (thread->depress_priority >= 0) { - thread->priority = thread->depress_priority; - thread->depress_priority = -1; - if (thread_call_cancel(&thread->depress_timer)) - thread_call_enter(&thread->depress_timer); - } - - /* clear the thread's policy field */ - thread->policy = POLICY_NULL; - - return(SF_SUCCESS); -} - -sf_return_t -_mk_sp_thread_processor( - sf_object_t policy, - thread_t *thread, - processor_t processor) -{ - return(SF_FAILURE); -} - -sf_return_t -_mk_sp_thread_processor_set( - sf_object_t policy, - thread_t thread, - processor_set_t processor_set) -{ - pset_add_thread(processor_set, thread); - - return(SF_SUCCESS); -} - -sf_return_t -_mk_sp_thread_setup( - sf_object_t policy, - thread_t thread) -{ - /* - * Determine thread's state. (It may be an "older" thread - * that has just been associated with this policy.) - */ - if (thread->state & TH_WAIT) - thread->sp_state = MK_SP_BLOCKED; - - /* recompute priority */ - thread->sched_stamp = sched_tick; - compute_priority(thread, TRUE); - - return(SF_SUCCESS); -} - -/* - * thread_priority_internal: - * - * Kernel-internal work function for thread_priority(). Called - * with thread "properly locked" to ensure synchrony with RPC - * (see act_lock_thread()). - */ -kern_return_t -thread_priority_internal( - thread_t thread, - int priority) -{ - kern_return_t result = KERN_SUCCESS; - spl_t s; - - s = splsched(); - thread_lock(thread); - - /* - * Check for violation of max priority - */ - if (priority > thread->max_priority) - priority = thread->max_priority; - - /* - * Set priorities. If a depression is in progress, - * change the priority to restore. - */ - if (thread->depress_priority >= 0) - thread->depress_priority = priority; - else { - thread->priority = priority; - compute_priority(thread, TRUE); - - /* - * If the current thread has changed its - * priority let the ast code decide whether - * a different thread should run. - */ - if (thread == current_thread()) - ast_on(AST_BLOCK); - } - - thread_unlock(thread); - splx(s); + else + thread_setrun(old_thread, FALSE, HEAD_Q); - return (result); + old_thread->reason = AST_NONE; } /* * thread_policy_common: * - * Set scheduling policy for thread. If pset == PROCESSOR_SET_NULL, - * policy will be checked to make sure it is enabled. + * Set scheduling policy & priority for thread. */ -kern_return_t +static kern_return_t thread_policy_common( thread_t thread, integer_t policy, - integer_t data, - processor_set_t pset) + integer_t priority) { - kern_return_t result = KERN_SUCCESS; - register int temp; spl_t s; if ( thread == THREAD_NULL || @@ -385,34 +186,63 @@ thread_policy_common( s = splsched(); thread_lock(thread); - /* - * Check if changing policy. - */ - if (policy != thread->policy) { - /* - * Changing policy. Check if new policy is allowed. - */ - if ( pset == PROCESSOR_SET_NULL && - (thread->processor_set->policies & policy) == 0 ) - result = KERN_FAILURE; - else { - if (pset != thread->processor_set) - result = KERN_FAILURE; - else { - /* - * Changing policy. Calculate new - * priority. - */ - thread->policy = policy; - compute_priority(thread, TRUE); - } - } + if ( !(thread->sched_mode & TH_MODE_REALTIME) && + !(thread->safe_mode & TH_MODE_REALTIME) ) { + if (!(thread->sched_mode & TH_MODE_FAILSAFE)) { + if (policy == POLICY_TIMESHARE) + thread->sched_mode |= TH_MODE_TIMESHARE; + else + thread->sched_mode &= ~TH_MODE_TIMESHARE; + } + else { + if (policy == POLICY_TIMESHARE) + thread->safe_mode |= TH_MODE_TIMESHARE; + else + thread->safe_mode &= ~TH_MODE_TIMESHARE; + } + + if (priority >= thread->max_priority) + priority = thread->max_priority - thread->task_priority; + else + if (priority >= MINPRI_KERNEL) + priority -= MINPRI_KERNEL; + else + if (priority >= MINPRI_SYSTEM) + priority -= MINPRI_SYSTEM; + else + priority -= BASEPRI_DEFAULT; + + priority += thread->task_priority; + + if (priority > thread->max_priority) + priority = thread->max_priority; + + thread->importance = priority - thread->task_priority; + + /* + * Set priorities. If a depression is in progress, + * change the priority to restore. + */ + if (thread->depress_priority >= 0) + thread->depress_priority = priority; + else { + thread->priority = priority; + compute_priority(thread, TRUE); + + /* + * If the current thread has changed its + * priority let the ast code decide whether + * a different thread should run. + */ + if (thread == current_thread()) + ast_on(AST_BLOCK); + } } thread_unlock(thread); splx(s); - return (result); + return (KERN_SUCCESS); } /* @@ -433,7 +263,7 @@ thread_set_policy( mach_msg_type_number_t limit_count) { thread_t thread; - int max, bas, dat, incr; + int max, bas; kern_return_t result = KERN_SUCCESS; if ( thr_act == THR_ACT_NULL || @@ -466,7 +296,6 @@ thread_set_policy( break; } - dat = rr_base->quantum; bas = rr_base->base_priority; max = rr_limit->max_priority; if (invalid_pri(bas) || invalid_pri(max)) { @@ -488,7 +317,6 @@ thread_set_policy( break; } - dat = 0; bas = fifo_base->base_priority; max = fifo_limit->max_priority; if (invalid_pri(bas) || invalid_pri(max)) { @@ -511,7 +339,6 @@ thread_set_policy( break; } - dat = 0; bas = ts_base->base_priority; max = ts_limit->max_priority; if (invalid_pri(bas) || invalid_pri(max)) { @@ -532,9 +359,7 @@ thread_set_policy( return(result); } - result = thread_priority_internal(thread, bas); - if (result == KERN_SUCCESS) - result = thread_policy_common(thread, policy, dat, pset); + result = thread_policy_common(thread, policy, bas); act_unlock_thread(thr_act); return(result); @@ -577,8 +402,8 @@ thread_policy( return(KERN_INVALID_ARGUMENT); } - if ( invalid_policy(policy) || - (pset->policies & policy) == 0 ) { + if ( invalid_policy(policy) || + ((POLICY_TIMESHARE | POLICY_RR | POLICY_FIFO) & policy) == 0 ) { act_unlock_thread(thr_act); return(KERN_INVALID_POLICY); @@ -815,7 +640,7 @@ compute_priority( { register int pri; - if (thread->policy == POLICY_TIMESHARE) { + if (thread->sched_mode & TH_MODE_TIMESHARE) { do_priority_computation(thread, pri); if (thread->depress_priority < 0) set_pri(thread, pri, resched); @@ -847,16 +672,6 @@ compute_my_priority( thread->sched_pri = pri; } -#if DEBUG -struct mk_sp_usage { - natural_t cpu_delta, sched_delta; - natural_t sched_tick, ticks; - natural_t cpu_usage, sched_usage, - aged_cpu, aged_sched; - thread_t thread; -} idled_info, loaded_info; -#endif - /* * update_priority * @@ -888,33 +703,9 @@ update_priority( thread->sched_usage = 0; } else { -#if DEBUG - struct mk_sp_usage *sp_usage; -#endif - thread->cpu_usage += thread->cpu_delta; thread->sched_usage += thread->sched_delta; -#if DEBUG - if (thread->state & TH_IDLE) - sp_usage = &idled_info; - else - if (thread == loaded_info.thread) - sp_usage = &loaded_info; - else - sp_usage = NULL; - - if (sp_usage != NULL) { - sp_usage->cpu_delta = thread->cpu_delta; - sp_usage->sched_delta = thread->sched_delta; - sp_usage->sched_tick = thread->sched_stamp; - sp_usage->ticks = ticks; - sp_usage->cpu_usage = thread->cpu_usage; - sp_usage->sched_usage = thread->sched_usage; - sp_usage->thread = thread; - } -#endif - shiftp = &wait_shift[ticks]; if (shiftp->shift2 > 0) { thread->cpu_usage = @@ -932,27 +723,51 @@ update_priority( (thread->sched_usage >> shiftp->shift1) - (thread->sched_usage >> -(shiftp->shift2)); } - -#if DEBUG - if (sp_usage != NULL) { - sp_usage->aged_cpu = thread->cpu_usage; - sp_usage->aged_sched = thread->sched_usage; - } -#endif } + thread->cpu_delta = 0; thread->sched_delta = 0; + if ( (thread->sched_mode & TH_MODE_FAILSAFE) && + thread->sched_stamp >= thread->safe_release ) { + if (!(thread->safe_mode & TH_MODE_TIMESHARE)) { + if (thread->safe_mode & TH_MODE_REALTIME) { + if (thread->depress_priority < 0) + thread->priority = BASEPRI_REALTIME; + else + thread->depress_priority = BASEPRI_REALTIME; + + thread->sched_mode |= TH_MODE_REALTIME; + } + + if ( thread->depress_priority < 0 && + thread->sched_pri != thread->priority ) { + run_queue_t runq; + + runq = rem_runq(thread); + thread->sched_pri = thread->priority; + if (runq != RUN_QUEUE_NULL) + thread_setrun(thread, TRUE, TAIL_Q); + } + + thread->sched_mode &= ~TH_MODE_TIMESHARE; + } + + thread->safe_mode = 0; + thread->sched_mode &= ~TH_MODE_FAILSAFE; + } + /* * Recompute priority if appropriate. */ - if ( thread->policy == POLICY_TIMESHARE && - thread->depress_priority < 0 ) { + if ( (thread->sched_mode & TH_MODE_TIMESHARE) && + thread->depress_priority < 0 ) { register int new_pri; - run_queue_t runq; do_priority_computation(thread, new_pri); if (new_pri != thread->sched_pri) { + run_queue_t runq; + runq = rem_runq(thread); thread->sched_pri = new_pri; if (runq != RUN_QUEUE_NULL) @@ -961,43 +776,6 @@ update_priority( } } -/* - * `mk_sp_swtch_pri()' attempts to context switch (logic in - * thread_block no-ops the context switch if nothing would happen). - * A boolean is returned that indicates whether there is anything - * else runnable. - * - * This boolean can be used by a thread waiting on a - * lock or condition: If FALSE is returned, the thread is justified - * in becoming a resource hog by continuing to spin because there's - * nothing else useful that the processor could do. If TRUE is - * returned, the thread should make one more check on the - * lock and then be a good citizen and really suspend. - */ - -void -_mk_sp_swtch_pri( - sf_object_t policy, - int pri) -{ - register thread_t self = current_thread(); - extern natural_t min_quantum_ms; - -#ifdef lint - pri++; -#endif /* lint */ - - /* - * XXX need to think about depression duration. - * XXX currently using min quantum. - */ - _mk_sp_thread_depress_priority(policy, min_quantum_ms); - - thread_block((void (*)(void)) 0); - - _mk_sp_thread_depress_abort(policy, self); -} - /* * thread_switch_continue: * @@ -1010,16 +788,18 @@ _mk_sp_swtch_pri( void _mk_sp_thread_switch_continue(void) { - thread_t self = current_thread(); - int wait_result = self->wait_result; - int option = self->saved.swtch.option; - sf_object_t policy = self->saved.swtch.policy; + register thread_t self = current_thread(); + int wait_result = self->wait_result; + int option = self->saved.swtch.option; if (option == SWITCH_OPTION_WAIT && wait_result != THREAD_TIMED_OUT) thread_cancel_timer(); - else if (option == SWITCH_OPTION_DEPRESS) - _mk_sp_thread_depress_abort(policy, self); + else + if (option == SWITCH_OPTION_DEPRESS) + _mk_sp_thread_depress_abort(self, FALSE); + thread_syscall_return(KERN_SUCCESS); + /*NOTREACHED*/ } /* @@ -1032,7 +812,6 @@ _mk_sp_thread_switch_continue(void) */ kern_return_t _mk_sp_thread_switch( - sf_object_t policy, thread_act_t hint_act, int option, mach_msg_timeout_t option_time) @@ -1064,12 +843,6 @@ _mk_sp_thread_switch( /* * Hah, got it!! */ - if (thread->policy & (POLICY_FIFO|POLICY_RR)) { - myprocessor = current_processor(); - - myprocessor->quantum = thread->unconsumed_quantum; - myprocessor->first_quantum = TRUE; - } thread_unlock(thread); act_unlock_thread(hint_act); @@ -1077,10 +850,10 @@ _mk_sp_thread_switch( if (option == SWITCH_OPTION_WAIT) assert_wait_timeout(option_time, THREAD_ABORTSAFE); - else if (option == SWITCH_OPTION_DEPRESS) - _mk_sp_thread_depress_priority(policy, option_time); + else + if (option == SWITCH_OPTION_DEPRESS) + _mk_sp_thread_depress_ms(option_time); - self->saved.swtch.policy = policy; self->saved.swtch.option = option; thread_run(self, _mk_sp_thread_switch_continue, thread); @@ -1110,15 +883,14 @@ _mk_sp_thread_switch( if ( option != SWITCH_OPTION_NONE || myprocessor->processor_set->runq.count > 0 || myprocessor->runq.count > 0 ) { - myprocessor->first_quantum = FALSE; mp_enable_preemption(); if (option == SWITCH_OPTION_WAIT) assert_wait_timeout(option_time, THREAD_ABORTSAFE); - else if (option == SWITCH_OPTION_DEPRESS) - _mk_sp_thread_depress_priority(policy, option_time); + else + if (option == SWITCH_OPTION_DEPRESS) + _mk_sp_thread_depress_ms(option_time); - self->saved.swtch.policy = policy; self->saved.swtch.option = option; thread_block(_mk_sp_thread_switch_continue); @@ -1129,89 +901,75 @@ _mk_sp_thread_switch( out: if (option == SWITCH_OPTION_WAIT) thread_cancel_timer(); - else if (option == SWITCH_OPTION_DEPRESS) - _mk_sp_thread_depress_abort(policy, self); + else + if (option == SWITCH_OPTION_DEPRESS) + _mk_sp_thread_depress_abort(self, FALSE); return (KERN_SUCCESS); } /* - * mk_sp_thread_depress_priority - * - * Depress thread's priority to lowest possible for specified period. - * Intended for use when thread wants a lock but doesn't know which - * other thread is holding it. As with thread_switch, fixed - * priority threads get exactly what they asked for. Users access - * this by the SWITCH_OPTION_DEPRESS option to thread_switch. A Time - * of zero will result in no timeout being scheduled. + * Depress thread's priority to lowest possible for the specified interval, + * with a value of zero resulting in no timeout being scheduled. */ void -_mk_sp_thread_depress_priority( - sf_object_t policy, - mach_msg_timeout_t interval) +_mk_sp_thread_depress_abstime( + uint64_t interval) { register thread_t self = current_thread(); - AbsoluteTime deadline; - boolean_t release = FALSE; + uint64_t deadline; spl_t s; s = splsched(); + wake_lock(self); thread_lock(self); - - if (self->policy == policy->policy_id) { - /* - * If we haven't already saved the priority to be restored - * (depress_priority), then save it. - */ - if (self->depress_priority < 0) - self->depress_priority = self->priority; - else if (thread_call_cancel(&self->depress_timer)) - release = TRUE; - + if (self->depress_priority < 0) { + self->depress_priority = self->priority; self->sched_pri = self->priority = DEPRESSPRI; + thread_unlock(self); if (interval != 0) { - clock_interval_to_deadline( - interval, 1000*NSEC_PER_USEC, &deadline); - thread_call_enter_delayed(&self->depress_timer, deadline); - if (!release) - self->ref_count++; - else - release = FALSE; + clock_absolutetime_interval_to_deadline(interval, &deadline); + if (!timer_call_enter(&self->depress_timer, deadline)) + self->depress_timer_active++; } } - - thread_unlock(self); + else + thread_unlock(self); + wake_unlock(self); splx(s); +} - if (release) - thread_deallocate(self); -} +void +_mk_sp_thread_depress_ms( + mach_msg_timeout_t interval) +{ + uint64_t abstime; + + clock_interval_to_absolutetime_interval( + interval, 1000*NSEC_PER_USEC, &abstime); + _mk_sp_thread_depress_abstime(abstime); +} /* - * mk_sp_thread_depress_timeout: - * - * Timeout routine for priority depression. + * Priority depression expiration. */ void -_mk_sp_thread_depress_timeout( - sf_object_t policy, - register thread_t thread) +thread_depress_expire( + timer_call_param_t p0, + timer_call_param_t p1) { - spl_t s; + thread_t thread = p0; + spl_t s; s = splsched(); - thread_lock(thread); - if (thread->policy == policy->policy_id) { - /* - * If we lose a race with mk_sp_thread_depress_abort, - * then depress_priority might be -1. - */ - if ( thread->depress_priority >= 0 && - !thread_call_is_delayed(&thread->depress_timer, NULL) ) { + wake_lock(thread); + if (--thread->depress_timer_active == 1) { + thread_lock(thread); + if (thread->depress_priority >= 0) { thread->priority = thread->depress_priority; thread->depress_priority = -1; - compute_priority(thread, FALSE); + compute_priority(thread, TRUE); } else if (thread->depress_priority == -2) { @@ -1223,58 +981,100 @@ _mk_sp_thread_depress_timeout( */ thread->depress_priority = -1; } + thread->sched_mode &= ~TH_MODE_POLLDEPRESS; + thread_unlock(thread); } - thread_unlock(thread); - splx(s); + else + if (thread->depress_timer_active == 0) + thread_wakeup_one(&thread->depress_timer_active); + wake_unlock(thread); + splx(s); } /* - * mk_sp_thread_depress_abort: - * * Prematurely abort priority depression if there is one. */ kern_return_t _mk_sp_thread_depress_abort( - sf_object_t policy, - register thread_t thread) + register thread_t thread, + boolean_t abortall) { - kern_return_t result = KERN_SUCCESS; - boolean_t release = FALSE; + kern_return_t result = KERN_NOT_DEPRESSED; spl_t s; s = splsched(); + wake_lock(thread); thread_lock(thread); - - if (thread->policy == policy->policy_id) { + if (abortall || !(thread->sched_mode & TH_MODE_POLLDEPRESS)) { if (thread->depress_priority >= 0) { - if (thread_call_cancel(&thread->depress_timer)) - release = TRUE; thread->priority = thread->depress_priority; thread->depress_priority = -1; - compute_priority(thread, FALSE); + compute_priority(thread, TRUE); + result = KERN_SUCCESS; } - else - result = KERN_NOT_DEPRESSED; - } - thread_unlock(thread); - splx(s); + thread->sched_mode &= ~TH_MODE_POLLDEPRESS; + thread_unlock(thread); - if (release) - thread_deallocate(thread); + if (timer_call_cancel(&thread->depress_timer)) + thread->depress_timer_active--; + } + else + thread_unlock(thread); + wake_unlock(thread); + splx(s); return (result); } -/* - * mk_sp_thread_runnable: - * - * Return TRUE iff policy believes thread is runnable - */ -boolean_t -_mk_sp_thread_runnable( - sf_object_t policy, - thread_t thread) +void +_mk_sp_thread_perhaps_yield( + thread_t self) { - return (thread->sp_state == MK_SP_RUNNABLE); + spl_t s; + + assert(self == current_thread()); + + s = splsched(); + thread_lock(self); + if (!(self->sched_mode & (TH_MODE_REALTIME|TH_MODE_TIMESHARE))) { + extern uint64_t max_poll_computation; + extern int sched_poll_yield_shift; + uint64_t abstime, total_computation; + + clock_get_uptime(&abstime); + total_computation = abstime - self->computation_epoch; + total_computation += self->metered_computation; + if (total_computation >= max_poll_computation) { + processor_t myprocessor; + + thread_unlock(self); + + wake_lock(self); + thread_lock(self); + if (self->depress_priority < 0) { + self->depress_priority = self->priority; + self->sched_pri = self->priority = DEPRESSPRI; + } + self->computation_epoch = abstime; + self->metered_computation = 0; + self->sched_mode |= TH_MODE_POLLDEPRESS; + thread_unlock(self); + + abstime += (total_computation >> sched_poll_yield_shift); + if (!timer_call_enter(&self->depress_timer, abstime)) + self->depress_timer_active++; + wake_unlock(self); + + myprocessor = current_processor(); + if (csw_needed(self, myprocessor)) + ast_on(AST_BLOCK); + } + else + thread_unlock(self); + } + else + thread_unlock(self); + + splx(s); } diff --git a/osfmk/kern/mk_sp.h b/osfmk/kern/mk_sp.h index c9ebcddd2..a7a2db358 100644 --- a/osfmk/kern/mk_sp.h +++ b/osfmk/kern/mk_sp.h @@ -28,104 +28,37 @@ #define _KERN_MK_SP_H_ /* -* Include Files -*/ - -/* - * Scheduling policy operation prototypes + * Scheduling operation prototypes */ -sf_return_t _mk_sp_init( - sf_object_t policy, - int policy_id); - -sf_return_t _mk_sp_enable_processor_set( - sf_object_t policy, - processor_set_t processor_set); - -sf_return_t _mk_sp_disable_processor_set( - sf_object_t policy, - processor_set_t processor_set); - -sf_return_t _mk_sp_enable_processor( - sf_object_t policy, - processor_t processor); - -sf_return_t _mk_sp_disable_processor( - sf_object_t policy, - processor_t processor); - -sf_return_t _mk_sp_thread_update_mpri( - sf_object_t policy, - thread_t thread); - -sf_return_t _mk_sp_thread_unblock( - sf_object_t policy, - thread_t thread); - -sf_return_t _mk_sp_thread_done( - sf_object_t policy, - thread_t old_thread); - -sf_return_t _mk_sp_thread_begin( - sf_object_t policy, - thread_t new_thread); +void _mk_sp_thread_unblock( + thread_t thread); -sf_return_t _mk_sp_thread_dispatch( - sf_object_t policy, - thread_t old_thread); +void _mk_sp_thread_done( + thread_t old_thread); -sf_return_t _mk_sp_thread_attach( - sf_object_t policy, - thread_t thread); +void _mk_sp_thread_begin( + thread_t new_thread); -sf_return_t _mk_sp_thread_detach( - sf_object_t policy, - thread_t thread); - -sf_return_t _mk_sp_thread_processor( - sf_object_t policy, - thread_t *thread, - processor_t processor); - -sf_return_t _mk_sp_thread_processor_set( - sf_object_t policy, - thread_t thread, - processor_set_t processor_set); - -sf_return_t _mk_sp_thread_setup( - sf_object_t policy, - thread_t thread); - -void _mk_sp_swtch_pri( - sf_object_t policy, - int pri); +void _mk_sp_thread_dispatch( + thread_t old_thread); kern_return_t _mk_sp_thread_switch( - sf_object_t policy, thread_act_t hint_act, int option, mach_msg_timeout_t option_time); -kern_return_t _mk_sp_thread_depress_abort( - sf_object_t policy, - thread_t thread); +void _mk_sp_thread_depress_ms( + mach_msg_timeout_t interval); -void _mk_sp_thread_depress_timeout( - sf_object_t policy, - thread_t thread); +void _mk_sp_thread_depress_abstime( + uint64_t interval); -boolean_t _mk_sp_thread_runnable( - sf_object_t policy, - thread_t thread); - -#define MK_SP_ATTACHED ( 0x0001 ) -#define MK_SP_RUNNABLE ( 0x0002 ) -#define MK_SP_BLOCKED ( 0x0004 ) +kern_return_t _mk_sp_thread_depress_abort( + thread_t thread, + boolean_t abortall); -/* - * Definitions of standard scheduling operations for this policy - */ -extern sp_ops_t mk_sp_ops; +void _mk_sp_thread_perhaps_yield( + thread_t self); #endif /* _KERN_MK_SP_H_ */ diff --git a/osfmk/kern/mk_timer.c b/osfmk/kern/mk_timer.c index 0f6850a13..668072763 100644 --- a/osfmk/kern/mk_timer.c +++ b/osfmk/kern/mk_timer.c @@ -136,7 +136,7 @@ mk_timer_expire( void *p0, void *p1) { - AbsoluteTime time_of_posting; + uint64_t time_of_posting; mk_timer_t timer = p0; ipc_port_t port; @@ -213,9 +213,9 @@ mk_timer_destroy( kern_return_t mk_timer_arm( mach_port_name_t name, - AbsoluteTime expire_time) + uint64_t expire_time) { - AbsoluteTime time_of_arming; + uint64_t time_of_arming; mk_timer_t timer; ipc_space_t myspace = current_space(); ipc_port_t port; @@ -252,9 +252,9 @@ mk_timer_arm( kern_return_t mk_timer_cancel( mach_port_name_t name, - AbsoluteTime *result_time) + uint64_t *result_time) { - AbsoluteTime armed_time = { 0, 0 }; + uint64_t armed_time = 0; mk_timer_t timer; ipc_space_t myspace = current_space(); ipc_port_t port; diff --git a/osfmk/kern/mk_timer.h b/osfmk/kern/mk_timer.h index 3236e7562..3ac2e415c 100644 --- a/osfmk/kern/mk_timer.h +++ b/osfmk/kern/mk_timer.h @@ -32,8 +32,6 @@ #define _KERN_MK_TIMER_H_ #ifdef MACH_KERNEL_PRIVATE -#include <libkern/OSBase.h> - #include <mach/mach_types.h> #include <kern/call_entry.h> @@ -41,7 +39,7 @@ struct mk_timer { decl_simple_lock_data(,lock) call_entry_data_t call_entry; - AbsoluteTime time_of_arming; + uint64_t time_of_arming; boolean_t is_dead:1, is_armed:1; int active; diff --git a/osfmk/kern/priority.c b/osfmk/kern/priority.c index d88ade25d..31caeb97a 100644 --- a/osfmk/kern/priority.c +++ b/osfmk/kern/priority.c @@ -69,154 +69,94 @@ #include <kern/thread.h> #include <kern/processor.h> #include <machine/machparam.h> -#include <kern/sf.h> -#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ -/*** ??? Should this file be MK SP-specific? Or is it more general purpose? ***/ - - - -/* - * USAGE_THRESHOLD is the amount by which usage must change to - * cause a priority shift that moves a thread between run queues. - */ - -#ifdef PRI_SHIFT_2 -#if PRI_SHIFT_2 > 0 -#define USAGE_THRESHOLD (((1 << PRI_SHIFT) + (1 << PRI_SHIFT_2)) << (2 + SCHED_SHIFT)) -#else /* PRI_SHIFT_2 > 0 */ -#define USAGE_THRESHOLD (((1 << PRI_SHIFT) - (1 << -(PRI_SHIFT_2))) << (2 + SCHED_SHIFT)) -#endif /* PRI_SHIFT_2 > 0 */ -#else /* PRI_SHIFT_2 */ -#define USAGE_THRESHOLD (1 << (PRI_SHIFT + 2 + SCHED_SHIFT)) -#endif /* PRI_SHIFT_2 */ /* - * thread_quantum_update: + * thread_quantum_expire: * * Recalculate the quantum and priority for a thread. - * The number of ticks that has elapsed since we were last called - * is passed as "nticks." */ void -thread_quantum_update( - register int mycpu, - register thread_t thread, - int nticks, - int state) +thread_quantum_expire( + timer_call_param_t p0, + timer_call_param_t p1) { - register int quantum; - register processor_t myprocessor; + register processor_t myprocessor = p0; + register thread_t thread = p1; register processor_set_t pset; spl_t s; - myprocessor = cpu_to_processor(mycpu); pset = myprocessor->processor_set; /* - * Account for thread's utilization of these ticks. - * This assumes that there is *always* a current thread. - * When the processor is idle, it should be the idle thread. + * Update set_quanta for timesharing. */ + pset->set_quanta = pset->machine_quanta[ + (pset->runq.count > pset->processor_count) ? + pset->processor_count : pset->runq.count]; + + s = splsched(); + thread_lock(thread); /* - * Update set_quantum and calculate the current quantum. + * Check for failsafe trip. */ - pset->set_quantum = pset->machine_quantum[ - (pset->runq.count > pset->processor_count) ? - pset->processor_count : pset->runq.count]; + if (!(thread->sched_mode & TH_MODE_TIMESHARE)) { + extern uint64_t max_unsafe_computation; + uint64_t new_computation; + + new_computation = myprocessor->quantum_end; + new_computation -= thread->computation_epoch; + if (new_computation + thread->metered_computation > + max_unsafe_computation) { + extern uint32_t sched_safe_duration; + + if (thread->sched_mode & TH_MODE_REALTIME) { + if (thread->depress_priority < 0) + thread->priority = MINPRI; + else + thread->depress_priority = MINPRI; + + thread->safe_mode |= TH_MODE_REALTIME; + thread->sched_mode &= ~TH_MODE_REALTIME; + } - if (myprocessor->runq.count != 0) - quantum = min_quantum; - else - quantum = pset->set_quantum; + thread->safe_release = sched_tick + sched_safe_duration; + thread->sched_mode |= (TH_MODE_FAILSAFE|TH_MODE_TIMESHARE); + } + } /* * Now recompute the priority of the thread if appropriate. */ + if (thread->sched_stamp != sched_tick) + update_priority(thread); + else + if ( (thread->sched_mode & TH_MODE_TIMESHARE) && + thread->depress_priority < 0 ) { + thread_timer_delta(thread); + thread->sched_usage += thread->sched_delta; + thread->sched_delta = 0; + compute_my_priority(thread); + } - { - s = splsched(); - thread_lock(thread); - - if (!(thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO))) { - thread_unlock(thread); - splx(s); - return; - } - - if (thread->state&TH_IDLE) { - /* Don't try to time-slice idle threads */ - myprocessor->first_quantum = TRUE; - if (thread->sched_stamp != sched_tick) - update_priority(thread); - thread_unlock(thread); - splx(s); - ast_check(); - return; - } - - myprocessor->quantum -= nticks; - /* - * Runtime quantum adjustment. Use quantum_adj_index - * to avoid synchronizing quantum expirations. - */ - if ( quantum != myprocessor->last_quantum && - pset->processor_count > 1 ) { - myprocessor->last_quantum = quantum; - simple_lock(&pset->quantum_adj_lock); - quantum = min_quantum + (pset->quantum_adj_index * - (quantum - min_quantum)) / - (pset->processor_count - 1); - if (++(pset->quantum_adj_index) >= pset->processor_count) - pset->quantum_adj_index = 0; - simple_unlock(&pset->quantum_adj_lock); - } - if (myprocessor->quantum <= 0) { - if (thread->sched_stamp != sched_tick) - update_priority(thread); - else - if ( thread->policy == POLICY_TIMESHARE && - thread->depress_priority < 0 ) { - thread_timer_delta(thread); - thread->sched_usage += thread->sched_delta; - thread->sched_delta = 0; - compute_my_priority(thread); - } + /* + * This quantum is up, give this thread another. + */ + if (first_quantum(myprocessor)) + myprocessor->slice_quanta--; - /* - * This quantum is up, give this thread another. - */ - myprocessor->first_quantum = FALSE; - if (thread->policy == POLICY_TIMESHARE) - myprocessor->quantum += quantum; - else - myprocessor->quantum += min_quantum; - } - /* - * Recompute priority if appropriate. - */ - else { - if (thread->sched_stamp != sched_tick) - update_priority(thread); - else - if ( thread->policy == POLICY_TIMESHARE && - thread->depress_priority < 0 ) { - thread_timer_delta(thread); - if (thread->sched_delta >= USAGE_THRESHOLD) { - thread->sched_usage += thread->sched_delta; - thread->sched_delta = 0; - compute_my_priority(thread); - } - } - } + thread->current_quantum = (thread->sched_mode & TH_MODE_REALTIME)? + thread->realtime.computation: std_quantum; + myprocessor->quantum_end += thread->current_quantum; + timer_call_enter1(&myprocessor->quantum_timer, + thread, myprocessor->quantum_end); - thread_unlock(thread); - splx(s); + thread_unlock(thread); + splx(s); - /* - * Check for and schedule ast if needed. - */ - ast_check(); - } + /* + * Check for and schedule ast if needed. + */ + ast_check(); } diff --git a/osfmk/kern/processor.c b/osfmk/kern/processor.c index 4e00eef38..a37913b15 100644 --- a/osfmk/kern/processor.c +++ b/osfmk/kern/processor.c @@ -55,7 +55,6 @@ */ #include <cpus.h> -#include <mach_host.h> #include <mach/boolean.h> #include <mach/policy.h> @@ -74,14 +73,6 @@ #include <ipc/ipc_port.h> #include <kern/kalloc.h> -#if MACH_HOST -#include <kern/zalloc.h> -zone_t pset_zone; -#endif /* MACH_HOST */ - -#include <kern/sf.h> -#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ - /* * Exported interface */ @@ -104,7 +95,7 @@ void processor_init( register processor_t pr, int slot_num); -void quantum_set( +void pset_quanta_set( processor_set_t pset); kern_return_t processor_set_base( @@ -185,25 +176,10 @@ void pset_init( mutex_init(&pset->lock, ETAP_THREAD_PSET); pset->pset_self = IP_NULL; pset->pset_name_self = IP_NULL; - pset->max_priority = MAXPRI_STANDARD; - pset->policies = POLICY_TIMESHARE | POLICY_FIFO | POLICY_RR; - pset->set_quantum = min_quantum; - - pset->quantum_adj_index = 0; - simple_lock_init(&pset->quantum_adj_lock, ETAP_THREAD_PSET_QUANT); - - for (i = 0; i <= NCPUS; i++) { - pset->machine_quantum[i] = min_quantum; - } + pset->set_quanta = 1; - pset->policy_default = POLICY_TIMESHARE; - pset->policy_limit.ts.max_priority = MAXPRI_STANDARD; - pset->policy_limit.rr.max_priority = MAXPRI_STANDARD; - pset->policy_limit.fifo.max_priority = MAXPRI_STANDARD; - pset->policy_base.ts.base_priority = BASEPRI_DEFAULT; - pset->policy_base.rr.base_priority = BASEPRI_DEFAULT; - pset->policy_base.rr.quantum = min_quantum; - pset->policy_base.fifo.base_priority = BASEPRI_DEFAULT; + for (i = 0; i <= NCPUS; i++) + pset->machine_quanta[i] = 1; } /* @@ -233,9 +209,8 @@ processor_init( pr->state = PROCESSOR_OFF_LINE; pr->next_thread = THREAD_NULL; pr->idle_thread = THREAD_NULL; - pr->quantum = 0; - pr->first_quantum = FALSE; - pr->last_quantum = 0; + timer_call_setup(&pr->quantum_timer, thread_quantum_expire, pr); + pr->slice_quanta = 0; pr->processor_set = PROCESSOR_SET_NULL; pr->processor_set_next = PROCESSOR_SET_NULL; queue_init(&pr->processors); @@ -260,7 +235,7 @@ pset_remove_processor( queue_remove(&pset->processors, processor, processor_t, processors); processor->processor_set = PROCESSOR_SET_NULL; pset->processor_count--; - quantum_set(pset); + pset_quanta_set(pset); } /* @@ -277,7 +252,7 @@ pset_add_processor( queue_enter(&pset->processors, processor, processor_t, processors); processor->processor_set = pset; pset->processor_count++; - quantum_set(pset); + pset_quanta_set(pset); } /* @@ -499,8 +474,14 @@ processor_start( if (processor == PROCESSOR_NULL) return(KERN_INVALID_ARGUMENT); - if (processor == master_processor) - return(cpu_start(processor->slot_num)); + if (processor == master_processor) { + thread_bind(current_thread(), processor); + thread_block((void (*)(void)) 0); + kr = cpu_start(processor->slot_num); + thread_bind(current_thread(), PROCESSOR_NULL); + + return(kr); + } s = splsched(); processor_lock(processor); @@ -519,8 +500,9 @@ processor_start( thread_t thread; extern void start_cpu_thread(void); - thread = kernel_thread_with_priority(kernel_task, MAXPRI_KERNBAND, - start_cpu_thread, FALSE); + thread = kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL, + start_cpu_thread, TRUE, FALSE); s = splsched(); thread_lock(thread); @@ -568,31 +550,27 @@ processor_control( } /* - * Precalculate the appropriate system quanta based on load. The - * index into machine_quantum is the number of threads on the + * Precalculate the appropriate timesharing quanta based on load. The + * index into machine_quanta is the number of threads on the * processor set queue. It is limited to the number of processors in * the set. */ void -quantum_set( +pset_quanta_set( processor_set_t pset) { -#if NCPUS > 1 register int i, ncpus; ncpus = pset->processor_count; for (i=1; i <= ncpus; i++) - pset->machine_quantum[i] = ((min_quantum * ncpus) + (i / 2)) / i ; + pset->machine_quanta[i] = (ncpus + (i / 2)) / i; - pset->machine_quantum[0] = pset->machine_quantum[1]; + pset->machine_quanta[0] = pset->machine_quanta[1]; - i = (pset->runq.count > ncpus) ? ncpus : pset->runq.count; - pset->set_quantum = pset->machine_quantum[i]; -#else /* NCPUS > 1 */ - default_pset.set_quantum = min_quantum; -#endif /* NCPUS > 1 */ + i = (pset->runq.count > ncpus)? ncpus: pset->runq.count; + pset->set_quanta = pset->machine_quanta[i]; } kern_return_t @@ -651,13 +629,8 @@ processor_set_info( return(KERN_FAILURE); basic_info = (processor_set_basic_info_t) info; - - pset_lock(pset); - simple_lock(&pset->processors_lock); basic_info->processor_count = pset->processor_count; - simple_unlock(&pset->processors_lock); - basic_info->default_policy = pset->policy_default; - pset_unlock(pset); + basic_info->default_policy = POLICY_TIMESHARE; *count = PROCESSOR_SET_BASIC_INFO_COUNT; *host = &realhost; @@ -670,10 +643,7 @@ processor_set_info( return(KERN_FAILURE); ts_base = (policy_timeshare_base_t) info; - - pset_lock(pset); - *ts_base = pset->policy_base.ts; - pset_unlock(pset); + ts_base->base_priority = BASEPRI_DEFAULT; *count = POLICY_TIMESHARE_BASE_COUNT; *host = &realhost; @@ -686,10 +656,7 @@ processor_set_info( return(KERN_FAILURE); fifo_base = (policy_fifo_base_t) info; - - pset_lock(pset); - *fifo_base = pset->policy_base.fifo; - pset_unlock(pset); + fifo_base->base_priority = BASEPRI_DEFAULT; *count = POLICY_FIFO_BASE_COUNT; *host = &realhost; @@ -702,10 +669,8 @@ processor_set_info( return(KERN_FAILURE); rr_base = (policy_rr_base_t) info; - - pset_lock(pset); - *rr_base = pset->policy_base.rr; - pset_unlock(pset); + rr_base->base_priority = BASEPRI_DEFAULT; + rr_base->quantum = 1; *count = POLICY_RR_BASE_COUNT; *host = &realhost; @@ -718,10 +683,7 @@ processor_set_info( return(KERN_FAILURE); ts_limit = (policy_timeshare_limit_t) info; - - pset_lock(pset); - *ts_limit = pset->policy_limit.ts; - pset_unlock(pset); + ts_limit->max_priority = MAXPRI_STANDARD; *count = POLICY_TIMESHARE_LIMIT_COUNT; *host = &realhost; @@ -734,10 +696,7 @@ processor_set_info( return(KERN_FAILURE); fifo_limit = (policy_fifo_limit_t) info; - - pset_lock(pset); - *fifo_limit = pset->policy_limit.fifo; - pset_unlock(pset); + fifo_limit->max_priority = MAXPRI_STANDARD; *count = POLICY_FIFO_LIMIT_COUNT; *host = &realhost; @@ -750,10 +709,7 @@ processor_set_info( return(KERN_FAILURE); rr_limit = (policy_rr_limit_t) info; - - pset_lock(pset); - *rr_limit = pset->policy_limit.rr; - pset_unlock(pset); + rr_limit->max_priority = MAXPRI_STANDARD; *count = POLICY_RR_LIMIT_COUNT; *host = &realhost; @@ -766,10 +722,7 @@ processor_set_info( return(KERN_FAILURE); enabled = (int *) info; - - pset_lock(pset); - *enabled = pset->policies; - pset_unlock(pset); + *enabled = POLICY_TIMESHARE | POLICY_RR | POLICY_FIFO; *count = sizeof(*enabled)/sizeof(int); *host = &realhost; diff --git a/osfmk/kern/processor.h b/osfmk/kern/processor.h index c7fcd9020..cc236cac8 100644 --- a/osfmk/kern/processor.h +++ b/osfmk/kern/processor.h @@ -70,7 +70,6 @@ extern processor_t master_processor; #ifdef MACH_KERNEL_PRIVATE #include <cpus.h> -#include <mach_host.h> #include <mach/mach_types.h> #include <kern/cpu_number.h> @@ -78,9 +77,7 @@ extern processor_t master_processor; #include <kern/queue.h> #include <kern/sched.h> -#if NCPUS > 1 #include <machine/ast_types.h> -#endif /* NCPUS > 1 */ struct processor_set { struct run_queue runq; /* runq for this set */ @@ -99,20 +96,11 @@ struct processor_set { decl_mutex_data(, lock) /* lock for everything else */ struct ipc_port * pset_self; /* port for operations */ struct ipc_port * pset_name_self; /* port for information */ - int max_priority; /* maximum priority */ - int policies; /* bit vector for policies */ - int set_quantum; /* current default quantum */ -#if NCPUS > 1 - int quantum_adj_index; /* runtime quantum adj. */ - decl_simple_lock_data(,quantum_adj_lock) /* lock for above */ - int machine_quantum[NCPUS+1]; /* ditto */ -#endif /* NCPUS > 1 */ + int set_quanta; /* timeslice quanta for timesharing */ + int machine_quanta[NCPUS+1]; integer_t mach_factor; /* mach_factor */ integer_t load_average; /* load_average */ long sched_load; /* load avg for scheduler */ - policy_t policy_default; /* per set default */ - policy_base_data_t policy_base; /* base attributes */ - policy_limit_data_t policy_limit; /* limit attributes */ }; struct processor { @@ -122,9 +110,10 @@ struct processor { struct thread_shuttle *next_thread, /* next thread to run if dispatched */ *idle_thread; /* this processor's idle thread. */ - int quantum; /* quantum for current thread */ - boolean_t first_quantum; /* first quantum in succession */ - int last_quantum; /* last quantum assigned */ + timer_call_data_t quantum_timer; /* timer for quantum expiration */ + int slice_quanta; /* quanta before timeslice ends */ + uint64_t quantum_end; /* time when current quantum ends */ + uint64_t last_dispatch; /* time of last dispatch */ processor_set_t processor_set; /* processor set I belong to */ processor_set_t processor_set_next; /* set I will belong to */ @@ -132,11 +121,6 @@ struct processor { decl_simple_lock_data(,lock) struct ipc_port *processor_self;/* port for operations */ int slot_num; /* machine-indep slot number */ -#if NCPUS > 1 - ast_check_t ast_check_data; /* for remote ast_check invocation */ - queue_chain_t softclock_queue;/* cpus handling softclocks */ -#endif /* NCPUS > 1 */ - /* punt id data temporarily */ }; extern struct processor processor_array[NCPUS]; diff --git a/osfmk/kern/sched.h b/osfmk/kern/sched.h index 9c98bd104..01f2d3ada 100644 --- a/osfmk/kern/sched.h +++ b/osfmk/kern/sched.h @@ -61,7 +61,6 @@ #ifndef _KERN_SCHED_H_ #define _KERN_SCHED_H_ -#include <cpus.h> #include <simple_clock.h> #include <stat_time.h> @@ -70,12 +69,12 @@ #include <kern/queue.h> #include <kern/lock.h> #include <kern/macro_help.h> +#include <kern/timer_call.h> #if STAT_TIME /* - * Statistical timing uses microseconds as timer units. 16 bit shift - * yields priorities. PRI_SHIFT_2 isn't needed. + * Statistical timing uses microseconds as timer units. */ #define PRI_SHIFT (16 - SCHED_TICK_SHIFT) @@ -114,13 +113,13 @@ * + * V * 80 Kernel mode only - * 79 High priority + * 79 System high priority * A * + * (16 levels) * + * V - * 64 High priority + * 64 System high priority * 63 Elevated priorities * A * + @@ -157,17 +156,18 @@ #define MAXPRI_STANDARD (BASEPRI_REALTIME - 1) /* 95 */ -#define MAXPRI_KERNBAND MAXPRI_STANDARD /* 95 */ -#define MINPRI_KERNBAND (MAXPRI_KERNBAND - (NRQS / 8) + 1) /* 80 */ +#define MAXPRI_KERNEL MAXPRI_STANDARD /* 95 */ +#define BASEPRI_PREEMPT (MAXPRI_KERNEL - 2) /* 93 */ +#define MINPRI_KERNEL (MAXPRI_KERNEL - (NRQS / 8) + 1) /* 80 */ -#define MAXPRI_HIGHBAND (MINPRI_KERNBAND - 1) /* 79 */ -#define MINPRI_HIGHBAND (MAXPRI_HIGHBAND - (NRQS / 8) + 1) /* 64 */ +#define MAXPRI_SYSTEM (MINPRI_KERNEL - 1) /* 79 */ +#define MINPRI_SYSTEM (MAXPRI_SYSTEM - (NRQS / 8) + 1) /* 64 */ -#define MAXPRI_MAINBAND (MINPRI_HIGHBAND - 1) /* 63 */ -#define BASEPRI_DEFAULT (MAXPRI_MAINBAND - (NRQS / 4)) /* 31 */ -#define MINPRI_MAINBAND MINPRI /* 0 */ +#define MAXPRI_USER (MINPRI_SYSTEM - 1) /* 63 */ +#define BASEPRI_DEFAULT (MAXPRI_USER - (NRQS / 4)) /* 31 */ +#define MINPRI_USER MINPRI /* 0 */ -#define MINPRI_STANDARD MINPRI_MAINBAND /* 0 */ +#define MINPRI_STANDARD MINPRI_USER /* 0 */ /* * Macro to check for invalid priorities. @@ -185,9 +185,11 @@ struct run_queue { typedef struct run_queue *run_queue_t; #define RUN_QUEUE_NULL ((run_queue_t) 0) +#define first_quantum(processor) ((processor)->slice_quanta > 0) + #define csw_needed(thread, processor) ( \ ((thread)->state & TH_SUSP) || \ - ((processor)->first_quantum? \ + (first_quantum(processor)? \ ((processor)->runq.highq > (thread)->sched_pri || \ (processor)->processor_set->runq.highq > (thread)->sched_pri) : \ ((processor)->runq.highq >= (thread)->sched_pri || \ @@ -199,19 +201,20 @@ typedef struct run_queue *run_queue_t; /* Remove thread from its run queue */ extern run_queue_t rem_runq( - thread_t thread); + thread_t thread); -/* Mach factor computation (in mach_factor.c) */ +/* Periodic computation of load factors */ extern void compute_mach_factor(void); -/* Update threads quantum (in priority.c) */ -extern void thread_quantum_update( - int mycpu, - thread_t thread, - int nticks, - int state); +/* Handle quantum expiration for an executing thread */ +extern void thread_quantum_expire( + timer_call_param_t processor, + timer_call_param_t thread); + +extern uint32_t std_quantum, min_std_quantum; +extern uint32_t std_quantum_us; -extern int min_quantum; /* defines max context switch rate */ +extern uint32_t max_rt_quantum, min_rt_quantum; /* * Shift structures for holding update shifts. Actual computation diff --git a/osfmk/kern/sched_prim.c b/osfmk/kern/sched_prim.c index e2da65ad1..b4f351d41 100644 --- a/osfmk/kern/sched_prim.c +++ b/osfmk/kern/sched_prim.c @@ -92,7 +92,6 @@ #include <vm/vm_map.h> #include <mach/policy.h> #include <mach/sync_policy.h> -#include <kern/sf.h> #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ #include <sys/kdebug.h> @@ -103,15 +102,23 @@ extern int task_swap_on; extern int hz; -#define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */ +#define DEFAULT_PREEMPTION_RATE 100 /* (1/s) */ int default_preemption_rate = DEFAULT_PREEMPTION_RATE; +#define MAX_UNSAFE_QUANTA 800 +int max_unsafe_quanta = MAX_UNSAFE_QUANTA; + +#define MAX_POLL_QUANTA 2 +int max_poll_quanta = MAX_POLL_QUANTA; + +#define SCHED_POLL_YIELD_SHIFT 4 /* 1/16 */ +int sched_poll_yield_shift = SCHED_POLL_YIELD_SHIFT; + #define NO_KERNEL_PREEMPT 0 #define KERNEL_PREEMPT 1 int kernel_preemption_mode = KERNEL_PREEMPT; -int min_quantum; -natural_t min_quantum_ms; +uint32_t std_quantum_us; unsigned sched_tick; @@ -165,11 +172,14 @@ void checkrq( void thread_check( thread_t thread, run_queue_t runq); -#endif /*DEBUG*/ +static boolean_t thread_runnable( thread_t thread); +#endif /*DEBUG*/ + + /* * State machine * @@ -233,25 +243,14 @@ void sched_init(void) { /* - * Calculate the minimum quantum - * in ticks. + * Calculate the timeslicing quantum + * in us. */ if (default_preemption_rate < 1) default_preemption_rate = DEFAULT_PREEMPTION_RATE; - min_quantum = hz / default_preemption_rate; - - /* - * Round up result (4/5) to an - * integral number of ticks. - */ - if (((hz * 10) / default_preemption_rate) - (min_quantum * 10) >= 5) - min_quantum++; - if (min_quantum < 1) - min_quantum = 1; + std_quantum_us = (1000 * 1000) / default_preemption_rate; - min_quantum_ms = (1000 / hz) * min_quantum; - - printf("scheduling quantum is %d ms\n", min_quantum_ms); + printf("standard timeslicing quantum is %d us\n", std_quantum_us); wait_queues_init(); pset_sys_bootstrap(); /* initialize processor mgmt. */ @@ -261,7 +260,6 @@ sched_init(void) sched_usec = 0; #endif /* SIMPLE_CLOCK */ ast_init(); - sf_init(); } void @@ -275,7 +273,7 @@ wait_queues_init(void) } /* - * Thread timeout routine, called when timer expires. + * Thread wait timer expiration. */ void thread_timer_expire( @@ -287,17 +285,17 @@ thread_timer_expire( s = splsched(); wake_lock(thread); - if ( thread->wait_timer_is_set && - !timer_call_is_delayed(&thread->wait_timer, NULL) ) { - thread->wait_timer_active--; - thread->wait_timer_is_set = FALSE; - thread_lock(thread); - if (thread->active) - clear_wait_internal(thread, THREAD_TIMED_OUT); - thread_unlock(thread); + if (--thread->wait_timer_active == 1) { + if (thread->wait_timer_is_set) { + thread->wait_timer_is_set = FALSE; + thread_lock(thread); + if (thread->active) + clear_wait_internal(thread, THREAD_TIMED_OUT); + thread_unlock(thread); + } } else - if (--thread->wait_timer_active == 0) + if (thread->wait_timer_active == 0) thread_wakeup_one(&thread->wait_timer_active); wake_unlock(thread); splx(s); @@ -312,11 +310,11 @@ thread_timer_expire( */ void thread_set_timer( - natural_t interval, - natural_t scale_factor) + uint32_t interval, + uint32_t scale_factor) { thread_t thread = current_thread(); - AbsoluteTime deadline; + uint64_t deadline; spl_t s; s = splsched(); @@ -336,7 +334,7 @@ thread_set_timer( void thread_set_timer_deadline( - AbsoluteTime deadline) + uint64_t deadline) { thread_t thread = current_thread(); spl_t s; @@ -372,32 +370,6 @@ thread_cancel_timer(void) splx(s); } -/* - * thread_depress_timeout: - * - * Timeout routine for priority depression. - */ -void -thread_depress_timeout( - thread_call_param_t p0, - thread_call_param_t p1) -{ - thread_t thread = p0; - sched_policy_t *policy; - spl_t s; - - s = splsched(); - thread_lock(thread); - policy = policy_id_to_sched_policy(thread->policy); - thread_unlock(thread); - splx(s); - - if (policy != SCHED_POLICY_NULL) - policy->sp_ops.sp_thread_depress_timeout(policy, thread); - - thread_deallocate(thread); -} - /* * Set up thread timeout element when thread is created. */ @@ -405,12 +377,18 @@ void thread_timer_setup( thread_t thread) { + extern void thread_depress_expire( + timer_call_param_t p0, + timer_call_param_t p1); + timer_call_setup(&thread->wait_timer, thread_timer_expire, thread); thread->wait_timer_is_set = FALSE; thread->wait_timer_active = 1; - thread->ref_count++; - thread_call_setup(&thread->depress_timer, thread_depress_timeout, thread); + timer_call_setup(&thread->depress_timer, thread_depress_expire, thread); + thread->depress_timer_active = 1; + + thread->ref_count++; } void @@ -440,6 +418,19 @@ thread_timer_terminate(void) wake_lock(thread); } + thread->depress_timer_active--; + + while (thread->depress_timer_active > 0) { + assert_wait((event_t)&thread->depress_timer_active, THREAD_UNINT); + wake_unlock(thread); + splx(s); + + thread_block((void (*)(void)) 0); + + s = splsched(); + wake_lock(thread); + } + wake_unlock(thread); splx(s); @@ -459,45 +450,20 @@ thread_go_locked( thread_t thread, int result) { - int state; - sched_policy_t *policy; - sf_return_t sfr; - assert(thread->at_safe_point == FALSE); assert(thread->wait_event == NO_EVENT); assert(thread->wait_queue == WAIT_QUEUE_NULL); if (thread->state & TH_WAIT) { - thread->state &= ~(TH_WAIT|TH_UNINT); if (!(thread->state & TH_RUN)) { thread->state |= TH_RUN; -#if THREAD_SWAPPER - if (thread->state & TH_SWAPPED_OUT) - thread_swapin(thread->top_act, FALSE); - else -#endif /* THREAD_SWAPPER */ - { - policy = &sched_policy[thread->policy]; - sfr = policy->sp_ops.sp_thread_unblock(policy, thread); - assert(sfr == SF_SUCCESS); - } + + _mk_sp_thread_unblock(thread); } + thread->wait_result = result; } - - - /* - * The next few lines are a major hack. Hopefully this will get us - * around all of the scheduling framework hooha. We can't call - * sp_thread_unblock yet because we could still be finishing up the - * durn two stage block on another processor and thread_setrun - * could be called by s_t_u and we'll really be messed up then. - */ - /* Don't mess with this if we are still swapped out */ - if (!(thread->state & TH_SWAPPED_OUT)) - thread->sp_state = MK_SP_RUNNABLE; - } void @@ -578,7 +544,7 @@ assert_wait( index = wait_hash(event); wq = &wait_queues[index]; - wait_queue_assert_wait(wq, + (void)wait_queue_assert_wait(wq, event, interruptible); } @@ -642,8 +608,6 @@ void thread_unstop( thread_t thread) { - sched_policy_t *policy; - sf_return_t sfr; spl_t s; s = splsched(); @@ -651,17 +615,10 @@ thread_unstop( thread_lock(thread); if ((thread->state & (TH_RUN|TH_WAIT|TH_SUSP/*|TH_UNINT*/)) == TH_SUSP) { - thread->state = (thread->state & ~TH_SUSP) | TH_RUN; -#if THREAD_SWAPPER - if (thread->state & TH_SWAPPED_OUT) - thread_swapin(thread->top_act, FALSE); - else -#endif /* THREAD_SWAPPER */ - { - policy = &sched_policy[thread->policy]; - sfr = policy->sp_ops.sp_thread_unblock(policy, thread); - assert(sfr == SF_SUCCESS); - } + thread->state &= ~TH_SUSP; + thread->state |= TH_RUN; + + _mk_sp_thread_unblock(thread); } else if (thread->state & TH_SUSP) { @@ -713,9 +670,11 @@ thread_wait( s = splsched(); wake_lock(thread); } + wake_unlock(thread); splx(s); - return TRUE; + + return (TRUE); } @@ -854,18 +813,23 @@ thread_select( processor_set_t pset; register run_queue_t runq = &myprocessor->runq; boolean_t other_runnable; - sched_policy_t *policy; /* * Check for other non-idle runnable threads. */ - myprocessor->first_quantum = TRUE; pset = myprocessor->processor_set; thread = current_thread(); -#if 0 /* CHECKME! */ - thread->unconsumed_quantum = myprocessor->quantum; -#endif + /* + * Update set_quanta for timesharing. + */ + pset->set_quanta = pset->machine_quanta[ + (pset->runq.count > pset->processor_count) ? + pset->processor_count : pset->runq.count]; + + /* Update the thread's priority */ + if (thread->sched_stamp != sched_tick) + update_priority(thread); simple_lock(&runq->lock); simple_lock(&pset->runq.lock); @@ -884,10 +848,8 @@ thread_select( simple_unlock(&pset->runq.lock); simple_unlock(&runq->lock); - /* Update the thread's meta-priority */ - policy = policy_id_to_sched_policy(thread->policy); - assert(policy != SCHED_POLICY_NULL); - (void)policy->sp_ops.sp_thread_update_mpri(policy, thread); + myprocessor->slice_quanta = + (thread->sched_mode & TH_MODE_TIMESHARE)? pset->set_quanta: 1; } else if (other_runnable) { @@ -934,12 +896,11 @@ thread_select( * If continuation is non-zero, and the current thread is blocked, * then it will resume by executing continuation on a new stack. * Returns TRUE if the hand-off succeeds. - * The reason parameter == AST_QUANTUM if the thread blocked + * The reason parameter contains | AST_QUANTUM if the thread blocked * because its quantum expired. * Assumes splsched. */ - static thread_t __current_thread(void) { @@ -953,27 +914,25 @@ thread_invoke( int reason, void (*continuation)(void)) { - sched_policy_t *policy; - sf_return_t sfr; void (*lcont)(void); + if (cpu_data[cpu_number()].preemption_level != 0) + panic("thread_invoke: preemption_level %d\n", + cpu_data[cpu_number()].preemption_level); + /* * Mark thread interruptible. */ thread_lock(new_thread); new_thread->state &= ~TH_UNINT; - if (cpu_data[cpu_number()].preemption_level != 1) - panic("thread_invoke: preemption_level %d\n", - cpu_data[cpu_number()].preemption_level); - - assert(thread_runnable(new_thread)); assert(old_thread->continuation == (void (*)(void))0); - if ((old_thread->sched_mode & TH_MODE_REALTIME) && (!old_thread->stack_privilege)) { - old_thread->stack_privilege = old_thread->kernel_stack; + if ( (old_thread->sched_mode & TH_MODE_REALTIME) && + !old_thread->stack_privilege ) { + old_thread->stack_privilege = old_thread->kernel_stack; } if (continuation != (void (*)()) 0) { @@ -1002,6 +961,8 @@ thread_invoke( ast_context(new_thread->top_act, cpu_number()); timer_switch(&new_thread->system_timer); thread_unlock(new_thread); + + current_task()->csw++; old_thread->continuation = continuation; stack_handoff(old_thread, new_thread); @@ -1009,14 +970,14 @@ thread_invoke( wake_lock(old_thread); thread_lock(old_thread); act_machine_sv_free(old_thread->top_act); + + _mk_sp_thread_done(old_thread); /* * inline thread_dispatch but don't free stack */ switch (old_thread->state & (TH_RUN|TH_WAIT|TH_UNINT|TH_IDLE)) { - sched_policy_t *policy; - sf_return_t sfr; case TH_RUN | TH_UNINT: case TH_RUN: @@ -1024,13 +985,7 @@ thread_invoke( * No reason to stop. Put back on a run queue. */ old_thread->state |= TH_STACK_HANDOFF; - - /* Get pointer to scheduling policy "object" */ - policy = &sched_policy[old_thread->policy]; - - /* Leave enqueueing thread up to scheduling policy */ - sfr = policy->sp_ops.sp_thread_dispatch(policy, old_thread); - assert(sfr == SF_SUCCESS); + _mk_sp_thread_dispatch(old_thread); break; case TH_RUN | TH_WAIT | TH_UNINT: @@ -1068,27 +1023,13 @@ thread_invoke( default: panic("State 0x%x \n",old_thread->state); } - - /* Get pointer to scheduling policy "object" */ - policy = &sched_policy[old_thread->policy]; - /* Indicate to sched policy that old thread has stopped execution */ - /*** ??? maybe use a macro -- rkc, 1/4/96 ***/ - sfr = policy->sp_ops.sp_thread_done(policy, old_thread); - assert(sfr == SF_SUCCESS); thread_unlock(old_thread); wake_unlock(old_thread); - thread_lock(new_thread); + thread_lock(new_thread); assert(thread_runnable(new_thread)); - - /* Get pointer to scheduling policy "object" */ - policy = &sched_policy[new_thread->policy]; - - /* Indicate to sched policy that new thread has started execution */ - /*** ??? maybe use a macro ***/ - sfr = policy->sp_ops.sp_thread_begin(policy, new_thread); - assert(sfr == SF_SUCCESS); + _mk_sp_thread_begin(new_thread); lcont = new_thread->continuation; new_thread->continuation = (void(*)(void))0; @@ -1116,7 +1057,7 @@ thread_invoke( /*NOTREACHED*/ return TRUE; - case TH_STACK_COMING_IN: + case TH_STACK_ALLOC: /* * waiting for a stack */ @@ -1159,7 +1100,7 @@ thread_invoke( if (new_thread->state & TH_STACK_STATE) { get_new_stack: /* has no stack. if not already waiting for one try to get one */ - if ((new_thread->state & TH_STACK_COMING_IN) || + if ((new_thread->state & TH_STACK_ALLOC) || /* not already waiting. nonblocking try to get one */ !stack_alloc_try(new_thread, thread_continue)) { @@ -1206,7 +1147,6 @@ thread_invoke( counter_always(c_thread_invoke_csw++); current_task()->csw++; - thread_lock(old_thread); old_thread->reason = reason; assert(old_thread->runq == RUN_QUEUE_NULL); @@ -1214,11 +1154,7 @@ thread_invoke( if (continuation != (void (*)(void))0) old_thread->continuation = continuation; - /* Indicate to sched policy that old thread has stopped execution */ - policy = &sched_policy[old_thread->policy]; - /*** ??? maybe use a macro -- ***/ - sfr = policy->sp_ops.sp_thread_done(policy, old_thread); - assert(sfr == SF_SUCCESS); + _mk_sp_thread_done(old_thread); thread_unlock(old_thread); /* @@ -1232,35 +1168,16 @@ thread_invoke( new_thread = __current_thread(); assert(old_thread != new_thread); - assert(thread_runnable(new_thread)); - thread_lock(new_thread); assert(thread_runnable(new_thread)); - /* Indicate to sched policy that new thread has started execution */ - policy = &sched_policy[new_thread->policy]; - /*** ??? maybe use a macro -- rkc, 1/4/96 ***/ - sfr = policy->sp_ops.sp_thread_begin(policy, new_thread); - assert(sfr == SF_SUCCESS); + _mk_sp_thread_begin(new_thread); thread_unlock(new_thread); /* * We're back. Now old_thread is the thread that resumed * us, and we have to dispatch it. */ - /* CHECKME! */ -// Code from OSF in Grenoble deleted the following fields. They were -// used in HPPA and 386 code, but not in the PPC for other than -// just setting and resetting. They didn't delete these lines from -// the MACH_RT builds, though, causing compile errors. I'm going -// to make a wild guess and assume we can just delete these. -#if 0 - if (old_thread->preempt == TH_NOT_PREEMPTABLE) { - /* - * Mark that we have been really preempted - */ - old_thread->preempt = TH_PREEMPTED; - } -#endif + thread_dispatch(old_thread); enable_preemption(); @@ -1282,14 +1199,10 @@ thread_invoke( */ void thread_continue( - register thread_t old_thread) + register thread_t old_thread) { - register thread_t self; - register void (*continuation)(); - sched_policy_t *policy; - sf_return_t sfr; - - self = current_thread(); + register thread_t self = current_thread(); + register void (*continuation)(); /* * We must dispatch the old thread and then @@ -1297,24 +1210,14 @@ thread_continue( * There might not be an old thread, if we are * the first thread to run on this processor. */ - if (old_thread != THREAD_NULL) { + if (old_thread != THREAD_NULL) thread_dispatch(old_thread); - thread_lock(self); - - /* Get pointer to scheduling policy "object" */ - policy = &sched_policy[self->policy]; - - /* Indicate to sched policy that new thread has started execution */ - /*** ??? maybe use a macro -- rkc, 1/4/96 ***/ - sfr = policy->sp_ops.sp_thread_begin(policy,self); - assert(sfr == SF_SUCCESS); - } else { - thread_lock(self); - } - + thread_lock(self); continuation = self->continuation; self->continuation = (void (*)(void))0; + + _mk_sp_thread_begin(self); thread_unlock(self); /* @@ -1327,15 +1230,17 @@ thread_continue( enable_preemption(); if (self->funnel_state & TH_FN_REFUNNEL) { - kern_return_t save_wait_result; - self->funnel_state = 0; - save_wait_result = self->wait_result; - KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0); - funnel_lock(self->funnel_lock); - KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0); - self->wait_result = save_wait_result; - self->funnel_state = TH_FN_OWNED; + kern_return_t save_wait_result; + + self->funnel_state = 0; + save_wait_result = self->wait_result; + KERNEL_DEBUG(0x6032428 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0); + funnel_lock(self->funnel_lock); + KERNEL_DEBUG(0x6032430 | DBG_FUNC_NONE, self->funnel_lock, 4, 0, 0, 0); + self->wait_result = save_wait_result; + self->funnel_state = TH_FN_OWNED; } + spllo(); assert(continuation); @@ -1439,11 +1344,10 @@ db_show_thread_log(void) /* * thread_block_reason: * - * Block the current thread. If the thread is runnable - * then someone must have woken it up between its request - * to sleep and now. In this case, it goes back on a - * run queue. - * + * Block the current thread if a wait has been asserted, + * otherwise unconditionally yield the remainder of the + * current quantum unless reason contains AST_BLOCK. + * * If a continuation is specified, then thread_block will * attempt to discard the thread's kernel stack. When the * thread resumes, it will execute the continuation function @@ -1481,8 +1385,11 @@ thread_block_reason( if (thread->state & TH_ABORT) clear_wait_internal(thread, THREAD_INTERRUPTED); + if (!(reason & AST_BLOCK)) + myprocessor->slice_quanta = 0; + /* Unconditionally remove either | both */ - ast_off(AST_QUANTUM|AST_BLOCK|AST_URGENT); + ast_off(AST_PREEMPT); new_thread = thread_select(myprocessor); assert(new_thread); @@ -1516,15 +1423,14 @@ thread_block_reason( /* * thread_block: * - * Now calls thread_block_reason() which forwards the - * the reason parameter to thread_invoke() so it can - * do the right thing if the thread's quantum expired. + * Block the current thread if a wait has been asserted, + * otherwise yield the remainder of the current quantum. */ int thread_block( void (*continuation)(void)) { - return thread_block_reason(continuation, 0); + return thread_block_reason(continuation, AST_NONE); } /* @@ -1560,9 +1466,6 @@ void thread_dispatch( register thread_t thread) { - sched_policy_t *policy; - sf_return_t sfr; - /* * If we are discarding the thread's stack, we must do it * before the thread has a chance to run. @@ -1589,11 +1492,7 @@ thread_dispatch( /* * No reason to stop. Put back on a run queue. */ - /* Leave enqueueing thread up to scheduling policy */ - policy = &sched_policy[thread->policy]; - /*** ??? maybe use a macro ***/ - sfr = policy->sp_ops.sp_thread_dispatch(policy, thread); - assert(sfr == SF_SUCCESS); + _mk_sp_thread_dispatch(thread); break; case TH_RUN | TH_WAIT | TH_UNINT: @@ -1694,9 +1593,6 @@ thread_setrun( thread_t thread; ast_t ast_flags = AST_BLOCK; - mp_disable_preemption(); - - assert(!(new_thread->state & TH_SWAPPED_OUT)); assert(thread_runnable(new_thread)); /* @@ -1705,11 +1601,9 @@ thread_setrun( if (new_thread->sched_stamp != sched_tick) update_priority(new_thread); - if (new_thread->policy & (POLICY_FIFO|POLICY_RR)) { - if ( new_thread->sched_pri >= (MAXPRI_KERNBAND - 2) && - kernel_preemption_mode == KERNEL_PREEMPT ) - ast_flags |= AST_URGENT; - } + if ( new_thread->sched_pri >= BASEPRI_PREEMPT && + kernel_preemption_mode == KERNEL_PREEMPT ) + ast_flags |= AST_URGENT; assert(new_thread->runq == RUN_QUEUE_NULL); @@ -1733,40 +1627,32 @@ thread_setrun( simple_unlock(&pset->idle_lock); if(processor->slot_num != cpu_number()) machine_signal_idle(processor); - mp_enable_preemption(); return; } simple_unlock(&pset->idle_lock); } - + /* + * Place thread on processor set run queue. + */ + runq = &pset->runq; + run_queue_enqueue(runq, new_thread, tail); + /* * Preempt check */ - runq = &pset->runq; thread = current_thread(); processor = current_processor(); - if ( may_preempt && - pset == processor->processor_set && - thread->sched_pri < new_thread->sched_pri ) { + if ( may_preempt && + pset == processor->processor_set ) { /* * XXX if we have a non-empty local runq or are * XXX running a bound thread, ought to check for * XXX another cpu running lower-pri thread to preempt. */ - /* - * Turn off first_quantum to allow csw. - */ - processor->first_quantum = FALSE; - - ast_on(ast_flags); + if (csw_needed(thread, processor)) + ast_on(ast_flags); } - - /* - * Put us on the end of the runq, if we are not preempting - * or the guy we are preempting. - */ - run_queue_enqueue(runq, new_thread, tail); } else { /* @@ -1787,7 +1673,6 @@ thread_setrun( simple_unlock(&processor->lock); if(processor->slot_num != cpu_number()) machine_signal_idle(processor); - mp_enable_preemption(); return; } simple_unlock(&pset->idle_lock); @@ -1803,15 +1688,13 @@ thread_setrun( * since the idle_thread is bound. */ runq = &processor->runq; - thread = current_thread(); if (processor == current_processor()) { - if ( thread->bound_processor == PROCESSOR_NULL || - thread->sched_pri < new_thread->sched_pri ) { - processor->first_quantum = FALSE; - ast_on(ast_flags); - } - run_queue_enqueue(runq, new_thread, tail); + + thread = current_thread(); + if ( thread->bound_processor == PROCESSOR_NULL || + csw_needed(thread, processor)) + ast_on(ast_flags); } else { thread = cpu_data[processor->slot_num].active_thread; @@ -1821,8 +1704,6 @@ thread_setrun( cause_ast_check(processor); } } - - mp_enable_preemption(); } /* @@ -2081,11 +1962,12 @@ idle_thread_continue(void) (*gcount == 0) && (*lcount == 0) ) { /* check for ASTs while we wait */ - - if (need_ast[mycpu] &~ (AST_SCHEDULING|AST_URGENT|AST_BSD|AST_BSD_INIT)) { + if (need_ast[mycpu] &~ ( AST_SCHEDULING | AST_PREEMPT | + AST_BSD | AST_BSD_INIT )) { /* don't allow scheduling ASTs */ - need_ast[mycpu] &= ~(AST_SCHEDULING|AST_URGENT|AST_BSD|AST_BSD_INIT); - ast_taken(FALSE, AST_ALL, TRUE); /* back at spllo */ + need_ast[mycpu] &= ~( AST_SCHEDULING | AST_PREEMPT | + AST_BSD | AST_BSD_INIT ); + ast_taken(AST_ALL, TRUE); /* back at spllo */ } else #ifdef __ppc__ @@ -2141,17 +2023,8 @@ retry: else { simple_unlock(&pset->runq.lock); simple_unlock(&myprocessor->runq.lock); - - /* - * set up quantum for new thread. - */ - if (new_thread->policy & (POLICY_RR|POLICY_FIFO)) - myprocessor->quantum = new_thread->unconsumed_quantum; - else - myprocessor->quantum = pset->set_quantum; thread_unlock(new_thread); - myprocessor->first_quantum = TRUE; counter(c_idle_thread_handoff++); thread_run(myprocessor->idle_thread, idle_thread_continue, new_thread); @@ -2218,7 +2091,6 @@ idle_thread(void) spl_t s; stack_privilege(self); - thread_swappable(current_act(), FALSE); s = splsched(); thread_lock(self); @@ -2235,7 +2107,17 @@ idle_thread(void) /*NOTREACHED*/ } -static AbsoluteTime sched_tick_interval, sched_tick_deadline; +static uint64_t sched_tick_interval, sched_tick_deadline; + +void sched_tick_thread(void); + +void +sched_tick_init(void) +{ + kernel_thread_with_priority( + kernel_task, MAXPRI_STANDARD, + sched_tick_thread, TRUE, TRUE); +} /* * sched_tick_thread @@ -2245,7 +2127,7 @@ static AbsoluteTime sched_tick_interval, sched_tick_deadline; void sched_tick_thread_continue(void) { - AbsoluteTime abstime; + uint64_t abstime; #if SIMPLE_CLOCK int new_usec; #endif /* SIMPLE_CLOCK */ @@ -2291,16 +2173,6 @@ sched_tick_thread(void) spl_t s; stack_privilege(self); - thread_swappable(self->top_act, FALSE); - - s = splsched(); - thread_lock(self); - - self->priority = MAXPRI_STANDARD; - self->sched_pri = self->priority; - - thread_unlock(self); - splx(s); rate = (1000 >> SCHED_TICK_SHIFT); clock_interval_to_absolutetime_interval(rate, USEC_PER_SEC, @@ -2354,8 +2226,8 @@ do_runq_scan( q = runq->queues + runq->highq; while (count > 0) { queue_iterate(q, thread, thread_t, links) { - if ( !(thread->state & (TH_WAIT|TH_SUSP)) && - thread->policy == POLICY_TIMESHARE ) { + if ( !(thread->state & (TH_WAIT|TH_SUSP)) && + (thread->sched_mode & TH_MODE_TIMESHARE) ) { if (thread->sched_stamp != sched_tick) { /* * Stuck, save its id for later. @@ -2423,6 +2295,16 @@ do_thread_scan(void) if (restart_needed = do_runq_scan(&processor->runq)) break; + thread = processor->idle_thread; + if (thread->sched_stamp != sched_tick) { + if (stuck_count == MAX_STUCK_THREADS) { + restart_needed = TRUE; + break; + } + + stuck_threads[stuck_count++] = thread; + } + processor = (processor_t)queue_next(&processor->processors); } simple_unlock(&pset->processors_lock); @@ -2436,14 +2318,16 @@ do_thread_scan(void) stuck_threads[stuck_count] = THREAD_NULL; s = splsched(); thread_lock(thread); - if (thread->policy == POLICY_TIMESHARE) { + if ( (thread->sched_mode & TH_MODE_TIMESHARE) || + (thread->state & TH_IDLE) ) { if ( !(thread->state & (TH_WAIT|TH_SUSP)) && - thread->sched_stamp != sched_tick ) + thread->sched_stamp != sched_tick ) update_priority(thread); } thread_unlock(thread); splx(s); - thread_deallocate(thread); + if (!(thread->state & TH_IDLE)) + thread_deallocate(thread); } } while (restart_needed); @@ -2464,21 +2348,15 @@ thread_wakeup( thread_wakeup_with_result(x, THREAD_AWAKENED); } -boolean_t +#if DEBUG + +static boolean_t thread_runnable( - thread_t thread) + thread_t thread) { - sched_policy_t *policy; - - /* Ask sched policy if thread is runnable */ - policy = policy_id_to_sched_policy(thread->policy); - - return ((policy != SCHED_POLICY_NULL)? - policy->sp_ops.sp_thread_runnable(policy, thread) : FALSE); + return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN); } -#if DEBUG - void dump_processor_set( processor_set_t ps) @@ -2495,8 +2373,7 @@ dump_processor_set( printf("ref_count: 0x%x, active: %x\n", ps->ref_count,ps->active); printf("pset_self: %08x, pset_name_self: %08x\n",ps->pset_self, ps->pset_name_self); - printf("max_priority: 0x%x, policies: 0x%x, set_quantum: 0x%x\n", - ps->max_priority, ps->policies, ps->set_quantum); + printf("set_quanta: 0x%x\n", ps->set_quanta); } #define processor_state(s) (((s)>PROCESSOR_SHUTDOWN)?"*unknown*":states[s]) @@ -2513,8 +2390,7 @@ dump_processor( p->processor_queue.next,p->processor_queue.prev); printf("state: %8s, next_thread: %08x, idle_thread: %08x\n", processor_state(p->state), p->next_thread, p->idle_thread); - printf("quantum: %u, first_quantum: %x, last_quantum: %u\n", - p->quantum, p->first_quantum, p->last_quantum); + printf("slice_quanta: %x\n", p->slice_quanta); printf("processor_set: %08x, processor_set_next: %08x\n", p->processor_set, p->processor_set_next); printf("processors: %08x %08x\n", p->processors.next,p->processors.prev); diff --git a/osfmk/kern/sched_prim.h b/osfmk/kern/sched_prim.h index b978cb01f..cd9e8e8d4 100644 --- a/osfmk/kern/sched_prim.h +++ b/osfmk/kern/sched_prim.h @@ -151,7 +151,7 @@ extern void compute_my_priority( thread_t thread); /* Periodic scheduler activity */ -extern void sched_tick_thread(void); +extern void sched_tick_init(void); /* Update priority of thread that has been sleeping or suspended. * Used to "catch up" with the system. @@ -288,11 +288,11 @@ extern void thread_bind( /* Set timer for current thread */ extern void thread_set_timer( - natural_t interval, - natural_t scale_factor); + uint32_t interval, + uint32_t scale_factor); extern void thread_set_timer_deadline( - AbsoluteTime deadline); + uint64_t deadline); extern void thread_cancel_timer(void); @@ -366,5 +366,13 @@ MACRO_BEGIN \ thread_block((void (*)(void)) 0); \ MACRO_END +#if !defined(MACH_KERNEL_PRIVATE) && !defined(ABSOLUTETIME_SCALAR_TYPE) + +#include <libkern/OSBase.h> + +#define thread_set_timer_deadline(a) \ + thread_set_timer_deadline(__OSAbsoluteTime(a)) + +#endif #endif /* _KERN_SCHED_PRIM_H_ */ diff --git a/osfmk/kern/sf.c b/osfmk/kern/sf.c deleted file mode 100644 index bde79e5a2..000000000 --- a/osfmk/kern/sf.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - * - */ - -#include <kern/sf.h> -#include <kern/mk_sp.h> -#include <mach/policy.h> - -sched_policy_t sched_policy[MAX_SCHED_POLS]; - -void -sf_init(void) -{ - sched_policy[POLICY_TIMESHARE].policy_id = POLICY_TIMESHARE; - sched_policy[POLICY_RR].policy_id = POLICY_RR; - sched_policy[POLICY_FIFO].policy_id = POLICY_FIFO; - - sched_policy[POLICY_TIMESHARE].sp_ops = - sched_policy[POLICY_RR].sp_ops = - sched_policy[POLICY_FIFO].sp_ops = mk_sp_ops; -} diff --git a/osfmk/kern/sf.h b/osfmk/kern/sf.h deleted file mode 100644 index f3810d0a6..000000000 --- a/osfmk/kern/sf.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - * - */ - -#ifndef _KERN_SF_H_ -#define _KERN_SF_H_ - -/* - * The calls most likely to change are: policy_thread_done and - * policy_thread_begin. They're the policy calls related to - * context switching. I'm not satisfied with what I have now and - * these are the forms I'm trying next. - * - * I still have to merge the data type names from my different sandboxes - * and I don't really talk about locking except for the run queue locking. - * - * There is a big change for run queues: there is a single lock for an - * entire run queue array structure (instead of a lock per queue header). - * It's OK for a policy to reorganize a particular queue BUT it has to - * disable the queue header (sched_queue_disable). Since a queue header - * isn't shared by multiple policies and the framework won't touch the - * queue header if it's disabled, the policy can do anything it wants - * without taking out a global lock. - * - * The only run queue primitives provided are the really fast ones: - * insert at the head (sched_queue_preempt), insert at the tail - * and if the queue was empty check for preemption - * (sched_queue_add_preempt), just insert at the tail - * (sched_queue_add_only), and remove (sched_queue_remove). Everything - * else needs to be done by first disabling the queue header (and then - * you can do whatever you want to the queue). - * - * BTW, the convention here is: - * - * policy_xxx - calls from the framework into policies (via the - * pointers in the policy object) - * - * sched_xxx - scheduling mechanisms provided by the framework - * which can be called by policies. - * - * ---------- - * - * Initializes an instance of a scheduling policy assigning it the - * corresponding policy_id and run queue headers. - * - * policy_init( - * sched_policy_object *policy, - * int policy_id, - * int minpri, maxpri); - * - * Enable/disable a scheduling policy on a processor [set] - * - * policy_enable_processor_set( - * sched_policy_object *policy, / * policy * / - * processor_set_t processor_set ); / * processor set * / - * - * policy_disable_processor_set( - * sched_policy_object *policy, - * processor_set_t processor_set); - * - * policy_enable_processor( - * sched_policy_object *policy, - * processor_t processor ); - * - * policy_disable_processor( - * sched_policy_object *policy, - * processor_t processor); - * - * Notifies the policy that the thread has become runnable - * - * policy_thread_unblock( - * sched_policy_object *policy, - * thread_t thread ) - * - * Notifies the policy that the current thread is done or - * a new thread has been selected to run - * - * policy_thread_done( - * sched_policy_object *policy, - * thread_t *old_thread ); - * - * policy_thread_begin( - * sched_policy_object *policy, - * thread_t *new_thread ); - * - * Attach/detach a thread from the scheduling policy - * - * policy_thread_attach( - * sched_policy_object *policy, - * thread_t *thread ); - * - * policy_thread_detach( - * sched_policy_object *policy, - * thread_t *thread ); - * - * Set the thread's processor [set] - * - * policy_thread_processor( - * sched_policy_object *policy, - * thread_t *thread, - * processor_t processor ); - * - * policy_thread_processor_set( - * sched_policy_object *policy, - * thread_t *thread, - * processor_set_t processor_set); - * - * Scheduling Framework Interfaces - * - * [en/dis]able particular run queue headers on a processor [set], - * - * Lock the run queues, update the mask, unlock the run queues. If - * enabling, check preemption. - * - * sched_queue_enable( - * run_queue_t runq, - * sched_priority_mask *mask ); - * - * sched_queue_disable( - * run_queue_t runq, - * sched_priority_mask *mask ); - * - * Lock the run queues, insert the thread at the head, unlock the - * run queues and preempt (if possible). - * - * sched_queue_preempt( - * integer_t priority, - * thread_t thread, - * run_queue_t run_queues ); - * - * Lock the run queues, add the thread to the tail, unlock the run queues - * and preempt if appropriate. - * - * sched_queue_add_preempt( - * integer_t priority, - * thread_t thread, - * run_queue_t run_queues ); - * - * Lock the run queues, add the thread to the tail, unlock the queues - * but don't check for preemption. - * - * sched_queue_add_only( - * integer_t priority, - * thread_t thread, - * run_queue_t run_queues ); - * - * Lock the run queues, remove the entry the thread, unlock the run queues. - * - * sched_queue_remove( - * thread_t thread ); - */ - -#include <kern/kern_types.h> -#include <kern/sched.h> -#include <mach/thread_switch.h> -#include <mach/mach_types.h> - -/* - * Type definitions and constants for MK Scheduling Framework - */ -typedef int sf_return_t; - -/* successful completion */ -#define SF_SUCCESS 0 - -/* error codes */ -#define SF_FAILURE 1 -#define SF_KERN_RESOURCE_SHORTAGE 2 - -/* Scheduler Framework Object -- i.e., a scheduling policy */ -typedef struct sf_policy *sf_object_t; - -/* - * maximum number of scheduling policies that the Scheduling Framework - * will host (picked arbitrarily) - */ -#define MAX_SCHED_POLS 10 - -/********** - * - * Scheduling Framework Interfaces - * - **********/ - -/* Initialize Framework and selected policies */ -void sf_init(void); - -/********** - * - * Scheduling Policy Interfaces - * - **********/ - -/* - * Operation list for scheduling policies. (Modeled after the - * device operations `.../mach_kernel/device/conf.h.') - * - * Key to some abbreviations: - * sp = scheduling policy - * sf = scheduling framework - */ -typedef struct sched_policy_ops { - /* Allow the policy to update the meta-priority of a running thread */ - sf_return_t (*sp_thread_update_mpri)( - sf_object_t policy, - thread_t thread); - - /* Notify the policy that a thread has become runnable */ - sf_return_t (*sp_thread_unblock)( - sf_object_t policy, - thread_t thread); - - /* Notify the policy that the current thread is done */ - /*** ??? Should this call take a `reason' argument? ***/ - sf_return_t (*sp_thread_done)( - sf_object_t policy, - thread_t old_thread); - - /* Notify the policy that a new thread has been selected to run */ - sf_return_t (*sp_thread_begin)( - sf_object_t policy, - thread_t new_thread); - - /* Notify the policy that an old thread is ready to be requeued */ - sf_return_t (*sp_thread_dispatch)( - sf_object_t policy, - thread_t old_thread); - - /* Attach/detach a thread from the scheduling policy */ - sf_return_t (*sp_thread_attach)( - sf_object_t policy, - thread_t thread); - - sf_return_t (*sp_thread_detach)( - sf_object_t policy, - thread_t thread); - - /* Set the thread's processor [set] */ - sf_return_t (*sp_thread_processor)( - sf_object_t policy, - thread_t *thread, - processor_t processor); - - sf_return_t (*sp_thread_processor_set)( - sf_object_t policy, - thread_t thread, - processor_set_t processor_set); - - sf_return_t (*sp_thread_setup)( - sf_object_t policy, - thread_t thread); - - /*** - *** ??? Hopefully, many of the following operations are only - *** temporary. Consequently, they haven't been forced to take - *** the same form as the others just yet. That should happen - *** for all of those that end up being permanent additions to the - *** list of standard operations. - ***/ - - /* `swtch_pri()' routine -- attempt to give up processor */ - void (*sp_swtch_pri)( - sf_object_t policy, - int pri); - - /* `thread_switch()' routine -- context switch w/ optional hint */ - kern_return_t (*sp_thread_switch)( - sf_object_t policy, - thread_act_t hint_act, - int option, - mach_msg_timeout_t option_time); - - /* `thread_depress_abort()' routine -- prematurely abort depression */ - kern_return_t (*sp_thread_depress_abort)( - sf_object_t policy, - thread_t thread); - - /* `thread_depress_timeout()' routine -- timeout on depression */ - void (*sp_thread_depress_timeout)( - sf_object_t policy, - thread_t thread); - - boolean_t (*sp_thread_runnable)( - sf_object_t policy, - thread_t thread); - -} sp_ops_t; - -/********** - * - * Scheduling Policy - * - **********/ - -typedef struct sf_policy { - int policy_id; /* policy number */ - sp_ops_t sp_ops; -} sched_policy_t; - -#define SCHED_POLICY_NULL ((sched_policy_t *) 0) - -#define policy_id_to_sched_policy(policy_id) \ - (((policy_id) != POLICY_NULL)? \ - &sched_policy[(policy_id)] : SCHED_POLICY_NULL) - -extern sched_policy_t sched_policy[MAX_SCHED_POLS]; - -#endif /* _KERN_SF_H_ */ diff --git a/osfmk/kern/simple_lock.h b/osfmk/kern/simple_lock.h index 7529bb018..f22979f3b 100644 --- a/osfmk/kern/simple_lock.h +++ b/osfmk/kern/simple_lock.h @@ -89,6 +89,7 @@ #include <kern/kern_types.h> #include <kern/simple_lock_types.h> +#include <machine/lock.h> #include <mach/etap_events.h> #include <mach/etap.h> @@ -153,6 +154,8 @@ extern unsigned int hw_lock_mbits(unsigned int *, unsigned int, unsigned int, void hw_unlock_bit(unsigned int *, unsigned int); extern int hw_atomic_add(int *area, int inc); extern int hw_atomic_sub(int *area, int dec); +extern int hw_atomic_or(int *area, int val); +extern int hw_atomic_and(int *area, int mask); extern unsigned int hw_compare_and_store(unsigned int oldValue, unsigned int newValue, unsigned int *area); extern void hw_queue_atomic(unsigned int *anchor, unsigned int *elem, unsigned int disp); extern void hw_queue_atomic_list(unsigned int *anchor, unsigned int *first, unsigned int *last, unsigned int disp); diff --git a/osfmk/kern/spl.h b/osfmk/kern/spl.h index 2eae497c5..e7553a211 100644 --- a/osfmk/kern/spl.h +++ b/osfmk/kern/spl.h @@ -24,14 +24,10 @@ typedef unsigned spl_t; -extern spl_t (splhigh)(void); /* Block all interrupts */ - -extern spl_t (splsched)(void); /* Block all scheduling activity */ - -extern spl_t (splclock)(void); /* Block clock interrupt */ - -extern void (splx)(spl_t); /* Restore previous level */ - -extern void (spllo)(void); /* Enable all interrupts */ +#define splhigh() (spl_t) ml_set_interrupts_enabled(FALSE) +#define splsched() (spl_t) ml_set_interrupts_enabled(FALSE) +#define splclock() (spl_t) ml_set_interrupts_enabled(FALSE) +#define splx(x) (void) ml_set_interrupts_enabled(x) +#define spllo() (void) ml_set_interrupts_enabled(TRUE) #endif /* _KERN_SPL_H_ */ diff --git a/osfmk/kern/startup.c b/osfmk/kern/startup.c index 7f94aeb7c..b3a5b0094 100644 --- a/osfmk/kern/startup.c +++ b/osfmk/kern/startup.c @@ -75,7 +75,7 @@ #include <kern/machine.h> #include <kern/processor.h> #include <kern/sched_prim.h> -#include <kern/sf.h> +#include <kern/mk_sp.h> #include <kern/startup.h> #include <kern/task.h> #include <kern/thread.h> @@ -122,7 +122,6 @@ setup_main(void) ipc_bootstrap(); vm_mem_init(); ipc_init(); - pager_mux_hash_init(); /* * As soon as the virtual memory system is up, we record @@ -151,7 +150,6 @@ setup_main(void) * Initialize the IPC, task, and thread subsystems. */ ledger_init(); - swapper_init(); task_init(); act_init(); thread_init(); @@ -169,8 +167,9 @@ setup_main(void) * thread_setrun, which may look at current thread; * we must avoid this, since there is no current thread. */ - startup_thread = kernel_thread_with_priority(kernel_task, MAXPRI_KERNBAND, - start_kernel_threads, FALSE); + startup_thread = kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL, + start_kernel_threads, TRUE, FALSE); /* * Pretend it is already running, and resume it. @@ -206,24 +205,34 @@ start_kernel_threads(void) * service threads. */ for (i = 0; i < NCPUS; i++) { - if (1 /*machine_slot[i].is_cpu*/) { - processor_t processor = cpu_to_processor(i); - thread_t thread; - spl_t s; - - thread = kernel_thread_with_priority(kernel_task, - MAXPRI_KERNBAND, idle_thread, FALSE); - s = splsched(); - thread_lock(thread); - thread_bind_locked(thread, processor); - processor->idle_thread = thread; - thread->state |= TH_IDLE; - thread_go_locked(thread, THREAD_AWAKENED); - thread_unlock(thread); - splx(s); - } + processor_t processor = cpu_to_processor(i); + thread_t thread; + spl_t s; + + thread = kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL, + idle_thread, TRUE, FALSE); + s = splsched(); + thread_lock(thread); + thread_bind_locked(thread, processor); + processor->idle_thread = thread; + thread->ref_count++; + thread->state |= TH_IDLE; + thread_go_locked(thread, THREAD_AWAKENED); + thread_unlock(thread); + splx(s); } + /* + * Initialize the stack swapin mechanism. + */ + swapin_init(); + + /* + * Initialize the periodic scheduler mechanism. + */ + sched_tick_init(); + /* * Initialize the thread callout mechanism. */ @@ -237,20 +246,10 @@ start_kernel_threads(void) #endif /* - * Invoke the thread reaper mechanism. + * Initialize the thread reaper mechanism. */ thread_reaper(); - /* - * Start the stack swapin thread - */ - kernel_thread(kernel_task, swapin_thread); - - /* - * Invoke the periodic scheduler mechanism. - */ - kernel_thread(kernel_task, sched_tick_thread); - /* * Create the clock service. */ @@ -303,6 +302,7 @@ slave_main(void) if (thread == THREAD_NULL) { thread = machine_wake_thread; machine_wake_thread = THREAD_NULL; + thread_bind(thread, myprocessor); } cpu_launch_first_thread(thread); /*NOTREACHED*/ @@ -326,11 +326,6 @@ start_cpu_thread(void) ipc_processor_enable(processor); } -#if 0 - printf("start_cpu_thread done on cpu %x\n", cpu_number()); -#endif - /* TODO: Mark this processor ready to dispatch threads */ - (void) thread_terminate(current_act()); } @@ -348,6 +343,7 @@ cpu_launch_first_thread( cpu_up(mycpu); start_timer(&kernel_timer[mycpu]); + clock_get_uptime(&cpu_to_processor(mycpu)->last_dispatch); if (thread == THREAD_NULL) { thread = cpu_to_processor(mycpu)->idle_thread; @@ -361,6 +357,7 @@ cpu_launch_first_thread( thread_machine_set_current(thread); thread_lock(thread); thread->state &= ~TH_UNINT; + _mk_sp_thread_begin(thread); thread_unlock(thread); timer_switch(&thread->system_timer); diff --git a/osfmk/kern/sync_lock.c b/osfmk/kern/sync_lock.c index 5849f6883..c6b997e54 100644 --- a/osfmk/kern/sync_lock.c +++ b/osfmk/kern/sync_lock.c @@ -317,7 +317,7 @@ lock_acquire (lock_set_t lock_set, int lock_id) } ulock->blocked = TRUE; - wait_queue_assert_wait(&ulock->wait_queue, + (void)wait_queue_assert_wait(&ulock->wait_queue, LOCK_SET_EVENT, THREAD_ABORTSAFE); ulock_unlock(ulock); @@ -681,7 +681,7 @@ lock_handoff (lock_set_t lock_set, int lock_id) * for an accepting thread. */ ulock->ho_wait = TRUE; - wait_queue_assert_wait(&ulock->wait_queue, + (void)wait_queue_assert_wait(&ulock->wait_queue, LOCK_SET_HANDOFF, THREAD_ABORTSAFE); ulock_unlock(ulock); @@ -792,7 +792,7 @@ lock_handoff_accept (lock_set_t lock_set, int lock_id) } ulock->accept_wait = TRUE; - wait_queue_assert_wait(&ulock->wait_queue, + (void)wait_queue_assert_wait(&ulock->wait_queue, LOCK_SET_HANDOFF, THREAD_ABORTSAFE); ulock_unlock(ulock); diff --git a/osfmk/kern/sync_sema.c b/osfmk/kern/sync_sema.c index 8fe37c371..d7bc25187 100644 --- a/osfmk/kern/sync_sema.c +++ b/osfmk/kern/sync_sema.c @@ -557,7 +557,7 @@ semaphore_wait_internal( void (*caller_cont)(kern_return_t)) { void (*continuation)(void); - AbsoluteTime abstime, nsinterval; + uint64_t abstime, nsinterval; boolean_t nonblocking; int wait_result; spl_t spl_level; @@ -582,7 +582,7 @@ semaphore_wait_internal( kr = KERN_OPERATION_TIMED_OUT; } else { wait_semaphore->count = -1; /* we don't keep an actual count */ - wait_queue_assert_wait_locked(&wait_semaphore->wait_queue, + (void)wait_queue_assert_wait_locked(&wait_semaphore->wait_queue, SEMAPHORE_EVENT, THREAD_ABORTSAFE, FALSE); /* unlock? */ @@ -648,7 +648,7 @@ semaphore_wait_internal( clock_interval_to_absolutetime_interval(wait_timep->tv_nsec, 1, &nsinterval); - ADD_ABSOLUTETIME(&abstime, &nsinterval); + abstime += nsinterval; clock_absolutetime_interval_to_deadline(abstime, &abstime); thread_set_timer_deadline(abstime); continuation = semaphore_timedwait_continue; diff --git a/osfmk/kern/syscall_subr.c b/osfmk/kern/syscall_subr.c index caca3545a..b5ff64c69 100644 --- a/osfmk/kern/syscall_subr.c +++ b/osfmk/kern/syscall_subr.c @@ -50,8 +50,6 @@ /* */ -#include <cpus.h> - #include <mach/boolean.h> #include <mach/thread_switch.h> #include <ipc/ipc_port.h> @@ -72,7 +70,7 @@ #include <mach/mach_host_server.h> #include <mach/mach_syscalls.h> -#include <kern/sf.h> +#include <kern/mk_sp.h> /* * swtch and swtch_pri both attempt to context switch (logic in @@ -88,27 +86,21 @@ * lock and then be a good citizen and really suspend. */ -#if 0 - -/* broken..do not enable */ - -swtch_continue() +void +swtch_continue(void) { - boolean_t retval; - register processor_t myprocessor; + register processor_t myprocessor; + boolean_t result; mp_disable_preemption(); myprocessor = current_processor(); - retval = ( -#if NCPUS > 1 - myprocessor->runq.count > 0 || -#endif /*NCPUS > 1*/ - myprocessor->processor_set->runq.count > 0); + result = myprocessor->runq.count > 0 || + myprocessor->processor_set->runq.count > 0; mp_enable_preemption(); - return retval; -} -#endif + thread_syscall_return(result); + /*NOTREACHED*/ +} boolean_t swtch(void) @@ -118,10 +110,7 @@ swtch(void) mp_disable_preemption(); myprocessor = current_processor(); - if ( -#if NCPUS > 1 - myprocessor->runq.count == 0 && -#endif /* NCPUS > 1 */ + if ( myprocessor->runq.count == 0 && myprocessor->processor_set->runq.count == 0 ) { mp_enable_preemption(); @@ -131,57 +120,64 @@ swtch(void) counter(c_swtch_block++); - thread_block((void (*)(void)) 0); + thread_block(swtch_continue); mp_disable_preemption(); myprocessor = current_processor(); - result = -#if NCPUS > 1 - myprocessor->runq.count > 0 || -#endif /*NCPUS > 1*/ - myprocessor->processor_set->runq.count > 0; + result = myprocessor->runq.count > 0 || + myprocessor->processor_set->runq.count > 0; mp_enable_preemption(); return (result); } +void +swtch_pri_continue(void) +{ + register processor_t myprocessor; + boolean_t result; + + _mk_sp_thread_depress_abort(current_thread(), FALSE); + + mp_disable_preemption(); + myprocessor = current_processor(); + result = myprocessor->runq.count > 0 || + myprocessor->processor_set->runq.count > 0; + mp_enable_preemption(); + + thread_syscall_return(result); + /*NOTREACHED*/ +} + boolean_t swtch_pri( int pri) { - thread_t self = current_thread(); register processor_t myprocessor; boolean_t result; - sched_policy_t *policy; - spl_t s; - s = splsched(); - thread_lock(self); + mp_disable_preemption(); myprocessor = current_processor(); - if ( -#if NCPUS > 1 - myprocessor->runq.count == 0 && -#endif /* NCPUS > 1 */ + if ( myprocessor->runq.count == 0 && myprocessor->processor_set->runq.count == 0 ) { - thread_unlock(self); - splx(s); + mp_enable_preemption(); return (FALSE); } + mp_enable_preemption(); + + counter(c_swtch_pri_block++); + + _mk_sp_thread_depress_abstime(std_quantum); - policy = &sched_policy[self->policy]; - thread_unlock(self); - splx(s); + thread_block(swtch_pri_continue); - policy->sp_ops.sp_swtch_pri(policy, pri); + _mk_sp_thread_depress_abort(current_thread(), FALSE); mp_disable_preemption(); myprocessor = current_processor(); - result = -#if NCPUS > 1 - myprocessor->runq.count > 0 || -#endif /*NCPUS > 1*/ - myprocessor->processor_set->runq.count > 0; + result = myprocessor->runq.count > 0 || + myprocessor->processor_set->runq.count > 0; mp_enable_preemption(); return (result); @@ -200,8 +196,6 @@ thread_switch( { register thread_t self = current_thread(); register thread_act_t hint_act = THR_ACT_NULL; - sched_policy_t *policy; - spl_t s; /* * Process option. @@ -230,17 +224,5 @@ thread_switch( } } - s = splsched(); - thread_lock(self); - policy = &sched_policy[self->policy]; - thread_unlock(self); - splx(s); - - /* - * This is a scheduling policy-dependent operation. - * Call the routine associated with the thread's - * scheduling policy. - */ - return (policy->sp_ops. - sp_thread_switch(policy, hint_act, option, option_time)); + return _mk_sp_thread_switch(hint_act, option, option_time); } diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c index bea0f27d0..aa8b142f6 100644 --- a/osfmk/kern/task.c +++ b/osfmk/kern/task.c @@ -98,8 +98,6 @@ #include <kern/kalloc.h> #include <kern/processor.h> #include <kern/sched_prim.h> /* for thread_wakeup */ -#include <kern/sf.h> -#include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ #include <kern/ipc_tt.h> #include <kern/ledger.h> #include <kern/host.h> @@ -122,6 +120,7 @@ #include <mach/task_server.h> #include <mach/mach_host_server.h> #include <mach/host_security_server.h> +#include <vm/task_working_set.h> task_t kernel_task; zone_t task_zone; @@ -354,7 +353,7 @@ task_create_local( new_task->res_act_count = 0; new_task->active_act_count = 0; new_task->user_stop_count = 0; - new_task->importance = 0; + new_task->role = TASK_UNSPECIFIED; new_task->active = TRUE; new_task->kernel_loaded = kernel_loaded; new_task->user_data = 0; @@ -366,6 +365,10 @@ task_create_local( new_task->syscalls_mach = 0; new_task->syscalls_unix=0; new_task->csw=0; + new_task->dynamic_working_set = 0; + + task_working_set_create(new_task, TWS_SMALL_HASH_LINE_COUNT, + 0, TWS_HASH_STYLE_DEFAULT); #ifdef MACH_BSD new_task->bsd_info = 0; @@ -412,11 +415,6 @@ task_create_local( if (!pset->active) pset = &default_pset; - new_task->policy = parent_task->policy; - - new_task->priority = parent_task->priority; - new_task->max_priority = parent_task->max_priority; - new_task->sec_token = parent_task->sec_token; shared_region_mapping_ref(parent_task->system_shared_region); @@ -430,24 +428,20 @@ task_create_local( else { pset = &default_pset; - if (kernel_task == TASK_NULL) { - new_task->policy = POLICY_RR; - - new_task->priority = MINPRI_KERNBAND; - new_task->max_priority = MAXPRI_KERNBAND; - } - else { - new_task->policy = POLICY_TIMESHARE; - - new_task->priority = BASEPRI_DEFAULT; - new_task->max_priority = MAXPRI_HIGHBAND; - } - new_task->sec_token = KERNEL_SECURITY_TOKEN; new_task->wired_ledger_port = ledger_copy(root_wired_ledger); new_task->paged_ledger_port = ledger_copy(root_paged_ledger); } + if (kernel_task == TASK_NULL) { + new_task->priority = MINPRI_KERNEL; + new_task->max_priority = MAXPRI_KERNEL; + } + else { + new_task->priority = BASEPRI_DEFAULT; + new_task->max_priority = MAXPRI_USER; + } + pset_lock(pset); pset_add_task(pset, new_task); pset_unlock(pset); @@ -555,6 +549,9 @@ task_free( vm_map_deallocate(task->map); is_release(task->itk_space); task_prof_deallocate(task); + if(task->dynamic_working_set) + tws_hash_destroy((tws_hash_t) + task->dynamic_working_set); zfree(task_zone, (vm_offset_t) task); } @@ -1335,7 +1332,8 @@ task_info( * PAGE_SIZE; task_lock(task); - basic_info->policy = task->policy; + basic_info->policy = ((task != kernel_task)? + POLICY_TIMESHARE: POLICY_RR); basic_info->suspend_count = task->user_stop_count; basic_info->user_time.seconds = task->total_user_time.seconds; @@ -1404,24 +1402,11 @@ task_info( case TASK_SCHED_FIFO_INFO: { - register policy_fifo_base_t fifo_base; if (*task_info_count < POLICY_FIFO_BASE_COUNT) return(KERN_INVALID_ARGUMENT); - fifo_base = (policy_fifo_base_t) task_info_out; - - task_lock(task); - if (task->policy != POLICY_FIFO) { - task_unlock(task); - return(KERN_INVALID_POLICY); - } - - fifo_base->base_priority = task->priority; - task_unlock(task); - - *task_info_count = POLICY_FIFO_BASE_COUNT; - break; + return(KERN_INVALID_POLICY); } case TASK_SCHED_RR_INFO: @@ -1434,7 +1419,7 @@ task_info( rr_base = (policy_rr_base_t) task_info_out; task_lock(task); - if (task->policy != POLICY_RR) { + if (task != kernel_task) { task_unlock(task); return(KERN_INVALID_POLICY); } @@ -1442,7 +1427,7 @@ task_info( rr_base->base_priority = task->priority; task_unlock(task); - rr_base->quantum = (min_quantum * tick) / 1000; + rr_base->quantum = tick / 1000; *task_info_count = POLICY_RR_BASE_COUNT; break; @@ -1458,7 +1443,7 @@ task_info( ts_base = (policy_timeshare_base_t) task_info_out; task_lock(task); - if (task->policy != POLICY_TIMESHARE) { + if (task == kernel_task) { task_unlock(task); return(KERN_INVALID_POLICY); } @@ -1651,6 +1636,7 @@ task_collect_scan(void) task_deallocate(prev_task); } +/* Also disabled in vm/vm_pageout.c */ boolean_t task_collect_allowed = FALSE; unsigned task_collect_last_tick = 0; unsigned task_collect_max_rate = 0; /* in ticks */ @@ -1670,7 +1656,7 @@ consider_task_collect(void) */ if (task_collect_max_rate == 0) - task_collect_max_rate = (2 << SCHED_TICK_SHIFT); + task_collect_max_rate = (1 << SCHED_TICK_SHIFT) + 1; if (task_collect_allowed && (sched_tick > (task_collect_last_tick + task_collect_max_rate))) { diff --git a/osfmk/kern/task.h b/osfmk/kern/task.h index 36d0fe040..569fa0292 100644 --- a/osfmk/kern/task.h +++ b/osfmk/kern/task.h @@ -142,12 +142,10 @@ typedef struct task { /* User-visible scheduling information */ integer_t user_stop_count; /* outstanding stops */ - integer_t importance; /* system-wide importance */ + task_role_t role; - integer_t priority; /* base priority */ - integer_t max_priority; /* maximum priority */ - - integer_t policy; /* obsolete */ + integer_t priority; /* base priority for threads */ + integer_t max_priority; /* maximum priority for threads */ /* Task security token */ security_token_t sec_token; @@ -211,6 +209,7 @@ typedef struct task { void *bsd_info; #endif vm_offset_t system_shared_region; + vm_offset_t dynamic_working_set; } Task; @@ -281,6 +280,12 @@ extern boolean_t task_reference_try(task_t task); /* Remove reference to task */ extern void task_deallocate(task_t task); +#if defined(MACH_KERNEL_PRIVATE) || defined(BSD_BUILD) +extern kern_return_t task_importance( + task_t task, + integer_t importance); +#endif + /* JMM - should just be temporary (implementation in bsd_kern still) */ extern void *get_bsdtask_info(task_t); extern void set_bsdtask_info(task_t,void *); diff --git a/osfmk/kern/task_policy.c b/osfmk/kern/task_policy.c index 4b9eb5fee..42e38211e 100644 --- a/osfmk/kern/task_policy.c +++ b/osfmk/kern/task_policy.c @@ -28,7 +28,13 @@ * Created. */ -#include <mach/mach_types.h> +#include <kern/task.h> + +static void +task_priority( + task_t task, + integer_t priority, + integer_t max_priority); kern_return_t task_policy_set( @@ -37,7 +43,9 @@ task_policy_set( task_policy_t policy_info, mach_msg_type_number_t count) { - if (task == TASK_NULL) + kern_return_t result = KERN_SUCCESS; + + if (task == TASK_NULL || task == kernel_task) return (KERN_INVALID_ARGUMENT); switch (flavor) { @@ -49,29 +57,125 @@ task_policy_set( if (count < TASK_CATEGORY_POLICY_COUNT) return (KERN_INVALID_ARGUMENT); - switch (info->role) { - - case TASK_UNSPECIFIED: - case TASK_FOREGROUND_APPLICATION: - case TASK_BACKGROUND_APPLICATION: - case TASK_CONTROL_APPLICATION: - case TASK_GRAPHICS_SERVER: - return (KERN_SUCCESS); - - default: - return (KERN_INVALID_ARGUMENT); + task_lock(task); + + if ( info->role == TASK_FOREGROUND_APPLICATION || + info->role == TASK_BACKGROUND_APPLICATION ) { + switch (task->role) { + + case TASK_FOREGROUND_APPLICATION: + case TASK_BACKGROUND_APPLICATION: + case TASK_UNSPECIFIED: + task_priority(task, BASEPRI_DEFAULT + + ((info->role == TASK_FOREGROUND_APPLICATION)? +16: +15), + task->max_priority); + task->role = info->role; + break; + + case TASK_CONTROL_APPLICATION: + case TASK_RENICED: + /* fail silently */ + break; + + default: + result = KERN_INVALID_ARGUMENT; + break; + } } + else + if (info->role == TASK_CONTROL_APPLICATION) { + if ( task != current_task() || + task->sec_token.val[0] != 0 ) + result = KERN_INVALID_ARGUMENT; + else { + task_priority(task, BASEPRI_DEFAULT + 17, task->max_priority); + task->role = info->role; + } + } + else + if (info->role == TASK_GRAPHICS_SERVER) { + if ( task != current_task() || + task->sec_token.val[0] != 0 ) + result = KERN_INVALID_ARGUMENT; + else { + task_priority(task, MAXPRI_SYSTEM - 3, MAXPRI_SYSTEM); + task->role = info->role; + } + } + else + result = KERN_INVALID_ARGUMENT; + + task_unlock(task); break; } default: + result = KERN_INVALID_ARGUMENT; + break; + } + + return (result); +} + +static void +task_priority( + task_t task, + integer_t priority, + integer_t max_priority) +{ + thread_act_t act; + + task->max_priority = max_priority; + + if (priority > task->max_priority) + priority = task->max_priority; + else + if (priority < MINPRI) + priority = MINPRI; + + task->priority = priority; + + queue_iterate(&task->thr_acts, act, thread_act_t, thr_acts) { + thread_t thread = act_lock_thread(act); + + if (act->active) + thread_task_priority(thread, priority, max_priority); + + act_unlock_thread(act); + } +} + +kern_return_t +task_importance( + task_t task, + integer_t importance) +{ + if (task == TASK_NULL || task == kernel_task) + return (KERN_INVALID_ARGUMENT); + + task_lock(task); + + if (!task->active) { + task_unlock(task); + + return (KERN_TERMINATED); + } + + if (task->role >= TASK_CONTROL_APPLICATION) { + task_unlock(task); + return (KERN_INVALID_ARGUMENT); } + task_priority(task, importance + BASEPRI_DEFAULT, task->max_priority); + task->role = TASK_RENICED; + + task_unlock(task); + return (KERN_SUCCESS); } - + kern_return_t task_policy_get( task_t task, @@ -80,7 +184,7 @@ task_policy_get( mach_msg_type_number_t *count, boolean_t *get_default) { - if (task == TASK_NULL) + if (task == TASK_NULL || task == kernel_task) return (KERN_INVALID_ARGUMENT); switch (flavor) { @@ -92,7 +196,13 @@ task_policy_get( if (*count < TASK_CATEGORY_POLICY_COUNT) return (KERN_INVALID_ARGUMENT); - info->role = TASK_UNSPECIFIED; + if (*get_default) + info->role = TASK_UNSPECIFIED; + else { + task_lock(task); + info->role = task->role; + task_unlock(task); + } break; } diff --git a/osfmk/kern/thread.c b/osfmk/kern/thread.c index 8d4523b15..09d283ab6 100644 --- a/osfmk/kern/thread.c +++ b/osfmk/kern/thread.c @@ -80,7 +80,6 @@ #include <simple_clock.h> #include <mach_debug.h> #include <mach_prof.h> -#include <stack_usage.h> #include <mach/boolean.h> #include <mach/policy.h> @@ -102,7 +101,6 @@ #include <kern/queue.h> #include <kern/sched.h> #include <kern/sched_prim.h> -#include <kern/sf.h> #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ #include <kern/task.h> #include <kern/thread.h> @@ -146,32 +144,12 @@ extern void pcb_module_init(void); static struct thread_shuttle thr_sh_template; #if MACH_DEBUG -#if STACK_USAGE -static void stack_init(vm_offset_t stack, unsigned int bytes); -void stack_finalize(vm_offset_t stack); -vm_size_t stack_usage(vm_offset_t stack); -#else /*STACK_USAGE*/ -#define stack_init(stack, size) -#define stack_finalize(stack) -#define stack_usage(stack) (vm_size_t)0 -#endif /*STACK_USAGE*/ #ifdef MACHINE_STACK -extern -#endif - void stack_statistics( +extern void stack_statistics( unsigned int *totalp, vm_size_t *maxusagep); - -#define STACK_MARKER 0xdeadbeef -#if STACK_USAGE -boolean_t stack_check_usage = TRUE; -#else /* STACK_USAGE */ -boolean_t stack_check_usage = FALSE; -#endif /* STACK_USAGE */ -decl_simple_lock_data(,stack_usage_lock) -vm_size_t stack_max_usage = 0; -vm_size_t stack_max_use = KERNEL_STACK_SIZE - 64; +#endif /* MACHINE_STACK */ #endif /* MACH_DEBUG */ /* Forwards */ @@ -202,6 +180,7 @@ extern void Load_context( * stack_alloc_try * stack_alloc * stack_free + * stack_free_stack * stack_collect * and if MACH_DEBUG: * stack_statistics @@ -220,16 +199,20 @@ decl_simple_lock_data(,stack_lock_data) /* splsched only */ #define stack_lock() simple_lock(&stack_lock_data) #define stack_unlock() simple_unlock(&stack_lock_data) +mutex_t stack_map_lock; /* Lock when allocating stacks maps */ +vm_map_t stack_map; /* Map for allocating stacks */ vm_offset_t stack_free_list; /* splsched only */ unsigned int stack_free_max = 0; unsigned int stack_free_count = 0; /* splsched only */ -unsigned int stack_free_limit = 1; /* patchable */ +unsigned int stack_free_limit = 1; /* Arbitrary */ unsigned int stack_alloc_hits = 0; /* debugging */ unsigned int stack_alloc_misses = 0; /* debugging */ unsigned int stack_alloc_total = 0; unsigned int stack_alloc_hiwater = 0; +unsigned int stack_alloc_bndry = 0; + /* * The next field is at the base of the stack, @@ -249,14 +232,31 @@ stack_alloc( thread_t thread, void (*start_pos)(thread_t)) { - vm_offset_t stack; - spl_t s; + vm_offset_t stack = thread->kernel_stack; + spl_t s; - /* - * We first try the free list. It is probably empty, - * or stack_alloc_try would have succeeded, but possibly - * a stack was freed before the swapin thread got to us. - */ + if (stack) + return (stack); + +/* + * We first try the free list. It is probably empty, or + * stack_alloc_try would have succeeded, but possibly a stack was + * freed before the swapin thread got to us. + * + * We allocate stacks from their own map which is submaps of the + * kernel map. Because we want to have a guard page (at least) in + * front of each stack to catch evil code that overruns its stack, we + * allocate the stack on aligned boundaries. The boundary is + * calculated as the next power of 2 above the stack size. For + * example, a stack of 4 pages would have a boundry of 8, likewise 5 + * would also be 8. + * + * We limit the number of stacks to be one allocation chunk + * (THREAD_CHUNK) more than the maximum number of threads + * (THREAD_MAX). The extra is to allow for priviliged threads that + * can sometimes have 2 stacks. + * + */ s = splsched(); stack_lock(); @@ -268,49 +268,21 @@ stack_alloc( stack_unlock(); splx(s); - if (stack == 0) { - /* - * Kernel stacks should be naturally aligned, - * so that it is easy to find the starting/ending - * addresses of a stack given an address in the middle. - */ - - if (kmem_alloc_aligned(kernel_map, &stack, - round_page(KERNEL_STACK_SIZE)) != KERN_SUCCESS) - panic("stack_alloc"); - - stack_alloc_total++; - if (stack_alloc_total > stack_alloc_hiwater) - stack_alloc_hiwater = stack_alloc_total; + if (stack != 0) { /* Did we find a free one? */ + stack_attach(thread, stack, start_pos); /* Initialize it */ + return (stack); /* Send it on home */ + } + + if (kernel_memory_allocate( + stack_map, &stack, + KERNEL_STACK_SIZE, stack_alloc_bndry - 1, + KMA_KOBJECT) != KERN_SUCCESS) + panic("stack_alloc: no space left for stack maps"); -#if MACH_DEBUG - stack_init(stack, round_page(KERNEL_STACK_SIZE)); -#endif /* MACH_DEBUG */ + stack_alloc_total++; + if (stack_alloc_total > stack_alloc_hiwater) + stack_alloc_hiwater = stack_alloc_total; - /* - * If using fractional pages, free the remainder(s) - */ - if (KERNEL_STACK_SIZE < round_page(KERNEL_STACK_SIZE)) { - vm_offset_t ptr = stack + KERNEL_STACK_SIZE; - vm_offset_t endp = stack + round_page(KERNEL_STACK_SIZE); - while (ptr < endp) { -#if MACH_DEBUG - /* - * We need to initialize just the end of the - * region. - */ - stack_init(ptr, (unsigned int) (endp - ptr)); -#endif - stack_lock(); - stack_next(stack) = stack_free_list; - stack_free_list = stack; - if (++stack_free_count > stack_free_max) - stack_free_max = stack_free_count; - stack_unlock(); - ptr += KERNEL_STACK_SIZE; - } - } - } stack_attach(thread, stack, start_pos); return (stack); } @@ -327,17 +299,34 @@ stack_free( thread_t thread) { vm_offset_t stack = stack_detach(thread); + assert(stack); if (stack != thread->stack_privilege) { - stack_lock(); - stack_next(stack) = stack_free_list; - stack_free_list = stack; - if (++stack_free_count > stack_free_max) - stack_free_max = stack_free_count; - stack_unlock(); + stack_lock(); + stack_next(stack) = stack_free_list; + stack_free_list = stack; + if (++stack_free_count > stack_free_max) + stack_free_max = stack_free_count; + stack_unlock(); } } +static void +stack_free_stack( + vm_offset_t stack) +{ + spl_t s; + + s = splsched(); + stack_lock(); + stack_next(stack) = stack_free_list; + stack_free_list = stack; + if (++stack_free_count > stack_free_max) + stack_free_max = stack_free_count; + stack_unlock(); + splx(s); +} + /* * stack_collect: * @@ -348,14 +337,9 @@ stack_free( void stack_collect(void) { - register vm_offset_t stack; - spl_t s; - - /* If using fractional pages, Cannot just call kmem_free(), - * and we're too lazy to coalesce small chunks. - */ - if (KERNEL_STACK_SIZE < round_page(KERNEL_STACK_SIZE)) - return; + vm_offset_t stack; + int i; + spl_t s; s = splsched(); stack_lock(); @@ -366,14 +350,14 @@ stack_collect(void) stack_unlock(); splx(s); -#if MACH_DEBUG - stack_finalize(stack); -#endif /* MACH_DEBUG */ - kmem_free(kernel_map, stack, KERNEL_STACK_SIZE); + if (vm_map_remove( + stack_map, stack, stack + KERNEL_STACK_SIZE, + VM_MAP_REMOVE_KUNWIRE) != KERN_SUCCESS) + panic("stack_collect: vm_map_remove failed"); s = splsched(); - stack_alloc_total--; stack_lock(); + stack_alloc_total--; } stack_unlock(); splx(s); @@ -398,27 +382,9 @@ stack_statistics( s = splsched(); stack_lock(); -#if STACK_USAGE - if (stack_check_usage) { - vm_offset_t stack; - - /* - * This is pretty expensive to do at splsched, - * but it only happens when someone makes - * a debugging call, so it should be OK. - */ - - for (stack = stack_free_list; stack != 0; - stack = stack_next(stack)) { - vm_size_t usage = stack_usage(stack); - - if (usage > *maxusagep) - *maxusagep = usage; - } - } -#endif /* STACK_USAGE */ - *totalp = stack_free_count; + *maxusagep = 0; + stack_unlock(); splx(s); } @@ -472,34 +438,53 @@ boolean_t stack_alloc_try( thread_t thread, void (*start_pos)(thread_t)) { - register vm_offset_t stack; - - if ((stack = thread->stack_privilege) == (vm_offset_t)0) { - stack_lock(); - stack = stack_free_list; - if (stack != (vm_offset_t)0) { - stack_free_list = stack_next(stack); - stack_free_count--; - } - stack_unlock(); + register vm_offset_t stack = thread->stack_privilege; + + if (stack == 0) { + stack_lock(); + + stack = stack_free_list; + if (stack != (vm_offset_t)0) { + stack_free_list = stack_next(stack); + stack_free_count--; + } + + stack_unlock(); } if (stack != 0) { stack_attach(thread, stack, start_pos); stack_alloc_hits++; - return TRUE; - } else { + + return (TRUE); + } + else { stack_alloc_misses++; - return FALSE; + + return (FALSE); } } -natural_t min_quantum_abstime; -extern natural_t min_quantum_ms; +uint64_t max_unsafe_computation; +extern int max_unsafe_quanta; + +uint32_t sched_safe_duration; + +uint64_t max_poll_computation; +extern int max_poll_quanta; + +uint32_t std_quantum; +uint32_t min_std_quantum; + +uint32_t max_rt_quantum; +uint32_t min_rt_quantum; void thread_init(void) { + kern_return_t ret; + unsigned int stack; + thread_shuttle_zone = zinit( sizeof(struct thread_shuttle), THREAD_MAX * sizeof(struct thread_shuttle), @@ -527,27 +512,33 @@ thread_init(void) thr_sh_template.wait_result = KERN_SUCCESS; thr_sh_template.wait_queue = WAIT_QUEUE_NULL; thr_sh_template.wake_active = FALSE; - thr_sh_template.state = TH_WAIT|TH_UNINT; + thr_sh_template.state = TH_STACK_HANDOFF | TH_WAIT | TH_UNINT; thr_sh_template.interruptible = TRUE; thr_sh_template.continuation = (void (*)(void))0; thr_sh_template.top_act = THR_ACT_NULL; thr_sh_template.importance = 0; thr_sh_template.sched_mode = 0; + thr_sh_template.safe_mode = 0; thr_sh_template.priority = 0; thr_sh_template.sched_pri = 0; thr_sh_template.depress_priority = -1; thr_sh_template.max_priority = 0; + thr_sh_template.task_priority = 0; + + thr_sh_template.current_quantum = 0; + + thr_sh_template.metered_computation = 0; + thr_sh_template.computation_epoch = 0; thr_sh_template.cpu_usage = 0; + thr_sh_template.cpu_delta = 0; thr_sh_template.sched_usage = 0; + thr_sh_template.sched_delta = 0; thr_sh_template.sched_stamp = 0; thr_sh_template.sleep_stamp = 0; - - thr_sh_template.policy = POLICY_NULL; - thr_sh_template.sp_state = 0; - thr_sh_template.unconsumed_quantum = 0; + thr_sh_template.safe_release = 0; thr_sh_template.vm_privilege = FALSE; @@ -557,8 +548,6 @@ thread_init(void) thr_sh_template.user_timer_save.high = 0; thr_sh_template.system_timer_save.low = 0; thr_sh_template.system_timer_save.high = 0; - thr_sh_template.cpu_delta = 0; - thr_sh_template.sched_delta = 0; thr_sh_template.active = FALSE; /* reset */ @@ -586,25 +575,76 @@ thread_init(void) thr_sh_template.funnel_lock = THR_FUNNEL_NULL; #ifndef MACHINE_STACK - simple_lock_init(&stack_lock_data, ETAP_THREAD_STACK); + simple_lock_init(&stack_lock_data, ETAP_THREAD_STACK); /* Initialize the stack lock */ + + if (KERNEL_STACK_SIZE < round_page(KERNEL_STACK_SIZE)) { /* Kernel stacks must be multiples of pages */ + panic("thread_init: kernel stack size (%08X) must be a multiple of page size (%08X)\n", + KERNEL_STACK_SIZE, PAGE_SIZE); + } + + for(stack_alloc_bndry = PAGE_SIZE; stack_alloc_bndry <= KERNEL_STACK_SIZE; stack_alloc_bndry <<= 1); /* Find next power of 2 above stack size */ + + ret = kmem_suballoc(kernel_map, /* Suballocate from the kernel map */ + + &stack, + (stack_alloc_bndry * (THREAD_MAX + 64)), /* Allocate enough for all of it */ + FALSE, /* Say not pageable so that it is wired */ + TRUE, /* Allocate from anywhere */ + &stack_map); /* Allocate a submap */ + + if(ret != KERN_SUCCESS) { /* Did we get one? */ + panic("thread_init: kmem_suballoc for stacks failed - ret = %d\n", ret); /* Die */ + } + stack = vm_map_min(stack_map); /* Make sure we skip the first hunk */ + ret = vm_map_enter(stack_map, &stack, PAGE_SIZE, 0, /* Make sure there is nothing at the start */ + 0, /* Force it at start */ + VM_OBJECT_NULL, 0, /* No object yet */ + FALSE, /* No copy */ + VM_PROT_NONE, /* Allow no access */ + VM_PROT_NONE, /* Allow no access */ + VM_INHERIT_DEFAULT); /* Just be normal */ + + if(ret != KERN_SUCCESS) { /* Did it work? */ + panic("thread_init: dummy alignment allocation failed; ret = %d\n", ret); + } + #endif /* MACHINE_STACK */ -#if MACH_DEBUG - simple_lock_init(&stack_usage_lock, ETAP_THREAD_STACK_USAGE); -#endif /* MACH_DEBUG */ - #if MACH_LDEBUG thr_sh_template.kthread = FALSE; thr_sh_template.mutex_count = 0; #endif /* MACH_LDEBUG */ { - AbsoluteTime abstime; + uint64_t abstime; + + clock_interval_to_absolutetime_interval( + std_quantum_us, NSEC_PER_USEC, &abstime); + assert((abstime >> 32) == 0 && (uint32_t)abstime != 0); + std_quantum = abstime; + /* 250 us */ + clock_interval_to_absolutetime_interval(250, NSEC_PER_USEC, &abstime); + assert((abstime >> 32) == 0 && (uint32_t)abstime != 0); + min_std_quantum = abstime; + + /* 50 us */ + clock_interval_to_absolutetime_interval(50, NSEC_PER_USEC, &abstime); + assert((abstime >> 32) == 0 && (uint32_t)abstime != 0); + min_rt_quantum = abstime; + + /* 50 ms */ clock_interval_to_absolutetime_interval( - min_quantum_ms, 1000*NSEC_PER_USEC, &abstime); - assert(abstime.hi == 0 && abstime.lo != 0); - min_quantum_abstime = abstime.lo; + 50, 1000*NSEC_PER_USEC, &abstime); + assert((abstime >> 32) == 0 && (uint32_t)abstime != 0); + max_rt_quantum = abstime; + + max_unsafe_computation = max_unsafe_quanta * std_quantum; + max_poll_computation = max_poll_quanta * std_quantum; + + sched_safe_duration = 2 * max_unsafe_quanta * + (std_quantum_us / (1000 * 1000)) * + (1 << SCHED_TICK_SHIFT); } /* @@ -623,16 +663,7 @@ thread_reaper_enqueue( * not necessary here. */ simple_lock(&reaper_lock); - enqueue_tail(&reaper_queue, (queue_entry_t)thread); -#if 0 /* CHECKME! */ - /* - * Since thread has been put in the reaper_queue, it must no longer - * be preempted (otherwise, it could be put back in a run queue). - */ - thread->preempt = TH_NOT_PREEMPTABLE; -#endif - simple_unlock(&reaper_lock); thread_call_enter(thread_reaper_call); @@ -670,6 +701,8 @@ thread_terminate_self(void) */ assert(thr_act->thread == thread); + _mk_sp_thread_depress_abort(thread, TRUE); + /* * Check to see if this is the last active activation. By * this we mean the last activation to call thread_terminate_self. @@ -733,13 +766,6 @@ thread_terminate_self(void) thread_lock(thread); thread->state |= (TH_HALTED|TH_TERMINATE); assert((thread->state & TH_UNINT) == 0); -#if 0 /* CHECKME! */ - /* - * Since thread has been put in the reaper_queue, it must no longer - * be preempted (otherwise, it could be put back in a run queue). - */ - thread->preempt = TH_NOT_PREEMPTABLE; -#endif thread_mark_wait_locked(thread, THREAD_UNINT); thread_unlock(thread); /* splx(s); */ @@ -767,8 +793,6 @@ thread_create_shuttle( task_t parent_task = thr_act->task; processor_set_t pset; kern_return_t result; - sched_policy_t *policy; - sf_return_t sfr; int suspcnt; assert(!thr_act->thread); @@ -788,6 +812,17 @@ thread_create_shuttle( wake_lock_init(new_shuttle); new_shuttle->sleep_stamp = sched_tick; + /* + * Thread still isn't runnable yet (our caller will do + * that). Initialize runtime-dependent fields here. + */ + result = thread_machine_create(new_shuttle, thr_act, thread_continue); + assert (result == KERN_SUCCESS); + + thread_start(new_shuttle, start); + thread_timer_setup(new_shuttle); + ipc_thread_init(new_shuttle); + pset = parent_task->processor_set; if (!pset->active) { pset = &default_pset; @@ -803,6 +838,7 @@ thread_create_shuttle( if (!parent_task->active) { task_unlock(parent_task); pset_unlock(pset); + thread_machine_destroy(new_shuttle); zfree(thread_shuttle_zone, (vm_offset_t) new_shuttle); return (KERN_FAILURE); } @@ -815,26 +851,21 @@ thread_create_shuttle( parent_task->res_act_count++; parent_task->active_act_count++; - /* Associate the thread with that scheduling policy */ - new_shuttle->policy = parent_task->policy; - policy = &sched_policy[new_shuttle->policy]; - sfr = policy->sp_ops.sp_thread_attach(policy, new_shuttle); - if (sfr != SF_SUCCESS) - panic("thread_create_shuttle: sp_thread_attach"); - /* Associate the thread with the processor set */ - sfr = policy->sp_ops.sp_thread_processor_set(policy, new_shuttle, pset); - if (sfr != SF_SUCCESS) - panic("thread_create_shuttle: sp_thread_proceessor_set"); + pset_add_thread(pset, new_shuttle); /* Set the thread's scheduling parameters */ + if (parent_task != kernel_task) + new_shuttle->sched_mode |= TH_MODE_TIMESHARE; new_shuttle->max_priority = parent_task->max_priority; + new_shuttle->task_priority = parent_task->priority; new_shuttle->priority = (priority < 0)? parent_task->priority: priority; if (new_shuttle->priority > new_shuttle->max_priority) new_shuttle->priority = new_shuttle->max_priority; - sfr = policy->sp_ops.sp_thread_setup(policy, new_shuttle); - if (sfr != SF_SUCCESS) - panic("thread_create_shuttle: sp_thread_setup"); + new_shuttle->importance = + new_shuttle->priority - new_shuttle->task_priority; + new_shuttle->sched_stamp = sched_tick; + compute_priority(new_shuttle, TRUE); #if ETAP_EVENT_MONITOR new_thread->etap_reason = 0; @@ -845,7 +876,6 @@ thread_create_shuttle( thr_act->active = TRUE; pset_unlock(pset); - /* * No need to lock thr_act, since it can't be known to anyone -- * we set its suspend_count to one more than the task suspend_count @@ -856,18 +886,6 @@ thread_create_shuttle( thread_hold(thr_act); task_unlock(parent_task); - /* - * Thread still isn't runnable yet (our caller will do - * that). Initialize runtime-dependent fields here. - */ - result = thread_machine_create(new_shuttle, thr_act, thread_continue); - assert (result == KERN_SUCCESS); - - machine_kernel_stack_init(new_shuttle, thread_continue); - ipc_thread_init(new_shuttle); - thread_start(new_shuttle, start); - thread_timer_setup(new_shuttle); - *new_thread = new_shuttle; { @@ -893,8 +911,6 @@ thread_create( thread_act_t thr_act; thread_t thread; kern_return_t result; - sched_policy_t *policy; - sf_return_t sfr; spl_t s; extern void thread_bootstrap_return(void); @@ -980,13 +996,12 @@ kernel_thread_with_priority( task_t task, integer_t priority, void (*start)(void), + boolean_t alloc_stack, boolean_t start_running) { kern_return_t result; thread_t thread; thread_act_t thr_act; - sched_policy_t *policy; - sf_return_t sfr; spl_t s; result = act_create(task, &thr_act); @@ -1000,7 +1015,8 @@ kernel_thread_with_priority( return THREAD_NULL; } - thread_swappable(thr_act, FALSE); + if (alloc_stack) + thread_doswapin(thread); s = splsched(); thread_lock(thread); @@ -1028,7 +1044,7 @@ kernel_thread( task_t task, void (*start)(void)) { - return kernel_thread_with_priority(task, -1, start, TRUE); + return kernel_thread_with_priority(task, -1, start, FALSE, TRUE); } unsigned int c_weird_pset_ref_exit = 0; /* pset code raced us */ @@ -1039,8 +1055,6 @@ thread_deallocate( { task_t task; processor_set_t pset; - sched_policy_t *policy; - sf_return_t sfr; spl_t s; if (thread == THREAD_NULL) @@ -1112,12 +1126,6 @@ thread_deallocate( if (thread == current_thread()) panic("thread deallocating itself"); - /* Detach thread (shuttle) from its sched policy */ - policy = &sched_policy[thread->policy]; - sfr = policy->sp_ops.sp_thread_detach(policy, thread); - if (sfr != SF_SUCCESS) - panic("thread_deallocate: sp_thread_detach"); - pset_remove_thread(pset, thread); thread->ref_count = 0; thread_unlock(thread); /* no more references - safe */ @@ -1126,16 +1134,12 @@ thread_deallocate( pset_deallocate(thread->processor_set); - /* frees kernel stack & other MD resources */ - if (thread->stack_privilege && (thread->stack_privilege != thread->kernel_stack)) { - vm_offset_t stack; - int s = splsched(); - stack = thread->stack_privilege; - stack_free(thread); - thread->kernel_stack = stack; - splx(s); + if (thread->stack_privilege != 0) { + if (thread->stack_privilege != thread->kernel_stack) + stack_free_stack(thread->stack_privilege); + thread->stack_privilege = 0; } - thread->stack_privilege = 0; + /* frees kernel stack & other MD resources */ thread_machine_destroy(thread); zfree(thread_shuttle_zone, (vm_offset_t) thread); @@ -1192,42 +1196,38 @@ thread_info_shuttle( thread_read_times(thread, &basic_info->user_time, &basic_info->system_time); - if (thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO)) { - /* - * Update lazy-evaluated scheduler info because someone wants it. - */ - if (thread->sched_stamp != sched_tick) - update_priority(thread); - - basic_info->sleep_time = 0; - - /* - * To calculate cpu_usage, first correct for timer rate, - * then for 5/8 ageing. The correction factor [3/5] is - * (1/(5/8) - 1). - */ - basic_info->cpu_usage = (thread->cpu_usage << SCHED_TICK_SHIFT) / - (TIMER_RATE / TH_USAGE_SCALE); - basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5; + /* + * Update lazy-evaluated scheduler info because someone wants it. + */ + if (thread->sched_stamp != sched_tick) + update_priority(thread); + + basic_info->sleep_time = 0; + + /* + * To calculate cpu_usage, first correct for timer rate, + * then for 5/8 ageing. The correction factor [3/5] is + * (1/(5/8) - 1). + */ + basic_info->cpu_usage = (thread->cpu_usage << SCHED_TICK_SHIFT) / + (TIMER_RATE / TH_USAGE_SCALE); + basic_info->cpu_usage = (basic_info->cpu_usage * 3) / 5; #if SIMPLE_CLOCK - /* - * Clock drift compensation. - */ - basic_info->cpu_usage = - (basic_info->cpu_usage * 1000000) / sched_usec; + /* + * Clock drift compensation. + */ + basic_info->cpu_usage = (basic_info->cpu_usage * 1000000) / sched_usec; #endif /* SIMPLE_CLOCK */ - } - else - basic_info->sleep_time = basic_info->cpu_usage = 0; - basic_info->policy = thread->policy; + basic_info->policy = ((thread->sched_mode & TH_MODE_TIMESHARE)? + POLICY_TIMESHARE: POLICY_RR); flags = 0; - if (thread->state & TH_SWAPPED_OUT) - flags = TH_FLAGS_SWAPPED; - else if (thread->state & TH_IDLE) - flags = TH_FLAGS_IDLE; + flags |= TH_FLAGS_IDLE; + + if (thread->state & TH_STACK_HANDOFF) + flags |= TH_FLAGS_SWAPPED; state = 0; if (thread->state & TH_HALTED) @@ -1269,7 +1269,7 @@ thread_info_shuttle( s = splsched(); thread_lock(thread); - if (thread->policy != POLICY_TIMESHARE) { + if (!(thread->sched_mode & TH_MODE_TIMESHARE)) { thread_unlock(thread); splx(s); @@ -1292,35 +1292,10 @@ thread_info_shuttle( } else if (flavor == THREAD_SCHED_FIFO_INFO) { - policy_fifo_info_t fifo_info; - if (*thread_info_count < POLICY_FIFO_INFO_COUNT) return (KERN_INVALID_ARGUMENT); - fifo_info = (policy_fifo_info_t)thread_info_out; - - s = splsched(); - thread_lock(thread); - - if (thread->policy != POLICY_FIFO) { - thread_unlock(thread); - splx(s); - - return (KERN_INVALID_POLICY); - } - - fifo_info->base_priority = thread->priority; - fifo_info->max_priority = thread->max_priority; - - fifo_info->depressed = (thread->depress_priority >= 0); - fifo_info->depress_priority = thread->depress_priority; - - thread_unlock(thread); - splx(s); - - *thread_info_count = POLICY_FIFO_INFO_COUNT; - - return (KERN_SUCCESS); + return (KERN_INVALID_POLICY); } else if (flavor == THREAD_SCHED_RR_INFO) { @@ -1334,7 +1309,7 @@ thread_info_shuttle( s = splsched(); thread_lock(thread); - if (thread->policy != POLICY_RR) { + if (thread->sched_mode & TH_MODE_TIMESHARE) { thread_unlock(thread); splx(s); @@ -1343,7 +1318,7 @@ thread_info_shuttle( rr_info->base_priority = thread->priority; rr_info->max_priority = thread->max_priority; - rr_info->quantum = min_quantum_ms; + rr_info->quantum = std_quantum_us / 1000; rr_info->depressed = (thread->depress_priority >= 0); rr_info->depress_priority = thread->depress_priority; @@ -1545,12 +1520,6 @@ thread_wire( splx(s); act_unlock_thread(thr_act); - /* - * Make the thread unswappable. - */ - if (wired) - thread_swappable(thr_act, FALSE); - return KERN_SUCCESS; } @@ -1566,7 +1535,8 @@ thread_collect_scan(void) /* This code runs very quickly! */ } -boolean_t thread_collect_allowed = TRUE; +/* Also disabled in vm/vm_pageout.c */ +boolean_t thread_collect_allowed = FALSE; unsigned thread_collect_last_tick = 0; unsigned thread_collect_max_rate = 0; /* in ticks */ @@ -1581,11 +1551,11 @@ consider_thread_collect(void) { /* * By default, don't attempt thread collection more frequently - * than once a second (one scheduler tick). + * than once a second. */ if (thread_collect_max_rate == 0) - thread_collect_max_rate = 2; /* sched_tick is a 1 second resolution 2 here insures at least 1 second interval */ + thread_collect_max_rate = (1 << SCHED_TICK_SHIFT) + 1; if (thread_collect_allowed && (sched_tick > @@ -1595,66 +1565,6 @@ consider_thread_collect(void) } } -#if MACH_DEBUG -#if STACK_USAGE - -vm_size_t -stack_usage( - register vm_offset_t stack) -{ - int i; - - for (i = 0; i < KERNEL_STACK_SIZE/sizeof(unsigned int); i++) - if (((unsigned int *)stack)[i] != STACK_MARKER) - break; - - return KERNEL_STACK_SIZE - i * sizeof(unsigned int); -} - -/* - * Machine-dependent code should call stack_init - * before doing its own initialization of the stack. - */ - -static void -stack_init( - register vm_offset_t stack, - unsigned int bytes) -{ - if (stack_check_usage) { - int i; - - for (i = 0; i < bytes / sizeof(unsigned int); i++) - ((unsigned int *)stack)[i] = STACK_MARKER; - } -} - -/* - * Machine-dependent code should call stack_finalize - * before releasing the stack memory. - */ - -void -stack_finalize( - register vm_offset_t stack) -{ - if (stack_check_usage) { - vm_size_t used = stack_usage(stack); - - simple_lock(&stack_usage_lock); - if (used > stack_max_usage) - stack_max_usage = used; - simple_unlock(&stack_usage_lock); - if (used > stack_max_use) { - printf("stack usage = %x\n", used); - panic("stack overflow"); - } - } -} - -#endif /*STACK_USAGE*/ -#endif /* MACH_DEBUG */ - kern_return_t host_stack_usage( host_t host, @@ -1674,9 +1584,7 @@ host_stack_usage( if (host == HOST_NULL) return KERN_INVALID_HOST; - simple_lock(&stack_usage_lock); - maxusage = stack_max_usage; - simple_unlock(&stack_usage_lock); + maxusage = 0; stack_statistics(&total, &maxusage); @@ -1795,15 +1703,6 @@ processor_set_stack_usage( if (stack != 0) { total++; - - if (stack_check_usage) { - vm_size_t usage = stack_usage(stack); - - if (usage > maxusage) { - maxusage = usage; - maxstack = (vm_offset_t) thread; - } - } } thread_deallocate(thread); @@ -1829,9 +1728,9 @@ funnel_alloc( mutex_t *m; funnel_t * fnl; if ((fnl = (funnel_t *)kalloc(sizeof(funnel_t))) != 0){ - bzero(fnl, sizeof(funnel_t)); + bzero((void *)fnl, sizeof(funnel_t)); if ((m = mutex_alloc(0)) == (mutex_t *)NULL) { - kfree(fnl, sizeof(funnel_t)); + kfree((vm_offset_t)fnl, sizeof(funnel_t)); return(THR_FUNNEL_NULL); } fnl->fnl_mutex = m; @@ -1847,7 +1746,7 @@ funnel_free( mutex_free(fnl->fnl_mutex); if (fnl->fnl_oldmutex) mutex_free(fnl->fnl_oldmutex); - kfree(fnl, sizeof(funnel_t)); + kfree((vm_offset_t)fnl, sizeof(funnel_t)); } void @@ -1972,17 +1871,20 @@ thread_funnel_merge( } void -thread_set_cont_arg(int arg) +thread_set_cont_arg( + int arg) { - thread_t th = current_thread(); - th->cont_arg = arg; + thread_t self = current_thread(); + + self->saved.misc = arg; } int thread_get_cont_arg(void) { - thread_t th = current_thread(); - return(th->cont_arg); + thread_t self = current_thread(); + + return (self->saved.misc); } /* diff --git a/osfmk/kern/thread.h b/osfmk/kern/thread.h index 80127b04d..559a640e0 100644 --- a/osfmk/kern/thread.h +++ b/osfmk/kern/thread.h @@ -131,9 +131,9 @@ * Interruptible flags for assert_wait * */ -#define THREAD_UNINT 0 /* not interruptible */ +#define THREAD_UNINT 0 /* not interruptible */ #define THREAD_INTERRUPTIBLE 1 /* may not be restartable */ -#define THREAD_ABORTSAFE 2 /* abortable safely */ +#define THREAD_ABORTSAFE 2 /* abortable safely */ #ifdef MACH_KERNEL_PRIVATE #include <cpus.h> @@ -159,26 +159,16 @@ #include <ipc/ipc_kmsg.h> #include <machine/thread.h> -typedef struct { - int fnl_type; /* funnel type */ - mutex_t * fnl_mutex; /* underlying mutex for the funnel */ - void * fnl_mtxholder; /* thread (last)holdng mutex */ - void * fnl_mtxrelease; /* thread (last)releasing mutex */ - mutex_t * fnl_oldmutex; /* Mutex before collapsing split funnel */ -} funnel_t; - - -typedef struct thread_shuttle { +struct thread_shuttle { /* * Beginning of thread_shuttle proper. When the thread is on * a wait queue, these three fields are in treated as an un- * official union with a wait_queue_element. If you change * these, you must change that definition as well. */ - queue_chain_t links; /* current run/wait queue links */ - run_queue_t runq; /* run queue p is on SEE BELOW */ - int whichq; /* which queue level p is on */ - + queue_chain_t links; /* current run/wait queue links */ + run_queue_t runq; /* run queue p is on SEE BELOW */ + int whichq; /* which queue level p is on */ /* * NOTE: The runq field in the thread structure has an unusual * locking protocol. If its value is RUN_QUEUE_NULL, then it is @@ -187,38 +177,35 @@ typedef struct thread_shuttle { */ /* Thread bookkeeping */ - queue_chain_t pset_threads; /* list of all shuttles in proc set */ + queue_chain_t pset_threads; /* list of all shuttles in proc set */ - /* Self-preservation */ - decl_simple_lock_data(,lock) /* scheduling lock (thread_lock()) */ - decl_simple_lock_data(,wake_lock) /* covers wake_active (wake_lock())*/ - decl_mutex_data(,rpc_lock) /* RPC lock (rpc_lock()) */ - int ref_count; /* number of references to me */ + /* Synchronization */ + decl_simple_lock_data(,lock) /* scheduling lock (thread_lock()) */ + decl_simple_lock_data(,wake_lock) /* covers wake_active (wake_lock())*/ + decl_mutex_data(,rpc_lock) /* RPC lock (rpc_lock()) */ + int ref_count; /* number of references to me */ - vm_offset_t kernel_stack; /* accurate only if the thread is - not swapped and not executing */ - - vm_offset_t stack_privilege;/* reserved kernel stack */ + vm_offset_t kernel_stack; + vm_offset_t stack_privilege; /* reserved kernel stack */ /* Blocking information */ - int reason; /* why we blocked */ - event_t wait_event; /* event we are waiting on */ - kern_return_t wait_result; /* outcome of wait - - may be examined by this thread - WITHOUT locking */ - wait_queue_t wait_queue; /* wait queue we are currently on */ - queue_chain_t wait_link; /* event's wait queue link */ - boolean_t wake_active; /* Someone is waiting for this - thread to become suspended */ - int state; /* Thread state: */ - boolean_t preempt; /* Thread is undergoing preemption */ - boolean_t interruptible; /* Thread is interruptible */ + int reason; /* why we blocked */ -#if ETAP_EVENT_MONITOR - int etap_reason; /* real reason why we blocked */ - boolean_t etap_trace; /* ETAP trace status */ -#endif /* ETAP_EVENT_MONITOR */ + event_t wait_event; /* event we are waiting on */ + kern_return_t wait_result; /* outcome of wait - + * may be examined by this thread + * WITHOUT locking */ + + wait_queue_t wait_queue; /* wait queue we are currently on */ + queue_chain_t wait_link; /* event's wait queue link */ + boolean_t wake_active; /* Someone is waiting for this + * thread to become suspended */ + + boolean_t interruptible; /* Thread is "interruptible" */ + + /* Thread state: */ + int state; /* * Thread states [bits or'ed] */ @@ -229,30 +216,32 @@ typedef struct thread_shuttle { #define TH_HALTED 0x10 /* thread is halted at clean point ? */ #define TH_ABORT 0x20 /* abort interruptible waits */ -#define TH_SWAPPED_OUT 0x40 /* thread is swapped out */ #define TH_IDLE 0x80 /* thread is an idle thread */ #define TH_SCHED_STATE (TH_WAIT|TH_SUSP|TH_RUN|TH_UNINT) #define TH_STACK_HANDOFF 0x0100 /* thread has no kernel stack */ -#define TH_STACK_COMING_IN 0x0200 /* thread is waiting for kernel stack */ -#define TH_STACK_STATE (TH_STACK_HANDOFF | TH_STACK_COMING_IN) +#define TH_STACK_ALLOC 0x0200 /* thread is waiting for kernel stack */ +#define TH_STACK_STATE (TH_STACK_HANDOFF | TH_STACK_ALLOC) #define TH_TERMINATE 0x0400 /* thread is terminating */ /* Stack handoff information */ - void (*continuation)(void); /* start here next time dispatched */ - int cont_arg; /* XXX continuation argument */ + void (*continuation)(void); /* re-start here next dispatch */ /* Scheduling information */ integer_t importance; /* task-relative importance */ integer_t sched_mode; /* scheduling mode bits */ -#define TH_MODE_REALTIME 0x0001 +#define TH_MODE_REALTIME 0x0001 +#define TH_MODE_TIMESHARE 0x0002 +#define TH_MODE_FAILSAFE 0x0004 +#define TH_MODE_POLLDEPRESS 0x0008 + integer_t safe_mode; /* saved mode during fail-safe */ struct { /* see mach/thread_policy.h */ - natural_t period; - natural_t computation; - natural_t constraint; + uint32_t period; + uint32_t computation; + uint32_t constraint; boolean_t preemptible; } realtime; @@ -260,20 +249,25 @@ typedef struct thread_shuttle { integer_t sched_pri; /* scheduled (current) priority */ integer_t depress_priority; /* priority to restore */ integer_t max_priority; + integer_t task_priority; /* copy of task base priority */ + + uint32_t current_quantum; /* duration of current quantum */ + + /* Fail-safe computation since last unblock or qualifying yield */ + uint64_t metered_computation; + uint64_t computation_epoch; natural_t cpu_usage; /* exp. decaying cpu usage [%cpu] */ + natural_t cpu_delta; /* cpu usage since last update */ natural_t sched_usage; /* load-weighted cpu usage [sched] */ - natural_t sched_stamp; /* last time priority was updated */ - natural_t sleep_stamp; /* last time in TH_WAIT state */ - - /* 'Obsolete' stuff that cannot be removed yet */ - integer_t policy; - integer_t sp_state; - integer_t unconsumed_quantum; + natural_t sched_delta; /* weighted cpu usage since update */ + natural_t sched_stamp; /* when priority was updated */ + natural_t sleep_stamp; /* when entered TH_WAIT state */ + natural_t safe_release; /* when to release fail-safe */ /* VM global variables */ - boolean_t vm_privilege; /* can use reserved memory? */ - vm_offset_t recover; /* page fault recovery (copyin/out) */ + boolean_t vm_privilege; /* can use reserved memory? */ + vm_offset_t recover; /* page fault recovery (copyin/out) */ /* IPC data structures */ @@ -285,39 +279,34 @@ typedef struct thread_shuttle { /* Various bits of stashed state */ union { struct { - mach_msg_return_t state; /* receive state */ - ipc_object_t object; /* object received on */ - mach_msg_header_t *msg; /* receive buffer pointer */ - mach_msg_size_t msize; /* max size for recvd msg */ - mach_msg_option_t option; /* options for receive */ - mach_msg_size_t slist_size; /* scatter list size */ - struct ipc_kmsg *kmsg; /* received message */ - mach_port_seqno_t seqno; /* seqno of recvd message */ - void (*continuation)(mach_msg_return_t); - } receive; + mach_msg_return_t state; /* receive state */ + ipc_object_t object; /* object received on */ + mach_msg_header_t *msg; /* receive buffer pointer */ + mach_msg_size_t msize; /* max size for recvd msg */ + mach_msg_option_t option; /* options for receive */ + mach_msg_size_t slist_size; /* scatter list size */ + struct ipc_kmsg *kmsg; /* received message */ + mach_port_seqno_t seqno; /* seqno of recvd message */ + void (*continuation)(mach_msg_return_t); + } receive; struct { - struct semaphore *waitsemaphore; /* semaphore ref */ - struct semaphore *signalsemaphore; /* semaphore ref */ - int options; /* semaphore options */ - kern_return_t result; /* primary result */ - void (*continuation)(kern_return_t); - } sema; + struct semaphore *waitsemaphore; /* semaphore ref */ + struct semaphore *signalsemaphore; /* semaphore ref */ + int options; /* semaphore options */ + kern_return_t result; /* primary result */ + void (*continuation)(kern_return_t); + } sema; struct { - struct sf_policy *policy; /* scheduling policy */ - int option; /* switch option */ - } swtch; - char *other; /* catch-all for other state */ - } saved; + int option; /* switch option */ + } swtch; + int misc; /* catch-all for other state */ + } saved; /* Timing data structures */ - timer_data_t user_timer; /* user mode timer */ - timer_data_t system_timer; /* system mode timer */ - timer_data_t depressed_timer;/* depressed priority timer */ - timer_save_data_t user_timer_save; /* saved user timer value */ - timer_save_data_t system_timer_save; /* saved sys timer val. */ - /*** ??? should the next two fields be moved to SP-specific struct?***/ - unsigned int cpu_delta; /* cpu usage since last update */ - unsigned int sched_delta; /* weighted cpu usage since update */ + timer_data_t user_timer; /* user mode timer */ + timer_data_t system_timer; /* system mode timer */ + timer_save_data_t user_timer_save; /* saved user timer value */ + timer_save_data_t system_timer_save; /* saved system timer value */ /* Timed wait expiration */ timer_call_data_t wait_timer; @@ -325,37 +314,41 @@ typedef struct thread_shuttle { boolean_t wait_timer_is_set; /* Priority depression expiration */ - thread_call_data_t depress_timer; + timer_call_data_t depress_timer; + integer_t depress_timer_active; /* Ast/Halt data structures */ - boolean_t active; /* how alive is the thread */ + boolean_t active; /* thread is active */ + + int at_safe_point; /* thread_abort_safely allowed */ /* Processor data structures */ - processor_set_t processor_set; /* assigned processor set */ -#if NCPUS > 1 - processor_t bound_processor; /* bound to processor ?*/ -#endif /* NCPUS > 1 */ + processor_set_t processor_set; /* assigned processor set */ + processor_t bound_processor; /* bound to processor ?*/ #if MACH_HOST - boolean_t may_assign; /* may assignment change? */ - boolean_t assign_active; /* someone waiting for may_assign */ + boolean_t may_assign; /* may assignment change? */ + boolean_t assign_active; /* waiting for may_assign */ #endif /* MACH_HOST */ -#if XKMACHKERNEL - int xk_type; -#endif /* XKMACHKERNEL */ + processor_t last_processor; /* processor last ran on */ + + /* Non-reentrancy funnel */ + struct funnel_lock *funnel_lock; + int funnel_state; +#define TH_FN_OWNED 0x1 /* we own the funnel */ +#define TH_FN_REFUNNEL 0x2 /* re-acquire funnel on dispatch */ + +/* BEGIN TRACING/DEBUG */ -#if NCPUS > 1 - processor_t last_processor; /* processor this last ran on */ #if MACH_LOCK_MON - unsigned lock_stack; /* number of locks held */ + unsigned lock_stack; /* number of locks held */ #endif /* MACH_LOCK_MON */ -#endif /* NCPUS > 1 */ - int at_safe_point; /* thread_abort_safely allowed */ - int funnel_state; -#define TH_FN_OWNED 0x1 /* we own the funnel lock */ -#define TH_FN_REFUNNEL 0x2 /* must reaquire funnel lock when unblocking */ - funnel_t *funnel_lock; +#if ETAP_EVENT_MONITOR + int etap_reason; /* real reason why we blocked */ + boolean_t etap_trace; /* ETAP trace status */ +#endif /* ETAP_EVENT_MONITOR */ + #if MACH_LDEBUG /* * Debugging: track acquired mutexes and locks. @@ -365,24 +358,19 @@ typedef struct thread_shuttle { */ #define MUTEX_STACK_DEPTH 20 #define LOCK_STACK_DEPTH 20 - mutex_t *mutex_stack[MUTEX_STACK_DEPTH]; - lock_t *lock_stack[LOCK_STACK_DEPTH]; - unsigned int mutex_stack_index; - unsigned int lock_stack_index; - unsigned mutex_count; /* XXX to be deleted XXX */ - boolean_t kthread; /* thread is a kernel thread */ + mutex_t *mutex_stack[MUTEX_STACK_DEPTH]; + lock_t *lock_stack[LOCK_STACK_DEPTH]; + unsigned int mutex_stack_index; + unsigned int lock_stack_index; + unsigned mutex_count; /* XXX to be deleted XXX */ + boolean_t kthread; /* thread is a kernel thread */ #endif /* MACH_LDEBUG */ - /* - * End of thread_shuttle proper - */ +/* END TRACING/DEBUG */ - /* - * Migration and thread_activation linkage information - */ - struct thread_activation *top_act; /* "current" thr_act */ - -} Thread_Shuttle; + /* Migration and thread_activation linkage */ + struct thread_activation *top_act; /* "current" thr_act */ +}; #define THREAD_SHUTTLE_NULL ((thread_shuttle_t)0) @@ -402,6 +390,16 @@ typedef struct thread_shuttle { #define sth_result saved.sema.result #define sth_continuation saved.sema.continuation +struct funnel_lock { + int fnl_type; /* funnel type */ + mutex_t *fnl_mutex; /* underlying mutex for the funnel */ + void * fnl_mtxholder; /* thread (last)holdng mutex */ + void * fnl_mtxrelease; /* thread (last)releasing mutex */ + mutex_t *fnl_oldmutex; /* Mutex before collapsing split funnel */ +}; + +typedef struct funnel_lock funnel_t; + extern thread_act_t active_kloaded[NCPUS]; /* "" kernel-loaded acts */ extern vm_offset_t active_stacks[NCPUS]; /* active kernel stacks */ extern vm_offset_t kernel_stack[NCPUS]; @@ -435,9 +433,11 @@ extern void thread_reference( extern void thread_deallocate( thread_t thread); -/* Set priority of calling thread */ -extern void thread_set_own_priority( - int priority); +/* Set task priority of member thread */ +extern void thread_task_priority( + thread_t thread, + integer_t priority, + integer_t max_priority); /* Start a thread at specified routine */ #define thread_start(thread, start) \ @@ -591,6 +591,7 @@ extern thread_t kernel_thread_with_priority( task_t task, integer_t priority, void (*start)(void), + boolean_t alloc_stack, boolean_t start_running); extern void funnel_lock(funnel_t *); @@ -599,7 +600,7 @@ extern void funnel_unlock(funnel_t *); #else /* !MACH_KERNEL_PRIVATE */ -typedef struct __funnel__ funnel_t; +typedef struct funnel_lock funnel_t; extern boolean_t thread_should_halt(thread_t); diff --git a/osfmk/kern/thread_act.c b/osfmk/kern/thread_act.c index 9a97f50a6..4320b05dd 100644 --- a/osfmk/kern/thread_act.c +++ b/osfmk/kern/thread_act.c @@ -68,8 +68,8 @@ #include <kern/spl.h> #include <kern/syscall_subr.h> #include <kern/sync_lock.h> -#include <kern/sf.h> #include <kern/mk_sp.h> /*** ??? fix so this can be removed ***/ +#include <kern/processor.h> #include <mach_prof.h> #include <mach/rpc.h> @@ -194,9 +194,10 @@ thread_terminate( * code - and all threads finish their own termination in the * special handler APC. */ - if (((thr_act->task == kernel_task) || (thr_act->kernel_loaded == TRUE)) - && (current_act() == thr_act)) { - ast_taken(FALSE, AST_APC, 0); + if ( ( thr_act->task == kernel_task || + thr_act->kernel_loaded == TRUE ) && + current_act() == thr_act ) { + ast_taken(AST_APC, FALSE); panic("thread_terminate(): returning from ast_taken() for %x kernel activation\n", thr_act); } @@ -347,8 +348,6 @@ thread_depress_abort( { register thread_t thread; kern_return_t result; - sched_policy_t *policy; - spl_t s; if (thr_act == THR_ACT_NULL) return (KERN_INVALID_ARGUMENT); @@ -361,13 +360,7 @@ thread_depress_abort( return (KERN_TERMINATED); } - s = splsched(); - thread_lock(thread); - policy = &sched_policy[thread->policy]; - thread_unlock(thread); - splx(s); - - result = policy->sp_ops.sp_thread_depress_abort(policy, thread); + result = _mk_sp_thread_depress_abort(thread, FALSE); act_unlock_thread(thr_act); @@ -732,11 +725,7 @@ thread_get_state( kern_return_t ret; thread_t thread, nthread; -#if 0 /* Grenoble - why?? */ if (thr_act == THR_ACT_NULL || thr_act == current_act()) -#else - if (thr_act == THR_ACT_NULL) -#endif return (KERN_INVALID_ARGUMENT); thread = act_lock_thread(thr_act); @@ -747,7 +736,7 @@ thread_get_state( thread_hold(thr_act); while (1) { - if (!thread || thr_act != thread->top_act) + if (!thread || thr_act != thread->top_act) break; act_unlock_thread(thr_act); (void)thread_stop_wait(thread); @@ -781,11 +770,7 @@ thread_set_state( kern_return_t ret; thread_t thread, nthread; -#if 0 /* Grenoble - why?? */ if (thr_act == THR_ACT_NULL || thr_act == current_act()) -#else - if (thr_act == THR_ACT_NULL) -#endif return (KERN_INVALID_ARGUMENT); /* * We have no kernel activations, so Utah's MO fails for signals etc. @@ -802,7 +787,7 @@ thread_set_state( thread_hold(thr_act); while (1) { - if (!thread || thr_act != thread->top_act) + if (!thread || thr_act != thread->top_act) break; act_unlock_thread(thr_act); (void)thread_stop_wait(thread); @@ -2225,12 +2210,34 @@ act_get_state(thread_act_t thr_act, int flavor, thread_state_t state, void act_set_apc(thread_act_t thr_act) { + + processor_t prssr; + thread_t thread; + + mp_disable_preemption(); + thread_ast_set(thr_act, AST_APC); if (thr_act == current_act()) { - mp_disable_preemption(); ast_propagate(thr_act->ast); mp_enable_preemption(); + return; /* If we are current act, we can't be on the other processor so leave now */ } + +/* + * Here we want to make sure that the apc is taken quickly. Therefore, we check + * if, and where, the activation is running. If it is not running, we don't need to do + * anything. If it is, we need to signal the other processor to trigger it to + * check the asts. Note that there is a race here and we may end up sending a signal + * after the thread has been switched off. Hopefully this is no big deal. + */ + + thread = thr_act->thread; /* Get the thread for the signaled activation */ + prssr = thread->last_processor; /* get the processor it was last on */ + if(prssr && (cpu_data[prssr->slot_num].active_thread == thread)) { /* Is the thread active on its processor? */ + cause_ast_check(prssr); /* Yes, kick it */ + } + + mp_enable_preemption(); } void diff --git a/osfmk/kern/thread_call.c b/osfmk/kern/thread_call.c index 693c80084..2a0004215 100644 --- a/osfmk/kern/thread_call.c +++ b/osfmk/kern/thread_call.c @@ -198,8 +198,9 @@ thread_call_initialize(void) simple_unlock(&thread_call_lock); splx(s); - activate_thread = kernel_thread_with_priority(kernel_task, - MAXPRI_KERNBAND-2, _activate_thread, TRUE); + activate_thread = kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL - 2, + _activate_thread, TRUE, TRUE); } void @@ -327,9 +328,8 @@ _delayed_call_enqueue( current = TC(queue_first(&delayed_call_queue)); while (TRUE) { - if ( queue_end(&delayed_call_queue, qe(current)) || - CMP_ABSOLUTETIME(&call->deadline, - ¤t->deadline) < 0 ) { + if ( queue_end(&delayed_call_queue, qe(current)) || + call->deadline < current->deadline ) { current = TC(queue_prev(qe(current))); break; } @@ -557,7 +557,7 @@ void thread_call_func_delayed( thread_call_func_t func, thread_call_param_t param, - AbsoluteTime deadline + uint64_t deadline ) { thread_call_t call; @@ -782,7 +782,7 @@ thread_call_enter1( boolean_t thread_call_enter_delayed( thread_call_t call, - AbsoluteTime deadline + uint64_t deadline ) { boolean_t result = TRUE; @@ -816,7 +816,7 @@ boolean_t thread_call_enter1_delayed( thread_call_t call, thread_call_param_t param1, - AbsoluteTime deadline + uint64_t deadline ) { boolean_t result = TRUE; @@ -901,7 +901,7 @@ thread_call_cancel( boolean_t thread_call_is_delayed( thread_call_t call, - AbsoluteTime *deadline) + uint64_t *deadline) { boolean_t result = FALSE; int s; @@ -1089,8 +1089,9 @@ _activate_thread_continue(void) simple_unlock(&thread_call_lock); (void) spllo(); - (void) kernel_thread_with_priority(kernel_task, - MAXPRI_KERNBAND-1, _call_thread, TRUE); + (void) kernel_thread_with_priority( + kernel_task, MAXPRI_KERNEL - 1, + _call_thread, TRUE, TRUE); #if NO_CONTINUATIONS thread_block((void (*)(void)) 0); goto loop; @@ -1150,7 +1151,7 @@ _delayed_call_timer( timer_call_param_t p1 ) { - AbsoluteTime timestamp; + uint64_t timestamp; thread_call_t call; boolean_t new_pending = FALSE; int s; @@ -1163,7 +1164,7 @@ _delayed_call_timer( call = TC(queue_first(&delayed_call_queue)); while (!queue_end(&delayed_call_queue, qe(call))) { - if (CMP_ABSOLUTETIME(&call->deadline, ×tamp) <= 0) { + if (call->deadline <= timestamp) { _delayed_call_dequeue(call); _pending_call_enqueue(call); diff --git a/osfmk/kern/thread_call.h b/osfmk/kern/thread_call.h index 0e63edf1c..19649709d 100644 --- a/osfmk/kern/thread_call.h +++ b/osfmk/kern/thread_call.h @@ -35,10 +35,10 @@ #ifndef _KERN_THREAD_CALL_H_ #define _KERN_THREAD_CALL_H_ -#include <libkern/OSBase.h> - #include <mach/mach_types.h> +#include <kern/clock.h> + typedef struct call_entry *thread_call_t; typedef void *thread_call_param_t; typedef void (*thread_call_func_t)( @@ -57,13 +57,13 @@ thread_call_enter1( boolean_t thread_call_enter_delayed( thread_call_t call, - AbsoluteTime deadline + uint64_t deadline ); boolean_t thread_call_enter1_delayed( thread_call_t call, thread_call_param_t param1, - AbsoluteTime deadline + uint64_t deadline ); boolean_t thread_call_cancel( @@ -72,7 +72,7 @@ thread_call_cancel( boolean_t thread_call_is_delayed( thread_call_t call, - AbsoluteTime *deadline + uint64_t *deadline ); thread_call_t @@ -100,7 +100,7 @@ void thread_call_func_delayed( thread_call_func_t func, thread_call_param_t param, - AbsoluteTime deadline + uint64_t deadline ); boolean_t @@ -128,4 +128,22 @@ thread_call_setup( #endif /* MACH_KERNEL_PRIVATE */ +#if !defined(MACH_KERNEL_PRIVATE) && !defined(ABSOLUTETIME_SCALAR_TYPE) + +#include <libkern/OSBase.h> + +#define thread_call_enter_delayed(a, b) \ + thread_call_enter_delayed((a), __OSAbsoluteTime(b)) + +#define thread_call_enter1_delayed(a, b, c) \ + thread_call_enter1_delayed((a), (b), __OSAbsoluteTime(c)) + +#define thread_call_is_delayed(a, b) \ + thread_call_is_delayed((a), __OSAbsoluteTimePtr(b)) + +#define thread_call_func_delayed(a, b, c) \ + thread_call_func_delayed((a), (b), __OSAbsoluteTime(c)) + +#endif + #endif /* _KERN_THREAD_CALL_H_ */ diff --git a/osfmk/kern/thread_policy.c b/osfmk/kern/thread_policy.c index b04cf8f01..e9eacf91b 100644 --- a/osfmk/kern/thread_policy.c +++ b/osfmk/kern/thread_policy.c @@ -30,6 +30,10 @@ #include <kern/thread.h> +static void +thread_recompute_priority( + thread_t thread); + kern_return_t thread_policy_set( thread_act_t act, @@ -39,76 +43,54 @@ thread_policy_set( { kern_return_t result = KERN_SUCCESS; thread_t thread; - task_t task; spl_t s; if (act == THR_ACT_NULL) return (KERN_INVALID_ARGUMENT); - act_lock(act); - task = act->task; - act_unlock(act); - - task_lock(task); - thread = act_lock_thread(act); if (!act->active) { act_unlock_thread(act); - task_unlock(task); return (KERN_TERMINATED); } - if (thread == THREAD_NULL) { - act_unlock_thread(act); - task_unlock(task); - - return (KERN_NOT_SUPPORTED); - } - -#define thread_priority_set(thread, pri) \ -MACRO_BEGIN \ - if ((thread)->depress_priority >= 0) \ - (thread)->depress_priority = (pri); \ - else { \ - (thread)->priority = (pri); \ - compute_priority((thread), TRUE); \ - \ - if ((thread) == current_thread()) \ - ast_on(AST_BLOCK); \ - } \ -MACRO_END + assert(thread != THREAD_NULL); switch (flavor) { - case THREAD_STANDARD_POLICY: + case THREAD_EXTENDED_POLICY: { - integer_t priority; + boolean_t timeshare = TRUE; + + if (count >= THREAD_EXTENDED_POLICY_COUNT) { + thread_extended_policy_t info; + + info = (thread_extended_policy_t)policy_info; + timeshare = info->timeshare; + } s = splsched(); thread_lock(thread); - thread->sched_mode &=~ TH_MODE_REALTIME; + if (!(thread->sched_mode & TH_MODE_FAILSAFE)) { + thread->sched_mode &= ~TH_MODE_REALTIME; - thread->policy = POLICY_TIMESHARE; - - if (thread->importance > MAXPRI) - priority = MAXPRI; - else - if (thread->importance < -MAXPRI) - priority = -MAXPRI; - else - priority = thread->importance; - - priority += task->priority; + if (timeshare) + thread->sched_mode |= TH_MODE_TIMESHARE; + else + thread->sched_mode &= ~TH_MODE_TIMESHARE; - if (priority > thread->max_priority) - priority = thread->max_priority; - else - if (priority < MINPRI) - priority = MINPRI; + thread_recompute_priority(thread); + } + else { + thread->safe_mode &= ~TH_MODE_REALTIME; - thread_priority_set(thread, priority); + if (timeshare) + thread->safe_mode |= TH_MODE_TIMESHARE; + else + thread->safe_mode &= ~TH_MODE_TIMESHARE; + } thread_unlock(thread); splx(s); @@ -126,20 +108,29 @@ MACRO_END } info = (thread_time_constraint_policy_t)policy_info; + if ( info->computation > max_rt_quantum || + info->computation < min_rt_quantum ) { + result = KERN_INVALID_ARGUMENT; + break; + } s = splsched(); thread_lock(thread); - thread->sched_mode |= TH_MODE_REALTIME; - thread->realtime.period = info->period; thread->realtime.computation = info->computation; thread->realtime.constraint = info->constraint; thread->realtime.preemptible = info->preemptible; - thread->policy = POLICY_RR; - - thread_priority_set(thread, BASEPRI_REALTIME); + if (!(thread->sched_mode & TH_MODE_FAILSAFE)) { + thread->sched_mode &= ~TH_MODE_TIMESHARE; + thread->sched_mode |= TH_MODE_REALTIME; + thread_recompute_priority(thread); + } + else { + thread->safe_mode &= ~TH_MODE_TIMESHARE; + thread->safe_mode |= TH_MODE_REALTIME; + } thread_unlock(thread); splx(s); @@ -163,27 +154,7 @@ MACRO_END thread->importance = info->importance; - if (!(thread->sched_mode & TH_MODE_REALTIME)) { - integer_t priority; - - if (thread->importance > MAXPRI) - priority = MAXPRI; - else - if (thread->importance < -MAXPRI) - priority = -MAXPRI; - else - priority = thread->importance; - - priority += task->priority; - - if (priority > thread->max_priority) - priority = thread->max_priority; - else - if (priority < MINPRI) - priority = MINPRI; - - thread_priority_set(thread, priority); - } + thread_recompute_priority(thread); thread_unlock(thread); splx(s); @@ -198,11 +169,68 @@ MACRO_END act_unlock_thread(act); - task_unlock(task); - return (result); } +static void +thread_recompute_priority( + thread_t thread) +{ + integer_t priority; + + if (thread->sched_mode & TH_MODE_REALTIME) + priority = BASEPRI_REALTIME; + else { + if (thread->importance > MAXPRI) + priority = MAXPRI; + else + if (thread->importance < -MAXPRI) + priority = -MAXPRI; + else + priority = thread->importance; + + priority += thread->task_priority; + + if (priority > thread->max_priority) + priority = thread->max_priority; + else + if (priority < MINPRI) + priority = MINPRI; + } + + if (thread->depress_priority >= 0) + thread->depress_priority = priority; + else { + thread->priority = priority; + compute_priority(thread, TRUE); + + if (thread == current_thread()) + ast_on(AST_BLOCK); + } +} + +void +thread_task_priority( + thread_t thread, + integer_t priority, + integer_t max_priority) +{ + spl_t s; + + assert(thread != THREAD_NULL); + + s = splsched(); + thread_lock(thread); + + thread->task_priority = priority; + thread->max_priority = max_priority; + + thread_recompute_priority(thread); + + thread_unlock(thread); + splx(s); +} + kern_return_t thread_policy_get( thread_act_t act, @@ -225,24 +253,41 @@ thread_policy_get( return (KERN_TERMINATED); } - if (thread == THREAD_NULL) { - act_unlock_thread(act); - - return (KERN_NOT_SUPPORTED); - } + assert(thread != THREAD_NULL); switch (flavor) { - case THREAD_STANDARD_POLICY: - s = splsched(); - thread_lock(thread); + case THREAD_EXTENDED_POLICY: + { + boolean_t timeshare = TRUE; - if (thread->sched_mode & TH_MODE_REALTIME) - *get_default = TRUE; + if (!(*get_default)) { + s = splsched(); + thread_lock(thread); + + if ( !(thread->sched_mode & TH_MODE_REALTIME) && + !(thread->safe_mode & TH_MODE_REALTIME) ) { + if (!(thread->sched_mode & TH_MODE_FAILSAFE)) + timeshare = (thread->sched_mode & TH_MODE_TIMESHARE) != 0; + else + timeshare = (thread->safe_mode & TH_MODE_TIMESHARE) != 0; + } + else + *get_default = TRUE; + + thread_unlock(thread); + splx(s); + } + + if (*count >= THREAD_EXTENDED_POLICY_COUNT) { + thread_extended_policy_t info; + + info = (thread_extended_policy_t)policy_info; + info->timeshare = timeshare; + } - thread_unlock(thread); - splx(s); break; + } case THREAD_TIME_CONSTRAINT_POLICY: { @@ -255,29 +300,31 @@ thread_policy_get( info = (thread_time_constraint_policy_t)policy_info; - s = splsched(); - thread_lock(thread); + if (!(*get_default)) { + s = splsched(); + thread_lock(thread); - if ((thread->sched_mode & TH_MODE_REALTIME) && !(*get_default)) { - info->period = thread->realtime.period; - info->computation = thread->realtime.computation; - info->constraint = thread->realtime.constraint; - info->preemptible = thread->realtime.preemptible; - } - else { - extern natural_t min_quantum_abstime; + if ( (thread->sched_mode & TH_MODE_REALTIME) || + (thread->safe_mode & TH_MODE_REALTIME) ) { + info->period = thread->realtime.period; + info->computation = thread->realtime.computation; + info->constraint = thread->realtime.constraint; + info->preemptible = thread->realtime.preemptible; + } + else + *get_default = TRUE; - *get_default = TRUE; + thread_unlock(thread); + splx(s); + } + if (*get_default) { info->period = 0; - info->computation = min_quantum_abstime / 2; - info->constraint = min_quantum_abstime; + info->computation = std_quantum / 2; + info->constraint = std_quantum; info->preemptible = TRUE; } - thread_unlock(thread); - splx(s); - break; } @@ -292,9 +339,7 @@ thread_policy_get( info = (thread_precedence_policy_t)policy_info; - if (*get_default) - info->importance = 0; - else { + if (!(*get_default)) { s = splsched(); thread_lock(thread); @@ -303,6 +348,8 @@ thread_policy_get( thread_unlock(thread); splx(s); } + else + info->importance = 0; break; } diff --git a/osfmk/kern/thread_swap.c b/osfmk/kern/thread_swap.c index 46bb6cc9e..6ca031df2 100644 --- a/osfmk/kern/thread_swap.c +++ b/osfmk/kern/thread_swap.c @@ -49,23 +49,6 @@ */ /* */ -/* - * - * File: kern/thread_swap.c - * Author: Avadis Tevanian, Jr. - * Date: 1987 - * - * Mach thread swapper: - * Swap in threads that need to be run. This is done here - * by the swapper thread since it cannot be done (in general) - * when the kernel tries to place a thread on a run queue. - * - * Note: The act of swapping a thread in Mach does not mean that - * its memory gets forcibly swapped to secondary storage. The memory - * for the task corresponding to a swapped thread is paged out - * through the normal paging mechanism. - * - */ #include <kern/thread.h> #include <kern/lock.h> @@ -73,7 +56,6 @@ #include <vm/vm_kern.h> #include <mach/vm_param.h> #include <kern/sched_prim.h> -#include <kern/sf.h> #include <kern/processor.h> #include <kern/thread_swap.h> #include <kern/spl.h> /* for splsched */ @@ -82,22 +64,28 @@ #include <mach/policy.h> queue_head_t swapin_queue; -decl_simple_lock_data(, swapper_lock_data) +decl_simple_lock_data(,swapin_lock_data) -#define swapper_lock() simple_lock(&swapper_lock_data) -#define swapper_unlock() simple_unlock(&swapper_lock_data) +#define swapin_lock() simple_lock(&swapin_lock_data) +#define swapin_unlock() simple_unlock(&swapin_lock_data) mach_counter_t c_swapin_thread_block; +void swapin_thread(void); + /* - * swapper_init: [exported] + * swapin_init: [exported] * * Initialize the swapper module. */ -void swapper_init() +void +swapin_init(void) { queue_init(&swapin_queue); - simple_lock_init(&swapper_lock_data, ETAP_THREAD_SWAPPER); + simple_lock_init(&swapin_lock_data, ETAP_THREAD_SWAPPER); + kernel_thread_with_priority( + kernel_task, BASEPRI_PREEMPT - 2, + swapin_thread, TRUE, TRUE); } /* @@ -110,23 +98,24 @@ void swapper_init() * our callers have already tried that route. */ -void thread_swapin(thread) - thread_t thread; +void +thread_swapin( + register thread_t thread) { switch (thread->state & TH_STACK_STATE) { + case TH_STACK_HANDOFF: /* * Swapped out - queue for swapin thread. */ - thread->state = (thread->state & ~TH_STACK_STATE) - | TH_STACK_COMING_IN; - swapper_lock(); + thread->state = (thread->state & ~TH_STACK_STATE) | TH_STACK_ALLOC; + swapin_lock(); enqueue_tail(&swapin_queue, (queue_entry_t) thread); - swapper_unlock(); + swapin_unlock(); thread_wakeup((event_t) &swapin_queue); break; - case TH_STACK_COMING_IN: + case TH_STACK_ALLOC: /* * Already queued for swapin thread, or being * swapped in. @@ -148,15 +137,12 @@ void thread_swapin(thread) * it on a run queue. No locks should be held on entry, as it is * likely that this routine will sleep (waiting for stack allocation). */ -void thread_doswapin(thread) - register thread_t thread; +void +thread_doswapin( + register thread_t thread) { - spl_t s; - vm_offset_t stack; - - /* - * do machdep allocation - */ + vm_offset_t stack; + spl_t s; /* * Allocate the kernel stack. @@ -170,7 +156,7 @@ void thread_doswapin(thread) s = splsched(); thread_lock(thread); - thread->state &= ~(TH_STACK_HANDOFF | TH_STACK_COMING_IN); + thread->state &= ~(TH_STACK_HANDOFF | TH_STACK_ALLOC); if (thread->state & TH_RUN) thread_setrun(thread, TRUE, FALSE); thread_unlock(thread); @@ -183,42 +169,47 @@ void thread_doswapin(thread) * This procedure executes as a kernel thread. Threads that need to * be swapped in are swapped in by this thread. */ -void swapin_thread_continue() +void +swapin_thread_continue(void) { - for (;;) { - register thread_t thread; - spl_t s; + register thread_t thread; + +#if defined(__i386__) +loop: +#endif + (void)splsched(); + swapin_lock(); - s = splsched(); - swapper_lock(); + while ((thread = (thread_t)dequeue_head(&swapin_queue)) != THREAD_NULL) { + swapin_unlock(); + (void)spllo(); - while ((thread = (thread_t) dequeue_head(&swapin_queue)) - != THREAD_NULL) { - swapper_unlock(); - (void) splx(s); + thread_doswapin(thread); - thread_doswapin(thread); /* may block */ + (void)splsched(); + swapin_lock(); + } - s = splsched(); - swapper_lock(); - } + assert_wait((event_t) &swapin_queue, THREAD_UNINT); + swapin_unlock(); + (void)spllo(); - assert_wait((event_t) &swapin_queue, THREAD_UNINT); - swapper_unlock(); - (void) splx(s); - counter(c_swapin_thread_block++); + counter(c_swapin_thread_block++); #if defined (__i386__) - thread_block((void (*)(void)) 0); + thread_block((void (*)(void)) 0); + goto loop; #else - thread_block(swapin_thread_continue); + thread_block(swapin_thread_continue); #endif - } + /*NOTREACHED*/ } -void swapin_thread() +void +swapin_thread(void) { - stack_privilege(current_thread()); - current_thread()->vm_privilege = TRUE; + thread_t self = current_thread(); + + stack_privilege(self); swapin_thread_continue(); /*NOTREACHED*/ diff --git a/osfmk/kern/thread_swap.h b/osfmk/kern/thread_swap.h index 63dde530c..a6b107e56 100644 --- a/osfmk/kern/thread_swap.h +++ b/osfmk/kern/thread_swap.h @@ -30,166 +30,24 @@ * All rights reserved. The CMU software License Agreement specifies * the terms and conditions for use and redistribution. */ -/* - * HISTORY - * - * Revision 1.1.1.1 1998/09/22 21:05:32 wsanchez - * Import of Mac OS X kernel (~semeria) - * - * Revision 1.1.1.1 1998/03/07 02:25:57 wsanchez - * Import of OSF Mach kernel (~mburg) - * - * Revision 1.1.11.7 1995/06/13 18:58:49 bolinger - * Fix ri-osc CR1391: New return type from thread_swapin_blocking(). - * [1995/06/13 18:56:52 bolinger] - * - * Revision 1.1.11.6 1995/06/05 21:46:36 dwm - * ri-osc CR1357 - ensure activation being returned to is swapped in. - * added thread_swapin_blocking [bolinger] - * [1995/06/05 21:34:08 dwm] - * - * Revision 1.1.11.5 1995/05/19 15:48:34 bernadat - * Let thread swapping be configurable. - * [95/05/19 bernadat] - * - * Revision 1.1.11.4 1995/04/07 19:04:46 barbou - * Merged into mainline. - * [95/03/09 barbou] - * - * Revision 1.1.12.2 1995/02/13 15:59:18 barbou - * Merged/ported to MK6. - * - * Revision 1.1.9.3 1994/08/12 14:22:30 barbou - * Overwritten with copy from IK. - * Old kern/thread_swap.h was renamed kern/thread_handoff.c. - * Added prototype for thread_swapout and thread_swapout_enqueue. - * [94/07/28 barbou] - * - * Revision 3.0.3.2 1994/01/20 19:53:20 chasb - * Remove excessively restrictive copyright notice - * [1994/01/20 17:50:56 chasb] - * - * Revision 3.0.3.1 1993/12/20 21:07:59 gupta - * Expanded C O P Y R I G H T - * [1993/12/17 22:19:43 gupta] - * - * Revision 3.0 1992/12/31 22:08:45 ede - * Initial revision for OSF/1 R1.3 - * - * Revision 1.6.2.2 1992/01/22 22:14:42 gmf - * Added TH_SW_TASK_SWAPPING flag to swap_state. This state - * indicates that the thread is about to be swapped out by - * the task swapping mechanism, and prevents the thread - * swapper from doing it first. - * [1992/01/20 22:06:36 gmf] - * - * Revision 1.6 1991/08/15 19:16:39 devrcs - * Prototype all functions, change name to thread_swapper_init. - * [91/06/26 10:45:44 jeffc] - * - * Revision 1.5 91/06/10 16:19:07 devrcs - * Additions to allow thread to be made non-swappable on swap in, - * change thread_swapin interface. - * [91/05/30 15:56:38 jeffc] - * - * Revision 1.4 91/03/04 17:07:14 devrcs - * A small step toward ansiC: commented else/endif/elif trailers. - * [91/01/12 16:39:43 dwm] - * - * Revision 1.3 90/10/07 13:57:13 devrcs - * Added EndLog Marker. - * [90/09/28 09:59:56 gm] - * - * Revision 1.2 90/01/02 20:06:28 gm - * Fixes for first snapshot. - * - * Revision 1.1 89/10/16 19:36:28 gm - * Mach 2.5 and Encore 0.6 merge - * - * Revision 2.4 89/03/09 20:17:07 rpd - * More cleanup. - * - * Revision 2.3 89/02/25 18:10:24 gm0w - * Kernel code cleanup. - * Put entire file under #indef KERNEL. - * [89/02/15 mrt] - * - * Revision 0.0 88/01/21 dbg - * Created. - * [88/01/21 dbg] - * - * $EndLog$ - */ + /* * File: kern/thread_swap.h * - * Declarations of thread swap_states and swapping routines. - */ - -/* - * Swap states for threads. + * Declarations of thread "swapping" routines. */ #ifndef _KERN_THREAD_SWAP_H_ #define _KERN_THREAD_SWAP_H_ -#if 1 /* USED CODE */ - /* * exported routines */ -extern void swapper_init(); -extern void thread_swapin(thread_t thread); -extern void thread_doswapin(thread_t thread); -extern void swapin_thread(); - -#define thread_swappable(act, bool) - - -#else /* UNUSED SWAPPER CODE */ -#if THREAD_SWAPPER -#define TH_SW_STATE 7 /* mask of swap state bits */ -#define TH_SW_UNSWAPPABLE 1 /* not swappable */ -#define TH_SW_IN 2 /* swapped in */ -#define TH_SW_GOING_OUT 3 /* being swapped out */ -#define TH_SW_WANT_IN 4 /* being swapped out, but should - immediately be swapped in */ -#define TH_SW_OUT 5 /* swapped out */ -#define TH_SW_COMING_IN 6 /* queued for swapin, or being - swapped in */ - -#define TH_SW_MAKE_UNSWAPPABLE 8 /*not state, command to swapin_thread */ - -/* - * This flag is only used by the task swapper. It implies that - * the thread is about to be swapped, but hasn't yet. - */ -#define TH_SW_TASK_SWAPPING 0x10 - -/* - * exported routines - */ -extern void thread_swapper_init(void); -extern void swapin_thread(void); -extern void swapout_thread(void); -extern void thread_doswapin(thread_act_t thr_act); -extern void thread_swapin(thread_act_t thr_act, - boolean_t make_unswappable); -extern boolean_t - thread_swapin_blocking(thread_act_t thr_act); -extern void thread_swapout(thread_act_t thr_act); -extern void swapout_threads(boolean_t now); -extern void thread_swapout_enqueue(thread_act_t thr_act); -extern void thread_swap_disable(thread_act_t thr_act); - -extern void thread_swappable(thread_act_t thr_act, boolean_t swappable); - -#else /* THREAD_SWAPPER */ -#define thread_swappable(thr_act, swappable) -#endif /* THREAD_SWAPPER */ - -#endif /* UNUSED SWAPPER CODE */ +extern void swapin_init(void); +extern void thread_swapin( + thread_t thread); +extern void thread_doswapin( + thread_t thread); #endif /*_KERN_THREAD_SWAP_H_*/ - diff --git a/osfmk/kern/time_out.h b/osfmk/kern/time_out.h index 344d2bd97..66b105af0 100644 --- a/osfmk/kern/time_out.h +++ b/osfmk/kern/time_out.h @@ -54,28 +54,23 @@ #define _KERN_TIME_OUT_H_ /* - * Mach time-out facility. + * Mach tick-based timing. */ #include <mach/boolean.h> -#include <kern/lock.h> -#include <kern/queue.h> -#include <kern/zalloc.h> #include <kern/kern_types.h> -/* - * Timers in kernel: - */ - extern int hz; /* num of ticks per second */ extern int tick; /* num of usec per tick */ -typedef void (*timeout_fcn_t)(void *); +#ifdef MACH_KERNEL_PRIVATE extern void hertz_tick( boolean_t usermode, /* executing user code */ natural_t pc); +typedef void (*timeout_fcn_t)(void *); + /* Set timeout */ extern void timeout( timeout_fcn_t fcn, @@ -87,4 +82,6 @@ extern void untimeout( timeout_fcn_t fcn, void *param); +#endif /* MACH_KERNEL_PRIVATE */ + #endif /* _KERN_TIME_OUT_H_ */ diff --git a/osfmk/kern/timer_call.c b/osfmk/kern/timer_call.c index e1e4bb649..66d69a833 100644 --- a/osfmk/kern/timer_call.c +++ b/osfmk/kern/timer_call.c @@ -54,7 +54,7 @@ static boolean_t static void timer_call_interrupt( - AbsoluteTime timestamp); + uint64_t timestamp); #define qe(x) ((queue_entry_t)(x)) #define TC(x) ((timer_call_t)(x)) @@ -104,9 +104,8 @@ _delayed_call_enqueue( current = TC(queue_first(queue)); while (TRUE) { - if ( queue_end(queue, qe(current)) || - CMP_ABSOLUTETIME(&call->deadline, - ¤t->deadline) < 0 ) { + if ( queue_end(queue, qe(current)) || + call->deadline < current->deadline ) { current = TC(queue_prev(qe(current))); break; } @@ -167,7 +166,7 @@ _set_delayed_call_timer( boolean_t timer_call_enter( timer_call_t call, - AbsoluteTime deadline) + uint64_t deadline) { boolean_t result = TRUE; queue_t delayed; @@ -203,7 +202,7 @@ boolean_t timer_call_enter1( timer_call_t call, timer_call_param_t param1, - AbsoluteTime deadline) + uint64_t deadline) { boolean_t result = TRUE; queue_t delayed; @@ -261,7 +260,7 @@ timer_call_cancel( boolean_t timer_call_is_delayed( timer_call_t call, - AbsoluteTime *deadline) + uint64_t *deadline) { boolean_t result = FALSE; spl_t s; @@ -284,7 +283,7 @@ timer_call_is_delayed( static void timer_call_interrupt( - AbsoluteTime timestamp) + uint64_t timestamp) { timer_call_t call; queue_t delayed = &delayed_call_queues[cpu_number()]; @@ -294,7 +293,7 @@ timer_call_interrupt( call = TC(queue_first(delayed)); while (!queue_end(delayed, qe(call))) { - if (CMP_ABSOLUTETIME(&call->deadline, ×tamp) <= 0) { + if (call->deadline <= timestamp) { timer_call_func_t func; timer_call_param_t param0, param1; diff --git a/osfmk/kern/timer_call.h b/osfmk/kern/timer_call.h index b8e85808c..632dcb5a4 100644 --- a/osfmk/kern/timer_call.h +++ b/osfmk/kern/timer_call.h @@ -32,8 +32,6 @@ #ifndef _KERN_TIMER_CALL_H_ #define _KERN_TIMER_CALL_H_ -#include <libkern/OSBase.h> - #include <mach/mach_types.h> #ifdef MACH_KERNEL_PRIVATE @@ -47,13 +45,13 @@ typedef void (*timer_call_func_t)( boolean_t timer_call_enter( timer_call_t call, - AbsoluteTime deadline); + uint64_t deadline); boolean_t timer_call_enter1( timer_call_t call, timer_call_param_t param1, - AbsoluteTime deadline); + uint64_t deadline); boolean_t timer_call_cancel( @@ -62,7 +60,7 @@ timer_call_cancel( boolean_t timer_call_is_delayed( timer_call_t call, - AbsoluteTime *deadline); + uint64_t *deadline); #include <kern/call_entry.h> diff --git a/osfmk/kern/wait_queue.c b/osfmk/kern/wait_queue.c index b71aba571..fc08865c4 100644 --- a/osfmk/kern/wait_queue.c +++ b/osfmk/kern/wait_queue.c @@ -87,9 +87,28 @@ wait_queue_sub_init( { wait_queue_init(&wqsub->wqs_wait_queue, policy); wqsub->wqs_wait_queue.wq_issub = TRUE; + if ( policy & SYNC_POLICY_PREPOST) { + wqsub->wqs_wait_queue.wq_isprepost = TRUE; + wqsub->wqs_refcount = 0; + } else + wqsub->wqs_wait_queue.wq_isprepost = FALSE; queue_init(&wqsub->wqs_sublinks); } +void +wait_queue_sub_clearrefs( + wait_queue_sub_t wq_sub) +{ + assert(wait_queue_is_sub(wq_sub)); + + wqs_lock(wq_sub); + + wq_sub->wqs_refcount = 0; + + wqs_unlock(wq_sub); + +} + void wait_queue_link_init( wait_queue_link_t wql) @@ -101,6 +120,47 @@ wait_queue_link_init( wql->wql_event = NO_EVENT; } +/* + * Routine: wait_queue_alloc + * Purpose: + * Allocate and initialize a wait queue for use outside of + * of the mach part of the kernel. + * + * Conditions: + * Nothing locked - can block. + * + * Returns: + * The allocated and initialized wait queue + * WAIT_QUEUE_NULL if there is a resource shortage + */ +wait_queue_t +wait_queue_alloc( + int policy) +{ + wait_queue_t wq; + + wq = (wait_queue_t) kalloc(sizeof(struct wait_queue)); + if (wq != WAIT_QUEUE_NULL) + wait_queue_init(wq, policy); + return wq; +} + +/* + * Routine: wait_queue_free + * Purpose: + * Free an allocated wait queue. + * + * Conditions: + * Nothing locked - can block. + */ +void +wait_queue_free( + wait_queue_t wq) +{ + assert(queue_empty(&wq->wq_queue)); + kfree((vm_offset_t)wq, sizeof(struct wait_queue)); +} + /* * Routine: wait_queue_lock @@ -275,6 +335,46 @@ wait_queue_link( return KERN_SUCCESS; } +/* + * Routine: wait_queue_link_noalloc + * Purpose: + * Insert a subordinate wait queue into a wait queue. This + * requires us to link the two together using a wait_queue_link + * structure that we allocate. + * Conditions: + * The wait queue being inserted must be inited as a sub queue + * The sub waitq is not already linked + * + */ +kern_return_t +wait_queue_link_noalloc( + wait_queue_t wq, + wait_queue_sub_t wq_sub, + wait_queue_link_t wql) +{ + spl_t s; + + assert(wait_queue_is_sub(wq_sub)); + assert(!wait_queue_member(wq, wq_sub)); + + wait_queue_link_init(wql); + + s = splsched(); + wait_queue_lock(wq); + wqs_lock(wq_sub); + + wql->wql_queue = wq; + wql->wql_subqueue = wq_sub; + wql->wql_event = WAIT_QUEUE_SUBORDINATE; + queue_enter(&wq->wq_queue, wql, wait_queue_link_t, wql_links); + queue_enter(&wq_sub->wqs_sublinks, wql, wait_queue_link_t, wql_sublinks); + + wqs_unlock(wq_sub); + wait_queue_unlock(wq); + splx(s); + + return KERN_SUCCESS; +} /* * Routine: wait_queue_unlink @@ -326,6 +426,152 @@ wait_queue_unlink( panic("wait_queue_unlink"); } +/* + * Routine: wait_queue_unlink_nofree + * Purpose: + * Remove the linkage between a wait queue and its subordinate. Do not deallcoate the wql + * Conditions: + * The wait queue being must be a member sub queue + */ +kern_return_t +wait_queue_unlink_nofree( + wait_queue_t wq, + wait_queue_sub_t wq_sub) +{ + wait_queue_element_t wq_element; + queue_t q; + + assert(wait_queue_is_sub(wq_sub)); + + q = &wq->wq_queue; + + wq_element = (wait_queue_element_t) queue_first(q); + while (!queue_end(q, (queue_entry_t)wq_element)) { + + if (wq_element->wqe_event == WAIT_QUEUE_SUBORDINATE) { + wait_queue_link_t wql = (wait_queue_link_t)wq_element; + queue_t sq; + + if (wql->wql_subqueue == wq_sub) { + sq = &wq_sub->wqs_sublinks; + queue_remove(q, wql, wait_queue_link_t, wql_links); + queue_remove(sq, wql, wait_queue_link_t, wql_sublinks); + return(KERN_SUCCESS); + } + } + + wq_element = (wait_queue_element_t) + queue_next((queue_t) wq_element); + } + /* due to dropping the sub's lock to get to this routine we can see + * no entries in waitqueue. It is valid case, so we should just return + */ + return(KERN_FAILURE); +} + +/* + * Routine: wait_subqueue_unlink_all + * Purpose: + * Remove the linkage between a wait queue and its subordinate. + * Conditions: + * The wait queue being must be a member sub queue + */ +kern_return_t +wait_subqueue_unlink_all( + wait_queue_sub_t wq_sub) +{ + wait_queue_link_t wql; + wait_queue_t wq; + queue_t q; + kern_return_t kret; + spl_t s; + + assert(wait_queue_is_sub(wq_sub)); + +retry: + s = splsched(); + wqs_lock(wq_sub); + + q = &wq_sub->wqs_sublinks; + + wql = (wait_queue_link_t)queue_first(q); + while (!queue_end(q, (queue_entry_t)wql)) { + wq = wql->wql_queue; + if (wait_queue_lock_try(wq)) { +#if 0 + queue_t q1; + + q1 = &wq->wq_queue; + + queue_remove(q1, wql, wait_queue_link_t, wql_links); + queue_remove(q, wql, wait_queue_link_t, wql_sublinks); +#else + if ((kret = wait_queue_unlink_nofree(wq, wq_sub)) != KERN_SUCCESS) { + queue_remove(q, wql, wait_queue_link_t, wql_sublinks); + +} +#endif + wait_queue_unlock(wq); + wql = (wait_queue_link_t)queue_first(q); + } else { + wqs_unlock(wq_sub); + splx(s); + mutex_pause(); + goto retry; + } + } + wqs_unlock(wq_sub); + splx(s); + return(KERN_SUCCESS); +} + + +/* + * Routine: wait_queue_unlinkall_nofree + * Purpose: + * Remove the linkage between a wait queue and all subordinates. + */ + +kern_return_t +wait_queue_unlinkall_nofree( + wait_queue_t wq) +{ + wait_queue_element_t wq_element; + wait_queue_sub_t wq_sub; + queue_t q; + spl_t s; + + + s = splsched(); + wait_queue_lock(wq); + + q = &wq->wq_queue; + + wq_element = (wait_queue_element_t) queue_first(q); + while (!queue_end(q, (queue_entry_t)wq_element)) { + + if (wq_element->wqe_event == WAIT_QUEUE_SUBORDINATE) { + wait_queue_link_t wql = (wait_queue_link_t)wq_element; + queue_t sq; + + wq_sub = wql->wql_subqueue; + wqs_lock(wq_sub); + sq = &wq_sub->wqs_sublinks; + queue_remove(q, wql, wait_queue_link_t, wql_links); + queue_remove(sq, wql, wait_queue_link_t, wql_sublinks); + wqs_unlock(wq_sub); + wq_element = (wait_queue_element_t) queue_first(q); + } else { + wq_element = (wait_queue_element_t) + queue_next((queue_t) wq_element); + } + + } + wait_queue_unlock(wq); + splx(s); + + return(KERN_SUCCESS); +} /* * Routine: wait_queue_unlink_one * Purpose: @@ -385,7 +631,7 @@ wait_queue_unlink_one( * The wait queue is assumed locked. * */ -void +boolean_t wait_queue_assert_wait_locked( wait_queue_t wq, event_t event, @@ -393,6 +639,18 @@ wait_queue_assert_wait_locked( boolean_t unlock) { thread_t thread = current_thread(); + boolean_t ret; + + + if (wq->wq_issub && wq->wq_isprepost) { + wait_queue_sub_t wqs = (wait_queue_sub_t)wq; + + if (wqs->wqs_refcount > 0) { + if (unlock) + wait_queue_unlock(wq); + return(FALSE); + } + } thread_lock(thread); @@ -412,6 +670,7 @@ wait_queue_assert_wait_locked( thread_unlock(thread); if (unlock) wait_queue_unlock(wq); + return(TRUE); } /* @@ -423,19 +682,21 @@ wait_queue_assert_wait_locked( * Conditions: * nothing of interest locked. */ -void +boolean_t wait_queue_assert_wait( wait_queue_t wq, event_t event, int interruptible) { spl_t s; + boolean_t ret; s = splsched(); wait_queue_lock(wq); - wait_queue_assert_wait_locked(wq, event, interruptible, TRUE); + ret = wait_queue_assert_wait_locked(wq, event, interruptible, TRUE); /* wait queue unlocked */ splx(s); + return(ret); } @@ -483,6 +744,15 @@ _wait_queue_select_all( */ sub_queue = (wait_queue_t)wql->wql_subqueue; wait_queue_lock(sub_queue); + if (sub_queue->wq_isprepost) { + wait_queue_sub_t wqs = (wait_queue_sub_t)sub_queue; + + /* + * Preposting is only for subordinates and wait queue + * is the first element of subordinate + */ + wqs->wqs_refcount++; + } if (! wait_queue_empty(sub_queue)) _wait_queue_select_all(sub_queue, event, wake_queue); wait_queue_unlock(sub_queue); diff --git a/osfmk/kern/wait_queue.h b/osfmk/kern/wait_queue.h index 34e24b5bf..edfb02799 100644 --- a/osfmk/kern/wait_queue.h +++ b/osfmk/kern/wait_queue.h @@ -24,8 +24,8 @@ #include <kern/kern_types.h> /* for wait_queue_t */ #include <mach/sync_policy.h> +#include <mach/kern_return.h> /* for kern_return_t */ -#ifdef MACH_KERNEL_PRIVATE #include <kern/lock.h> #include <kern/queue.h> @@ -44,29 +44,39 @@ * NOTE: Hardware locks are used to protect event wait * queues since interrupt code is free to post events to * them. + * WARNING: Cannot change this data structure without updating SIZEOF_WAITQUEUE */ typedef struct wait_queue { hw_lock_data_t wq_interlock; /* interlock */ unsigned int /* flags */ /* boolean_t */ wq_fifo:1, /* fifo wakeup policy? */ wq_issub:1, /* is waitq linked? */ + wq_isprepost:1, /* is waitq preposted? sub only */ :0; /* force to long boundary */ queue_head_t wq_queue; /* queue of elements */ } WaitQueue; +#define SIZEOF_WAITQUEUE 16 /* 16 bytes for wq */ +#define SIZEOF_WAITQUEUE_SUB 28 /* 24 byets for wqs */ +#define SIZEOF_WAITQUEUE_ELEMENT 16 /* 16 byets per wqe */ +#define SIZEOF_WAITQUEUE_LINK 28 /* 28 byets per wqe */ + +#ifdef MACH_KERNEL_PRIVATE + /* * wait_queue_sub_t * This is the common definition for a subordinate wait queue. * These can be linked as members/elements of multiple regular * wait queues. They have an additional set of linkages to * identify the linkage structures that point to them. + * WARNING: Cannot change this data structure without updating SIZEOF_WAITQUEUE_SUB */ typedef struct wait_queue_sub { WaitQueue wqs_wait_queue; /* our wait queue */ queue_head_t wqs_sublinks; /* links from sub perspective */ + unsigned int wqs_refcount; /* refcount for preposting */ } WaitQueueSub; -typedef WaitQueueSub *wait_queue_sub_t; #define WAIT_QUEUE_SUB_NULL ((wait_queue_sub_t)0) @@ -82,6 +92,7 @@ typedef WaitQueueSub *wait_queue_sub_t; * WARNING: The first three fields of the thread shuttle * definition does not use this definition yet. Any change in * the layout here will have to be matched with a change there. + * WARNING: Cannot change this data structure without updating SIZEOF_WAITQUEUE_ELEMENT */ typedef struct wait_queue_element { queue_chain_t wqe_links; /* link of elements on this queue */ @@ -89,6 +100,7 @@ typedef struct wait_queue_element { event_t wqe_event; /* event this element is waiting for */ } *wait_queue_element_t; + /* * wait_queue_link_t * Specialized wait queue element type for linking subordinate @@ -103,12 +115,14 @@ typedef struct wait_queue_element { * event queues of which it is a member. An IPC event post associated * with that port may wake up any thread from any of those portsets, * or one that was waiting locally on the port itself. + * WARNING: Cannot change this data structure without updating SIZEOF_WAITQUEUE_LINK */ typedef struct wait_queue_link { struct wait_queue_element wql_element; /* element on master */ - wait_queue_sub_t wql_subqueue; /* sub queue */ queue_chain_t wql_sublinks; /* element on sub */ -} *wait_queue_link_t; + wait_queue_sub_t wql_subqueue; /* sub queue */ +} WaitQueueLink; + #define WAIT_QUEUE_LINK_NULL ((wait_queue_link_t)0) @@ -116,6 +130,15 @@ typedef struct wait_queue_link { #define wql_queue wql_element.wqe_queue #define wql_event wql_element.wqe_event +#define wait_queue_empty(wq) (queue_empty(&(wq)->wq_queue)) + +#define wait_queue_held(wq) (hw_lock_held(&(wq)->wq_interlock)) + +#define wait_queue_is_sub(wqs) ((wqs)->wqs_wait_queue.wq_issub) +#define wqs_lock(wqs) wait_queue_lock(&(wqs)->wqs_wait_queue) +#define wqs_unlock(wqs) wait_queue_unlock(&(wqs)->wqs_wait_queue) +#define wqs_lock_try(wqs) wait_queue__try_lock(&(wqs)->wqs_wait_queue) + extern int wait_queue_subordinate; #define WAIT_QUEUE_SUBORDINATE &_wait_queue_subordinate @@ -149,14 +172,6 @@ extern kern_return_t wait_queue_remove( ((thread)->wait_queue == WAIT_QUEUE_NULL) -#define wait_queue_empty(wq) (queue_empty(&(wq)->wq_queue)) - -#define wait_queue_held(wq) (hw_lock_held(&(wq)->wq_interlock)) - -#define wait_queue_is_sub(wqs) ((wqs)->wqs_wait_queue.wq_issub) -#define wqs_lock(wqs) wait_queue_lock(&(wqs)->wqs_wait_queue) -#define wqs_unlock(wqs) wait_queue_unlock(&(wqs)->wqs_wait_queue) -#define wqs_lock_try(wqs) wait_queue__try_lock(&(wqs)->wqs_wait_queue) /******** Decomposed interfaces (to build higher level constructs) ***********/ @@ -170,7 +185,7 @@ extern boolean_t wait_queue_lock_try( wait_queue_t wait_queue); /* assert intent to wait on a locked wait queue */ -extern void wait_queue_assert_wait_locked( +extern boolean_t wait_queue_assert_wait_locked( wait_queue_t wait_queue, event_t wait_event, int interruptible, @@ -234,7 +249,7 @@ extern void wait_queue_free( /******** Standalone interfaces (not a part of a higher construct) ************/ /* assert intent to wait on <wait_queue,event> pair */ -extern void wait_queue_assert_wait( +extern boolean_t wait_queue_assert_wait( wait_queue_t wait_queue, event_t wait_event, int interruptible); diff --git a/osfmk/kern/zalloc.c b/osfmk/kern/zalloc.c index 12ed64e03..0020560ea 100644 --- a/osfmk/kern/zalloc.c +++ b/osfmk/kern/zalloc.c @@ -66,6 +66,7 @@ #include <kern/lock.h> #include <kern/sched_prim.h> #include <kern/misc_protos.h> +#include <kern/thread_call.h> #include <kern/zalloc.h> #include <mach/vm_param.h> #include <vm/vm_kern.h> @@ -198,6 +199,11 @@ void zone_page_keep( vm_offset_t addr, vm_size_t size); +void zalloc_async( + thread_call_param_t p0, + thread_call_param_t p1); + + #if ZONE_DEBUG && MACH_KDB int zone_count( zone_t z, @@ -273,6 +279,12 @@ zone_t first_zone; zone_t *last_zone; int num_zones; +boolean_t zone_gc_allowed = TRUE; +boolean_t zone_gc_forced = FALSE; +unsigned zone_gc_last_tick = 0; +unsigned zone_gc_max_rate = 0; /* in ticks */ + + /* * zinit initializes a new zone. The zone data structures themselves * are stored in a zone, which is initially a static structure that @@ -340,6 +352,7 @@ zinit( z->allows_foreign = FALSE; z->expandable = TRUE; z->waiting = FALSE; + z->async_pending = FALSE; #if ZONE_DEBUG z->active_zones.next = z->active_zones.prev = 0; @@ -352,6 +365,7 @@ zinit( */ z->next_zone = ZONE_NULL; + thread_call_setup(&z->call_async_alloc, zalloc_async, z); simple_lock(&all_zones_lock); *last_zone = z; last_zone = &z->next_zone; @@ -600,20 +614,17 @@ zalloc_canblock( lock_zone(zone); REMOVE_FROM_ZONE(zone, addr, vm_offset_t); - while (addr == 0) { + + while ((addr == 0) && canblock) { /* * If nothing was there, try to get more */ if (zone->doing_alloc) { - if (!canblock) { - unlock_zone(zone); - return(0); - } /* * Someone is allocating memory for this zone. * Wait for it to show up, then try again. */ - assert_wait((event_t)zone, THREAD_INTERRUPTIBLE); + assert_wait((event_t)zone, THREAD_UNINT); zone->waiting = TRUE; unlock_zone(zone); thread_block((void (*)(void)) 0); @@ -639,10 +650,6 @@ zalloc_canblock( } else { unlock_zone(zone); - if (!canblock) { - return(0); - } - panic("zalloc: zone \"%s\" empty.", zone->zone_name); } } @@ -669,10 +676,6 @@ zalloc_canblock( } else if (retval != KERN_RESOURCE_SHORTAGE) { /* would like to cause a zone_gc() */ - if (!canblock) { - return(0); - } - panic("zalloc"); } lock_zone(zone); @@ -686,10 +689,6 @@ zalloc_canblock( retval == KERN_RESOURCE_SHORTAGE) { unlock_zone(zone); - if (!canblock) { - return(0); - } - VM_PAGE_WAIT(); lock_zone(zone); } @@ -722,17 +721,9 @@ zalloc_canblock( if (retval == KERN_RESOURCE_SHORTAGE) { unlock_zone(zone); - if (!canblock) { - return(0); - } - VM_PAGE_WAIT(); lock_zone(zone); } else { - if (!canblock) { - return(0); - } - panic("zalloc"); } } @@ -741,6 +732,14 @@ zalloc_canblock( REMOVE_FROM_ZONE(zone, addr, vm_offset_t); } + if ((addr == 0) && !canblock && (zone->async_pending == FALSE) && (!vm_pool_low())) { + zone->async_pending = TRUE; + unlock_zone(zone); + thread_call_enter(&zone->call_async_alloc); + lock_zone(zone); + REMOVE_FROM_ZONE(zone, addr, vm_offset_t); + } + #if ZONE_DEBUG if (addr && zone_debug_enabled(zone)) { enqueue_tail(&zone->active_zones, (queue_entry_t)addr); @@ -749,6 +748,7 @@ zalloc_canblock( #endif unlock_zone(zone); + return(addr); } @@ -767,6 +767,20 @@ zalloc_noblock( return( zalloc_canblock(zone, FALSE) ); } +void +zalloc_async( + thread_call_param_t p0, + thread_call_param_t p1) +{ + vm_offset_t elt; + + elt = zalloc_canblock((zone_t)p0, TRUE); + zfree((zone_t)p0, elt); + lock_zone(((zone_t)p0)); + ((zone_t)p0)->async_pending = FALSE; + unlock_zone(((zone_t)p0)); +} + /* * zget returns an element from the specified zone @@ -851,24 +865,17 @@ zfree( if (!pmap_kernel_va(this) || this == elem) panic("zfree"); } + ADD_TO_ZONE(zone, elem); + /* * If elements have one or more pages, and memory is low, - * put it directly back into circulation rather than - * back into a zone, where a non-vm_privileged task can grab it. - * This lessens the impact of a privileged task cycling reserved - * memory into a publicly accessible zone. + * request to run the garbage collection in the zone the next + * time the pageout thread runs. */ if (zone->elem_size >= PAGE_SIZE && vm_pool_low()){ - assert( !(zone->elem_size & (zone->alloc_size-1)) ); - zone->count--; - zone->cur_size -= zone->elem_size; - zone_page_init(elem, zone->elem_size, ZONE_PAGE_UNUSED); - unlock_zone(zone); - kmem_free(zone_map, elem, zone->elem_size); - return; + zone_gc_forced = TRUE; } - ADD_TO_ZONE(zone, elem); unlock_zone(zone); } @@ -1308,10 +1315,6 @@ zone_gc(void) mutex_unlock(&zone_gc_lock); } -boolean_t zone_gc_allowed = TRUE; /* XXX */ -unsigned zone_gc_last_tick = 0; -unsigned zone_gc_max_rate = 0; /* in ticks */ - /* * consider_zone_gc: * @@ -1323,14 +1326,16 @@ consider_zone_gc(void) { /* * By default, don't attempt zone GC more frequently - * than once a second (which is one scheduler tick). + * than once a second. */ if (zone_gc_max_rate == 0) - zone_gc_max_rate = 2; /* sched_tick is a 1 second resolution 2 here insures at least 1 second interval */ + zone_gc_max_rate = (1 << SCHED_TICK_SHIFT) + 1; if (zone_gc_allowed && - (sched_tick > (zone_gc_last_tick + zone_gc_max_rate))) { + ((sched_tick > (zone_gc_last_tick + zone_gc_max_rate)) || + zone_gc_forced)) { + zone_gc_forced = FALSE; zone_gc_last_tick = sched_tick; zone_gc(); } diff --git a/osfmk/kern/zalloc.h b/osfmk/kern/zalloc.h index ae48dfcd9..c2554d815 100644 --- a/osfmk/kern/zalloc.h +++ b/osfmk/kern/zalloc.h @@ -67,6 +67,7 @@ #include <mach_kdb.h> #include <kern/lock.h> #include <kern/queue.h> +#include <kern/call_entry.h> /* * A zone is a collection of fixed size blocks for which there @@ -90,8 +91,10 @@ struct zone { /* boolean_t */ expandable :1, /* (T) expand zone (with message)? */ /* boolean_t */ allows_foreign :1,/* (F) allow non-zalloc space */ /* boolean_t */ doing_alloc :1, /* is zone expanding now? */ - /* boolean_t */ waiting :1; /* is thread waiting for expansion? */ + /* boolean_t */ waiting :1, /* is thread waiting for expansion? */ + /* boolean_t */ async_pending :1; /* asynchronous allocation pending? */ struct zone * next_zone; /* Link for all-zones list */ + call_entry_data_t call_async_alloc; /* callout for asynchronous alloc */ #if ZONE_DEBUG queue_head_t active_zones; /* active elements */ #endif /* ZONE_DEBUG */ diff --git a/osfmk/mach/Makefile b/osfmk/mach/Makefile index 833dcca3c..697fcae44 100644 --- a/osfmk/mach/Makefile +++ b/osfmk/mach/Makefile @@ -204,6 +204,7 @@ MIG_KUHDRS = \ clock_reply.h \ exc.h \ memory_object.h \ + memory_object_control.h \ memory_object_default.h \ upl.h \ vm_map.h @@ -212,6 +213,7 @@ MIG_KUSRC = \ clock_reply_user.c \ exc_user.c \ memory_object_user.c \ + memory_object_control_user.c \ memory_object_default_user.c \ upl_user.c \ vm_map_user.c diff --git a/osfmk/mach/host_info.h b/osfmk/mach/host_info.h index 728860232..b5554be32 100644 --- a/osfmk/mach/host_info.h +++ b/osfmk/mach/host_info.h @@ -22,150 +22,6 @@ /* * @OSF_COPYRIGHT@ */ -/* - * HISTORY - * - * Revision 1.1.1.1 1998/09/22 21:05:30 wsanchez - * Import of Mac OS X kernel (~semeria) - * - * Revision 1.1.1.1 1998/03/07 02:25:45 wsanchez - * Import of OSF Mach kernel (~mburg) - * - * Revision 1.2.29.1 1997/10/30 15:32:29 barbou - * Added HOST_CPU_LOAD_INFO flavor for host_statistics(). - * [1997/10/30 15:22:10 barbou] - * - * Revision 1.2.18.6 1996/01/09 19:21:44 devrcs - * Changed members of struct host_priority_info to type integer_t. - * Change HOST_RESOURCE_SIZES_COUNT and HOST_PRIORITY_INFO_COUNT - * to be in integer_t units, not int. host_info expects the count - * to be the number of integer_t's to copy. - * [1995/12/01 19:49:11 jfraser] - * - * Merged '64-bit safe' changes from DEC alpha port. - * [1995/11/21 18:08:49 jfraser] - * - * Revision 1.2.18.5 1995/04/07 19:05:07 barbou - * VM Merge - Task Swapper. - * Add new host_paging_info flavor. - * [91/09/22 13:20:45 jeffc] - * [94/07/28 barbou] - * [95/03/10 barbou] - * - * Revision 1.2.18.4 1995/02/24 14:48:07 alanl - * Merged with DIPC2_SHARED. - * [95/01/03 alanl] - * - * Revision 1.2.22.2 1994/10/14 03:50:38 dwm - * mk6 CR668 - 1.3b26 merge - * 64bit cleanup - * [1994/10/14 03:42:37 dwm] - * - * Revision 1.2.18.2 1994/09/23 02:36:22 ezf - * change marker to not FREE - * [1994/09/22 21:39:41 ezf] - * - * Revision 1.2.18.1 1994/08/07 20:48:45 bolinger - * Merge up to colo_b7. - * [1994/08/01 21:01:21 bolinger] - * - * Revision 1.2.15.2 1994/06/25 03:47:01 dwm - * mk6 CR98 - add flavor interface typedefs (host_flavor_t). - * [1994/06/24 21:54:43 dwm] - * - * Revision 1.2.15.1 1994/02/24 19:05:22 rwd - * Add HOST_PRIORITY_INFO - * [94/02/22 rwd] - * - * Revision 1.2.4.6 1993/10/28 17:17:10 jeffc - * CR10039 -- Add flavor interface typedefs - * [1993/10/28 13:55:48 jeffc] - * - * Revision 1.2.20.1 1994/10/03 18:47:25 sjs - * Intel update: often used KERNEL_BOOTMAGIC_MAX. - * [94/09/22 sjs] - * - * Revision 1.2.4.7 1994/01/28 18:14:07 chasb - * Expand Copyrights - * [1994/01/27 20:04:11 chasb] - * - * Revision 1.2.4.6 1993/10/28 17:17:10 jeffc - * CR10039 -- Add flavor interface typedefs - * [1993/10/28 13:55:48 jeffc] - * - * Revision 1.2.4.5 1993/07/07 15:48:51 brezak - * Add host_info() flavor HOST_RESOURCE_SIZES and attendant struct. - * [1993/07/07 15:47:32 brezak] - * - * Revision 1.2.4.4 1993/06/29 17:54:26 brezak - * Remove HOST_PROCESSOR_SLOTS host_info flavor. Use host_processot_slots(). - * [1993/06/28 20:58:50 brezak] - * - * Revision 1.2.4.3 1993/06/15 20:28:11 brezak - * HOST_LOAD_INFO is now returned by host_statistics(). - * Add HOST_VM_INFO for host_statistics(). Include <mach/vm_statistics.h>. - * [1993/06/14 14:18:40 brezak] - * - * Revision 1.1.5.2 1993/06/02 23:43:38 jeffc - * Added to OSF/1 R1.3 from NMK15.0. - * [1993/06/02 21:15:59 jeffc] - * - * Revision 1.2 1993/04/19 16:33:24 devrcs - * ansi C conformance changes - * [1993/02/02 18:53:04 david] - * - * Revision 1.1 1992/09/30 02:30:38 robert - * Initial revision - * - * $EndLog$ - */ -/* CMU_HIST */ -/* - * Revision 2.4.2.1 92/01/09 18:44:17 jsb - * From durriya@ri.osf.org: defined kernel_boot_info_t. - * [92/01/08 15:01:53 jsb] - * - * Revision 2.4 91/05/14 16:51:48 mrt - * Correcting copyright - * - * Revision 2.3 91/02/05 17:31:58 mrt - * Changed to new Mach copyright - * [91/02/01 17:17:13 mrt] - * - * Revision 2.2 90/06/02 14:57:58 rpd - * Added HOST_LOAD_INFO and related definitions. - * [90/04/27 rpd] - * Created for new host/processor technology. - * [90/03/26 23:50:51 rpd] - * - * Cleanup changes. - * [89/08/02 dlb] - * Add sched_info flavor to return minimum times for use by - * external schedulers. - * [89/06/08 dlb] - * Added kernel_version type definitions. - * [88/12/02 dlb] - * - * Revision 2.4 89/10/15 02:05:31 rpd - * Minor cleanups. - * - * Revision 2.3 89/10/11 17:32:15 dlb - * Include mach/machine/vm_types.h instead of mach/vm_param.h - * [89/10/11 dlb] - * - * Revision 2.2 89/10/11 14:36:55 dlb - * Add sched_info flavor to return minimum times for use by - * external schedulers. - * [89/06/08 dlb] - * - * Added kernel_version type definitions. - * [88/12/02 dlb] - * - * 30-Nov-88 David Black (dlb) at Carnegie-Mellon University - * Created. 2 flavors so far: basic info, slot numbers. - * - */ -/* CMU_ENDHIST */ /* * Mach Operating System * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University @@ -314,37 +170,4 @@ typedef struct host_cpu_load_info *host_cpu_load_info_t; #define HOST_CPU_LOAD_INFO_COUNT \ (sizeof (host_cpu_load_info_data_t) / sizeof (integer_t)) -struct host_paging_info { - time_value_t sample_time; /* (TOD) time sample taken */ - time_value_t reset_time; /* (TOD) time at last reset */ - - /* Information about page queues */ - long pagesize; /* page size in bytes */ - long free_count; /* # of pages free */ - long active_count; /* # of pages active */ - long inactive_count; /* # of pages inactive */ - long wire_count; /* # of pages wired down */ - - /* Information about page faults */ - long faults; /* # of faults */ - long zero_fill_count; /* # of zero fill pages */ - long pageins; /* # of faults resulting in pageins */ - long pages_pagedin; /* # of pages paged in */ - long cow_faults; /* # of copy-on-write faults */ - long reactivations; /* # of pages reactivated */ - - /* Information about object cache performance */ - long lookups; /* object cache lookups */ - long hits; /* object cache hits */ - - /* Information about page replacement algorithm */ - long pageouts; /* # of pageout operations (clusters) */ - long pages_pagedout; /* # of pages paged out */ -}; - -typedef struct host_paging_info host_paging_info_data_t; -typedef struct host_paging_info *host_paging_info_t; -#define HOST_PAGING_INFO_COUNT \ - (sizeof(host_paging_info_data_t)/sizeof(int)) - #endif /* _MACH_HOST_INFO_H_ */ diff --git a/osfmk/mach/kmod.h b/osfmk/mach/kmod.h index a3007a2ff..c582f5e39 100644 --- a/osfmk/mach/kmod.h +++ b/osfmk/mach/kmod.h @@ -137,7 +137,7 @@ extern void kmod_init(); extern kern_return_t kmod_create_fake(char *name, char *version); -extern kmod_info_t *kmod_lookupbyname(char * name); +extern kmod_info_t *kmod_lookupbyname(const char * name); extern kmod_info_t *kmod_lookupbyid(kmod_t id); extern kern_return_t kmod_load_extension(char *name); diff --git a/osfmk/mach/mach_port.defs b/osfmk/mach/mach_port.defs index 10c622034..dffabb668 100644 --- a/osfmk/mach/mach_port.defs +++ b/osfmk/mach/mach_port.defs @@ -197,7 +197,7 @@ routine mach_port_mod_refs( /* * Allocates a new receive right, and associates it with the - * specified RPC subsystem. + * specified RPC subsystem attributes. */ routine mach_port_allocate_subsystem( task : ipc_space_t; @@ -263,7 +263,7 @@ routine mach_port_request_notification( msgid : mach_msg_id_t; sync : mach_port_mscount_t; notify : mach_port_send_once_t; - out previous : mach_port_send_once_t); + out previous : mach_port_move_send_once_t); /* * Inserts the specified rights into the target task, diff --git a/osfmk/mach/mach_time.h b/osfmk/mach/mach_time.h index ee41f9a4d..fe70975e0 100644 --- a/osfmk/mach/mach_time.h +++ b/osfmk/mach/mach_time.h @@ -31,8 +31,6 @@ #ifndef _MACH_MACH_TIME_H_ #define _MACH_MACH_TIME_H_ -#include <stdint.h> - #include <mach/mach_types.h> uint64_t mach_absolute_time(void); diff --git a/osfmk/mach/mach_types.defs b/osfmk/mach/mach_types.defs index dd0e5022f..48c7f668b 100644 --- a/osfmk/mach/mach_types.defs +++ b/osfmk/mach/mach_types.defs @@ -59,9 +59,11 @@ #include <mach/std_types.defs> -type upl_page_info_t = struct[2] of integer_t; -type memory_object_offset_t = struct[2] of integer_t; -type memory_object_size_t = struct[2] of integer_t; +type upl_page_info_t = struct[2] of integer_t; +type upl_page_info_array_t = array[*:20] of upl_page_info_t; + +type memory_object_offset_t = struct[2] of integer_t; +type memory_object_size_t = struct[2] of integer_t; @@ -138,22 +140,6 @@ type vm_task_entry_t = mach_port_t #endif /* KERNEL_SERVER */ ; -type vm_object_entry_t = mach_port_t - ctype: vm_object_t -#if KERNEL_SERVER - intran: vm_object_t convert_port_entry_to_object(mach_port_t) - destructor: vm_object_deallocate(vm_object_t) -#endif /* KERNEL_SERVER */ - ; - -type upl_object_entry_t = mach_port_t - ctype: upl_t -#if KERNEL_SERVER - intran: upl_t convert_port_to_upl(mach_port_t) - destructor: mach_destroy_upl(upl_t) -#endif /* KERNEL_SERVER */ - ; - type ipc_space_t = mach_port_t #if KERNEL_SERVER intran: ipc_space_t convert_port_to_space(mach_port_t) @@ -205,39 +191,46 @@ type task_policy_t = array[*:16] of integer_t; type mem_entry_name_port_t = mach_port_t #if KERNEL_SERVER - intran: mem_entry_name_port_t null_conversion(mach_port_t) + intran: mem_entry_name_port_t null_conversion(mach_port_t) #endif /* KERNEL_SERVER */ ; - -type memory_object_t = mach_port_t -#if KERNEL_SERVER - intran: memory_object_t null_conversion(mach_port_t) -#endif /* KERNEL_SERVER */ - ; - type memory_object_default_t = mach_port_t -#if KERNEL_SERVER +#if KERNEL_PRIVATE intran: memory_object_default_t null_conversion(mach_port_t) -#endif /* KERNEL_SERVER */ + outtran: mach_port_t null_conversion(memory_object_default_t) +#endif /* KERNEL_PRIVATE */ ; - -type upl_object_t = mach_port_t -#if KERNEL_SERVER - intran: upl_object_t null_conversion(mach_port_t) -#endif /* KERNEL_SERVER */ + +type memory_object_t = mach_port_t +#if KERNEL_PRIVATE + intran: memory_object_t convert_port_to_memory_object(mach_port_t) + outtran: mach_port_t convert_memory_object_to_port(memory_object_t) +#endif /* KERNEL_PRIVATE */ ; -type vm_object_t = mach_port_t -#if KERNEL_SERVER - intran: vm_object_t vm_object_lookup(mach_port_t) -#endif /* KERNEL_SERVER */ + +type memory_object_control_t = mach_port_t +#if KERNEL_PRIVATE + intran: memory_object_control_t convert_port_to_mo_control(mach_port_t) + outtran: mach_port_t convert_mo_control_to_port(memory_object_control_t) + destructor: memory_object_control_deallocate(memory_object_control_t) +#endif /* KERNEL_PRIVATE */ ; type memory_object_name_t = mach_port_t ctype: mach_port_t ; +type upl_t = mach_port_t +#if KERNEL_PRIVATE + intran: upl_t convert_port_to_upl(mach_port_t) + outtran: mach_port_t convert_upl_to_port(upl_t) + destructor: upl_deallocate(upl_t) +#endif /* KERNEL_PRIVATE */ + ; + + type memory_object_copy_strategy_t = int; type memory_object_return_t = int; @@ -428,6 +421,7 @@ type semaphore_consume_ref_t = mach_port_move_send_t ctype: semaphore_t #if KERNEL_SERVER intran: semaphore_t convert_port_to_semaphore(mach_port_t) + outtran: mach_port_t convert_semaphore_to_port(semaphore_t) destructor: semaphore_dereference(semaphore_t) #endif /* KERNEL_SERVER */ ; @@ -440,8 +434,6 @@ type lock_set_t = mach_port_t #endif /* KERNEL_SERVER */ ; -type upl_page_list_ptr_t = array[*:20] of upl_page_info_t; - /* kernel module loader */ type kmod_t = int; type kmod_control_flavor_t = int; @@ -459,6 +451,7 @@ simport <kern/ipc_tt.h>; /* for task/thread conversion */ simport <kern/ipc_host.h>; /* for host/processor/pset conversions */ simport <kern/ipc_subsystem.h>; /* for subsystem conversions */ simport <kern/ipc_sync.h>; /* for lock_set and semaphore conversions */ +simport <vm/memory_object.h>; /* for memory object type conversions */ #endif /* MACH_KERNEL_PRIVATE */ simport <kern/ipc_mig.h>; /* pick up kernel-specific MIG things */ diff --git a/osfmk/mach/mach_types.h b/osfmk/mach/mach_types.h index 0e44e2b43..60591de17 100644 --- a/osfmk/mach/mach_types.h +++ b/osfmk/mach/mach_types.h @@ -61,6 +61,8 @@ #ifndef _MACH_MACH_TYPES_H_ #define _MACH_MACH_TYPES_H_ +#include <stdint.h> + #include <mach/host_info.h> #include <mach/machine.h> #include <mach/machine/vm_types.h> @@ -123,9 +125,6 @@ typedef mach_port_t ledger_t; typedef mach_port_t alarm_t; typedef mach_port_t clock_serv_t; typedef mach_port_t clock_ctrl_t; -typedef mach_port_t vm_map_t; -typedef mach_port_t vm_map_copy_t; -typedef mach_port_t vm_object_t; #endif /* !KERNEL_PRIVATE */ @@ -138,9 +137,7 @@ typedef mach_port_t bootstrap_t; typedef mach_port_t mem_entry_name_port_t; typedef mach_port_t exception_handler_t; typedef exception_handler_t *exception_handler_array_t; -typedef mach_port_t vm_object_entry_t; typedef mach_port_t vm_task_entry_t; -typedef mach_port_t upl_object_entry_t; typedef mach_port_t io_master_t; typedef mach_port_t UNDServerRef; @@ -187,8 +184,6 @@ typedef ledger_array_t ledger_port_array_t; typedef alarm_t alarm_port_t; typedef clock_serv_t clock_serv_port_t; typedef clock_ctrl_t clock_ctrl_port_t; -typedef vm_map_t vm_map_port_t; -typedef vm_map_copy_t vm_map_copy_port_t; typedef exception_handler_t exception_port_t; typedef exception_handler_array_t exception_port_arrary_t; @@ -205,9 +200,6 @@ typedef exception_handler_array_t exception_port_arrary_t; #define LOCK_SET_NULL ((lock_set_t) 0) #define ALARM_NULL ((alarm_t) 0) #define CLOCK_NULL ((clock_t) 0) -#define VM_MAP_NULL ((vm_map_t) 0) -#define VM_MAP_COPY_NULL ((vm_map_copy_t) 0) -#define VM_OBJECT_NULL ((vm_object_t) 0) #define UND_SERVER_NULL ((UNDServerRef) 0) typedef integer_t ledger_item_t; diff --git a/osfmk/mach/memory_object.defs b/osfmk/mach/memory_object.defs index 2e8ffe8f4..63c50d18c 100644 --- a/osfmk/mach/memory_object.defs +++ b/osfmk/mach/memory_object.defs @@ -74,30 +74,21 @@ subsystem #if KERNEL_SERVER serverprefix dp_; -#else -#if SEQNOS -serverprefix seqnos_; -serverdemux seqnos_memory_object_server; -#endif SEQNOS #endif /* * Initialize the specified memory object, providing - * a reqeust port on which control calls can be made. + * a memory object control reference on which to make + * cache control calls. * [To allow the mapping of this object to be used, the * memory manager must call memory_object_set_attributes, * specifying the "ready" parameter as TRUE. To reject * all mappings of this object, the memory manager may * use memory_object_destroy.] */ -simpleroutine memory_object_init( +routine memory_object_init( memory_object : memory_object_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; + memory_control : memory_object_control_t; memory_object_page_size : vm_size_t); @@ -105,85 +96,29 @@ simpleroutine memory_object_init( * Indicates that the specified memory object is no longer * mapped (or cached -- see memory_object_set_attributes), * and that further mappings will cause another memory_object_init - * call to be made. No further calls will be made on - * the memory object by this kernel. + * call to be made. * - * [All rights to the control and name ports are included - * in this call. The memory manager should use port_deallocate - * to release them once they are no longer needed.] + * [The kernel will release its reference on the memory object + * after this call returns. The memory object control associated + * with the memory object is no longer usable - the pager should + * drop the control reference granted to it by memory_object_init.] */ -simpleroutine memory_object_terminate( - memory_object : memory_object_t = - MACH_MSG_TYPE_MOVE_SEND - ctype: mach_port_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MOVE_RECEIVE - ctype: mach_port_t); +routine memory_object_terminate( + memory_object : memory_object_t); /* * Request data from this memory object. At least * the specified data should be returned with at * least the specified access permitted. * - * [Reply should be memory_object_data_provided.] + * [Response should be upl commit over the specified range.] */ -simpleroutine memory_object_data_request( +routine memory_object_data_request( memory_object : memory_object_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; offset : memory_object_offset_t; length : vm_size_t; desired_access : vm_prot_t); -/* - * Request that the specified portion of this - * memory object be unlocked to allow the specified - * forms of access; the kernel already has the data. - * - * [Reply should be memory_object_lock_request.] - */ -simpleroutine memory_object_data_unlock( - memory_object : memory_object_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; - offset : memory_object_offset_t; - length : vm_size_t; - desired_access : vm_prot_t); - -/* - * Indicate that a previous memory_object_lock_reqeust has been - * completed. Note that this call is made on whatever - * port is specified in the memory_object_lock_request; that port - * need not be the memory object port itself. - * - * [No reply expected.] - */ -simpleroutine memory_object_lock_completed( - memory_object : memory_object_t = - polymorphic|MACH_MSG_TYPE_PORT_SEND_ONCE - ctype: mach_port_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; - offset : memory_object_offset_t; - length : vm_size_t); - - skip; - /* * Return data to manager. This call is used in place of data_write * for objects initialized by object_ready instead of set_attributes. @@ -193,49 +128,66 @@ simpleroutine memory_object_lock_completed( * is only a hint if the data is not precious; the cleaned copy may * be discarded without further notifying the manager. * - * [Reply should be vm_deallocate to release the data.] + * [response should be a upl_commit over the range specified] */ -simpleroutine memory_object_data_return( +routine memory_object_data_return( memory_object : memory_object_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; offset : memory_object_offset_t; - data : pointer_t; + size : vm_size_t; dirty : boolean_t; kernel_copy : boolean_t); +/* + * Provide initial data contents for this region of + * the memory object. If data has already been written + * to the object, this value must be discarded; otherwise, + * this call acts identically to memory_object_data_return. + * + * [response should be UPL commit over the specified range.] + */ +routine memory_object_data_initialize( + memory_object : memory_object_t; + offset : memory_object_offset_t; + size : vm_size_t); + +/* + * Request that the specified portion of this + * memory object be unlocked to allow the specified + * forms of access; the kernel already has the data. + * + * [Response should be memory_object_lock_request when + * the operation is fully complete.] + */ +routine memory_object_data_unlock( + memory_object : memory_object_t; + offset : memory_object_offset_t; + size : vm_size_t; + desired_access : vm_prot_t); -simpleroutine memory_object_synchronize( - memory_object : memory_object_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; - offset : memory_object_offset_t; - length : vm_offset_t; - sync_flags : vm_sync_t ); +/* + * Request that the specified portion of this + * memory object be synchronized with its backing + * store according to the supplied flags. + * + * [Response should be memory_object_synchronize_completed when + * the operation is fully complete.] + */ +routine memory_object_synchronize( + memory_object : memory_object_t; + offset : memory_object_offset_t; + size : vm_size_t; + sync_flags : vm_sync_t ); /* - * Confirm a successful memory_object_change attributes message. + * Notify the pager that the specified memory object + * has no other (mapped) references besides the named + * reference held by the pager itself. + * + * [Response should be a release of the named reference when + * the pager deems that appropriate.] */ -simpleroutine memory_object_change_completed( - memory_object : memory_object_t = - polymorphic|MACH_MSG_TYPE_PORT_SEND_ONCE - ctype: mach_port_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND - ctype: mach_port_t; - flavor : memory_object_flavor_t); - - - skip; +routine memory_object_unmap( + memory_object : memory_object_t); + + diff --git a/osfmk/mach/memory_object_control.defs b/osfmk/mach/memory_object_control.defs index ea4eb53b0..72f91d927 100644 --- a/osfmk/mach/memory_object_control.defs +++ b/osfmk/mach/memory_object_control.defs @@ -50,7 +50,7 @@ /* */ /* - * File: mach/memory_object.defs + * File: mach/memory_object_control.defs * * Abstract: * Basic Mach external memory management interface declaration. @@ -72,38 +72,26 @@ subsystem #include <mach/std_types.defs> #include <mach/mach_types.defs> -/* - * JMM - For now we define back-and-forth paging until we get the code - * cleaned up. - */ -#define _BACK_AND_FORTH_PAGING_ - /* * Retrieves the attributes currently associated with * a memory object. */ routine memory_object_get_attributes( - memory_control : vm_object_t; + memory_control : memory_object_control_t; flavor : memory_object_flavor_t; out attributes : memory_object_info_t, CountInOut); -simpleroutine memory_object_change_attributes( - memory_control : vm_object_t; +routine memory_object_change_attributes( + memory_control : memory_object_control_t; flavor : memory_object_flavor_t; attributes : memory_object_info_t -#ifdef _BACK_AND_FORTH_PAGING_ - ; reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND|polymorphic -#endif ); -simpleroutine memory_object_synchronize_completed ( - memory_control : vm_object_t; - offset : memory_object_offset_t; - length : vm_offset_t); - -skip; +routine memory_object_synchronize_completed ( + memory_control : memory_object_control_t; + offset : memory_object_offset_t; + length : vm_offset_t); /* * Control use of the data associated with the given @@ -121,99 +109,69 @@ skip; * ("offset") and size ("size"). Only pages with the * same page alignment as the starting offset are * considered. - * - * A single acknowledgement is sent (to the "reply_to" - * port) when these actions are complete. - * - * There are two versions of this routine because IPC distinguishes - * between booleans and integers (a 2-valued integer is NOT a - * boolean). The new routine is backwards compatible at the C - * language interface. */ -simpleroutine memory_object_lock_request( - memory_control : vm_object_t; +routine memory_object_lock_request( + memory_control : memory_object_control_t; offset : memory_object_offset_t; size : memory_object_size_t; should_return : memory_object_return_t; flags : integer_t; lock_value : vm_prot_t -#ifdef _BACK_AND_FORTH_PAGING_ - ; reply_to : mach_port_t = - MACH_MSG_TYPE_MAKE_SEND|polymorphic -#endif ); - skip; - /* */ -simpleroutine memory_object_destroy( - memory_control : vm_object_t; +routine memory_object_destroy( + memory_control : memory_object_control_t; reason : kern_return_t); /* - * Provide the data contents of a range of the given memory - * object, with the access restriction specified, optional - * precious attribute, and reply message. [Only - * whole virtual pages of data can be accepted; partial pages - * will be discarded. Data should be provided on request, but - * may be provided in advance as desired. When data already - * held by this kernel is provided again, the new data is ignored. - * The access restriction is the subset of {read, write, execute} - * which are prohibited. The kernel may not provide any data (or - * protection) consistency among pages with different virtual page - * alignments within the same object. The precious value controls - * how the kernel treats the data. If it is FALSE, the kernel treats - * its copy as a temporary and may throw it away if it hasn't been - * changed. If the precious value is TRUE, the kernel treats its - * copy as a data repository and promises to return it to the manager; - * the manager may tell the kernel to throw it away instead by flushing - * and not cleaning the data -- see memory_object_lock_request. The - * reply_to port is for a compeletion message; it will be - * memory_object_supply_completed.] + * The pager gets memory_object_data_request and memory_object_data_return + * calls to inform it that data within the memory object needs to be + * manipulated. Those requests simply identify the range in the memory + * object that needs servicing, but not the data itself. The pager + * turns around and requests one (or several) Universal Page Lists (UPLs) + * from the VM cache object associated with the memory object via one + * of the following calls. These UPLs are then committed (or aborted) + * in whole (or in ranges) as the processing completes. */ - skip; - - skip; - -routine vm_object_upl_request( - object :vm_object_entry_t; - in offset :memory_object_offset_t; - in size :vm_size_t; - out upl :mach_port_move_send_t; - out page_list :upl_page_list_ptr_t, CountInOut; - in cntrl_flags :integer_t); - -routine vm_pager_upl_request( - object :vm_object_entry_t; - in offset :memory_object_offset_t; - in size :vm_size_t; - in super_size :vm_size_t; - out upl :mach_port_move_send_t; - out page_list :upl_page_list_ptr_t, CountInOut; - in cntrl_flags :integer_t); - -routine vm_upl_map( - map :vm_task_entry_t; - in upl :upl_object_t; - inout dst_addr :vm_offset_t); - -routine vm_upl_unmap( - map :vm_task_entry_t; - in upl :upl_object_t); - -routine vm_upl_abort( - upl_object :upl_object_entry_t; - in abort_cond :integer_t); - -routine vm_upl_commit( - upl_object :upl_object_entry_t; - in page_list :upl_page_list_ptr_t); - -routine vm_upl_commit_range( - upl_object :upl_object_entry_t; - offset :vm_offset_t; - size :vm_size_t; - in page_list :upl_page_list_ptr_t); +routine memory_object_upl_request( + memory_control : memory_object_control_t; + in offset : memory_object_offset_t; + in size : vm_size_t; + out upl : upl_t; + out page_list : upl_page_info_array_t, CountInOut; + in cntrl_flags : integer_t); + +routine memory_object_super_upl_request( + memory_control : memory_object_control_t; + in offset : memory_object_offset_t; + in size : vm_size_t; + in super_size : vm_size_t; + out upl : upl_t; + out page_list : upl_page_info_array_t, CountInOut; + in cntrl_flags : integer_t); + +/* + * This functions allows a single page to be manipulated with less overhead + * than creating a UPL. + */ +routine memory_object_page_op( + memory_control : memory_object_control_t; + in offset : memory_object_offset_t; + in ops : integer_t; + out phys_entry : vm_offset_t; + out flags : integer_t); + +routine memory_object_recover_named( + memory_control : memory_object_control_t; + in wait_on_terminating : boolean_t); + +routine memory_object_release_name( + memory_control : memory_object_control_t; + flags : integer_t); + + + diff --git a/osfmk/mach/memory_object_default.defs b/osfmk/mach/memory_object_default.defs index e86a41357..1a15e1bbd 100644 --- a/osfmk/mach/memory_object_default.defs +++ b/osfmk/mach/memory_object_default.defs @@ -70,12 +70,7 @@ subsystem #include <mach/mach_types.defs> #if KERNEL_SERVER -serverprefix dp_; -#else -#if SEQNOS -serverprefix seqnos_; -serverdemux seqnos_memory_object_default_server; -#endif /* SEQNOS */ +serverprefix default_pager_; #endif /* @@ -86,28 +81,7 @@ serverdemux seqnos_memory_object_default_server; * [No reply required.] */ routine memory_object_create( - old_memory_object : memory_object_default_t = - MACH_MSG_TYPE_MOVE_SEND; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - out new_memory_object : memory_object_default_t = - MACH_MSG_TYPE_MAKE_SEND; - new_object_size : vm_size_t); - -/* - * Provide initial data contents for this region of - * the memory object. If data has already been written - * to the object, this value must be discarded; otherwise, - * this call acts identically to memory_object_data_write. - */ -simpleroutine memory_object_data_initialize( - memory_object : memory_object_default_t; -#if SEQNOS - msgseqno seqno : mach_port_seqno_t; -#endif SEQNOS - memory_control_port : memory_object_control_t = - MACH_MSG_TYPE_MAKE_SEND; - offset : memory_object_offset_t; - data : pointer_t); + default_memory_manager : memory_object_default_t; + new_memory_object_size : vm_size_t; + out new_memory_object : memory_object_t); diff --git a/osfmk/mach/memory_object_types.h b/osfmk/mach/memory_object_types.h index 21f84e39c..90437610e 100644 --- a/osfmk/mach/memory_object_types.h +++ b/osfmk/mach/memory_object_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -69,30 +69,47 @@ #include <mach/machine/vm_types.h> #define VM_64_BIT_DATA_OBJECTS -#define SHARED_LIBRARY_SERVER_SUPPORTED -#define GLOBAL_SHARED_TEXT_SEGMENT 0x70000000 -#define GLOBAL_SHARED_DATA_SEGMENT 0x80000000 -#define GLOBAL_SHARED_SEGMENT_MASK 0xF0000000 -typedef mach_port_t memory_object_default_t; +typedef unsigned long long memory_object_offset_t; +typedef unsigned long long memory_object_size_t; + +/* + * Temporary until real EMMI version gets re-implemented + */ +#ifdef KERNEL_PRIVATE +typedef struct memory_object { + int *pager; +} *memory_object_t; + +typedef struct memory_object_control { + struct vm_object *object; +} *memory_object_control_t; + +#else /* !KERNEL_PRIVATE */ + +typedef mach_port_t memory_object_t; +typedef mach_port_t memory_object_control_t; -typedef mach_port_t memory_object_t; +#endif /* !KERNEL_PRIVATE */ + +typedef memory_object_t *memory_object_array_t; /* A memory object ... */ /* Used by the kernel to retrieve */ /* or store data */ -typedef mach_port_t memory_object_control_t; - /* Provided to a memory manager; ... */ - /* used to control a memory object */ - typedef mach_port_t memory_object_name_t; /* Used to describe the memory ... */ /* object in vm_regions() calls */ -typedef mach_port_t memory_object_rep_t; - /* Per-client handle for mem object */ - /* Used by user programs to specify */ - /* the object to map */ +typedef mach_port_t memory_object_default_t; + /* Registered with the host ... */ + /* for creating new internal objects */ + +#define MEMORY_OBJECT_NULL ((memory_object_t) 0) +#define MEMORY_OBJECT_CONTROL_NULL ((memory_object_control_t) 0) +#define MEMORY_OBJECT_NAME_NULL ((memory_object_name_t) 0) +#define MEMORY_OBJECT_DEFAULT_NULL ((memory_object_default_t) 0) + typedef int memory_object_copy_strategy_t; /* How memory manager handles copy: */ @@ -142,8 +159,6 @@ typedef int memory_object_return_t; #define MEMORY_OBJECT_RETURN_ANYTHING 3 /* ... any resident page. */ -#define MEMORY_OBJECT_NULL MACH_PORT_NULL - /* * Data lock request flags */ @@ -237,20 +252,17 @@ typedef struct memory_object_attr_info memory_object_attr_info_data_t; f != OLD_MEMORY_OBJECT_ATTRIBUTE_INFO) +/* + * Used to support options on memory_object_release_name call + */ +#define MEMORY_OBJECT_TERMINATE_IDLE 0x1 +#define MEMORY_OBJECT_RESPECT_CACHE 0x2 +#define MEMORY_OBJECT_RELEASE_NO_OP 0x4 + /* - * Even before we have components, we do not want to export upl internal - * structure to non mach components. + * Universal Page List data structures */ -#ifndef MACH_KERNEL_PRIVATE -#ifdef KERNEL_PRIVATE -typedef struct { - unsigned int opaque; - } * upl_t; -#else -typedef mach_port_t upl_t; -#endif /* KERNEL_PRIVATE */ -#endif #define MAX_UPL_TRANSFER 64 @@ -266,16 +278,13 @@ struct upl_page_info { }; typedef struct upl_page_info upl_page_info_t; - -typedef unsigned long long memory_object_offset_t; -typedef unsigned long long memory_object_size_t; -typedef upl_page_info_t *upl_page_list_ptr_t; -typedef mach_port_t upl_object_t; - +typedef upl_page_info_t *upl_page_info_array_t; +typedef upl_page_info_array_t upl_page_list_ptr_t; /* upl invocation flags */ +#define UPL_FLAGS_NONE 0x0 #define UPL_COPYOUT_FROM 0x1 #define UPL_PRECIOUS 0x2 #define UPL_NO_SYNC 0x4 @@ -283,13 +292,15 @@ typedef mach_port_t upl_object_t; #define UPL_NOBLOCK 0x10 #define UPL_RET_ONLY_DIRTY 0x20 #define UPL_SET_INTERNAL 0x40 +#define UPL_QUERY_OBJECT_TYPE 0x80 /* upl abort error flags */ #define UPL_ABORT_RESTART 0x1 #define UPL_ABORT_UNAVAILABLE 0x2 #define UPL_ABORT_ERROR 0x4 -#define UPL_ABORT_FREE_ON_EMPTY 0x8 +#define UPL_ABORT_FREE_ON_EMPTY 0x8 /* only implemented in wrappers */ #define UPL_ABORT_DUMP_PAGES 0x10 +#define UPL_ABORT_NOTIFY_EMPTY 0x20 /* upl pages check flags */ #define UPL_CHECK_DIRTY 0x1 @@ -300,10 +311,11 @@ typedef mach_port_t upl_object_t; #define UPL_NORDAHEAD 0x4 /* upl commit flags */ -#define UPL_COMMIT_FREE_ON_EMPTY 0x1 +#define UPL_COMMIT_FREE_ON_EMPTY 0x1 /* only implemented in wrappers */ #define UPL_COMMIT_CLEAR_DIRTY 0x2 #define UPL_COMMIT_SET_DIRTY 0x4 #define UPL_COMMIT_INACTIVATE 0x8 +#define UPL_COMMIT_NOTIFY_EMPTY 0x10 /* flags for return of state from vm_map_get_upl, vm_upl address space */ /* based call */ @@ -332,6 +344,9 @@ typedef mach_port_t upl_object_t; #define UPL_VALID_PAGE(upl, index) \ (((upl)[(index)].phys_addr != 0) ? (!((upl)[(index)].absent)) : FALSE) +#define UPL_PAGEOUT_PAGE(upl, index) \ + (((upl)[(index)].phys_addr != 0) ? ((upl)[(index)].pageout) : FALSE) + #define UPL_SET_PAGE_FREE_ON_COMMIT(upl, index) \ if ((upl)[(index)].phys_addr != 0) \ ((upl)[(index)].pageout) = TRUE @@ -341,15 +356,33 @@ typedef mach_port_t upl_object_t; ((upl)[(index)].pageout) = FALSE -#ifdef KERNEL_PRIVATE -/* - * iokit code doesn't include prerequisite header files, thus the - * !defined(IOKIT). But osfmk code defines IOKIT! Thus the - * defined(MACH_KERNEL). To clean this gorp up "just" fix all - * iokit & driver code to include the prereqs. +/* + * Flags for the UPL page ops routine. This routine is not exported + * out of the kernel at the moment and so the defs live here. */ -#if !defined(IOKIT) || defined(MACH_KERNEL) -#include <mach/error.h> +#define UPL_POP_DIRTY 0x1 +#define UPL_POP_PAGEOUT 0x2 +#define UPL_POP_PRECIOUS 0x4 +#define UPL_POP_ABSENT 0x8 +#define UPL_POP_BUSY 0x10 + +#define UPL_POP_PHYSICAL 0x10000000 +#define UPL_POP_DUMP 0x20000000 +#define UPL_POP_SET 0x40000000 +#define UPL_POP_CLR 0x80000000 + + +#ifdef KERNEL_PRIVATE + +extern void memory_object_reference(memory_object_t object); +extern void memory_object_deallocate(memory_object_t object); + +extern void memory_object_default_reference(memory_object_default_t); +extern void memory_object_default_deallocate(memory_object_default_t); + +extern void memory_object_control_reference(memory_object_control_t control); +extern void memory_object_control_deallocate(memory_object_control_t control); + /* The call prototyped below is used strictly by UPL_GET_INTERNAL_PAGE_LIST */ @@ -364,212 +397,18 @@ extern vm_size_t upl_get_internal_pagelist_offset(); (unsigned int)upl + (unsigned int)(upl_offset_to_pagelist = upl_get_internal_pagelist_offset()): \ (unsigned int)upl + (unsigned int)upl_offset_to_pagelist)) -extern kern_return_t vm_fault_list_request( - vm_object_t object, - vm_object_offset_t offset, - vm_size_t size, - upl_t *upl, - upl_page_info_t **user_page_list, - int page_list_count, - int cntrol_flags); - -extern kern_return_t upl_system_list_request( - vm_object_t object, - vm_object_offset_t offset, - vm_size_t size, - vm_size_t super_size, - upl_t *upl, - upl_page_info_t **user_page_list, - int page_list_count, - int cntrol_flags); - -extern kern_return_t upl_map( - vm_map_t map, - upl_t upl, - vm_offset_t *dst_addr); - -extern kern_return_t upl_un_map( - vm_map_t map, - upl_t upl); - -extern kern_return_t upl_commit_range( - upl_t upl, - vm_offset_t offset, - vm_size_t size, - boolean_t free_on_empty, - upl_page_info_t *page_list); - -extern kern_return_t upl_commit( - upl_t upl, - upl_page_info_t *page_list); - -extern upl_t upl_create( - boolean_t internal); - -extern void upl_destroy( - upl_t page_list); - -extern kern_return_t upl_abort( - upl_t page_list, - int error); - -extern kern_return_t upl_abort_range( - upl_t page_list, - vm_offset_t offset, - vm_size_t size, - int error); - -extern void upl_set_dirty( - upl_t upl); - -extern void upl_clear_dirty( - upl_t upl); - - - -extern kern_return_t memory_object_page_op( - vm_object_t object, - vm_object_offset_t offset, - int ops, - vm_offset_t *phys_entry, - int *flags); - -extern kern_return_t memory_object_release_name( - vm_object_t object, - int flags); - -extern kern_return_t vm_map_get_upl( - vm_map_t map, - vm_offset_t offset, - vm_size_t *upl_size, - upl_t *upl, - upl_page_info_t **page_list, - int *count, - int *flags, - int force_data_sync); - -extern kern_return_t vm_region_clone( - ipc_port_t src_region, - ipc_port_t dst_region); - -extern kern_return_t vm_map_region_replace( - vm_map_t target_map, - ipc_port_t old_region, - ipc_port_t new_region, - vm_offset_t start, - vm_offset_t end); - - - - -#ifndef MACH_KERNEL_PRIVATE - -/* address space shared region descriptor */ - -typedef void *shared_region_mapping_t; -typedef void *vm_named_entry_t; - -extern kern_return_t memory_object_destroy_named( - vm_object_t object, - kern_return_t reason); - -extern kern_return_t memory_object_lock_request_named( - vm_object_t object, - vm_object_offset_t offset, - memory_object_size_t size, - memory_object_return_t should_return, - int flags, - int prot, - ipc_port_t reply_to); +extern boolean_t upl_page_present(upl_page_info_t *upl, int index); -extern kern_return_t memory_object_change_attributes_named( - vm_object_t object, - memory_object_flavor_t flavor, - memory_object_info_t attributes, - int count, - int reply_to, - int reply_to_type); +extern boolean_t upl_dirty_page(upl_page_info_t *upl, int index); -extern kern_return_t memory_object_create_named( - ipc_port_t port, - vm_size_t size, - vm_object_t *object_ptr); +extern boolean_t upl_valid_page(upl_page_info_t *upl, int index); -/* -extern kern_return_t vm_get_shared_region( - task_t task, - shared_region_mapping_t *shared_region); - -extern kern_return_t vm_set_shared_region( - task_t task, - shared_region_mapping_t shared_region); -*/ - -extern kern_return_t shared_region_mapping_info( - shared_region_mapping_t shared_region, - ipc_port_t *text_region, - vm_size_t *text_size, - ipc_port_t *data_region, - vm_size_t *data_size, - vm_offset_t *region_mappings, - vm_offset_t *client_base, - vm_offset_t *alternate_base, - vm_offset_t *alternate_next, - int *flags, - shared_region_mapping_t *next); - -extern kern_return_t shared_region_mapping_create( - ipc_port_t text_region, - vm_size_t text_size, - ipc_port_t data_region, - vm_size_t data_size, - vm_offset_t region_mappings, - vm_offset_t client_base, - shared_region_mapping_t *shared_region); - -extern kern_return_t shared_region_mapping_ref( - shared_region_mapping_t shared_region); - -extern kern_return_t shared_region_mapping_dealloc( - shared_region_mapping_t shared_region); - -extern kern_return_t -shared_region_object_chain_attach( - shared_region_mapping_t target_region, - shared_region_mapping_t object_chain); - - -#endif MACH_KERNEL_PRIVATE +extern vm_offset_t upl_phys_page(upl_page_info_t *upl, int index); +extern void upl_set_dirty(upl_t upl); -/* - * Flags for the UPL page ops routine. This routine is not exported - * out of the kernel at the moment and so the defs live here. - */ - +extern void upl_clear_dirty(upl_t upl); -#define UPL_POP_DIRTY 0x1 -#define UPL_POP_PAGEOUT 0x2 -#define UPL_POP_PRECIOUS 0x4 -#define UPL_POP_ABSENT 0x8 -#define UPL_POP_BUSY 0x10 - -#define UPL_POP_DUMP 0x20000000 -#define UPL_POP_SET 0x40000000 -#define UPL_POP_CLR 0x80000000 - -/* - * Used to support options on memory_object_release_name call - */ - -#define MEMORY_OBJECT_TERMINATE_IDLE 0x1 -#define MEMORY_OBJECT_RESPECT_CACHE 0x2 -#define MEMORY_OBJECT_RELEASE_NO_OP 0x4 - - -#endif /* !defined(IOKIT) || defined(MACH_KERNEL) */ #endif /* KERNEL_PRIVATE */ - - #endif /* _MACH_MEMORY_OBJECT_TYPES_H_ */ diff --git a/osfmk/mach/message.h b/osfmk/mach/message.h index 003373bc8..acf2f7eff 100644 --- a/osfmk/mach/message.h +++ b/osfmk/mach/message.h @@ -64,6 +64,9 @@ #define _MIG_KERNEL_SPECIFIC_CODE_ 1 #endif /* MACH_KERNEL */ +/* static templates are slower and bigger */ +/* #define UseStaticTemplates 0 */ + #include <mach/kern_return.h> #include <mach/port.h> @@ -183,7 +186,6 @@ typedef unsigned int mach_msg_copy_options_t; #define MACH_MSG_OVERWRITE 3 #ifdef MACH_KERNEL #define MACH_MSG_KALLOC_COPY_T 4 -#define MACH_MSG_PAGE_LIST_COPY_T 5 #endif /* MACH_KERNEL */ typedef unsigned int mach_msg_descriptor_type_t; diff --git a/osfmk/mach/mig.h b/osfmk/mach/mig.h index 501d6a8dc..8bc149230 100644 --- a/osfmk/mach/mig.h +++ b/osfmk/mach/mig.h @@ -45,11 +45,146 @@ typedef void (*mig_stub_routine_t) (mach_msg_header_t *InHeadP, typedef mig_stub_routine_t mig_routine_t; /* - * Definition for server implementation routines. This is the routine - * called by the MIG-generated server stub routine. + * Definition for MIG-generated server routine. This routine takes a + * message, and returns the appropriate stub function for handling that + * message. + */ +typedef mig_routine_t (*mig_server_routine_t) (mach_msg_header_t *InHeadP); + +/* + * Generic definition for implementation routines. These routines do + * the real work associated with this request. This generic type is + * used for keeping the pointers in the subsystem array. */ typedef kern_return_t (*mig_impl_routine_t)(void); -typedef mig_impl_routine_t entry_function_t; +typedef struct mig_routine_descriptor { + mig_stub_routine_t stub_routine; /* Unmarshalling function */ + mach_msg_size_t max_reply_msg; /* Max size for this reply */ +} mig_routine_descriptor; +typedef mig_routine_descriptor *mig_routine_descriptor_t; + +typedef struct mig_subsystem { + mig_server_routine_t server; /* server routine */ + mach_msg_id_t start; /* Min routine number */ + mach_msg_id_t end; /* Max routine number + 1 */ + mach_msg_size_t max_reply; /* Max reply message size */ + mach_msg_size_t max_request; /* Max request msg size */ + mig_routine_descriptor routine[1]; /* Routine descriptor array */ +} *mig_subsystem_t; + +#ifdef KERNEL_PRIVATE +/* + * MIG object runtime definitions + * + * Conforming MIG subsystems may enable this support to get + * significant assistance from the base mig_object_t implementation. + * + * Support includes: + * - Transparency from port manipulation. + * - Dymanic port allocation on first "remoting" of an object. + * - Reference conversions from object to port and vice versa. + * - Automatic port deallocation on no-more-senders. + * - Support for multiple server implementations in a single space. + * - Messaging bypass for local servers. + * - Automatic hookup to base dispatch mechanism. + * - General notification support + * Coming soon: + * - User-level support + */ +typedef unsigned int mig_notify_type_t; + +typedef struct MIGIID { + unsigned long data1; + unsigned short data2; + unsigned short data3; + unsigned char data4[8]; +} MIGIID; + +typedef struct IMIGObjectVtbl IMIGObjectVtbl; +typedef struct IMIGNotifyObjectVtbl IMIGNotifyObjectVtbl; + +typedef struct IMIGObject { + IMIGObjectVtbl *pVtbl; +} IMIGObject; + +typedef struct IMIGNotifyObject { + IMIGNotifyObjectVtbl *pVtbl; +} IMIGNotifyObject; + +struct IMIGObjectVtbl { + kern_return_t (*QueryInterface)( + IMIGObject *object, + const MIGIID *iid, + void **ppv); + + unsigned long (*AddRef)( + IMIGObject *object); + + unsigned long (*Release)( + IMIGObject *object); + + unsigned long (*GetServer)( + IMIGObject *object, + mig_server_routine_t *server); + + boolean_t (*RaiseNotification)( + IMIGObject *object, + mig_notify_type_t notify_type); + + boolean_t (*RequestNotification)( + IMIGObject *object, + IMIGNotifyObject *notify, + mig_notify_type_t notify_type); +}; + +/* + * IMIGNotifyObject + * + * A variant of the IMIGObject interface that is a sink for + * MIG notifications. + * + * A reference is held on both the subject MIGObject and the target + * MIGNotifyObject. Because of this, care must be exercised to avoid + * reference cycles. Once a notification is raised, the object + * reference is returned and the request must be re-requested (if + * desired). + * + * One interesting note: because this interface is itself a MIG + * object, one may request notification about state changes in + * the MIGNotifyObject itself. + */ +struct IMIGNotifyObjectVtbl { + kern_return_t (*QueryInterface)( + IMIGNotifyObject *notify, + const MIGIID *iid, + void **ppv); + + unsigned long (*AddRef)( + IMIGNotifyObject *notify); + + unsigned long (*Release)( + IMIGNotifyObject *notify); + + unsigned long (*GetServer)( + IMIGNotifyObject *notify, + mig_server_routine_t *server); + + boolean_t (*RaiseNotification)( + IMIGNotifyObject *notify, + mig_notify_type_t notify_type); + + boolean_t (*RequestNotification)( + IMIGNotifyObject *notify, + IMIGNotifyObject *notify_notify, + mig_notify_type_t notify_type); + + void (*HandleNotification)( + IMIGNotifyObject *notify, + IMIGObject *object, + mig_notify_type_t notify_type); +}; + +#endif /* KERNEL_PRIVATE */ #endif /* _MACH_MIG_H_ */ diff --git a/osfmk/mach/mk_timer.h b/osfmk/mach/mk_timer.h index bb2e8bd6c..df8a66997 100644 --- a/osfmk/mach/mk_timer.h +++ b/osfmk/mach/mk_timer.h @@ -31,9 +31,7 @@ #ifndef _MACH_MK_TIMER_H_ #define _MACH_MK_TIMER_H_ -#include <libkern/OSTypes.h> - -#include <mach/mach_types.h> +#include <mach/mach_time.h> mach_port_name_t mk_timer_create(void); @@ -42,17 +40,17 @@ kern_return_t mk_timer_destroy( kern_return_t mk_timer_arm( mach_port_name_t name, - AbsoluteTime expire_time); + uint64_t expire_time); kern_return_t mk_timer_cancel( mach_port_name_t name, - AbsoluteTime *result_time); + uint64_t *result_time); struct mk_timer_expire_msg { mach_msg_header_t header; - AbsoluteTime time_of_arming; - AbsoluteTime armed_time; - AbsoluteTime time_of_posting; + uint64_t time_of_arming; + uint64_t armed_time; + uint64_t time_of_posting; }; typedef struct mk_timer_expire_msg mk_timer_expire_msg_t; diff --git a/osfmk/mach/ppc/syscall_sw.h b/osfmk/mach/ppc/syscall_sw.h index d6c7a7234..72d4151e4 100644 --- a/osfmk/mach/ppc/syscall_sw.h +++ b/osfmk/mach/ppc/syscall_sw.h @@ -69,6 +69,7 @@ ppc_trap(vmm_dispatch,0x6004) ppc_trap(bb_enable_bluebox,0x6005) ppc_trap(bb_disable_bluebox,0x6006) ppc_trap(bb_settaskenv,0x6007) +ppc_trap(vmm_stop_vm,0x6008) #endif /* _MACH_SYSCALL_SW_H_ */ #endif /* _MACH_PPC_SYSCALL_SW_H_ */ diff --git a/osfmk/mach/shared_memory_server.h b/osfmk/mach/shared_memory_server.h index 8d324489e..2f31ef1fc 100644 --- a/osfmk/mach/shared_memory_server.h +++ b/osfmk/mach/shared_memory_server.h @@ -29,8 +29,15 @@ #ifndef _SHARED_MEMORY_SERVER_H_ #define _SHARED_MEMORY_SERVER_H_ +#define SHARED_LIBRARY_SERVER_SUPPORTED +#define GLOBAL_SHARED_TEXT_SEGMENT 0x70000000 +#define GLOBAL_SHARED_DATA_SEGMENT 0x80000000 +#define GLOBAL_SHARED_SEGMENT_MASK 0xF0000000 + #define SHARED_TEXT_REGION_SIZE 0x10000000 #define SHARED_DATA_REGION_SIZE 0x10000000 +#define SHARED_ALTERNATE_LOAD_BASE 0x9000000 + /* * Note: the two masks below are useful because the assumption is * made that these shared regions will always be mapped on natural boundaries @@ -40,7 +47,6 @@ #define SHARED_TEXT_REGION_MASK 0xFFFFFFF #define SHARED_DATA_REGION_MASK 0xFFFFFFF -#define SHARED_ALTERNATE_LOAD_BASE 0x9000000 #include <mach/vm_prot.h> #ifndef MACH_KERNEL @@ -53,6 +59,7 @@ #include <kern/queue.h> #include <vm/vm_object.h> +#include <vm/memory_object.h> extern ipc_port_t shared_text_region_handle; extern ipc_port_t shared_data_region_handle; @@ -172,7 +179,7 @@ copyin_shared_file( vm_offset_t *base_address, int map_cnt, sf_mapping_t *mappings, - vm_object_t file_object, + memory_object_control_t file_control, shared_region_task_mappings_t shared_region, int *flags); diff --git a/osfmk/mach/std_types.defs b/osfmk/mach/std_types.defs index adf6056bd..c5e101ef7 100644 --- a/osfmk/mach/std_types.defs +++ b/osfmk/mach/std_types.defs @@ -93,6 +93,7 @@ type mach_port_mscount_t = unsigned; type mach_port_msgcount_t = unsigned; type mach_port_rights_t = unsigned; type mach_msg_id_t = integer_t; +type mach_msg_size_t = natural_t; type mach_msg_type_name_t = unsigned; type mach_msg_options_t = integer_t; diff --git a/osfmk/mach/sync_policy.h b/osfmk/mach/sync_policy.h index 913ae11bb..263770e0a 100644 --- a/osfmk/mach/sync_policy.h +++ b/osfmk/mach/sync_policy.h @@ -30,6 +30,7 @@ typedef int sync_policy_t; #define SYNC_POLICY_FIFO 0 #define SYNC_POLICY_FIXED_PRIORITY 1 -#define SYNC_POLICY_MAX 1 +#define SYNC_POLICY_PREPOST 2 +#define SYNC_POLICY_MAX 2 #endif /*_SYNC_POLICY_H_*/ diff --git a/osfmk/mach/task.defs b/osfmk/mach/task.defs index 599cfada0..efc244f15 100644 --- a/osfmk/mach/task.defs +++ b/osfmk/mach/task.defs @@ -371,7 +371,8 @@ routine task_set_policy( change : boolean_t); /* - * Registers the caller-specified RPC subsystem as a new object. + * Registers the caller-specified RPC subsystem attributes + * as a new object. */ routine mach_subsystem_create( task : task_t; diff --git a/osfmk/mach/task_policy.h b/osfmk/mach/task_policy.h index 9a57a45fd..cbf35f467 100644 --- a/osfmk/mach/task_policy.h +++ b/osfmk/mach/task_policy.h @@ -108,14 +108,19 @@ kern_return_t task_policy_get( #define TASK_CATEGORY_POLICY 1 +enum task_role { + TASK_RENICED = -1, + TASK_UNSPECIFIED = 0, + TASK_FOREGROUND_APPLICATION, + TASK_BACKGROUND_APPLICATION, + TASK_CONTROL_APPLICATION, + TASK_GRAPHICS_SERVER +}; + +typedef enum task_role task_role_t; + struct task_category_policy { - enum { - TASK_UNSPECIFIED = 0, - TASK_FOREGROUND_APPLICATION, - TASK_BACKGROUND_APPLICATION, - TASK_CONTROL_APPLICATION, - TASK_GRAPHICS_SERVER, - } role; + task_role_t role; }; typedef struct task_category_policy task_category_policy_data_t; diff --git a/osfmk/mach/thread_policy.h b/osfmk/mach/thread_policy.h index 3f2e29cad..143081614 100644 --- a/osfmk/mach/thread_policy.h +++ b/osfmk/mach/thread_policy.h @@ -77,9 +77,10 @@ kern_return_t thread_policy_get( /* * THREAD_STANDARD_POLICY: * - * This is the standard [fair] scheduling mode, assigned to new - * threads. Specifying it explicitly is not typically required, - * but may be used to return a thread to the default mode setting. + * This is the standard (fair) scheduling mode, assigned to new + * threads. The thread will be given processor time in a manner + * which apportions approximately equal share to long running + * computations. * * Parameters: * [none] @@ -88,14 +89,37 @@ kern_return_t thread_policy_get( #define THREAD_STANDARD_POLICY 1 struct thread_standard_policy { - /* no data */ + natural_t no_data; }; typedef struct thread_standard_policy thread_standard_policy_data_t; typedef struct thread_standard_policy *thread_standard_policy_t; -#define THREAD_STANDARD_POLICY_COUNT \ - (sizeof (thread_standard_policy_data_t) / sizeof (integer_t)) +#define THREAD_STANDARD_POLICY_COUNT 0 + +/* + * THREAD_EXTENDED_POLICY: + * + * Extended form of THREAD_STANDARD_POLICY, which supplies a + * hint indicating whether this is a long running computation. + * + * Parameters: + * + * timeshare: TRUE (the default) results in identical scheduling + * behavior as THREAD_STANDARD_POLICY. + */ + +#define THREAD_EXTENDED_POLICY 1 + +struct thread_extended_policy { + boolean_t timeshare; +}; + +typedef struct thread_extended_policy thread_extended_policy_data_t; +typedef struct thread_extended_policy *thread_extended_policy_t; + +#define THREAD_EXTENDED_POLICY_COUNT \ + (sizeof (thread_extended_policy_data_t) / sizeof (integer_t)) /* * THREAD_TIME_CONSTRAINT_POLICY: @@ -127,9 +151,9 @@ typedef struct thread_standard_policy *thread_standard_policy_t; #define THREAD_TIME_CONSTRAINT_POLICY 2 struct thread_time_constraint_policy { - natural_t period; - natural_t computation; - natural_t constraint; + uint32_t period; + uint32_t computation; + uint32_t constraint; boolean_t preemptible; }; diff --git a/osfmk/mach/upl.defs b/osfmk/mach/upl.defs index f642ad3e8..89fc94389 100644 --- a/osfmk/mach/upl.defs +++ b/osfmk/mach/upl.defs @@ -72,41 +72,26 @@ subsystem #include <mach/std_types.defs> #include <mach/mach_types.defs> +routine upl_abort( + upl_object : upl_t; + in abort_cond : integer_t); -routine vm_object_upl_request( - object :vm_object_entry_t; - in offset :memory_object_offset_t; - in size :vm_size_t; - out upl :mach_port_move_send_t; - out page_list :upl_page_list_ptr_t, CountInOut; - in cntrl_flags :integer_t); - -routine vm_pager_upl_request( - object :vm_object_entry_t; - in offset :memory_object_offset_t; - in size :vm_size_t; - in super_size :vm_size_t; - out upl :mach_port_move_send_t; - out page_list :upl_page_list_ptr_t, CountInOut; - in cntrl_flags :integer_t); - -routine vm_upl_abort( - upl_object :upl_object_entry_t; - in abort_cond :integer_t); - -routine vm_upl_abort_range( - upl_object :upl_object_entry_t; - offset :vm_offset_t; - size :vm_size_t; - in abort_cond :integer_t); +routine upl_abort_range( + upl_object : upl_t; + offset : vm_offset_t; + size : vm_size_t; + in abort_cond : integer_t; + out empty : boolean_t); -routine vm_upl_commit( - upl_object :upl_object_entry_t; - in page_list :upl_page_list_ptr_t); +routine upl_commit( + upl_object : upl_t; + in page_list : upl_page_info_array_t); + +routine upl_commit_range( + upl_object : upl_t; + offset : vm_offset_t; + size : vm_size_t; + in cntrl_flags : integer_t; + in page_list : upl_page_info_array_t; + out empty : boolean_t); -routine vm_upl_commit_range( - upl_object :upl_object_entry_t; - offset :vm_offset_t; - size :vm_size_t; - in cntrl_flags :integer_t; - in page_list :upl_page_list_ptr_t); diff --git a/osfmk/mach/vm_map.defs b/osfmk/mach/vm_map.defs index 682d98577..e0f88b10a 100644 --- a/osfmk/mach/vm_map.defs +++ b/osfmk/mach/vm_map.defs @@ -261,7 +261,7 @@ routine vm_map( size : vm_size_t; mask : vm_address_t; flags : int; - memory_object : memory_object_t; + object : mem_entry_name_port_t; offset : vm_offset_t; copy : boolean_t; cur_protection : vm_prot_t; @@ -417,10 +417,29 @@ routine vm_map_64( size : vm_size_t; mask : vm_address_t; flags : int; - memory_object : memory_object_t; + object : mem_entry_name_port_t; offset : memory_object_offset_t; copy : boolean_t; cur_protection : vm_prot_t; max_protection : vm_prot_t; inheritance : vm_inherit_t); +routine vm_map_get_upl( + target_task : vm_map_t; + address : vm_address_t; + inout size : vm_size_t; + out upl : upl_t; + out page_info : upl_page_info_array_t, CountInOut; + inout flags : integer_t; + force_data_sync : integer_t); + +routine vm_upl_map( + target_task : vm_map_t; + upl : upl_t; + inout address : vm_address_t); + +routine vm_upl_unmap( + target_task : vm_map_t; + upl : upl_t); + + diff --git a/osfmk/mach/vm_region.h b/osfmk/mach/vm_region.h index 2f46e4e0d..6d48c380a 100644 --- a/osfmk/mach/vm_region.h +++ b/osfmk/mach/vm_region.h @@ -141,7 +141,7 @@ struct vm_region_extended_info { unsigned int pages_resident; unsigned int pages_shared_now_private; unsigned int pages_swapped_out; - unsigned int pages_referenced; + unsigned int pages_dirtied; unsigned int ref_count; unsigned short shadow_depth; unsigned char external_pager; @@ -205,7 +205,7 @@ struct vm_region_submap_info { unsigned int pages_resident; /* only valid for objects */ unsigned int pages_shared_now_private; /* only for objects */ unsigned int pages_swapped_out; /* only for objects */ - unsigned int pages_referenced; /* only for objects */ + unsigned int pages_dirtied; /* only for objects */ unsigned int ref_count; /* obj/map mappers, etc */ unsigned short shadow_depth; /* only for obj */ unsigned char external_pager; /* only for obj */ @@ -233,7 +233,7 @@ struct vm_region_submap_info_64 { unsigned int pages_resident; /* only valid for objects */ unsigned int pages_shared_now_private; /* only for objects */ unsigned int pages_swapped_out; /* only for objects */ - unsigned int pages_referenced; /* only for objects */ + unsigned int pages_dirtied; /* only for objects */ unsigned int ref_count; /* obj/map mappers, etc */ unsigned short shadow_depth; /* only for obj */ unsigned char external_pager; /* only for obj */ diff --git a/osfmk/mach/vm_types.h b/osfmk/mach/vm_types.h index a47492be7..cd69b3b78 100644 --- a/osfmk/mach/vm_types.h +++ b/osfmk/mach/vm_types.h @@ -26,6 +26,7 @@ #ifndef MACH_VM_TYPES_H_ #define MACH_VM_TYPES_H_ +#include <mach/port.h> #include <mach/machine/vm_types.h> typedef vm_offset_t pointer_t; @@ -35,6 +36,7 @@ typedef unsigned long long vm_object_offset_t; #ifdef KERNEL_PRIVATE #if !defined(MACH_KERNEL_PRIVATE) + /* * Use specifically typed null structures for these in * other parts of the kernel to enable compiler warnings @@ -45,15 +47,30 @@ struct upl ; struct vm_map ; struct vm_object ; struct vm_map_copy ; -#else -typedef struct upl *upl_t; +struct vm_named_entry ; + #endif /* !MACH_KERNEL_PRIVATE */ -typedef struct vm_map *vm_map_t; -typedef struct vm_object *vm_object_t; -typedef struct vm_map_copy *vm_map_copy_t; +typedef struct upl *upl_t; +typedef struct vm_map *vm_map_t; +typedef struct vm_named_entry *vm_named_entry_t; + +typedef struct vm_object *vm_object_t; +typedef struct vm_map_copy *vm_map_copy_t; +#define VM_OBJECT_NULL ((vm_object_t) 0) +#define VM_MAP_COPY_NULL ((vm_map_copy_t) 0) + +#else /* !KERNEL_PRIVATE */ + +typedef mach_port_t upl_t; +typedef mach_port_t vm_map_t; +typedef mach_port_t vm_named_entry_t; + +#endif /* !KERNEL_PRIVATE */ -#endif +#define UPL_NULL ((upl_t) 0) +#define VM_MAP_NULL ((vm_map_t) 0) +#define VM_NAMED_ENTRY_NULL ((vm_named_entry_t) 0) #endif /* MACH_VM_TYPES_H_ */ diff --git a/osfmk/ppc/Diagnostics.c b/osfmk/ppc/Diagnostics.c index 6e52de770..454b878bc 100644 --- a/osfmk/ppc/Diagnostics.c +++ b/osfmk/ppc/Diagnostics.c @@ -59,6 +59,9 @@ #include <ppc/Diagnostics.h> #include <ppc/machine_cpu.h> #include <pexpert/pexpert.h> +#include <ppc/POWERMAC/video_console.h> + +extern struct vc_info vinfo; int diagCall(struct savearea *save) { @@ -69,6 +72,7 @@ int diagCall(struct savearea *save) { natural_t tbu, tbu2, tbl; struct per_proc_info *per_proc; /* Area for my per_proc address */ int cpu; + unsigned int tstrt, tend; if(!(dgWork.dgFlags & enaDiagSCs)) return 0; /* If not enabled, cause an exception */ @@ -146,6 +150,23 @@ int diagCall(struct savearea *save) { return 1; /* Return and check for ASTs... */ +/* + * Force cache flush + */ + case dgflush: + +#if 1 + cacheInit(); /* Blow cache */ +#else + asm volatile(" mftb %0" : "=r" (tstrt)); + tend = tstrt; + while((tend - tstrt) < 0x000A2837) { + asm volatile(" mftb %0" : "=r" (tend)); + } + +#endif + return 1; /* Return and check for ASTs... */ + /* * various hack tests */ @@ -156,6 +177,43 @@ int diagCall(struct savearea *save) { return 1; /* Return and check for ASTs... */ + +/* + * Create a physical block map into the current task + * Don't bother to check for any errors. + * parms - vaddr, paddr, size, prot, attributes + */ + case dgBMphys: + + pmap_map_block(current_act()->map->pmap, save->save_r4, save->save_r5, save->save_r6, /* Map in the block */ + save->save_r7, save->save_r8, 0); + + return 1; /* Return and check for ASTs... */ + + +/* + * Remove any mapping from the current task + * Don't bother to check for any errors. + * parms - vaddr + */ + case dgUnMap: + + (void)mapping_remove(current_act()->map->pmap, save->save_r4); /* Remove mapping */ + return 1; /* Return and check for ASTs... */ + +/* + * Return info for boot screen + */ + case dgBootScreen: + +#if 0 + ml_set_interrupts_enabled(1); + (void)copyout((char *)&vinfo, (char *)save->save_r4, sizeof(struct vc_info)); /* Copy out the video info */ + ml_set_interrupts_enabled(0); +#endif + return 1; /* Return and check for ASTs... */ + + default: /* Handle invalid ones */ return 0; /* Return an exception */ diff --git a/osfmk/ppc/Diagnostics.h b/osfmk/ppc/Diagnostics.h index c06672f83..4c344be85 100644 --- a/osfmk/ppc/Diagnostics.h +++ b/osfmk/ppc/Diagnostics.h @@ -47,6 +47,11 @@ int diagCall(struct savearea *save); #define dgpcpy 2 #define dgreset 3 #define dgtest 4 +#define dgBMphys 5 +#define dgUnMap 6 +#define dgBootScreen 7 +#define dgflush 8 + typedef struct diagWork { /* Diagnostic work area */ diff --git a/osfmk/ppc/Firmware.h b/osfmk/ppc/Firmware.h index 213787b5f..23b25171f 100644 --- a/osfmk/ppc/Firmware.h +++ b/osfmk/ppc/Firmware.h @@ -95,6 +95,15 @@ extern __inline__ void CreateShutdownCTX(void) { return; } +extern void ChokeSys(unsigned int ercd); +extern __inline__ void ChokeSys(unsigned int ercd) { + __asm__ volatile("mr r3,%0" : : "r" (ercd) : "r3"); + __asm__ volatile("lis r0,hi16(Choke)" : : : "r0"); + __asm__ volatile("ori r0,r0,lo16(Choke)" : : : "r0"); + __asm__ volatile("sc"); + return; +} + typedef struct Boot_Video bootBumbleC; extern void StoreReal(unsigned int val, unsigned int addr); diff --git a/osfmk/ppc/Firmware.s b/osfmk/ppc/Firmware.s index c7db5a174..fc040ffe2 100644 --- a/osfmk/ppc/Firmware.s +++ b/osfmk/ppc/Firmware.s @@ -323,6 +323,17 @@ ENTRY(CreateShutdownCTX, TAG_NO_FRAME_USED) sc /* Do it to it */ blr /* Bye bye, Birdie... */ +/* + * This is the glue to choke system + */ + +ENTRY(ChokeSys, TAG_NO_FRAME_USED) + + lis r0,HIGH_ADDR(Choke) /* Top half of Choke firmware call number */ + ori r0,r0,LOW_ADDR(Choke) /* Bottom half */ + sc /* Do it to it */ + blr /* Bye bye, Birdie... */ + /* * Used to initialize the SCC for debugging output */ @@ -1604,14 +1615,18 @@ ENTRY(CreateFakeDECLL, TAG_NO_FRAME_USED) blr /* Return to interrupt handler */ /* - * Choke the system. This is just a dummy for now, - * but we'll eventually do something. + * Choke the system. */ ENTRY(DoChokeLL, TAG_NO_FRAME_USED) - BREAKPOINT_TRAP /* Dummy for now */ - + mfsprg r11,0 ; Get the per_proc address + lwz r11,PP_TEMPWORK1(r11) ; Restore the return address + li r3,T_CHOKE ; Set external interrupt value + mtlr r11 ; Restore the LR + stw r3,saveexception(r13) ; Modify the exception type to external + blr ; Return to interrupt handler + /* * Set the low level trace flags */ @@ -2107,6 +2122,7 @@ LEXT(stFloat) .globl EXT(stVectors) LEXT(stVectors) +#if 0 mfpvr r6 ; Get machine type mr r5,r3 ; Save area address @@ -2191,6 +2207,8 @@ LEXT(stVectors) lvxl v31,0,r5 mtmsr r0 isync + +#endif blr @@ -2202,6 +2220,7 @@ LEXT(stVectors) .globl EXT(stSpecrs) LEXT(stSpecrs) +#if 0 mfmsr r0 ; Save the MSR rlwinm r4,r0,0,MSR_EE_BIT,MSR_EE_BIT ; Turn off interruptions @@ -2332,4 +2351,6 @@ nnmax: stw r4,(48*4)(r3) mtmsr r0 isync + +#endif blr diff --git a/osfmk/ppc/POWERMAC/serial_io.c b/osfmk/ppc/POWERMAC/serial_io.c index 498bd3755..f3f9eb742 100644 --- a/osfmk/ppc/POWERMAC/serial_io.c +++ b/osfmk/ppc/POWERMAC/serial_io.c @@ -142,7 +142,7 @@ enum scc_error {SCC_ERR_NONE, SCC_ERR_PARITY, SCC_ERR_BREAK, SCC_ERR_OVERRUN}; #define SERIAL_CLOCK_FREQUENCY (115200*2) /* Power Mac value */ #define convert_baud_rate(rate) ((((SERIAL_CLOCK_FREQUENCY) + (rate)) / (2 * (rate))) - 2) -#define DEFAULT_SPEED 38400 +#define DEFAULT_SPEED 57600 #define DEFAULT_FLAGS (TF_LITOUT|TF_ECHO) int scc_param(struct scc_tty *tp); diff --git a/osfmk/ppc/POWERMAC/video_console.c b/osfmk/ppc/POWERMAC/video_console.c index 2ed27aeec..cf286337c 100644 --- a/osfmk/ppc/POWERMAC/video_console.c +++ b/osfmk/ppc/POWERMAC/video_console.c @@ -999,13 +999,9 @@ putc_normal(unsigned char ch) switch (ch) { case '\a': /* Beep */ { - extern int asc_ringbell(); //In IOBSDConsole.cpp - int rang; spl_t s; - rang = asc_ringbell(); - - if(!rang) { + if(FALSE) { /* * No sound hardware, invert the screen twice instead */ diff --git a/osfmk/ppc/PPCcalls.h b/osfmk/ppc/PPCcalls.h index 073a24057..8dbbafaad 100644 --- a/osfmk/ppc/PPCcalls.h +++ b/osfmk/ppc/PPCcalls.h @@ -47,8 +47,8 @@ PPCcallEnt PPCcalls[] = { PPCcall(bb_enable_bluebox), /* 0x6005 Enable this thread for use in the blue box virtual machine */ PPCcall(bb_disable_bluebox), /* 0x6006 Disable this thread for use in the blue box virtual machine */ PPCcall(bb_settaskenv), /* 0x6007 Set the BlueBox per thread task environment data */ + PPCcall(vmm_stop_vm), /* 0x6008 Stop a running VM */ - PPCcall(dis), /* 0x6008 disabled */ PPCcall(dis), /* 0x6009 disabled */ PPCcall(dis), /* 0x600A disabled */ PPCcall(dis), /* 0x600B disabled */ diff --git a/osfmk/ppc/PseudoKernel.c b/osfmk/ppc/PseudoKernel.c index 79ad19dbd..449836187 100644 --- a/osfmk/ppc/PseudoKernel.c +++ b/osfmk/ppc/PseudoKernel.c @@ -42,7 +42,6 @@ #include <vm/vm_kern.h> void bbSetRupt(ReturnHandler *rh, thread_act_t ct); -void DumpTheSave(struct savearea *save); /* (TEST/DEBUG) */ /* ** Function: NotifyInterruption @@ -106,7 +105,7 @@ kern_return_t syscall_notify_interrupt ( void ) { return KERN_SUCCESS; } - if(act->mact.bbPendRupt >= 16) { /* Have we hit the arbitrary maximum? */ + if(act->mact.emPendRupts >= 16) { /* Have we hit the arbitrary maximum? */ act_unlock_thread(act); /* Unlock the activation */ return KERN_RESOURCE_SHORTAGE; /* Too many pending right now */ } @@ -116,7 +115,7 @@ kern_return_t syscall_notify_interrupt ( void ) { return KERN_RESOURCE_SHORTAGE; /* No storage... */ } - (void)hw_atomic_add(&act->mact.bbPendRupt, 1); /* Count this 'rupt */ + (void)hw_atomic_add(&act->mact.emPendRupts, 1); /* Count this 'rupt */ bbr->rh.handler = bbSetRupt; /* Set interruption routine */ bbr->rh.next = act->handlers; /* Put our interrupt at the start of the list */ @@ -150,7 +149,7 @@ void bbSetRupt(ReturnHandler *rh, thread_act_t act) { return; } - (void)hw_atomic_sub(&act->mact.bbPendRupt, 1); /* Uncount this 'rupt */ + (void)hw_atomic_sub(&act->mact.emPendRupts, 1); /* Uncount this 'rupt */ if(!(sv = (savearea *)find_user_regs(act))) { /* Find the user state registers */ kfree((vm_offset_t)bbr, sizeof(bbRupt)); /* Couldn't find 'em, release the control block */ @@ -178,6 +177,9 @@ void bbSetRupt(ReturnHandler *rh, thread_act_t act) { bttd->exceptionInfo.srr1 = sv->save_srr1; /* Save the original MSR */ sv->save_srr1 &= ~(MASK(MSR_BE)|MASK(MSR_SE)); /* Clear SE|BE bits in MSR */ act->mact.specFlags &= ~bbNoMachSC; /* reactivate Mach SCs */ + disable_preemption(); /* Don't move us around */ + per_proc_info[cpu_number()].spcFlags = act->mact.specFlags; /* Copy the flags */ + enable_preemption(); /* Ok to move us around */ /* drop through to post int in backup CR2 in ICW */ case kInExceptionHandler: @@ -257,12 +259,21 @@ kern_return_t enable_bluebox( TRUE); th->top_act->mact.bbDescAddr = (unsigned int)kerndescaddr+origdescoffset; /* Set kernel address of the table */ - th->top_act->mact.bbUserDA = (unsigned int)Desc_TableStart; /* Set user address of the table */ - th->top_act->mact.bbTableStart = (unsigned int)TWI_TableStart; /* Set address of the trap table */ - th->top_act->mact.bbTaskID = (unsigned int)taskID; /* Assign opaque task ID */ - th->top_act->mact.bbTaskEnv = 0; /* Clean task environment data */ - th->top_act->mact.bbPendRupt = 0; /* Clean pending 'rupt count */ - th->top_act->mact.specFlags &= ~bbNoMachSC; /* Make sure mach SCs are enabled */ + th->top_act->mact.bbUserDA = (unsigned int)Desc_TableStart; /* Set user address of the table */ + th->top_act->mact.bbTableStart = (unsigned int)TWI_TableStart; /* Set address of the trap table */ + th->top_act->mact.bbTaskID = (unsigned int)taskID; /* Assign opaque task ID */ + th->top_act->mact.bbTaskEnv = 0; /* Clean task environment data */ + th->top_act->mact.emPendRupts = 0; /* Clean pending 'rupt count */ + th->top_act->mact.specFlags &= ~(bbNoMachSC | bbPreemptive); /* Make sure mach SCs are enabled and we are not marked preemptive */ + th->top_act->mact.specFlags |= bbThread; /* Set that we are Classic thread */ + + if(!(((BTTD_t *)kerndescaddr)->InterruptVector)) { /* See if this is a preemptive (MP) BlueBox thread */ + th->top_act->mact.specFlags |= bbPreemptive; /* Yes, remember it */ + } + + disable_preemption(); /* Don't move us around */ + per_proc_info[cpu_number()].spcFlags = th->top_act->mact.specFlags; /* Copy the flags */ + enable_preemption(); /* Ok to move us around */ { /* mark the proc to indicate that this is a TBE proc */ @@ -303,8 +314,11 @@ void disable_bluebox_internal(thread_act_t act) { /* Terminate bluebox */ act->mact.bbTableStart = 0; /* Clear user pointer to TWI table */ act->mact.bbTaskID = 0; /* Clear opaque task ID */ act->mact.bbTaskEnv = 0; /* Clean task environment data */ - act->mact.bbPendRupt = 0; /* Clean pending 'rupt count */ - act->mact.specFlags &= ~bbNoMachSC; /* Clean up Blue Box enables */ + act->mact.emPendRupts = 0; /* Clean pending 'rupt count */ + act->mact.specFlags &= ~(bbNoMachSC | bbPreemptive | bbThread); /* Clean up Blue Box enables */ + disable_preemption(); /* Don't move us around */ + per_proc_info[cpu_number()].spcFlags = act->mact.specFlags; /* Copy the flags */ + enable_preemption(); /* Ok to move us around */ return; } @@ -379,12 +393,17 @@ int bb_settaskenv( struct savearea *save ) task_unlock(task); /* Safe to release now */ act->mact.bbTaskEnv = save->save_r4; + if(act == current_act()) { /* Are we setting our own? */ + disable_preemption(); /* Don't move us around */ + per_proc_info[cpu_number()].spcFlags = act->mact.specFlags; /* Copy the flags */ + enable_preemption(); /* Ok to move us around */ + } act_unlock_thread(act); /* Unlock the activation */ save->save_r3 = 0; - return KERN_SUCCESS; + return 1; failure: save->save_r3 = -1; /* we failed to find the taskID */ - return KERN_FAILURE; + return 1; } diff --git a/osfmk/ppc/PseudoKernel.h b/osfmk/ppc/PseudoKernel.h index 943a861b3..ca3722b2c 100644 --- a/osfmk/ppc/PseudoKernel.h +++ b/osfmk/ppc/PseudoKernel.h @@ -27,6 +27,8 @@ Copyright: (c) 2000 Apple Computer, Inc. All rights reserved. */ +#include <libkern/OSTypes.h> + #include <ppc/exception.h> /* Support firmware PseudoKernel FastTrap architectural extension */ diff --git a/osfmk/ppc/alignment.c b/osfmk/ppc/alignment.c index e5ac61c0b..bfc4a7717 100644 --- a/osfmk/ppc/alignment.c +++ b/osfmk/ppc/alignment.c @@ -257,7 +257,7 @@ _ANIL, /* 10 0 0100 ?*/ _ANIL, /* 10 0 0101 ?*/ _ANIL, /* 10 0 0110 ?*/ _ANIL, /* 10 0 0111 ?*/ -_AENTRY(lwbrx, 2, 0), /* 10 0 1000 */ +_AENTRY(lwbrx, 4, 0), /* 10 0 1000 */ _ANIL, /* 10 0 1001 ?*/ _AENTRY(stwbrx, 0, 4), /* 10 0 1010 */ _ANIL, /* 10 0 1011 */ @@ -309,7 +309,7 @@ _AENTRY(lhaux, 4, 0), /* 11 1 0101 */ _AENTRY(sthux, 0, 4), /* 11 1 0110 */ _ANIL, /* 11 1 0111 ?*/ _AFENTRY(lfsux, 4, 0), /* 11 1 1000 */ -_AFENTRY(lfdux, 0, 8), /* 11 1 1001 */ +_AFENTRY(lfdux, 8, 0), /* 11 1 1001 */ _AFENTRY(stfsux, 0, 4), /* 11 1 1010 */ _AFENTRY(stfdux, 0, 8), /* 11 1 1011 */ }; @@ -379,6 +379,8 @@ alignment(unsigned long dsisr, unsigned long dar, else (void)hw_atomic_add(&alignment_exception_count_kernel, 1); #endif + act = current_act(); /* Get the current activation */ + table = &align_tables[DSISR_BITS_15_16(dsisr)]; if (table == (void *) 0 @@ -411,7 +413,7 @@ alignment(unsigned long dsisr, unsigned long dar, */ if (entry->a_is_float) - fpu_save(); + fpu_save(act); /* * Pull in any bytes which are going to be @@ -440,12 +442,10 @@ alignment(unsigned long dsisr, unsigned long dar, printf(" pc=(0x%08X), msr=(0x%X)",ssp->srr0, ssp->srr1); #endif - act = current_act(); /* Get the current activation */ success = entry->a_instruct(dsisr, ssp, - find_user_fpu(act), /* Find this user's FPU state. NULL if none */ - /* NULL should never happen */ + (entry->a_is_float ? find_user_fpu(act) : 0), /* Find this user's FPU state if FP op */ align_buffer, dar); @@ -464,8 +464,10 @@ alignment(unsigned long dsisr, unsigned long dar, } } else { - for(i=0; i < real_ncpus; i++) { /* Cycle through processors */ - (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */ + if(entry->a_is_float) { /* If we are an FP op, blow away live context */ + for(i=0; i < real_ncpus; i++) { /* Cycle through processors */ + (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */ + } } if (USER_MODE(ssp->srr1)) { diff --git a/osfmk/ppc/asm.h b/osfmk/ppc/asm.h index 496b31c05..4e3ed2e79 100644 --- a/osfmk/ppc/asm.h +++ b/osfmk/ppc/asm.h @@ -139,6 +139,7 @@ #define hid1 1009 /* Clock configuration */ #define iabr 1010 /* Instruction address breakpoint register */ #define ictrl 1011 /* Instruction Cache Control */ +#define ldstdb 1012 /* Load/Store Debug */ #define dabr 1013 /* Data address breakpoint register */ #define msscr0 1014 /* Memory subsystem control */ #define msscr1 1015 /* Memory subsystem debug */ @@ -239,6 +240,9 @@ #define tfsts 24 #define tfste 25 #define tfstm 0x000000C0 +#define l2pfes 30 +#define l2pfee 31 +#define l2pfem 0x00000003 ; msscr1 bits #define cqd 15 diff --git a/osfmk/ppc/atomic_switch.s b/osfmk/ppc/atomic_switch.s index 4133b1220..607bc04a4 100644 --- a/osfmk/ppc/atomic_switch.s +++ b/osfmk/ppc/atomic_switch.s @@ -57,33 +57,9 @@ ENTRY(atomic_switch_syscall, TAG_NO_FRAME_USED) /* - * Here's where we check for special Blue Box fast traps - * If we don't recognize the syscall, we'll go back to regular processing + * Note: the BlueBox fast path system calls (-1 and -2) we handled as + * an ultra-fast trap in lowmem_vectors. */ - cmpwi r0,-1 ; Is it NKIsPreemptiveTask - beq- isBBpretask ; It is a fast syscall... - cmpwi r0,-2 ; Is it kcNKIsPreemptiveTaskEnv - bne- nofastSC ; Not a fast syscall... - - ; kcNKIsPreemptiveTaskEnv return task.taskEnv in r0 - - lwz r23, ACT_MACT_BTE(r13) ; Get the taskEnv - stw r23, saver0(r4) ; Return the taskEnv in R0 - -isBBpretask: ; answer the question is this a preemptive task ? - rlwinm r6,r26,0,0,19 ; Start of page is bttd - lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector - lwz r6, savecr(r4) ; Get the current CCRs - cmpwi r1,0 ; Is this a preemptive thread ? - rlwinm r6,r6,0,cr0_eq+1,cr0_eq-1 ; Clear CR0 EQ bit - bne notpretask ; Only the cooperative thread has an interrupt vector - oris r6,r6,(0x8000 >> cr0_eq) ; Set CR0[eq] if task is preemptive. -notpretask: - stw r6, savecr(r4) ; Save the new current CCRs - - b EXT(fastexit) ; Take the fast path exit... - -nofastSC: li r5, BTTD_SYSCALL_VECTOR b .L_CallPseudoKernel @@ -128,6 +104,7 @@ ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED) .L_CallPseudoKernel: + mfsprg r2,0 ; Get the per_proc rlwinm r6,r26,0,0,19 ; Start of page is bttd lwz r7,ACT_MACT_SPF(r13) ; Get special flags lwz r1,BTTD_INTERRUPT_VECTOR(r6) ; Get interrupt vector @@ -136,6 +113,7 @@ ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED) lwz r8,BTTD_INTCONTROLWORD(r6) ; Get Interrupt Control Word cmpwi r1,0 ; Is this a preemptive thread ? stw r7,ACT_MACT_SPF(r13) ; Update special flags + stw r7,spcFlags(r2) ; Update per_proc version beq .L_CallFromPreemptiveThread ; No int vector means preemptive thread rlwinm r1,r8,0,INTSTATEMASK_B,INTSTATEMASK_E @@ -202,7 +180,7 @@ ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED) lwz r7,ACT_MACT_SPF(r13) ; Get special flags lwz r2,BTTD_INTERRUPT_VECTOR(r6) ; Get the interrupt vector lwz r1,BEDA_SPRG1(r26) ; Get saved CTR - oris r7,r7,(0x8000 >> bbNoMachSCbit) ; Disable Mach SCs for Blue Box + ori r7,r7,(0x8000 >> (bbNoMachSCbit - 16)) ; Disable Mach SCs for Blue Box cmpwi r2,0 ; Is this a preemptive thread stw r1,savectr(r4) ; Update CTR @@ -236,9 +214,11 @@ ENTRY(atomic_switch_trap, TAG_NO_FRAME_USED) stw r1,savecr(r4) ; Update CR .L_ExitFromPreemptiveThread: + mfsprg r3,0 ; Get the per_proc lwz r2,savesrr1(r4) ; Get current MSR lwz r1,BEDA_SRR1(r26) ; Get new MSR stw r7,ACT_MACT_SPF(r13) ; Update special flags + stw r7,spcFlags(r3) ; Update per_proc version rlwimi r2,r1,0,MSR_FE0_BIT,MSR_FE1_BIT ; Insert FE0,FE1,SE,BE bits lwz r3,BEDA_SRR0(r26) ; Get new PC diff --git a/osfmk/ppc/bat_init.c b/osfmk/ppc/bat_init.c index 9d297538e..5d36e6fa4 100644 --- a/osfmk/ppc/bat_init.c +++ b/osfmk/ppc/bat_init.c @@ -24,29 +24,6 @@ #include <ppc/boot.h> #include <ppc/mem.h> -#ifdef XXX_LOADER -unsigned int kernel_seg_regs[] = { - KERNEL_SEG_REG0_VALUE, - KERNEL_SEG_REG1_VALUE, - SEG_REG_INVALID, /* 2 */ - SEG_REG_INVALID, /* 3 */ - SEG_REG_INVALID, /* 4 */ - KERNEL_SEG_REG5_VALUE, /* 5 - I/O segment */ - SEG_REG_INVALID, /* 6 */ - SEG_REG_INVALID, /* 7 */ - KERNEL_SEG_REG8_VALUE, /* 8-F are possible IO space */ - KERNEL_SEG_REG9_VALUE, - KERNEL_SEG_REG10_VALUE, - KERNEL_SEG_REG11_VALUE, - KERNEL_SEG_REG12_VALUE, - KERNEL_SEG_REG13_VALUE, - KERNEL_SEG_REG14_VALUE, /* 14 - A/V video */ - KERNEL_SEG_REG15_VALUE /* 15 - NuBus etc */ -}; -#else -extern unsigned int kernel_seg_regs[]; -#endif - // The sophisticated BAT manager unsigned int mappedSegments = 0; diff --git a/osfmk/ppc/bsd_ppc.c b/osfmk/ppc/bsd_ppc.c index 8918fed40..e866c31bf 100644 --- a/osfmk/ppc/bsd_ppc.c +++ b/osfmk/ppc/bsd_ppc.c @@ -119,7 +119,7 @@ unix_syscall( code = regs->r0; thread = current_act(); - p = get_bsdtask_info(current_task()); + p = current_proc(); rval = (int *)get_bsduthreadrval(thread); /* @@ -189,6 +189,10 @@ unix_syscall( current_task()->syscalls_unix++; error = (*(callp->sy_call))(p, (void *)vt, rval); + regs = find_user_regs(thread); + if (regs == (struct ppc_saved_state *)0) + panic("No user savearea while returning from system call"); + if (error == ERESTART) { regs->srr0 -= 8; } @@ -232,7 +236,7 @@ unix_syscall_return(error) extern int nsysent; thread = current_act(); - p = get_bsdtask_info(current_task()); + p = current_proc(); rval = (int *)get_bsduthreadrval(thread); pcb = thread->mact.pcb; regs = &pcb->ss; diff --git a/osfmk/ppc/cpu.c b/osfmk/ppc/cpu.c index 360c29c6e..2b6d36a9c 100644 --- a/osfmk/ppc/cpu.c +++ b/osfmk/ppc/cpu.c @@ -59,7 +59,7 @@ struct SIGtimebase { boolean_t avail; boolean_t ready; boolean_t done; - AbsoluteTime abstime; + uint64_t abstime; }; extern struct SIGtimebase syncClkSpot; @@ -390,18 +390,23 @@ void cpu_machine_init( void) { - struct per_proc_info *proc_info; + struct per_proc_info *tproc_info; + volatile struct per_proc_info *mproc_info; int cpu; /* TODO: realese mutex lock reset_handler_lock */ cpu = cpu_number(); - proc_info = &per_proc_info[cpu]; - PE_cpu_machine_init(proc_info->cpu_id, !(proc_info->cpu_flags & BootDone)); - if (cpu != master_cpu) + tproc_info = &per_proc_info[cpu]; + mproc_info = &per_proc_info[master_cpu]; + PE_cpu_machine_init(tproc_info->cpu_id, !(tproc_info->cpu_flags & BootDone)); + if (cpu != master_cpu) { + while (!((mproc_info->cpu_flags) & SignalReady)) + continue; cpu_sync_timebase(); + } ml_init_interrupt(); - proc_info->cpu_flags |= BootDone; + tproc_info->cpu_flags |= BootDone|SignalReady; } kern_return_t @@ -447,7 +452,7 @@ cpu_start( if (cpu == cpu_number()) { PE_cpu_machine_init(proc_info->cpu_id, !(proc_info->cpu_flags & BootDone)); ml_init_interrupt(); - proc_info->cpu_flags |= BootDone; + proc_info->cpu_flags |= BootDone|SignalReady; return KERN_SUCCESS; } else { @@ -461,8 +466,7 @@ cpu_start( proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state); proc_info->debstack_top_ss = proc_info->debstackptr; #endif /* MACH_KDP || MACH_KDB */ - proc_info->get_interrupts_enabled = fake_get_interrupts_enabled; - proc_info->set_interrupts_enabled = fake_set_interrupts_enabled; + proc_info->interrupts_enabled = 0; proc_info->active_kloaded = (unsigned int)&active_kloaded[cpu]; proc_info->cpu_data = (unsigned int)&cpu_data[cpu]; proc_info->active_stacks = (unsigned int)&active_stacks[cpu]; @@ -589,7 +593,7 @@ cpu_signal_handler( if(pproc->time_base_enable != (void(*)(cpu_id_t, boolean_t ))NULL) pproc->time_base_enable(pproc->cpu_id, FALSE); - timebaseAddr->abstime.hi = 0; /* Touch to force into cache */ + timebaseAddr->abstime = 0; /* Touch to force into cache */ sync(); do { @@ -598,8 +602,7 @@ cpu_signal_handler( asm volatile(" mftbu %0" : "=r" (tbu2)); } while (tbu != tbu2); - timebaseAddr->abstime.lo = tbl; /* Set low order */ - timebaseAddr->abstime.hi = tbu; /* Set high order */ + timebaseAddr->abstime = ((uint64_t)tbu << 32) | tbl; sync(); /* Force order */ timebaseAddr->avail = TRUE; @@ -681,6 +684,8 @@ cpu_signal( mpproc = &per_proc_info[cpu]; /* Point to our block */ tpproc = &per_proc_info[target]; /* Point to the target's block */ + + if (!(tpproc->cpu_flags & SignalReady)) return KERN_FAILURE; if(!hw_lock_mbits(&tpproc->MPsigpStat, MPsigpMsgp, 0, MPsigpBusy, (gPEClockFrequencyInfo.bus_clock_rate_hz >> 7))) { /* Try to lock the message block */ @@ -735,8 +740,7 @@ cpu_sleep( proc_info->debstackptr = (vm_offset_t)&debstack + (KERNEL_STACK_SIZE*(cpu+1)) - sizeof (struct ppc_saved_state); proc_info->debstack_top_ss = proc_info->debstackptr; #endif /* MACH_KDP || MACH_KDB */ - proc_info->get_interrupts_enabled = fake_get_interrupts_enabled; - proc_info->set_interrupts_enabled = fake_set_interrupts_enabled; + proc_info->interrupts_enabled = 0; proc_info->FPU_thread = 0; if (proc_info->start_paddr == EXCEPTION_VECTOR(T_RESET)) { @@ -775,19 +779,21 @@ cpu_sync_timebase( syncClkSpot.ready = FALSE; syncClkSpot.done = FALSE; - while (cpu_signal(master_cpu, SIGPcpureq, CPRQtimebase, (unsigned int)&syncClkSpot) - != KERN_SUCCESS); + while (cpu_signal(master_cpu, SIGPcpureq, CPRQtimebase, + (unsigned int)&syncClkSpot) != KERN_SUCCESS) + continue; + while (*(volatile int *)&(syncClkSpot.avail) == FALSE) + continue; - while (*(volatile int *)&(syncClkSpot.avail) == FALSE); isync(); /* * We do the following to keep the compiler from generating extra stuff * in tb set part */ - tbu = syncClkSpot.abstime.hi; - tbl = syncClkSpot.abstime.lo; + tbu = syncClkSpot.abstime >> 32; + tbl = (uint32_t)syncClkSpot.abstime; mttb(0); mttbu(tbu); @@ -795,7 +801,8 @@ cpu_sync_timebase( syncClkSpot.ready = TRUE; - while (*(volatile int *)&(syncClkSpot.done) == FALSE); + while (*(volatile int *)&(syncClkSpot.done) == FALSE) + continue; (void)ml_set_interrupts_enabled(intr); } diff --git a/osfmk/ppc/cswtch.s b/osfmk/ppc/cswtch.s index d9ef06022..8a4d0ac65 100644 --- a/osfmk/ppc/cswtch.s +++ b/osfmk/ppc/cswtch.s @@ -142,13 +142,13 @@ notonintstack: #endif stw r4,THREAD_CONTINUATION(r3) cmpwi cr1,r4,0 /* used waaaay down below */ - lwz r11,0(r12) - stw r11,THREAD_KERNEL_STACK(r3) + lwz r7,0(r12) /* * Make the new thread the current thread. */ lwz r11,PP_CPU_DATA(r6) + stw r7,THREAD_KERNEL_STACK(r3) stw r5, CPU_ACTIVE_THREAD(r11) lwz r11,THREAD_KERNEL_STACK(r5) @@ -156,14 +156,17 @@ notonintstack: lwz r5,THREAD_TOP_ACT(r5) lwz r10,PP_ACTIVE_STACKS(r6) lwz r7,CTHREAD_SELF(r5) ; Pick up the user assist word - lwz r8,ACT_MACT_PCB(r5) /* Get the PCB for the new guy */ + lwz r8,ACT_MACT_PCB(r5) ; Get the PCB for the new guy stw r11,0(r10) ; Save the kernel stack address stw r7,UAW(r6) ; Save the assist word for the "ultra fast path" + + lwz r11,ACT_MACT_BTE(r5) ; Get BlueBox Task Environment lwz r7,ACT_MACT_SPF(r5) ; Get the special flags lwz r10,ACT_KLOADED(r5) + stw r11,ppbbTaskEnv(r6) ; Save the bb task env li r0,0 cmpwi cr0,r10,0 lwz r10,PP_ACTIVE_KLOADED(r6) @@ -272,7 +275,7 @@ ENTRY(switch_in, TAG_NO_FRAME_USED) /* - * void fpu_save(void) + * void fpu_save(thread_act_t act) * * To do the floating point and VMX, we keep three thread pointers: one * to the current thread, one to the thread that has the floating point context @@ -441,11 +444,10 @@ ENTRY(switch_in, TAG_NO_FRAME_USED) ; 7) exit to interrupt return ; ; -; Context save (operates on current activation's data; only used during context switch): -; (context switch always disables the facility) -; +; Context save (operates on specified activation's data): + ; 1) if no owner exit -; 2) if owner != current activation exit +; 2) if owner != specified activation exit ; 3) if context processor != current processor ; 1) clear owner ; 2) exit @@ -507,6 +509,7 @@ ENTRY(fpu_save, TAG_NO_FRAME_USED) #if FPVECDBG mr r7,r0 ; (TEST/DEBUG) li r4,0 ; (TEST/DEBUG) + mr r10,r3 ; (TEST/DEBUG) lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) mr. r3,r12 ; (TEST/DEBUG) li r2,0x6F00 ; (TEST/DEBUG) @@ -518,23 +521,29 @@ ENTRY(fpu_save, TAG_NO_FRAME_USED) noowneryet: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) sc ; (TEST/DEBUG) mr r0,r7 ; (TEST/DEBUG) + mr r3,r10 ; (TEST/DEBUG) #endif mflr r2 ; Save the return address - lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number mr. r12,r12 ; Anyone own the FPU? + cmplw cr1,r3,r12 ; Is the specified thread the owner? - lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread + beq- fsretnr ; Nobody owns the FPU, no save required... - beq- fsret ; Nobody owns the FPU, no save required... + li r4,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word + bne- cr1,fsretnr ; Facility belongs to some other activation... - lwz r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running - lwz r9,ACT_MACT_FPUcpu(r12) ; Get the last CPU to use this context +fsvSpin2: lwarx r9,r4,r12 ; Get and reserve the last used CPU + mr. r9,r9 ; Is it changing now? + oris r3,r9,hi16(fvChk) ; Set the "changing" flag + blt- fsvSpin2 ; Spin if changing + stwcx. r3,r4,r12 ; Lock it up + bne- fsvSpin2 ; Someone is messing right now + + isync ; Make sure we see everything - cmplw r12,r10 ; Do we own the FPU? cmplw cr1,r9,r11 ; Was the context for this processor? - bne+ fsret ; Facility belongs to some other activation... li r3,0 ; Assume we need a fix-me-up beq- cr1,fsgoodcpu ; Facility last used on this processor... stw r3,PP_FPU_THREAD(r6) ; Clear owner because it was really on the other processor @@ -648,7 +657,12 @@ dontkillmedead: ; (TEST/DEBUG) ble+ cr1,chkkillmedead ; (TEST/DEBUG) #endif -fsret: mtmsr r0 ; Put interrupts on if they were and floating point off +fsret: lwz r4,ACT_MACT_FPUcpu(r12) ; Get back the owner CPU + rlwinm r4,r4,0,fvChkb+1,31 ; Clear lock + sync + stw r4,ACT_MACT_FPUcpu(r12) ; Unlock the context + +fsretnr: mtmsr r0 ; Put interrupts on if they were and floating point off isync blr @@ -725,11 +739,21 @@ ENTRY(fpu_switch, TAG_NO_FRAME_USED) beq- fsnosave ; No live context, so nothing to save... - lwz r19,ACT_MACT_FPUcpu(r12) ; Get the "old" active CPU + li r20,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word + +fsSpin1: lwarx r19,r20,r12 ; Get and reserve the last used CPU + mr. r19,r19 ; Is it changing now? + oris r21,r19,hi16(fvChk) ; Set the "changing" flag + blt- fsSpin1 ; Spin if changing + stwcx. r21,r20,r12 ; Lock it up + bne- fsSpin1 ; Someone is messing right now + + isync ; Make sure we see everything + lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one cmplw r18,r19 ; Check the CPU that the old context is live on lwz r14,ACT_MACT_FPU(r12) ; Point to the top of the old context stack - bne- fsnosave ; Context is not live if used on a different CPU... + bne- fsnosaverel ; Context is not live if used on a different CPU... lwz r13,ACT_MACT_FPUlvl(r12) ; Get the "old" active level ; @@ -768,7 +792,7 @@ ENTRY(fpu_switch, TAG_NO_FRAME_USED) cmplwi cr2,r14,0 ; Is there any saved context? bne- fsmstsave ; Levels are different, we need to save... - beq- cr2,fsenable ; No saved context at all, enable and go... + beq- cr2,fsenableret ; No saved context at all, enable and go... lwz r20,SAVlvlfp(r14) ; Get the level of the top savearea @@ -782,9 +806,12 @@ ENTRY(fpu_switch, TAG_NO_FRAME_USED) #endif cmplw r15,r20 ; Is the top level the same as the current? li r0,1 ; Get the invalid flag - bne- fsenable ; Not the same, just enable and go... + bne- fsenableret ; Not the same, just enable and go... stw r0,SAVlvlfp(r14) ; Invalidate that top savearea +fsenableret: + sync ; Make sure everything is saved + stw r19,ACT_MACT_FPUcpu(r12) ; Say we are not using the context anymore b fsenable ; Then enable and go... @@ -811,7 +838,7 @@ fsmstsave: beq- cr2,fsgetsave ; There is no possible cached save area cmplwi r5,1 ; Is it invalid? cmplw cr1,r5,r13 ; Is the SA level the active one? beq+ fsusecache ; Invalid, just use it... - beq- cr1,fsnosave ; The SA level is active, it is already saved... + beq- cr1,fsnosaverel ; The SA level is active, it is already saved... fsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached #if FPVECDBG @@ -919,8 +946,24 @@ fsusecache: la r11,savefp0(r3) ; Point to the 1st line in area ; would be safe! My God! It is terrifying! ; + +fsnosaverel: + sync ; Make sure everything is saved + stw r19,ACT_MACT_FPUcpu(r12) ; Say we are not using the context anymore -fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one +fsnosave: + li r20,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word + +fsSpin2: lwarx r19,r20,r17 ; Get and reserve the last used CPU + mr. r19,r19 ; Is it changing now? + oris r21,r19,hi16(fvChk) ; Set the "changing" flag + blt- fsSpin2 ; Spin if changing + stwcx. r21,r20,r17 ; Lock it up + bne- fsSpin2 ; Someone is messing right now + + isync ; Make sure we see everything + + lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one lwz r14,ACT_MACT_FPU(r17) ; Point to the top of the "new" context stack lwz r13,ACT_MACT_FPUlvl(r17) ; Get the "new" active level #if FPVECDBG @@ -935,7 +978,6 @@ fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one cmplwi cr1,r14,0 ; Do we possibly have some context to load? stw r15,ACT_MACT_FPUlvl(r17) ; Set the "new" active level - stw r18,ACT_MACT_FPUcpu(r17) ; Set the active CPU la r11,savefp0(r14) ; Point to first line to bring in stw r17,PP_FPU_THREAD(r6) ; Store current thread address in fpu_thread to claim fpu for thread @@ -1002,6 +1044,9 @@ fsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one lfd f30,savefp30(r14) lfd f31,savefp31(r14) +fsenablexx: sync ; Make sure all is saved + stw r18,ACT_MACT_FPUcpu(r17) ; Set the active CPU and release + fsenable: lwz r9,SAVflags(r4) /* Get the flags of the current savearea */ lwz r8,savesrr1(r4) ; Get the msr of the interrupted guy rlwinm r5,r4,0,0,19 /* Get the page address of the savearea */ @@ -1034,7 +1079,18 @@ fsnuser: */ MakeSureThatNoTerroristsCanHurtUsByGod: - + +#if 0 + lwz r10,savesrr1(r4) ; (TEST/DEBUG) + rlwinm. r10,r10,0,MSR_PR_BIT,MSR_PR_BIT ; (TEST/DEBUG) + beq- nxxxxxx ; (TEST/DEBUG) + lwz r10,ACT_MACT_SPF(r17) ; (TEST/DEBUG) + rlwinm. r10,r10,0,1,1 ; (TEST/DEBUG) + beq+ nxxxxxx + BREAKPOINT_TRAP ; (TEST/DEBUG) +nxxxxxx: +#endif + #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) li r2,0x7F09 ; (TEST/DEBUG) @@ -1077,7 +1133,7 @@ MakeSureThatNoTerroristsCanHurtUsByGod: fmr f29,f0 fmr f30,f0 fmr f31,f0 - b fsenable ; Finish setting it all up... + b fsenablexx ; Finish setting it all up... ; ; Finds an unused floating point area in the activation pointed @@ -1148,6 +1204,7 @@ ENTRY(vec_save, TAG_NO_FRAME_USED) #if FPVECDBG mr r7,r0 ; (TEST/DEBUG) li r4,0 ; (TEST/DEBUG) + mr r10,r3 ; (TEST/DEBUG) lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) mr. r3,r12 ; (TEST/DEBUG) li r2,0x5F00 ; (TEST/DEBUG) @@ -1159,23 +1216,29 @@ ENTRY(vec_save, TAG_NO_FRAME_USED) noowneryeu: oris r0,r0,LOW_ADDR(CutTrace) ; (TEST/DEBUG) sc ; (TEST/DEBUG) mr r0,r7 ; (TEST/DEBUG) + mr r3,r10 ; (TEST/DEBUG) #endif mflr r2 ; Save the return address - lwz r10,PP_CPU_DATA(r6) ; Get the CPU data pointer lhz r11,PP_CPU_NUMBER(r6) ; Get our CPU number mr. r12,r12 ; Anyone own the vector? + cmplw cr1,r3,r12 ; Is the specified thread the owner? + + beq- vsretnr ; Nobody owns the vector, no save required... - lwz r10,CPU_ACTIVE_THREAD(r10) ; Get the pointer to the active thread - - beq- vsret ; Nobody owns the vector, no save required... + li r4,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word + bne- cr1,vsretnr ; Facility belongs to some other activation... - lwz r10,THREAD_TOP_ACT(r10) ; Now get the activation that is running - lwz r9,ACT_MACT_VMXcpu(r12) ; Get the last CPU to use this context +vsvSpin2: lwarx r9,r4,r12 ; Get and reserve the last used CPU + mr. r9,r9 ; Is it changing now? + oris r3,r9,hi16(fvChk) ; Set the "changing" flag + blt- vsvSpin2 ; Spin if changing + stwcx. r3,r4,r12 ; Lock it up + bne- vsvSpin2 ; Someone is messing right now + + isync ; Make sure we see everything - cmplw r12,r10 ; Do we own the thread? cmplw cr1,r9,r11 ; Was the context for this processor? - bne+ vsret ; Facility belongs to some other activation... li r3,0 ; Assume we need a fix-me-up beq- cr1,vsgoodcpu ; Facility last used on this processor... stw r3,PP_VMX_THREAD(r6) ; Clear owner because it was really on the other processor @@ -1213,9 +1276,9 @@ vsusespare: stw r9,SAVlvlvec(r3) ; And set the level this savearea is for lis r9,0x5555 ; Mask with odd bits set rlwinm r11,r10,1,0,31 ; Shift over 1 ori r9,r9,0x5555 ; Finish mask - or r12,r10,r11 ; After this, even bits show which lines to zap + or r4,r10,r11 ; After this, even bits show which lines to zap - andc r11,r12,r9 ; Clear out odd bits + andc r11,r4,r9 ; Clear out odd bits la r6,savevr0(r3) ; Point to line 0 rlwinm r4,r11,15,0,15 ; Move line 8-15 flags to high order odd bits @@ -1495,7 +1558,12 @@ v27ok: mtcrf 255,r2 ; Restore all non-volatile CRs ; Save the current vector state into the savearea of the thread that owns it. ; -vsret: mtmsr r0 ; Put interrupts on if they were and vector off +vsret: lwz r4,ACT_MACT_VMXcpu(r12) ; Get back the owner CPU + rlwinm r4,r4,0,fvChkb+1,31 ; Clear lock + sync + stw r4,ACT_MACT_VMXcpu(r12) ; Unlock the context + +vsretnr: mtmsr r0 ; Put interrupts on if they were and vector off isync blr @@ -1582,14 +1650,23 @@ ENTRY(vec_switch, TAG_NO_FRAME_USED) mtmsr r19 /* Set vector available */ isync - beq- vsnosave ; No live context, so nothing to save... - - lwz r19,ACT_MACT_VMXcpu(r12) ; Get the "old" active CPU + + li r20,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word + +vsSpin1: lwarx r19,r20,r12 ; Get and reserve the last used CPU + mr. r19,r19 ; Is it changing now? + oris r21,r19,hi16(fvChk) ; Set the "changing" flag + blt- vsSpin1 ; Spin if changing + stwcx. r21,r20,r12 ; Lock it up + bne- vsSpin1 ; Someone is messing right now + + isync ; Make sure we see everything + lwz r15,ACT_MACT_PCB(r12) ; Get the current level of the "old" one cmplw r18,r19 ; Check the CPU that the old context is live on lwz r14,ACT_MACT_VMX(r12) ; Point to the top of the old context stack - bne- vsnosave ; Context is not live if used on a different CPU... + bne- vsnosaverel ; Context is not live if used on a different CPU... lwz r13,ACT_MACT_VMXlvl(r12) ; Get the "old" active level ; @@ -1638,7 +1715,7 @@ ENTRY(vec_switch, TAG_NO_FRAME_USED) cmplwi cr2,r14,0 ; Is there any saved context? bne- vsmstsave ; Levels are different, we need to save... - beq- cr2,vrenable ; No saved context at all, enable and go... + beq- cr2,vrenableret ; No saved context at all, enable and go... lwz r20,SAVlvlvec(r14) ; Get the level of the top savearea @@ -1662,10 +1739,13 @@ ENTRY(vec_switch, TAG_NO_FRAME_USED) #endif cmplw r15,r20 ; Is the top level the same as the current? li r0,1 ; Get the invalid flag - bne- vrenable ; Not the same, just enable and go... + bne- vrenableret ; Not the same, just enable and go... stw r0,SAVlvlvec(r14) ; Invalidate that top savearea +vrenableret: + sync ; Make sure everything is saved + stw r19,ACT_MACT_VMXcpu(r12) ; Say we are not using the context anymore b vrenable ; Then enable and go... ; @@ -1703,7 +1783,7 @@ vsmstsave: beq- cr2,vsgetsave ; There is no possible cached save area cmplwi r5,1 ; Is it invalid? cmplw cr1,r5,r13 ; Is the SA level the active one? beq+ vsusecache ; Invalid, just use it... - beq- cr1,vsnosave ; The SA level is active, it is already saved... + beq- cr1,vsnosaverel ; The SA level is active, it is already saved... vsgetsave: mr r3,r4 ; Use the interrupt save as the context savearea if none cached #if FPVECDBG @@ -1761,10 +1841,10 @@ vsgotsave: lis r9,0x5555 ; Mask with odd bits set rlwinm r11,r10,1,0,31 ; Shift over 1 ori r9,r9,0x5555 ; Finish mask - or r12,r10,r11 ; After this, even bits show which lines to zap + or r21,r10,r11 ; After this, even bits show which lines to zap stw r13,SAVlvlvec(r3) ; Set the savearea level - andc r13,r12,r9 ; Clear out odd bits + andc r13,r21,r9 ; Clear out odd bits la r20,savevr0(r3) ; Point to line 0 rlwinm r24,r13,15,0,15 ; Move line 8-15 flags to high order odd bits @@ -2046,7 +2126,24 @@ novr31: * would be safe! My Gosh! It's terrifying! */ -vsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one +vsnosaverel: + sync ; Make sure everything is saved + stw r19,ACT_MACT_VMXcpu(r12) ; Say we are not using the context anymore + + +vsnosave: + li r20,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word + +vsSpin2: lwarx r19,r20,r17 ; Get and reserve the last used CPU + mr. r19,r19 ; Is it changing now? + oris r21,r19,hi16(fvChk) ; Set the "changing" flag + blt- vsSpin2 ; Spin if changing + stwcx. r21,r20,r17 ; Lock it up + bne- vsSpin2 ; Someone is messing right now + + isync ; Make sure we see everything + + lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one lwz r14,ACT_MACT_VMX(r17) ; Point to the top of the "new" context stack lwz r13,ACT_MACT_VMXlvl(r17) ; Get the "new" active level @@ -2063,7 +2160,6 @@ vsnosave: lwz r15,ACT_MACT_PCB(r17) ; Get the current level of the "new" one cmplwi cr1,r14,0 ; Do we possibly have some context to load? stw r15,ACT_MACT_VMXlvl(r17) ; Set the "new" active level la r23,savevscr(r14) ; Point to the VSCR - stw r18,ACT_MACT_VMXcpu(r17) ; Set the active CPU la r20,savevr0(r14) ; Point to first line to bring in stw r17,PP_VMX_THREAD(r6) ; Store current thread address in vmx_thread to claim vector for thread beq- cr1,ProtectTheAmericanWay ; Nothing to restore, first time use... @@ -2468,6 +2564,9 @@ ni30: mstlvr31: lvxl v31,r30,r23 ; Restore VR31 lnovr31: + +vrenablexx: sync ; Make sure all is saved + stw r18,ACT_MACT_VMXcpu(r17) ; Set the active CPU and release vrenable: lwz r9,SAVflags(r4) /* Get the flags of the current savearea */ @@ -2513,6 +2612,16 @@ vrnuser: ProtectTheAmericanWay: +#if 0 + lwz r10,savesrr1(r4) ; (TEST/DEBUG) + rlwinm. r10,r10,0,MSR_PR_BIT,MSR_PR_BIT ; (TEST/DEBUG) + beq- nxxxxxx2 ; (TEST/DEBUG) + lwz r10,ACT_MACT_SPF(r17) ; (TEST/DEBUG) + rlwinm. r10,r10,0,2,2 ; (TEST/DEBUG) + beq+ nxxxxxx2 + BREAKPOINT_TRAP ; (TEST/DEBUG) +nxxxxxx2: +#endif #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) li r2,0x5F09 ; (TEST/DEBUG) @@ -2568,7 +2677,7 @@ ProtectTheAmericanWay: vor v29,v0,v0 ; Copy into the next register vor v30,v0,v0 ; Copy into the next register vor v31,v0,v0 ; Copy into the next register - b vrenable ; Finish setting it all up... + b vrenablexx ; Finish setting it all up... ; ; Finds a unused vector area in the activation pointed diff --git a/osfmk/ppc/db_machdep.h b/osfmk/ppc/db_machdep.h index 44c768e62..2d997f922 100644 --- a/osfmk/ppc/db_machdep.h +++ b/osfmk/ppc/db_machdep.h @@ -183,8 +183,6 @@ extern void kdb_on( extern void cnpollc( boolean_t on); -extern void kdb_kintr(void); - extern void db_phys_copy( vm_offset_t, vm_offset_t, diff --git a/osfmk/ppc/exception.h b/osfmk/ppc/exception.h index 4db360ba0..1a4f1dbe7 100644 --- a/osfmk/ppc/exception.h +++ b/osfmk/ppc/exception.h @@ -63,8 +63,8 @@ struct procFeatures { #define pfThermalb 7 #define pfThermInt 0x00800000 #define pfThermIntb 8 -#define pfL23lck 0x00001000 -#define pfL23lckb 19 +#define pfLClck 0x00001000 +#define pfLClckb 19 #define pfWillNap 0x00000800 #define pfWillNapb 20 #define pfNoMSRir 0x00000400 @@ -105,6 +105,8 @@ struct procFeatures { unsigned int pfMSSCR1; unsigned int pfICTRL; unsigned int pfLDSTCR; + unsigned int pfLDSTDB; + unsigned int reserved[7]; }; typedef struct procFeatures procFeatures; @@ -128,12 +130,8 @@ struct per_proc_info { vm_offset_t istackptr; vm_offset_t intstack_top_ss; -#if MACH_KDP || MACH_KDB vm_offset_t debstackptr; vm_offset_t debstack_top_ss; -#else - unsigned int ppigas1[2]; /* Take up some space if no KDP or KDB */ -#endif unsigned int tempwork1; /* Temp work area - monitor use carefully */ unsigned int save_exception_type; @@ -162,11 +160,11 @@ struct per_proc_info { unsigned int liveVRSave; /* VRSave assiciated with live vector registers */ unsigned int spcFlags; /* Special thread flags */ unsigned int liveFPSCR; /* FPSCR which is for the live context */ - unsigned int ppigas05C; /* Reserved area */ + unsigned int ppbbTaskEnv; /* BlueBox Task Environment */ /* PPC cache line boundary here - 060 */ - boolean_t (*set_interrupts_enabled)(boolean_t); - boolean_t (*get_interrupts_enabled)(void); + boolean_t interrupts_enabled; + unsigned int rsrvd064; IOInterruptHandler interrupt_handler; void * interrupt_nub; unsigned int interrupt_source; @@ -201,10 +199,10 @@ struct per_proc_info { /* PPC cache line boundary here - 0A0 */ procFeatures pf; /* Processor features */ - /* PPC cache line boundary here - 0E0 */ + /* PPC cache line boundary here - 100 */ thrmControl thrm; /* Thermal controls */ - /* PPC cache line boundary here - 100 */ + /* PPC cache line boundary here - 120 */ unsigned int napStamp[2]; /* Time base when we napped */ unsigned int napTotal[2]; /* Total nap time in ticks */ unsigned int numSIGPast; /* Number of SIGP asts recieved */ @@ -212,18 +210,15 @@ struct per_proc_info { unsigned int numSIGPdebug; /* Number of SIGP debugs recieved */ unsigned int numSIGPwake; /* Number of SIGP wakes recieved */ - /* PPC cache line boundary here - 120 */ + /* PPC cache line boundary here - 140 */ unsigned int spcTRc; /* Special trace count */ unsigned int spcTRp; /* Special trace buffer pointer */ unsigned int Uassist; /* User Assist Word */ - unsigned int rsrvd12C[5]; /* Reserved slots */ - - /* PPC cache line boundary here - 140 */ - time_base_enable_t time_base_enable; - unsigned int rsrvd140[7]; /* Reserved slots */ + unsigned int rsrvd14C[5]; /* Reserved slots */ /* PPC cache line boundary here - 160 */ - unsigned int rsrvd160[8]; /* Reserved slots */ + time_base_enable_t time_base_enable; + unsigned int rsrvd164[7]; /* Reserved slots */ /* PPC cache line boundary here - 180 */ unsigned int rsrvd180[8]; /* Reserved slots */ @@ -566,6 +561,7 @@ extern char *trap_type[]; #define traceBE 0x1000 /* user mode BE tracing in enabled */ #define traceBEb 3 /* bit number for traceBE */ #define BootDone 0x0100 +#define SignalReady 0x0200 #define loadMSR 0x7FF4 #define T_VECTOR_SIZE 4 /* function pointer size */ @@ -618,12 +614,25 @@ extern char *trap_type[]; #define T_PREEMPT (0x23 * T_VECTOR_SIZE) #define T_CSWITCH (0x24 * T_VECTOR_SIZE) #define T_SHUTDOWN (0x25 * T_VECTOR_SIZE) +#define T_CHOKE (0x26 * T_VECTOR_SIZE) #define T_AST (0x100 * T_VECTOR_SIZE) -#define T_MAX T_SHUTDOWN /* Maximum exception no */ +#define T_MAX T_CHOKE /* Maximum exception no */ #define EXCEPTION_VECTOR(exception) (exception * 0x100 /T_VECTOR_SIZE ) +/* + * System choke (failure) codes + */ + +#define failDebug 0 +#define failStack 1 +#define failMapping 2 +#define failContext 3 + +/* Always must be last - update failNames table in model_dep.c as well */ +#define failUnknown 4 + #ifndef ASSEMBLER typedef struct resethandler { diff --git a/osfmk/ppc/fpu_protos.h b/osfmk/ppc/fpu_protos.h index ac5ba8775..6781cc8ce 100644 --- a/osfmk/ppc/fpu_protos.h +++ b/osfmk/ppc/fpu_protos.h @@ -29,7 +29,7 @@ #include <ppc/thread_act.h> -extern void fpu_save(void); +extern void fpu_save(thread_act_t act); extern void fpu_disable(void); #endif /* _PPC_FPU_PROTOS_H_ */ diff --git a/osfmk/ppc/genassym.c b/osfmk/ppc/genassym.c index cdf366c63..0d8dd2416 100644 --- a/osfmk/ppc/genassym.c +++ b/osfmk/ppc/genassym.c @@ -130,6 +130,14 @@ int main(int argc, char *argv[]) DECLARE("vectorCng", vectorCng); DECLARE("floatCngbit", floatCngbit); DECLARE("vectorCngbit", vectorCngbit); + DECLARE("bbThreadbit", bbThreadbit); + DECLARE("bbPreemptivebit", bbPreemptivebit); + DECLARE("bbThread", bbThread); + DECLARE("bbPreemptive", bbPreemptive); + DECLARE("fvChkb", fvChkb); + DECLARE("fvChk", fvChk); + DECLARE("userProtKeybit", userProtKeybit); + DECLARE("userProtKey", userProtKey); DECLARE("PCB_SIZE", sizeof(struct pcb)); @@ -181,10 +189,8 @@ int main(int argc, char *argv[]) DECLARE("PP_CPU_FLAGS", offsetof(struct per_proc_info *, cpu_flags)); DECLARE("PP_ISTACKPTR", offsetof(struct per_proc_info *, istackptr)); DECLARE("PP_INTSTACK_TOP_SS", offsetof(struct per_proc_info *, intstack_top_ss)); -#if MACH_KDP || MACH_KDB DECLARE("PP_DEBSTACKPTR", offsetof(struct per_proc_info *, debstackptr)); DECLARE("PP_DEBSTACK_TOP_SS", offsetof(struct per_proc_info *, debstack_top_ss)); -#endif DECLARE("PP_TEMPWORK1", offsetof(struct per_proc_info *, tempwork1)); DECLARE("PP_USERSPACE", offsetof(struct per_proc_info *, userspace)); DECLARE("PP_USERPMAP", offsetof(struct per_proc_info *, userpmap)); @@ -201,7 +207,9 @@ int main(int argc, char *argv[]) DECLARE("PP_VMX_THREAD", offsetof(struct per_proc_info *, VMX_thread)); DECLARE("VMX_vmmCtx", offsetof(struct per_proc_info *, VMX_vmmCtx)); DECLARE("PP_QUICKFRET", offsetof(struct per_proc_info *, quickfret)); + DECLARE("PP_INTS_ENABLED", offsetof(struct per_proc_info *, interrupts_enabled)); DECLARE("UAW", offsetof(struct per_proc_info *, Uassist)); + DECLARE("ppbbTaskEnv", offsetof(struct per_proc_info *, ppbbTaskEnv)); DECLARE("liveVRS", offsetof(struct per_proc_info *, liveVRSave)); DECLARE("liveFPSCR", offsetof(struct per_proc_info *, liveFPSCR)); DECLARE("spcFlags", offsetof(struct per_proc_info *, spcFlags)); @@ -229,8 +237,8 @@ int main(int argc, char *argv[]) DECLARE("pfThermalb", pfThermalb); DECLARE("pfThermInt", pfThermInt); DECLARE("pfThermIntb", pfThermIntb); - DECLARE("pfL23lck", pfL23lck); - DECLARE("pfL23lckb", pfL23lckb); + DECLARE("pfLClck", pfLClck); + DECLARE("pfLClckb", pfLClckb); DECLARE("pfWillNap", pfWillNap); DECLARE("pfWillNapb", pfWillNapb); DECLARE("pfNoMSRir", pfNoMSRir); @@ -271,6 +279,7 @@ int main(int argc, char *argv[]) DECLARE("pfMSSCR1", offsetof(struct per_proc_info *, pf.pfMSSCR1)); DECLARE("pfICTRL", offsetof(struct per_proc_info *, pf.pfICTRL)); DECLARE("pfLDSTCR", offsetof(struct per_proc_info *, pf.pfLDSTCR)); + DECLARE("pfLDSTDB", offsetof(struct per_proc_info *, pf.pfLDSTDB)); DECLARE("pfSize", sizeof(procFeatures)); DECLARE("thrmmaxTemp", offsetof(struct per_proc_info *, thrm.maxTemp)); @@ -352,6 +361,7 @@ int main(int argc, char *argv[]) DECLARE("emvr31", offsetof(struct per_proc_info *, emvr31)); DECLARE("empadvr", offsetof(struct per_proc_info *, empadvr)); DECLARE("ppSize", sizeof(struct per_proc_info)); + DECLARE("patcharea", offsetof(struct per_proc_info *, patcharea)); DECLARE("RESETHANDLER_TYPE", offsetof(struct resethandler *, type)); DECLARE("RESETHANDLER_CALL", offsetof(struct resethandler *, call_paddr)); @@ -423,8 +433,10 @@ int main(int argc, char *argv[]) DECLARE("kVmmGetVectorState", kVmmGetVectorState); DECLARE("kVmmSetTimer", kVmmSetTimer); DECLARE("kVmmExecuteVM", kVmmExecuteVM); + DECLARE("kVmmProtectPage", kVmmProtectPage); DECLARE("kVmmReturnNull", kVmmReturnNull); + DECLARE("kVmmStopped", kVmmStopped); DECLARE("kVmmBogusContext", kVmmBogusContext); DECLARE("kVmmReturnDataPageFault", kVmmReturnDataPageFault); DECLARE("kVmmReturnInstrPageFault", kVmmReturnInstrPageFault); @@ -432,6 +444,12 @@ int main(int argc, char *argv[]) DECLARE("kVmmReturnProgramException", kVmmReturnProgramException); DECLARE("kVmmReturnSystemCall", kVmmReturnSystemCall); DECLARE("kVmmReturnTraceException", kVmmReturnTraceException); + + DECLARE("kVmmProtXtnd", kVmmProtXtnd); + DECLARE("kVmmProtNARW", kVmmProtNARW); + DECLARE("kVmmProtRORW", kVmmProtRORW); + DECLARE("kVmmProtRWRW", kVmmProtRWRW); + DECLARE("kVmmProtRORO", kVmmProtRORO); DECLARE("vmmFlags", offsetof(struct vmmCntrlEntry *, vmmFlags)); DECLARE("vmmInUseb", vmmInUseb); @@ -477,6 +495,12 @@ int main(int argc, char *argv[]) DECLARE("vmmVectVRallb", vmmVectVRallb); DECLARE("vmmVectVAss", vmmVectVAss); DECLARE("vmmVectVAssb", vmmVectVAssb); + DECLARE("vmmXStart", vmmXStart); + DECLARE("vmmXStartb", vmmXStartb); + DECLARE("vmmXStop", vmmXStop); + DECLARE("vmmXStopb", vmmXStopb); + DECLARE("vmmKey", vmmKey); + DECLARE("vmmKeyb", vmmKeyb); /* values from kern/task.h */ DECLARE("TASK_MACH_EXC_PORT", @@ -535,8 +559,7 @@ int main(int argc, char *argv[]) #endif /* MACH_LDEBUG */ /* Mutex structure */ - DECLARE("MUTEX_ILK", offsetof(mutex_t *, interlock)); - DECLARE("MUTEX_LOCKED", offsetof(mutex_t *, locked)); + DECLARE("LOCK_DATA", offsetof(mutex_t *, interlock)); DECLARE("MUTEX_WAITERS",offsetof(mutex_t *, waiters)); #if MACH_LDEBUG DECLARE("MUTEX_TYPE", offsetof(mutex_t *, type)); diff --git a/osfmk/ppc/hw_exception.s b/osfmk/ppc/hw_exception.s index af24433e1..55b30c73e 100644 --- a/osfmk/ppc/hw_exception.s +++ b/osfmk/ppc/hw_exception.s @@ -74,8 +74,6 @@ * and pcb.ksp is set to the top of stack */ -#if DEBUG - /* TRAP_SPACE_NEEDED is the space assumed free on the kernel stack when * another trap is taken. We need at least enough space for a saved state * structure plus two small backpointer frames, and we add a few @@ -85,27 +83,46 @@ #define TRAP_SPACE_NEEDED FM_REDZONE+(2*FM_SIZE)+256 -#endif /* DEBUG */ - .text -ENTRY(thandler, TAG_NO_FRAME_USED) /* What tag should this have?! */ + .align 5 + .globl EXT(thandler) +LEXT(thandler) /* Trap handler */ + +#if 0 +; +; NOTE: This trap will hang VPC running Windows98 (and probably others)... +; + lwz r25,savedar(r4) ; (TEST/DEBUG) + cmplwi r25,0x298 ; (TEST/DEBUG) + +deadloop: addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + addi r25,r25,1 ; (TEST/DEBUG) + beq- deadloop ; (TEST/DEBUG) +#endif mfsprg r25,0 /* Get the per_proc */ lwz r1,PP_ISTACKPTR(r25) ; Get interrupt stack pointer - lwz r6,PP_CPU_DATA(r25) /* Get point to cpu specific data */ cmpwi cr0,r1,0 ; Are we on interrupt stack? lwz r6,CPU_ACTIVE_THREAD(r6) /* Get the pointer to the currently active thread */ - beq- cr0,EXT(ihandler) ; Yes, not allowed except when debugger - ; is active. We will let the ihandler do this... + beq- cr0,EXT(ihandler) ; If on interrupt stack, treat this as interrupt... lwz r13,THREAD_TOP_ACT(r6) /* Point to the active activation */ - lwz r26,ACT_MACT_BEDA(r13) /* Pick up the pointer to the blue box data area */ + lwz r26,ACT_MACT_SPF(r13) ; Get special flags lwz r8,ACT_MACT_PCB(r13) /* Get the last savearea used */ - mr. r26,r26 /* Do we have Blue Box Assist active? */ - lwz r1,ACT_MACT_KSP(r13) /* Get the stack */ + rlwinm. r26,r26,0,bbThreadbit,bbThreadbit ; Do we have Blue Box Assist active? + lwz r1,ACT_MACT_KSP(r13) ; Get the top of kernel stack bnel- checkassist /* See if we should assist this */ stw r4,ACT_MACT_PCB(r13) /* Point to our savearea */ stw r8,SAVprev(r4) /* Queue the new save area in the front */ @@ -114,44 +131,28 @@ ENTRY(thandler, TAG_NO_FRAME_USED) /* What tag should this have?! */ bl versave ; (TEST/DEBUG) #endif - cmpwi cr1,r1, 0 /* zero implies already on kstack */ - stw r13,SAVact(r4) /* Point the savearea at its activation */ - bne cr1,.L_kstackfree /* This test is also used below */ - lwz r1,saver1(r4) /* Get the stack at 'rupt time */ + lwz r9,THREAD_KERNEL_STACK(r6) ; Get our kernel stack start + cmpwi cr1,r1,0 ; Are we already on kernel stack? + stw r13,SAVact(r4) ; Mark the savearea as belonging to this activation + lwz r26,saver1(r4) ; Get the stack at interrupt time + bne+ cr1,.L_kstackfree ; We are not on kernel stack yet... -/* On kernel stack, allocate stack frame and check for overflow */ -#if DEBUG -/* - * Test if we will overflow the Kernel Stack. We - * check that there is at least TRAP_SPACE_NEEDED bytes - * free on the kernel stack -*/ - - lwz r7,THREAD_KERNEL_STACK(r6) - addi r7,r7,TRAP_SPACE_NEEDED - cmp cr0,r1,r7 - bng- EXT(ihandler) -#endif /* DEBUG */ - - subi r1,r1,FM_REDZONE /* Back up stack and leave room for a red zone */ + subi r1,r26,FM_REDZONE ; Make a red zone on interrupt time kernel stack .L_kstackfree: -#if 0 - lis r0,HIGH_ADDR(CutTrace) /* (TEST/DEBUG) */ - oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ - sc /* (TEST/DEBUG) */ -#endif lwz r7,savesrr1(r4) /* Pick up the entry MSR */ + sub r9,r1,r9 ; Get displacment into the kernel stack li r0,0 /* Make this 0 */ - + cmplwi cr2,r9,KERNEL_STACK_SIZE ; Do we still have room on the stack? beq cr1,.L_state_on_kstack /* using above test for pcb/stack */ stw r0,ACT_MACT_KSP(r13) /* Show that we have taken the stack */ .L_state_on_kstack: rlwinm. r6,r7,0,MSR_VEC_BIT,MSR_VEC_BIT ; Was vector on? - lwz r6,saver1(r4) /* Grab interrupt time stack */ + bgt- cr2,kernelStackBad ; Kernel stack is bogus... +kernelStackNotBad: ; Not really beq+ tvecoff ; Vector off, do not save vrsave... lwz r3,savevrsave(r4) ; Get the VRSAVE register stw r3,liveVRS(r25) ; Set the live value @@ -162,7 +163,7 @@ tvecoff: rlwinm. r3,r7,0,MSR_FP_BIT,MSR_FP_BIT ; Was floating point on? lwz r3,savexfpscr(r4) ; Grab the just saved FPSCR stw r3,liveFPSCR(r25) ; Make it the live copy -tfpoff: stw r6,FM_BACKPTR(r1) /* Link backwards */ +tfpoff: stw r26,FM_BACKPTR(r1) ; Link back to the previous frame #if DEBUG /* If debugging, we need two frames, the first being a dummy @@ -259,6 +260,24 @@ thread_return: b chkfac /* Go end it all... */ +; +; Here is where we go when we detect that the kernel stack is all messed up. +; We just try to dump some info and get into the debugger. +; + +kernelStackBad: + + lwz r3,PP_DEBSTACK_TOP_SS(r25) ; Pick up debug stack top + subi r3,r3,KERNEL_STACK_SIZE-FM_SIZE ; Adjust to start of stack + sub r3,r1,r3 ; Get displacement into debug stack + cmplwi cr2,r3,KERNEL_STACK_SIZE-FM_SIZE ; Check if we are on debug stack + blt+ cr2,kernelStackNotBad ; Yeah, that is ok too... + + lis r0,hi16(Choke) ; Choke code + ori r0,r0,lo16(Choke) ; and the rest + li r3,failStack ; Bad stack code + sc ; System ABEND + /* * shandler(type) @@ -290,7 +309,9 @@ thread_return: * PPC-only "fast" traps are in the range 0x7xxx */ -ENTRY(shandler, TAG_NO_FRAME_USED) + .align 5 + .globl EXT(shandler) +LEXT(shandler) /* System call handler */ mfsprg r25,0 /* Get the per proc area */ lwz r0,saver0(r4) /* Get the original syscall number */ @@ -304,8 +325,8 @@ ENTRY(shandler, TAG_NO_FRAME_USED) lwz r16,CPU_ACTIVE_THREAD(r16) /* Get the thread pointer */ beq+ svecoff ; Vector off, do not save vrsave... - lwz r7,savevrsave(r4) ; Get the VRSAVE register - stw r7,liveVRS(r25) ; Set the live value + lwz r6,savevrsave(r4) ; Get the VRSAVE register + stw r6,liveVRS(r25) ; Set the live value svecoff: rlwinm. r6,r7,0,MSR_FP_BIT,MSR_FP_BIT ; Was floating point on? lwz r13,THREAD_TOP_ACT(r16) /* Pick up the active thread */ @@ -316,18 +337,13 @@ svecoff: rlwinm. r6,r7,0,MSR_FP_BIT,MSR_FP_BIT ; Was floating point on? ; Check if SCs are being redirected for the BlueBox or to VMM sfpoff: lwz r6,ACT_MACT_SPF(r13) ; Pick up activation special flags + mtcrf 0x41,r6 ; Check special flags + crmove cr6_eq,runningVMbit ; Remember if we are in VMM + bf+ bbNoMachSCbit,noassist ; Take branch if SCs are not redirected lwz r26,ACT_MACT_BEDA(r13) ; Pick up the pointer to the blue box exception area - rlwinm. r9,r6,0,runningVMbit,runningVMbit ; Are we running in alternate context right now? - cmpwi cr1,r26,0 ; Do we have Blue Box Assist active? - crmove cr2_eq,cr0_eq ; Remember if we are in VMM - rlwinm. r6,r6,0,bbNoMachSCbit,bbNoMachSCbit ; Are mach SCs redirected for this thread - beq+ noassist ; Take branch if SCs are not redirected - beq- cr1,noassist ; No assist for non-bluebox threads - mr r9,r13 ; Setup ACT for atomic_switch api b EXT(atomic_switch_syscall) ; Go to the assist... -noassist: - cmplwi r15,0x7000 /* Do we have a fast path trap? */ +noassist: cmplwi r15,0x7000 /* Do we have a fast path trap? */ lwz r14,ACT_MACT_PCB(r13) /* Now point to the PCB */ beql+ fastpath /* We think it's a fastpath... */ @@ -371,7 +387,7 @@ noassist: stwu r1,-(FM_SIZE+ARG_SIZE)(r1) /* Make a stack frame */ cmplwi r10,0x6000 ; Is it the special ppc-only guy? stw r15,SAVflags(r30) /* Save syscall marker */ - bne- cr2,exitFromVM ; It is time to exit from alternate context... + beq- cr6,exitFromVM ; It is time to exit from alternate context... beq- ppcscall ; Call the ppc-only system call handler... @@ -467,6 +483,7 @@ LEXT(ppcscret) mr. r3,r3 ; See what we should do mr r31,r16 ; Restore the current thread pointer bgt+ .L_thread_syscall_ret_check_ast ; Take normal AST checking return.... + mfsprg r10,0 ; Get the per_proc blt+ .L_thread_syscall_return ; Return, but no ASTs.... lwz r0,saver0(r30) ; Restore the system call number b .L_call_server_syscall_exception ; Go to common exit... @@ -709,13 +726,17 @@ LEXT(ppcscret) andi. r3,r3,MASK(MSR_PR) bne+ 0f /* returning to user level, check */ - BREAKPOINT_TRAP + lis r0,hi16(Choke) ; Choke code + ori r0,r0,lo16(Choke) ; and the rest + li r3,failContext ; Bad state code + sc ; System ABEND + + 0: #endif /* DEBUG */ - li r3, 0 - li r4, AST_ALL - li r5, 1 + li r3, AST_ALL + li r4, 1 bl EXT(ast_taken) b .L_thread_syscall_ret_check_ast @@ -767,23 +788,18 @@ LEXT(ppcscret) b .L_syscall_return -/* - * thread_bootstrap_return() - * - * NOTE: THIS IS GOING AWAY IN A FEW DAYS.... - * - */ - -ENTRY(thread_bootstrap_return, TAG_NO_FRAME_USED) - b .L_thread_exc_ret_check_ast ; Do the same as thread_exception_return... - /* * thread_exception_return() * * Return to user mode directly from within a system call. */ -ENTRY(thread_exception_return, TAG_NO_FRAME_USED) + .align 5 + .globl EXT(thread_bootstrap_return) +LEXT(thread_bootstrap_return) ; NOTE: THIS IS GOING AWAY IN A FEW DAYS.... + + .globl EXT(thread_exception_return) +LEXT(thread_exception_return) ; Directly return to user mode .L_thread_exc_ret_check_ast: @@ -809,9 +825,8 @@ ENTRY(thread_exception_return, TAG_NO_FRAME_USED) */ - li r3,0 - li r4,AST_ALL - li r5,1 + li r3,AST_ALL + li r4,1 bl EXT(ast_taken) b .L_thread_exc_ret_check_ast /* check for a second AST (rare)*/ @@ -837,7 +852,11 @@ ENTRY(thread_exception_return, TAG_NO_FRAME_USED) andi. r3,r3,MASK(MSR_PR) bne+ ret_user2 ; We are ok... - BREAKPOINT_TRAP + lis r0,hi16(Choke) ; Choke code + ori r0,r0,lo16(Choke) ; and the rest + li r3,failContext ; Bad state code + sc ; System ABEND + ret_user2: #endif /* DEBUG */ @@ -884,7 +903,9 @@ cleardummy: stw r0,0(r4) ; Clear stuff * */ -ENTRY(ihandler, TAG_NO_FRAME_USED) + .align 5 + .globl EXT(ihandler) +LEXT(ihandler) /* Interrupt handler */ /* * get the value of istackptr, if it's zero then we're already on the @@ -930,9 +951,26 @@ ihboot4: bne .L_istackfree /* Nope... */ * stack pointer and make room for a frame */ - subi r1,r9,FM_REDZONE /* Back up beyond the red zone */ - b ihsetback /* Go set up the back chain... */ - + lwz r10,PP_INTSTACK_TOP_SS(r25) ; Get the top of the interrupt stack + addi r5,r9,INTSTACK_SIZE-FM_SIZE ; Shift stack for bounds check + subi r1,r9,FM_REDZONE ; Back up beyond the red zone + sub r5,r5,r10 ; Get displacement into stack + cmplwi r5,INTSTACK_SIZE-FM_SIZE ; Is the stack actually invalid? + blt+ ihsetback ; The stack is ok... + + lwz r5,PP_DEBSTACK_TOP_SS(r25) ; Pick up debug stack top + subi r5,r5,KERNEL_STACK_SIZE-FM_SIZE ; Adjust to start of stack + sub r5,r1,r5 ; Get displacement into debug stack + cmplwi cr2,r5,KERNEL_STACK_SIZE-FM_SIZE ; Check if we are on debug stack + blt+ ihsetback ; Yeah, that is ok too... + + lis r0,hi16(Choke) ; Choke code + ori r0,r0,lo16(Choke) ; and the rest + li r3,failStack ; Bad stack code + sc ; System ABEND + + .align 5 + .L_istackfree: lwz r10,SAVflags(r4) stw r0,PP_ISTACKPTR(r25) /* Mark the stack in use */ @@ -940,7 +978,7 @@ ihboot4: bne .L_istackfree /* Nope... */ stw r10,SAVflags(r4) /* Stick it back */ /* - * To summarise, when we reach here, the state has been saved and + * To summarize, when we reach here, the state has been saved and * the stack is marked as busy. We now generate a small * stack frame with backpointers to follow the calling * conventions. We set up the backpointers to the trapped @@ -1068,13 +1106,13 @@ chkfac: mr. r8,r8 ; Are we still in boot? lwz r20,ACT_MACT_FPUlvl(r8) ; Get the FPU level lwz r12,savesrr1(r3) ; Get the current MSR - cmplw r20,r3 ; Are we returning from the active level? + cmplw cr1,r20,r3 ; Are we returning from the active level? lwz r23,PP_FPU_THREAD(r10) ; Get floating point owner rlwinm r12,r12,0,MSR_FP_BIT+1,MSR_FP_BIT-1 ; Turn off floating point for now - cmplw cr1,r23,r8 ; Are we the facility owner? + cmplw cr2,r23,r8 ; Are we the facility owner? lhz r26,PP_CPU_NUMBER(r10) ; Get the current CPU number - beq- chkfpfree ; Leaving active level, can not possibly enable... - bne- cr1,chkvec ; Not our facility, nothing to do here... + cror cr0_eq,cr1_eq,cr2_eq ; Check if returning from active or we own facility + bne- cr0,chkvecnr ; Nothing to do if not returning from active or not us... #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) @@ -1083,9 +1121,20 @@ chkfac: mr. r8,r8 ; Are we still in boot? sc ; (TEST/DEBUG) #endif - lwz r24,ACT_MACT_FPUcpu(r8) ; Get the CPU this context was enabled on last + li r22,ACT_MACT_FPUcpu ; Point to the CPU indication/lock word + +cfSpin2: lwarx r27,r22,r8 ; Get and reserve the last used CPU + mr. r27,r27 ; Is it changing now? + oris r0,r27,hi16(fvChk) ; Set the "changing" flag + blt- cfSpin2 ; Spin if changing + stwcx. r0,r22,r8 ; Lock it up + bne- cfSpin2 ; Someone is messing right now + + isync ; Make sure we see everything + cmplw r4,r20 ; Are we going to be in the right level? - cmplw cr1,r24,r26 ; Are we on the right CPU? + beq- cr1,chkfpfree ; Leaving active level, can not possibly enable... + cmplw cr1,r27,r26 ; Are we on the right CPU? li r0,0 ; Get a constant 0 beq+ cr1,chkfpnlvl ; Right CPU... @@ -1102,78 +1151,12 @@ chkfpnlvl: bne- chkvec ; Different level, can not enable... cmplw r4,r25 ; Is the top one ours? bne+ chkvec ; Not ours... stw r0,SAVlvlfp(r24) ; Invalidate the first one - -#if 0 - mfmsr r0 ; (TEST/DEBUG) - ori r0,r0,0x2000 ; (TEST/DEBUG) - mtmsr r0 ; (TEST/DEBUG) - isync ; (TEST/DEBUG) - - stfd f0,savevr0(r3) ; (TEST/DEBUG) - stfd f1,savevr0+8(r3) ; (TEST/DEBUG) - stfd f2,savevr0+0x10(r3) ; (TEST/DEBUG) - stfd f3,savevr0+0x18(r3) ; (TEST/DEBUG) - stfd f4,savevr0+0x20(r3) ; (TEST/DEBUG) - stfd f5,savevr0+0x28(r3) ; (TEST/DEBUG) - stfd f6,savevr0+0x30(r3) ; (TEST/DEBUG) - stfd f7,savevr0+0x38(r3) ; (TEST/DEBUG) - stfd f8,savevr0+0x40(r3) ; (TEST/DEBUG) - stfd f9,savevr0+0x48(r3) ; (TEST/DEBUG) - stfd f10,savevr0+0x50(r3) ; (TEST/DEBUG) - stfd f11,savevr0+0x58(r3) ; (TEST/DEBUG) - stfd f12,savevr0+0x60(r3) ; (TEST/DEBUG) - stfd f13,savevr0+0x68(r3) ; (TEST/DEBUG) - stfd f14,savevr0+0x70(r3) ; (TEST/DEBUG) - stfd f15,savevr0+0x78(r3) ; (TEST/DEBUG) - stfd f16,savevr0+0x80(r3) ; (TEST/DEBUG) - stfd f17,savevr0+0x88(r3 ; (TEST/DEBUG) - stfd f18,savevr0+0x90(r3) ; (TEST/DEBUG) - stfd f19,savevr0+0x98(r3) ; (TEST/DEBUG) - stfd f20,savevr0+0xA0(r3) ; (TEST/DEBUG) - stfd f21,savevr0+0xA8(r3) ; (TEST/DEBUG) - stfd f22,savevr0+0xB0(r3) ; (TEST/DEBUG) - stfd f23,savevr0+0xB8(r3) ; (TEST/DEBUG) - stfd f24,savevr0+0xC0(r3) ; (TEST/DEBUG) - stfd f25,savevr0+0xC8(r3) ; (TEST/DEBUG) - stfd f26,savevr0+0xD0(r3) ; (TEST/DEBUG) - stfd f27,savevr0+0xD8(r3) ; (TEST/DEBUG) - stfd f28,savevr0+0xE0(r3) ; (TEST/DEBUG) - stfd f29,savevr0+0xE8(r3) ; (TEST/DEBUG) - stfd f30,savevr0+0xF0(r3) ; (TEST/DEBUG) - stfd f31,savevr0+0xF8(r3) ; (TEST/DEBUG) - - li r2,64 ; (TEST/DEBUG) - la r20,savevr0(r3) ; (TEST/DEBUG) - la r21,savefp0(r24) ; (TEST/DEBUG) - -ckmurderdeath2: - lwz r22,0(r20) ; (TEST/DEBUG) - subic. r2,r2,1 ; (TEST/DEBUG) - lwz r23,0(r21) ; (TEST/DEBUG) - addi r20,r20,4 ; (TEST/DEBUG) - cmplw cr1,r22,r23 ; (TEST/DEBUG) - addi r21,r21,4 ; (TEST/DEBUG) - bne- cr1,diekilldead2 ; (TEST/DEBUG) - bne+ ckmurderdeath2 ; (TEST/DEBUG) - b dontdiekilldead2 ; (TEST/DEBUG) - -diekilldead2: ; (TEST/DEBUG) - mr r4,r24 ; (TEST/DEBUG) - BREAKPOINT_TRAP ; (TEST/DEBUG) - -dontdiekilldead2: - lfd f0,savevr0(r3) ; (TEST/DEBUG) - lfd f1,savevr0+8(r3) ; (TEST/DEBUG) -#endif - - - b chkvec ; Go check out the vector facility... chkfpfree: li r0,0 ; Clear a register lwz r24,ACT_MACT_FPU(r8) ; Get the floating point save area - bne- cr1,chkfpnfr ; Not our facility, do not clear... + bne- cr2,chkfpnfr ; Not our facility, do not clear... stw r0,PP_FPU_THREAD(r10) ; Clear floating point owner chkfpnfr: @@ -1242,7 +1225,7 @@ donotdie3: ; (TEST/DEBUG) stw r25,ACT_MACT_FPUlvl(r8) ; Set the new top level andis. r0,r19,hi16(SAVinuse) ; Still in use? stw r19,SAVflags(r24) ; Set the savearea flags - bne- chkvec ; Yes, go check out vector... + bne- invlivefp ; Go invalidate live FP #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) li r2,0x3306 ; (TEST/DEBUG) @@ -1261,17 +1244,42 @@ notbadxxx3: ; (TEST/DEBUG) stw r20,SAVqfret(r24) ; Back chain the quick release queue stw r23,PP_QUICKFRET(r10) ; Anchor it +invlivefp: lis r20,hi16(EXT(real_ncpus)) ; Get number of CPUs + lis r23,hi16(EXT(per_proc_info)) ; Set base per_proc + ori r20,r20,lo16(EXT(real_ncpus)) ; Other half of number of CPUs + li r25,PP_FPU_THREAD ; Point to the FP owner address + lwz r20,0(r20) ; Get number of processors active + ori r23,r23,lo16(EXT(per_proc_info)) ; Set base per_proc + li r2,0 ; Get something clear + +invlivefl: cmplw r23,r10 ; We can skip our processor + addi r20,r20,-1 ; Count remaining processors + beq invlivefn ; Skip ourselves... + +invlivefa: lwarx r0,r25,r23 ; Get FP owner for this processor + cmplw r0,r8 ; Do we own it? + bne invlivefn ; Nope... + stwcx. r2,r25,r23 ; Show not live + bne- invlivefa ; Someone else did this, try again... + +invlivefn: mr. r20,r20 ; Have we finished? + addi r23,r23,ppSize ; Bump to next + bgt invlivefl ; Make sure we do all processors... + + ; ; Check out vector stuff (and translate savearea to physical for exit) ; -chkvec: - lwz r20,ACT_MACT_VMXlvl(r8) ; Get the vector level +chkvec: sync ; Make sure all is saved + stw r27,ACT_MACT_FPUcpu(r8) ; Set the active CPU and release + +chkvecnr: lwz r20,ACT_MACT_VMXlvl(r8) ; Get the vector level lwz r23,PP_VMX_THREAD(r10) ; Get vector owner - cmplw r20,r3 ; Are we returning from the active level? + cmplw cr1,r20,r3 ; Are we returning from the active level? + cmplw cr2,r23,r8 ; Are we the facility owner? rlwinm r12,r12,0,MSR_VEC_BIT+1,MSR_VEC_BIT-1 ; Turn off vector for now - cmplw cr1,r23,r8 ; Are we the facility owner? - beq- chkvecfree ; Leaving active level, can not possibly enable... - bne- cr1,setena ; Not our facility, nothing to do here... + cror cr0_eq,cr1_eq,cr2_eq ; Check if returning from active or we own facility + bne- cr0,setenanr ; Not our facility, nothing to do here... #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) @@ -1280,9 +1288,20 @@ chkvec: sc ; (TEST/DEBUG) #endif - lwz r24,ACT_MACT_VMXcpu(r8) ; Get the CPU this context was enabled on last + li r22,ACT_MACT_VMXcpu ; Point to the CPU indication/lock word + +cvSpin2: lwarx r27,r22,r8 ; Get and reserve the last used CPU + mr. r27,r27 ; Is it changing now? + oris r0,r27,hi16(fvChk) ; Set the "changing" flag + blt- cvSpin2 ; Spin if changing + stwcx. r0,r22,r8 ; Lock it up + bne- cvSpin2 ; Someone is messing right now + + isync ; Make sure we see everything + cmplw r4,r20 ; Are we going to be in the right level? - cmplw cr1,r24,r26 ; Are we on the right CPU? + beq- cr1,chkvecfree ; Leaving active level, can not possibly enable... + cmplw cr1,r27,r26 ; Are we on the right CPU? li r0,0 ; Get a constant 0 beq+ cr1,chkvecnlvl ; Right CPU... @@ -1303,7 +1322,8 @@ chkvecnlvl: bne- setena ; Different level, can not enable... chkvecfree: li r0,0 ; Clear a register lwz r24,ACT_MACT_VMX(r8) ; Get the vector save area - bne- cr1,chkvecnfr ; Not our facility, do not clear... + + bne- cr2,chkvecnfr ; Not our facility, do not clear... stw r0,PP_VMX_THREAD(r10) ; Clear vector owner chkvecnfr: @@ -1355,7 +1375,7 @@ vectoplvl: lwz r19,SAVflags(r24) ; Get the savearea flags stw r25,ACT_MACT_VMXlvl(r8) ; Set the new top level andis. r0,r19,hi16(SAVinuse) ; Still in use? stw r19,SAVflags(r24) ; Set the savearea flags - bne- setena ; Yes, all done... + bne- invliveve ; Go invalidate live vec... #if FPVECDBG lis r0,HIGH_ADDR(CutTrace) ; (TEST/DEBUG) li r2,0x3406 ; (TEST/DEBUG) @@ -1368,7 +1388,32 @@ vectoplvl: lwz r19,SAVflags(r24) ; Get the savearea flags stw r20,SAVqfret(r24) ; Back chain the quick release queue stw r23,PP_QUICKFRET(r10) ; Anchor it -setena: rlwinm r20,r12,(((31-vectorCngbit)+(MSR_VEC_BIT+1))&31),vectorCngbit,vectorCngbit ; Set flag if we enabled vector +invliveve: lis r20,hi16(EXT(real_ncpus)) ; Get number of CPUs + lis r23,hi16(EXT(per_proc_info)) ; Set base per_proc + ori r20,r20,lo16(EXT(real_ncpus)) ; Other half of number of CPUs + li r25,PP_VMX_THREAD ; Point to the vector owner address + lwz r20,0(r20) ; Get number of processors active + ori r23,r23,lo16(EXT(per_proc_info)) ; Set base per_proc + li r2,0 ; Get something clear + +invlivevl: cmplw r23,r10 ; We can skip our processor + addi r20,r20,-1 ; Count remaining processors + beq invlivevn ; Skip ourselves... + +invliveva: lwarx r0,r25,r23 ; Get vector owner for this processor + cmplw r0,r8 ; Do we own it? + bne invlivevn ; Nope... + stwcx. r2,r25,r23 ; Show not live + bne- invliveva ; Someone else did this, try again... + +invlivevn: mr. r20,r20 ; Have we finished? + addi r23,r23,ppSize ; Bump to next + bgt invlivevl ; Make sure we do all processors... + +setena: sync ; Make sure all is saved + stw r27,ACT_MACT_VMXcpu(r8) ; Set the active CPU and release + +setenanr: rlwinm r20,r12,(((31-vectorCngbit)+(MSR_VEC_BIT+1))&31),vectorCngbit,vectorCngbit ; Set flag if we enabled vector rlwimi. r20,r12,(((31-floatCngbit)+(MSR_FP_BIT+1))&31),floatCngbit,floatCngbit ; Set flag if we enabled floats beq setenaa ; Neither float nor vector turned on.... @@ -1412,14 +1457,19 @@ chkenax: lwz r6,SAVflags(r3) ; Pick up the flags of the old savearea #if DEBUG lwz r20,SAVact(r3) ; (TEST/DEBUG) Make sure our restore - lwz r21,PP_CPU_DATA(r10) ; (TEST/DEBUG) context is associated - lwz r21,CPU_ACTIVE_THREAD(r21) ; (TEST/DEBUG) with the current act. + lwz r21,PP_CPU_DATA(r10) ; (TEST/DEBUG) context is associated + lwz r21,CPU_ACTIVE_THREAD(r21) ; (TEST/DEBUG) with the current act. cmpwi r21,0 ; (TEST/DEBUG) beq- yeswereok ; (TEST/DEBUG) lwz r21,THREAD_TOP_ACT(r21) ; (TEST/DEBUG) cmplw r21,r20 ; (TEST/DEBUG) beq+ yeswereok ; (TEST/DEBUG) - BREAKPOINT_TRAP ; (TEST/DEBUG) + + lis r0,hi16(Choke) ; (TEST/DEBUG) Choke code + ori r0,r0,lo16(Choke) ; (TEST/DEBUG) and the rest + mr r21,r3 ; (TEST/DEBUG) Save the savearea address + li r3,failContext ; (TEST/DEBUG) Bad state code + sc ; (TEST/DEBUG) System ABEND yeswereok: #endif @@ -1449,6 +1499,8 @@ yeswereok: * r25 = per_proc */ + .align 5 + fastpath: cmplwi cr3,r0,0x7FF1 ; Is it CthreadSetSelfNumber? bnelr- cr3 ; Not a fast path... @@ -1489,26 +1541,23 @@ EXT(fastexit): * Otherwise we transfer to the assist code. */ + .align 5 + checkassist: - lwz r23,saveexception(r4) /* Get the exception code */ - cmpi cr0, r23, T_AST /* Check for T_AST trap */ - beqlr- /* Go handle it */ - - lwz r23,savesrr1(r4) /* Get the interrupted MSR */ - lwz r24,ACT_MACT_BTS(r13) /* Get the table start */ - rlwinm. r27,r23,0,MSR_PR_BIT,MSR_PR_BIT ; Are we in userland? - rlwinm r23,r23,0,SRR1_PRG_TRAP_BIT,SRR1_PRG_TRAP_BIT ; See if this was actually a trap instruction - beqlr- /* No assist in kernel mode... */ - mr. r23,r23 ; Check for trap - lwz r27,savesrr0(r4) /* Get trapped address */ - beqlr- ; No assist if not trap instruction... - -checkassistBP: /* Safe place to breakpoint */ - - sub r24,r27,r24 /* See how far into it we are */ - cmplwi r24,BB_MAX_TRAP /* Do we fit in the list? */ - bgtlr- /* Nope, it's a regular trap... */ - b EXT(atomic_switch_trap) /* Go to the assist... */ + lwz r0,saveexception(r4) ; Get the exception code + lwz r23,savesrr1(r4) ; Get the interrupted MSR + lwz r26,ACT_MACT_BEDA(r13) ; Get Blue Box Descriptor Area + mtcrf 0x18,r23 ; Check what SRR1 says + lwz r24,ACT_MACT_BTS(r13) ; Get the table start + cmplwi r0,T_AST ; Check for T_AST trap + lwz r27,savesrr0(r4) ; Get trapped address + crnand cr1_eq,SRR1_PRG_TRAP_BIT,MSR_PR_BIT ; We need both trap and user state + sub r24,r27,r24 ; See how far into it we are + cror cr0_eq,cr0_eq,cr1_eq ; Need to bail if AST or not trap or not user state + cmplwi cr1,r24,BB_MAX_TRAP ; Do we fit in the list? + cror cr0_eq,cr0_eq,cr1_gt ; Also leave it trap not in range + btlr- cr0_eq ; No assist if AST or not trap or not user state or trap not in range + b EXT(atomic_switch_trap) ; Go to the assist... ; ; Virtual Machine Monitor @@ -1518,6 +1567,8 @@ checkassistBP: /* Safe place to breakpoint */ ; and savearea respectivily. ; + .align 5 + exitFromVM: mr r30,r4 ; Get the savearea mr r3,r13 ; Get the activation @@ -1544,61 +1595,67 @@ LEXT(retFromVM) b chkfac ; Go end it all... -#if MACH_KDB -/* - * Here's where we jump into the debugger. This is called from - * either an MP signal from another processor, or a command-power NMI - * on the main processor. - * - * Note that somewhere in our stack should be a return into the interrupt - * handler. If there isn't, we'll crash off the end of the stack, actually, - * it'll just quietly return. hahahahaha. - */ +; +; chandler (note: not a candle maker or tallow merchant) +; +; Here is the system choke handler. This is where the system goes +; to die. +; +; We get here as a result of a T_CHOKE exception which is generated +; by the Choke firmware call or by lowmem_vectors when it detects a +; fatal error. Examples of where this may be used is when we detect +; problems in low-level mapping chains, trashed savearea free chains, +; or stack guardpage violations. +; +; Note that we can not set a back chain in the stack when we come +; here because we are probably here because the chain was corrupt. +; -ENTRY(kdb_kintr, TAG_NO_FRAME_USED) - - lis r9,HIGH_ADDR(EXT(ihandler_ret)) /* Top part of interrupt return */ - lis r10,HIGH_ADDR(EXT(intercept_ret)) /* Top part of intercept return */ - ori r9,r9,LOW_ADDR(EXT(ihandler_ret)) /* Bottom part of interrupt return */ - ori r10,r10,LOW_ADDR(EXT(intercept_ret)) /* Bottom part of intercept return */ - - lwz r8,0(r1) /* Get our caller's stack frame */ -srchrets: mr. r8,r8 /* Have we reached the end of our rope? */ - beqlr- /* Yeah, just bail... */ - lwz r7,FM_LR_SAVE(r8) /* The whoever called them */ - cmplw cr0,r9,r7 /* Was it the interrupt handler? */ - beq srchfnd /* Yeah... */ - lwz r8,0(r8) /* Chain back to the previous frame */ - b srchrets /* Ok, check again... */ + .align 5 + .globl EXT(chandler) +LEXT(chandler) /* Choke handler */ + + lis r25,hi16(EXT(trcWork)) ; (TEST/DEBUG) + li r31,0 ; (TEST/DEBUG) + ori r25,r25,lo16(EXT(trcWork)) ; (TEST/DEBUG) + stw r31,traceMask(r25) ; (TEST/DEBUG) + + + mfsprg r25,0 ; Get the per_proc + + lwz r1,PP_DEBSTACKPTR(r25) ; Get debug stack pointer + cmpwi r1,-1 ; Are we already choking? + bne chokefirst ; Nope... -srchfnd: stw r10,FM_LR_SAVE(r8) /* Modify return to come to us instead */ - blr /* Finish up and get back here... */ +chokespin: addi r31,r31,1 ; Spin and hope for an analyzer connection... + addi r31,r31,1 ; Spin and hope for an analyzer connection... + addi r31,r31,1 ; Spin and hope for an analyzer connection... + addi r31,r31,1 ; Spin and hope for an analyzer connection... + addi r31,r31,1 ; Spin and hope for an analyzer connection... + addi r31,r31,1 ; Spin and hope for an analyzer connection... + b chokespin ; Spin and hope for an analyzer connection... -/* - * We come here when we've returned all the way to the interrupt handler. - * That way we can enter the debugger with the registers and stack which - * existed at the point of interruption. - * - * R3 points to the saved state at entry - */ - - ENTRY(intercept_ret, TAG_NO_FRAME_USED) - - lis r6,HIGH_ADDR(EXT(kdb_trap)) /* Get the top part of the KDB enter routine */ - mr r5,r3 /* Move saved state to the correct parameter */ - ori r6,r6,LOW_ADDR(EXT(kdb_trap)) /* Get the last part of the KDB enter routine */ - li r4,0 /* Set a code of 0 */ - mr r13,r3 /* Save the saved state pointer in a non-volatile */ - mtlr r6 /* Set the routine address */ - li r3,-1 /* Show we had an interrupt type */ - - blrl /* Go enter KDB */ +chokefirst: li r0,-1 ; Set choke value + mr. r1,r1 ; See if we are on debug stack yet + lwz r10,saver1(r4) ; + stw r0,PP_DEBSTACKPTR(r25) ; Show we are choking + bne chokestart ; We are not on the debug stack yet... + + lwz r2,PP_DEBSTACK_TOP_SS(r25) ; Get debug stack top + sub r11,r2,r10 ; Get stack depth - mr r3,r13 /* Put the saved state where expected */ - b EXT(ihandler_ret) /* Go return from the interruption... */ + cmplwi r11,KERNEL_STACK_SIZE-FM_SIZE-TRAP_SPACE_NEEDED ; Check if stack pointer is ok + bgt chokespin ; Bad stack pointer or too little left, just die... -#endif + subi r1,r10,FM_REDZONE ; Make a red zone + +chokestart: li r0,0 ; Get a zero + stw r0,FM_BACKPTR(r1) ; We now have terminated the back chain + + bl EXT(SysChoked) ; Call the "C" phase of this + b chokespin ; Should not be here so just go spin... + #if VERIFYSAVE ; diff --git a/osfmk/ppc/hw_lock.s b/osfmk/ppc/hw_lock.s index a317068d1..14678dfd5 100644 --- a/osfmk/ppc/hw_lock.s +++ b/osfmk/ppc/hw_lock.s @@ -37,6 +37,10 @@ #define SWT_LO 4+FM_SIZE #define MISSED 8+FM_SIZE +#define ILK_LOCKED 0x01 +#define MUTEX_LOCKED 0x02 +#define SLOCK_FAST 0x02 + ; ; NOTE: make sure that PREEMPTSTACK in aligned_data is ; set the same as it is here. This is the number of @@ -218,7 +222,7 @@ ENTRY(hw_lock_init, TAG_NO_FRAME_USED) * void hw_lock_unlock(hw_lock_t) * * Unconditionally release lock. - * MACH_RT: release preemption level. + * Release preemption level. */ @@ -237,11 +241,7 @@ LEXT(hw_lock_unlock) li r0, 0 /* set lock to free */ stw r0, 0(r3) -#if MACH_RT b epStart /* Go enable preemption... */ -#else - blr -#endif /* @@ -261,7 +261,7 @@ lockLock: lis r4,HIGH_ADDR(EXT(LockTimeOut)) /* Get the high part */ * void hw_lock_lock(hw_lock_t) * * Acquire lock, spinning until it becomes available. - * MACH_RT: also return with preemption disabled. + * Return with preemption disabled. * Apparently not used except by mach_perf. * We will just set a default timeout and jump into the NORMAL timeout lock. */ @@ -320,27 +320,22 @@ lockComm: mfmsr r9 /* Get the MSR value */ mtmsr r7 /* Turn off interruptions */ mftb r8 /* Get the low part of the time base */ - lwarx r6,0,r5 ; ? - lcktry: lwarx r6,0,r5 /* Grab the lock value */ - li r3,1 /* Use part of the delay time */ - mr. r6,r6 /* Is it locked? */ + andi. r3,r6,ILK_LOCKED /* Is it locked? */ + ori r6,r6,ILK_LOCKED /* Set interlock */ bne- lcksniff /* Yeah, wait for it to clear... */ - stwcx. r3,0,r5 /* Try to seize that there durn lock */ -#if MACH_RT + stwcx. r6,0,r5 /* Try to seize that there durn lock */ bne- lcktry /* Couldn't get it... */ + li r3,1 /* return true */ + isync /* Make sure we don't use a speculativily loaded value */ beq+ cr1,daPreComm /* We got it, go disable preemption if we're supposed to... */ mtmsr r9 ; Restore interrupt state blr /* Go on home... */ -#else /* MACH_RT */ - beq+ lckgot /* We got it, yahoo... */ - b lcktry /* Just start up again if the store failed... */ -#endif /* MACH_RT */ .align 5 lcksniff: lwz r3,0(r5) /* Get that lock in here */ - mr. r3,r3 /* Is it free yet? */ + andi. r3,r3,ILK_LOCKED /* Is it free yet? */ beq+ lcktry /* Yeah, try for it again... */ mftb r10 /* Time stamp us now */ @@ -365,12 +360,6 @@ lcksniff: lwz r3,0(r5) /* Get that lock in here */ mftb r8 /* Get the low part of the time base */ b lcksniff /* Now that we've opened an enable window, keep trying... */ -#if !MACH_RT -lckgot: mtmsr r9 /* Enable for interruptions */ - isync /* Make sure we don't use a speculativily loaded value */ - blr -#endif /* !MACH_RT */ - lckfail: /* We couldn't get the lock */ li r3,0 /* Set failure return code */ blr /* Return, head hanging low... */ @@ -413,8 +402,6 @@ LEXT(hw_lock_bit) mftb r8 /* Get the low part of the time base */ - lwarx r0,0,r3 ; ? - bittry: lwarx r6,0,r3 /* Grab the lock value */ and. r0,r6,r4 /* See if any of the lock bits are on */ or r6,r6,r4 /* Turn on the lock bits */ @@ -479,7 +466,6 @@ bitfail: li r3,0 /* Set failure return code */ LEXT(hw_unlock_bit) sync - lwarx r0,0,r3 ; ? ubittry: lwarx r0,0,r3 /* Grab the lock value */ andc r0,r0,r4 /* Clear the lock bits */ @@ -523,8 +509,6 @@ LEXT(hw_lock_mbits) mftb r10 ; Get the low part of the time base - lwarx r0,0,r3 ; ? - mbittry: lwarx r12,0,r3 ; Grab the lock value and r0,r12,r4 ; Clear extra bits or r12,r12,r6 ; Turn on the lock bits @@ -629,7 +613,7 @@ csynctry: lwz r11,0(r9) ; Grab the sync value .align 5 - .globl EXT(hw_cpu_sync) + .globl EXT(hw_cpu_wcng) LEXT(hw_cpu_wcng) @@ -653,8 +637,8 @@ wcngtry: lwz r11,0(r9) ; Grab the value /* * unsigned int hw_lock_try(hw_lock_t) * - * try to acquire spin-lock. Return success (1) or failure (0) - * MACH_RT: returns with preemption disabled on success. + * Try to acquire spin-lock. Return success (1) or failure (0) + * Returns with preemption disabled on success. * */ .align 5 @@ -669,7 +653,6 @@ LEXT(hw_lock_try) sc /* (TEST/DEBUG) */ #endif mfmsr r9 /* Save the MSR value */ - li r4, 1 /* value to be stored... 1==taken */ rlwinm r7,r9,0,MSR_EE_BIT+1,MSR_EE_BIT-1 /* Clear interruption bit */ #if MACH_LDEBUG @@ -679,8 +662,6 @@ LEXT(hw_lock_try) mtmsr r7 /* Disable interruptions and thus, preemption */ - lwarx r5,0,r3 ; ? - .L_lock_try_loop: #if MACH_LDEBUG @@ -693,23 +674,21 @@ LEXT(hw_lock_try) lwarx r5,0,r3 /* Ld from addr of arg and reserve */ - cmpwi r5, 0 /* TEST... */ + andi. r6,r5,ILK_LOCKED /* TEST... */ + ori r5,r5,ILK_LOCKED bne- .L_lock_try_failed /* branch if taken. Predict free */ - stwcx. r4, 0,r3 /* And SET (if still reserved) */ + stwcx. r5,0,r3 /* And SET (if still reserved) */ mfsprg r6,0 /* Get the per_proc block */ bne- .L_lock_try_loop /* If set failed, loop back */ lwz r6,PP_CPU_DATA(r6) /* Get the pointer to the CPU data from per proc */ isync -#if MACH_RT lwz r5,CPU_PREEMPTION_LEVEL(r6) /* Get the preemption level */ addi r5,r5,1 /* Bring up the disable count */ stw r5,CPU_PREEMPTION_LEVEL(r6) /* Save it back */ -#endif /* MACH_RT */ - mtmsr r9 /* Allow interruptions now */ li r3,1 /* Set that the lock was free */ blr @@ -723,7 +702,7 @@ LEXT(hw_lock_try) * unsigned int hw_lock_held(hw_lock_t) * * Return 1 if lock is held - * MACH_RT: doesn't change preemption state. + * Doesn't change preemption state. * N.B. Racy, of course. * */ @@ -757,8 +736,6 @@ LEXT(hw_compare_and_store) mr r6,r3 /* Save the old value */ - lwarx r9,0,r5 ; ? - cstry: lwarx r9,0,r5 /* Grab the area value */ li r3,1 /* Assume it works */ cmplw cr0,r9,r6 /* Does it match the old value? */ @@ -773,7 +750,7 @@ csfail: li r3,0 /* Set failure */ /* - * unsigned int hw_atomic_add(unsigned int *area, int *val) + * unsigned int hw_atomic_add(unsigned int *area, int val) * * Atomically add the second parameter to the first. * Returns the result. @@ -786,8 +763,6 @@ LEXT(hw_atomic_add) mr r6,r3 /* Save the area */ - lwarx r3,0,r6 ; ? - addtry: lwarx r3,0,r6 /* Grab the area value */ add r3,r3,r4 /* Add the value */ stwcx. r3,0,r6 /* Try to save the new value */ @@ -796,7 +771,7 @@ addtry: lwarx r3,0,r6 /* Grab the area value */ /* - * unsigned int hw_atomic_sub(unsigned int *area, int *val) + * unsigned int hw_atomic_sub(unsigned int *area, int val) * * Atomically subtract the second parameter from the first. * Returns the result. @@ -809,8 +784,6 @@ LEXT(hw_atomic_sub) mr r6,r3 /* Save the area */ - lwarx r3,0,r6 ; ? - subtry: lwarx r3,0,r6 /* Grab the area value */ sub r3,r3,r4 /* Subtract the value */ stwcx. r3,0,r6 /* Try to save the new value */ @@ -818,6 +791,48 @@ subtry: lwarx r3,0,r6 /* Grab the area value */ blr /* Return... */ +/* + * unsigned int hw_atomic_or(unsigned int *area, int val) + * + * Atomically ORs the second parameter into the first. + * Returns the result. + * + */ + .align 5 + .globl EXT(hw_atomic_or) + +LEXT(hw_atomic_or) + + mr r6,r3 ; Save the area + +ortry: lwarx r3,0,r6 ; Grab the area value + or r3,r3,r4 ; OR the value + stwcx. r3,0,r6 ; Try to save the new value + bne- ortry ; Did not get it, try again... + blr ; Return... + + +/* + * unsigned int hw_atomic_and(unsigned int *area, int val) + * + * Atomically ANDs the second parameter with the first. + * Returns the result. + * + */ + .align 5 + .globl EXT(hw_atomic_and) + +LEXT(hw_atomic_and) + + mr r6,r3 ; Save the area + +andtry: lwarx r3,0,r6 ; Grab the area value + and r3,r3,r4 ; AND the value + stwcx. r3,0,r6 ; Try to save the new value + bne- andtry ; Did not get it, try again... + blr ; Return... + + /* * void hw_queue_atomic(unsigned int * anchor, unsigned int * elem, unsigned int disp) * @@ -855,13 +870,10 @@ LEXT(hw_queue_atomic_list) mr r8,r6 /* Copy the displacement also */ hw_queue_comm: - lwarx r9,0,r3 ; ? - -hw_queue_comm2: lwarx r9,0,r3 /* Pick up the anchor */ stwx r9,r8,r7 /* Chain that to the end of the new stuff */ stwcx. r4,0,r3 /* Try to chain into the front */ - bne- hw_queue_comm2 /* Didn't make it, try again... */ + bne- hw_queue_comm /* Didn't make it, try again... */ blr /* Return... */ @@ -882,16 +894,13 @@ LEXT(hw_dequeue_atomic) mr r5,r3 /* Save the anchor */ hw_dequeue_comm: - lwarx r9,0,r3 ; ? - -hw_dequeue_comm2: lwarx r3,0,r5 /* Pick up the anchor */ mr. r3,r3 /* Is the list empty? */ beqlr- /* Leave it list empty... */ lwzx r9,r4,r3 /* Get the next in line */ stwcx. r9,0,r5 /* Try to chain into the front */ beqlr+ ; Got the thing, go away with it... - b hw_dequeue_comm2 ; Did not make it, try again... + b hw_dequeue_comm ; Did not make it, try again... /* * void mutex_init(mutex_t* l, etap_event_t etap) @@ -899,35 +908,48 @@ hw_dequeue_comm2: ENTRY(mutex_init,TAG_NO_FRAME_USED) - PROLOG(0) - li r10, 0 - stw r10, MUTEX_ILK(r3) /* clear interlock */ - stw r10, MUTEX_LOCKED(r3) /* clear locked flag */ - sth r10, MUTEX_WAITERS(r3) /* init waiter count */ + PROLOG(0) + li r10, 0 + stw r10, LOCK_DATA(r3) /* clear lock word */ + sth r10, MUTEX_WAITERS(r3) /* init waiter count */ #if MACH_LDEBUG - stw r10, MUTEX_PC(r3) /* init caller pc */ - stw r10, MUTEX_THREAD(r3) /* and owning thread */ - li r10, MUTEX_TAG - stw r10, MUTEX_TYPE(r3) /* set lock type */ + stw r10, MUTEX_PC(r3) /* init caller pc */ + stw r10, MUTEX_THREAD(r3) /* and owning thread */ + li r10, MUTEX_TAG + stw r10, MUTEX_TYPE(r3) /* set lock type */ #endif /* MACH_LDEBUG */ #if ETAP_LOCK_TRACE - bl EXT(etap_mutex_init) /* init ETAP data */ + bl EXT(etap_mutex_init) /* init ETAP data */ #endif /* ETAP_LOCK_TRACE */ - EPILOG - blr + EPILOG + blr /* - * void _mutex_lock(mutex_t*) + * void mutex_lock(mutex_t*) */ .align 5 - .globl EXT(_mutex_lock) + .globl EXT(mutex_lock) +LEXT(mutex_lock) + .globl EXT(_mutex_lock) LEXT(_mutex_lock) +#if !MACH_LDEBUG +L_mutex_lock_loop: + lwarx r5,0,r3 + andi. r4,r5,ILK_LOCKED|MUTEX_LOCKED + bne- L_mutex_lock_slow + ori r5,r5,MUTEX_LOCKED + stwcx. r5,0,r3 + bne- L_mutex_lock_loop + isync + blr +L_mutex_lock_slow: +#endif #if CHECKNMI mflr r12 ; (TEST/DEBUG) bl EXT(ml_sense_nmi) ; (TEST/DEBUG) @@ -935,6 +957,22 @@ LEXT(_mutex_lock) #endif PROLOG(12) +#if MACH_LDEBUG + bl EXT(assert_wait_possible) + mr. r3,r3 + bne L_mutex_lock_assert_wait_1 + lis r3,hi16(L_mutex_lock_assert_wait_panic_str) + ori r3,r3,lo16(L_mutex_lock_assert_wait_panic_str) + bl EXT(panic) + + .data +L_mutex_lock_assert_wait_panic_str: + STRINGD "mutex_lock: assert_wait_possible false\n\000" + .text + +L_mutex_lock_assert_wait_1: + lwz r3,FM_ARG0(r1) +#endif #if ETAP_LOCK_TRACE li r0, 0 @@ -979,25 +1017,21 @@ mlGotInt: hold the interlock lock and no one can touch this field unless they have that, so, we're free to play */ - lwz r4,MUTEX_LOCKED(r3) /* Get the mutex's lock field */ - - li r10,1 /* Set the lock value */ - - mr. r4,r4 /* So, can we have it? */ + lwz r4,LOCK_DATA(r3) /* Get the mutex's lock field */ + andi. r9,r4,MUTEX_LOCKED /* So, can we have it? */ + ori r10,r4,MUTEX_LOCKED /* Set the lock value */ bne- mlInUse /* Nope, sombody's playing already... */ - - stw r10,MUTEX_LOCKED(r3) /* Take it unto ourselves */ #if MACH_LDEBUG mfmsr r11 - rlwinm r10,r11,0,MSR_EE_BIT+1,MSR_EE_BIT-1 - mtmsr r10 + rlwinm r5,r11,0,MSR_EE_BIT+1,MSR_EE_BIT-1 + mtmsr r5 mfsprg r9,0 /* Get the per_proc block */ - lwz r10,0(r1) /* Get previous save frame */ + lwz r5,0(r1) /* Get previous save frame */ lwz r9,PP_CPU_DATA(r9) /* Point to the cpu data area */ - lwz r10,FM_LR_SAVE(r10) /* Get our caller's address */ + lwz r5,FM_LR_SAVE(r5) /* Get our caller's address */ lwz r8, CPU_ACTIVE_THREAD(r9) /* Get the active thread */ - stw r10,MUTEX_PC(r3) /* Save our caller */ + stw r5,MUTEX_PC(r3) /* Save our caller */ mr. r8,r8 /* Is there any thread? */ stw r8,MUTEX_THREAD(r3) /* Set the mutex's holding thread */ beq- .L_ml_no_active_thread /* No owning thread... */ @@ -1008,9 +1042,8 @@ mlGotInt: mtmsr r11 #endif /* MACH_LDEBUG */ - li r10,0 /* Get the unlock value */ - sync /* Push it all out */ - stw r10,MUTEX_ILK(r3) /* free the interlock */ + rlwinm r10,r10,0,0,30 /* Get the unlock value */ + stw r10,LOCK_DATA(r3) /* grab the mutexlock and free the interlock */ #if ETAP_LOCK_TRACE mflr r4 @@ -1021,11 +1054,7 @@ mlGotInt: EPILOG /* Restore all saved registers */ -#if MACH_RT b epStart /* Go enable preemption... */ -#else - blr /* Return... */ -#endif /* * We come to here when we have a resource conflict. In other words, @@ -1054,6 +1083,8 @@ mlInUse: /* Note that we come in here with the interlock set. The wait routine * will unlock it before waiting. */ + addis r4,r4,1 /* Bump the wait count */ + stw r4,LOCK_DATA(r3) bl EXT(mutex_lock_wait) /* Wait for our turn at the lock */ lwz r3,FM_ARG0(r1) /* restore r3 (saved in prolog) */ @@ -1066,9 +1097,23 @@ mlInUse: */ .align 5 + .globl EXT(mutex_try) +LEXT(mutex_try) .globl EXT(_mutex_try) - LEXT(_mutex_try) +#if !MACH_LDEBUG +L_mutex_try_loop: + lwarx r5,0,r3 + andi. r4,r5,ILK_LOCKED|MUTEX_LOCKED + bne- L_mutex_try_slow + ori r5,r5,MUTEX_LOCKED + stwcx. r5,0,r3 + bne- L_mutex_try_loop + isync + li r3, 1 + blr +L_mutex_try_slow: +#endif PROLOG(8) /* reserve space for SWT_HI and SWT_LO */ @@ -1088,8 +1133,8 @@ LEXT(_mutex_try) CHECK_MUTEX_TYPE() CHECK_NO_SIMPLELOCKS() - lwz r6,MUTEX_LOCKED(r3) /* Quick check */ - mr. r6,r6 /* to see if someone has this lock already */ + lwz r6,LOCK_DATA(r3) /* Quick check */ + andi. r6,r6,MUTEX_LOCKED /* to see if someone has this lock already */ bne- mtFail /* Someone's got it already... */ bl lockDisa /* Go get a lock on the mutex's interlock lock */ @@ -1113,25 +1158,21 @@ mtGotInt: hold the interlock and no one can touch at this field unless they have that, so, we're free to play */ - lwz r4,MUTEX_LOCKED(r3) /* Get the mutex's lock field */ - - li r10,1 /* Set the lock value */ - - mr. r4,r4 /* So, can we have it? */ + lwz r4,LOCK_DATA(r3) /* Get the mutex's lock field */ + andi. r9,r4,MUTEX_LOCKED /* So, can we have it? */ + ori r10,r4,MUTEX_LOCKED /* Set the lock value */ bne- mtInUse /* Nope, sombody's playing already... */ - stw r10,MUTEX_LOCKED(r3) /* Take it unto ourselves */ - #if MACH_LDEBUG mfmsr r11 - rlwinm r10,r11,0,MSR_EE_BIT+1,MSR_EE_BIT-1 - mtmsr r10 + rlwinm r5,r11,0,MSR_EE_BIT+1,MSR_EE_BIT-1 + mtmsr r5 mfsprg r9,0 /* Get the per_proc block */ - lwz r10,0(r1) /* Get previous save frame */ + lwz r5,0(r1) /* Get previous save frame */ lwz r9,PP_CPU_DATA(r9) /* Point to the cpu data area */ - lwz r10,FM_LR_SAVE(r10) /* Get our caller's address */ + lwz r5,FM_LR_SAVE(r5) /* Get our caller's address */ lwz r8, CPU_ACTIVE_THREAD(r9) /* Get the active thread */ - stw r10,MUTEX_PC(r3) /* Save our caller */ + stw r5,MUTEX_PC(r3) /* Save our caller */ mr. r8,r8 /* Is there any thread? */ stw r8,MUTEX_THREAD(r3) /* Set the mutex's holding thread */ beq- .L_mt_no_active_thread /* No owning thread... */ @@ -1142,9 +1183,10 @@ mtGotInt: mtmsr r11 #endif /* MACH_LDEBUG */ - li r10,0 /* Get the unlock value */ + rlwinm r10,r10,0,0,30 /* Get the unlock value */ sync /* Push it all out */ - stw r10,MUTEX_ILK(r3) /* free the interlock */ + stw r10,LOCK_DATA(r3) /* grab the mutexlock and free the interlock */ + isync /* stop speculative instructions */ #if ETAP_LOCK_TRACE lwz r4,0(r1) /* Back chain the stack */ @@ -1154,9 +1196,8 @@ mtGotInt: bl EXT(etap_mutex_hold) /* collect hold timestamp */ #endif /* ETAP_LOCK_TRACE */ -#if MACH_RT bl epStart /* Go enable preemption... */ -#endif + li r3, 1 EPILOG /* Restore all saved registers */ blr /* Return... */ @@ -1166,12 +1207,10 @@ mtGotInt: * the mutex is held. */ -mtInUse: li r10,0 /* Get the unlock value */ - sync /* Push it all out */ - stw r10,MUTEX_ILK(r3) /* free the interlock */ -#if MACH_RT +mtInUse: + rlwinm r10,r10,0,0,30 /* Get the unlock value */ + stw r10,LOCK_DATA(r3) /* free the interlock */ bl epStart /* Go enable preemption... */ -#endif mtFail: li r3,0 /* Set failure code */ EPILOG /* Restore all saved registers */ @@ -1186,7 +1225,18 @@ mtFail: li r3,0 /* Set failure code */ .globl EXT(mutex_unlock) LEXT(mutex_unlock) - +#if !MACH_LDEBUG +L_mutex_unlock_loop: + lwarx r5,0,r3 + rlwinm. r4,r5,16,15,31 /* Bail if pending waiter or interlock set */ + rlwinm r5,r5,0,0,29 /* Clear the mutexlock */ + bne- L_mutex_unlock_slow + stwcx. r5,0,r3 + bne- L_mutex_unlock_loop + sync + blr +L_mutex_unlock_slow: +#endif PROLOG(0) #if ETAP_LOCK_TRACE @@ -1224,13 +1274,14 @@ mutex_failed3: muGotInt: - lhz r10,MUTEX_WAITERS(r3) /* are there any waiters ? */ - cmpwi r10,0 + lhz r5,LOCK_DATA(r3) + mr. r5,r5 /* are there any waiters ? */ beq+ muUnlock /* Nope, we're done... */ bl EXT(mutex_unlock_wakeup) /* yes, wake a thread */ lwz r3,FM_ARG0(r1) /* restore r3 (saved in prolog) */ - li r10,0 /* Get unlock value */ + lhz r5,LOCK_DATA(r3) /* load the wait count */ + subi r5,r5,1 muUnlock: #if MACH_LDEBUG @@ -1240,7 +1291,7 @@ muUnlock: mfsprg r9,0 lwz r9,PP_CPU_DATA(r9) lwz r9,CPU_ACTIVE_THREAD(r9) - stw r10,MUTEX_THREAD(r3) /* disown thread */ + stw r9,MUTEX_THREAD(r3) /* disown thread */ cmpwi r9,0 beq- .L_mu_no_active_thread lwz r8,THREAD_MUTEX_COUNT(r9) @@ -1250,16 +1301,12 @@ muUnlock: mtmsr r11 #endif /* MACH_LDEBUG */ - stw r10,MUTEX_LOCKED(r3) /* release the mutex */ + rlwinm r5,r5,16,0,15 /* Shift wait count */ sync /* Make sure it's all there before we release */ - stw r10,MUTEX_ILK(r3) /* unlock the interlock */ + stw r5,LOCK_DATA(r3) /* unlock the interlock and lock */ EPILOG /* Deal with the stack now, enable_preemption doesn't always want one */ -#if MACH_RT b epStart /* Go enable preemption... */ -#else - blr /* Return... */ -#endif /* * void interlock_unlock(hw_lock_t lock) @@ -1276,17 +1323,13 @@ LEXT(interlock_unlock) oris r0,r0,LOW_ADDR(CutTrace) /* (TEST/DEBUG) */ sc /* (TEST/DEBUG) */ #endif - li r10,0 + lwz r10,LOCK_DATA(r3) + rlwinm r10,r10,0,0,30 sync - stw r10,0(r3) + stw r10,LOCK_DATA(r3) -#if MACH_RT b epStart /* Go enable preemption... */ -#else - blr /* Return... */ -#endif -#if MACH_RT /* * Here is where we enable preemption. We need to be protected * against ourselves, we can't chance getting interrupted and modifying @@ -1554,4 +1597,96 @@ LEXT(get_simple_lock_count) mtmsr r9 /* Restore interruptions to entry */ blr /* Return... */ -#endif /* MACH_RT */ +/* + * fast_usimple_lock(): + * + * If EE is off, get the simple lock without incrementing the preemption count and + * mark The simple lock with SLOCK_FAST. + * If EE is on, call usimple_lock(). + */ + .align 5 + .globl EXT(fast_usimple_lock) + +LEXT(fast_usimple_lock) + + mfmsr r9 + andi. r7,r9,lo16(MASK(MSR_EE)) + bne- L_usimple_lock_c +L_usimple_lock_loop: + lwarx r4,0,r3 + li r5,ILK_LOCKED|SLOCK_FAST + mr. r4,r4 + bne- L_usimple_lock_c + stwcx. r5,0,r3 + bne- L_usimple_lock_loop + isync + blr +L_usimple_lock_c: + b EXT(usimple_lock) + +/* + * fast_usimple_lock_try(): + * + * If EE is off, try to get the simple lock. The preemption count doesn't get incremented and + * if successfully held, the simple lock is marked with SLOCK_FAST. + * If EE is on, call usimple_lock_try() + */ + .align 5 + .globl EXT(fast_usimple_lock_try) + +LEXT(fast_usimple_lock_try) + + mfmsr r9 + andi. r7,r9,lo16(MASK(MSR_EE)) + bne- L_usimple_lock_try_c +L_usimple_lock_try_loop: + lwarx r4,0,r3 + li r5,ILK_LOCKED|SLOCK_FAST + mr. r4,r4 + bne- L_usimple_lock_try_fail + stwcx. r5,0,r3 + bne- L_usimple_lock_try_loop + li r3,1 + isync + blr +L_usimple_lock_try_fail: + li r3,0 + blr +L_usimple_lock_try_c: + b EXT(usimple_lock_try) + +/* + * fast_usimple_unlock(): + * + * If the simple lock is marked SLOCK_FAST, release it without decrementing the preemption count. + * Call usimple_unlock() otherwise. + */ + .align 5 + .globl EXT(fast_usimple_unlock) + +LEXT(fast_usimple_unlock) + + lwz r5,LOCK_DATA(r3) + li r0,0 + cmpi cr0,r5,ILK_LOCKED|SLOCK_FAST + bne- L_usimple_unlock_c + sync +#if 0 + mfmsr r9 + andi. r7,r9,lo16(MASK(MSR_EE)) + beq L_usimple_unlock_cont + lis r3,hi16(L_usimple_unlock_panic) + ori r3,r3,lo16(L_usimple_unlock_panic) + bl EXT(panic) + + .data +L_usimple_unlock_panic: + STRINGD "fast_usimple_unlock: interrupts not disabled\n\000" + .text +L_usimple_unlock_cont: +#endif + stw r0, LOCK_DATA(r3) + blr +L_usimple_unlock_c: + b EXT(usimple_unlock) + diff --git a/osfmk/ppc/hw_vm.s b/osfmk/ppc/hw_vm.s index c0e8c75c8..18b11ef36 100644 --- a/osfmk/ppc/hw_vm.s +++ b/osfmk/ppc/hw_vm.s @@ -2685,6 +2685,9 @@ rbChk: mr r12,r10 ; Save the previous rbnFirst: bne- rbPerm ; This is permanent, do not remove... lwz r8,bmspace(r10) ; Get the VSID stw r2,bmnext(r12) ; Unchain us + + sync + stw r9,0(r3) ; Unlock and chain the new first one eqv r4,r4,r4 ; Fill the bottom with foxes mfspr r12,sdr1 ; Get hash table base and size @@ -2799,7 +2802,6 @@ rbits603a: sync ; Wait for quiet again sync ; Make sure that is done - stw r9,0(r3) ; Unlock and chain the new first one mtmsr r0 ; Restore xlation and rupts mr r3,r10 ; Pass back the removed block isync diff --git a/osfmk/ppc/interrupt.c b/osfmk/ppc/interrupt.c index 5e72b712a..3e08c2538 100644 --- a/osfmk/ppc/interrupt.c +++ b/osfmk/ppc/interrupt.c @@ -47,7 +47,7 @@ struct ppc_saved_state * interrupt( { int current_cpu, tmpr, targtemp; unsigned int throttle; - AbsoluteTime now; + uint64_t now; thread_act_t act; disable_preemption(); @@ -110,11 +110,10 @@ struct ppc_saved_state * interrupt( #endif act = current_act(); /* Find ourselves */ - if(act->mact.qactTimer.hi | act->mact.qactTimer.lo) { /* Is the timer set? */ + if(act->mact.qactTimer != 0) { /* Is the timer set? */ clock_get_uptime(&now); /* Find out what time it is */ - if (CMP_ABSOLUTETIME(&act->mact.qactTimer, &now) <= 0) { /* It is set, has it popped? */ - act->mact.qactTimer.hi = 0; /* Clear single shot timer */ - act->mact.qactTimer.lo = 0; /* and the other half */ + if (act->mact.qactTimer <= now) { /* It is set, has it popped? */ + act->mact.qactTimer = 0; /* Clear single shot timer */ if((unsigned int)act->mact.vmmControl & 0xFFFFFFFE) { /* Are there any virtual machines? */ vmm_timer_pop(act); /* Yes, check out them out... */ } diff --git a/osfmk/ppc/lock.h b/osfmk/ppc/lock.h index ec40b5f43..8748bf8ac 100644 --- a/osfmk/ppc/lock.h +++ b/osfmk/ppc/lock.h @@ -53,21 +53,26 @@ * the rights to redistribute these changes. */ -#ifndef _PPC_HW_LOCK_H_ -#define _PPC_HW_LOCK_H_ +#ifndef _PPC_LOCK_H_ +#define _PPC_LOCK_H_ #include <kern/macro_help.h> #include <kern/assert.h> -#define NEED_ATOMIC 1 +extern unsigned int LockTimeOut; /* Number of hardware ticks of a lock timeout */ -#define mutex_try _mutex_try -#define mutex_lock(m) \ -MACRO_BEGIN \ - assert(assert_wait_possible()); \ - _mutex_lock((m)); \ -MACRO_END +#if defined(MACH_KERNEL_PRIVATE) && !(NCPUS == 1 && !ETAP_LOCK_TRACE && !USLOCK_DEBUG) +extern void fast_usimple_lock(usimple_lock_t); +extern void fast_usimple_unlock(usimple_lock_t); +extern unsigned int fast_usimple_lock_try(usimple_lock_t); -extern unsigned int LockTimeOut; /* Number of hardware ticks of a lock timeout */ +#define simple_lock_init(l,t) usimple_lock_init(l,t) +#define simple_lock(l) fast_usimple_lock(l) +#define simple_unlock(l) fast_usimple_unlock(l) +#define simple_lock_try(l) fast_usimple_lock_try(l) +#define simple_lock_addr(l) (&(l)) +#define __slock_held_func__(l) usimple_lock_held(l) + +#endif -#endif /* _PPC_HW_LOCK_H_ */ +#endif /* _PPC_LOCK_H_ */ diff --git a/osfmk/ppc/lowmem_vectors.s b/osfmk/ppc/lowmem_vectors.s index acf0d31d7..7ba5621f5 100644 --- a/osfmk/ppc/lowmem_vectors.s +++ b/osfmk/ppc/lowmem_vectors.s @@ -243,54 +243,111 @@ resetexc: li r11,T_RESERVED /* Set 'rupt code */ b .L_exception_entry /* Join common... */ -/* - * System call - generated by the sc instruction - */ +#if 0 +hackxxxx1: + stmw r29,4(br0) + lwz r29,0(br0) + mr. r29,r29 + bne+ xxxx1 + lis r29,0x4000 + +xxxx1: + stw r0,0(r29) + mfsrr0 r30 + stw r30,4(r29) + mtlr r30 + stw r30,8(r29) + + addi r29,r29,12 + stw r29,0(br0) + + lmw r29,4(br0) + b hackxxxx2 +#endif + + +; +; System call - generated by the sc instruction +; +; We handle the ultra-fast traps right here. They are: +; +; 0xFFFFFFFF - BlueBox only - MKIsPreemptiveTask +; 0xFFFFFFFE - BlueBox only - kcNKIsPreemptiveTaskEnv +; 0x00007FF2 - User state only - thread info +; 0x00007FF3 - User state only - floating point / vector facility status +; 0x00007FF4 - Kernel only - loadMSR +; +; Note: none handled if virtual machine is running +; . = 0xC00 .L_handlerC00: - mtsprg 3,r11 ; Save R11 mtsprg 2,r13 ; Save R13 + mfsrr1 r13 ; Get SRR1 for loadMSR + mtsprg 3,r11 ; Save R11 mfcr r11 ; Save the CR + rlwinm. r13,r13,0,MSR_PR_BIT,MSR_PR_BIT ; From problem state? + mfsprg r13,0 ; Get the per_proc_area + beq- uftInKern ; We are in the kernel... + + cmplwi cr5,r0,0x7FF2 ; Ultra fast path cthread info call? + cmpwi cr6,r0,0x7FF3 ; Ultra fast path facility status? + cror cr1_eq,cr5_lt,cr6_gt ; Set true if not 0x7FF2 and not 0x7FF3 and not negative + lwz r13,spcFlags(r13) ; Get the special flags + bt- cr1_eq,notufp ; Exit if we can not be ultra fast... + + rlwimi r13,r13,runningVMbit+1,31,31 ; Move VM flag after the 3 blue box flags + not. r0,r0 ; Flip bits and kind of subtract 1 + mtcrf 1,r13 ; Set BB and VMM flags in CR7 + + cmplwi cr1,r0,1 ; Is this a bb fast path? + not r0,r0 ; Restore to entry state + bt- 31,notufp ; No fast paths if running VM (assume not)... + bf- bbNoMachSCbit,ufpUSuft ; We are not running BlueBox... + bgt cr1,notufp ; This can not be a bb ufp... +#if 0 + b hackxxxx1 +hackxxxx2: +#endif -; Note: this first compare takes care of almost all of the non-fast paths -; BSD system calls are negative and, platform-specific and mach system -; calls are all less than 0x7000. -; -; Note that 0x7FF2 and 0x7FF3 are user state only and do not need to set sprg2. + rlwimi r11,r13,bbPreemptivebit-cr0_eq,cr0_eq,cr0_eq ; Copy preemptive task flag into user cr0_eq + mfsprg r13,0 ; Get back pre_proc + + + bne cr1,ufpIsBBpre ; This is the "isPreemptiveTask" call... + + lwz r0,ppbbTaskEnv(r13) ; Get the shadowed taskEnv from per_proc_area - cmpwi r0,0x7FF2 ; Ultra fast path cthread info call? - blt+ notufp ; Not ultra fast... - mfsprg r13,0 ; Get the per_proc_area - cmplwi cr1,r0,0x7FF4 ; Ultra fast path fp/vec facility state? - bgt+ cr1,notufp ; Not ultra fast... - beq+ cr1,scloadmsr ; It is the load msr guy... - lwz r13,spcFlags(r13) ; Get the facility status - rlwinm. r13,r13,0,runningVMbit,runningVMbit ; Are we running a VM right now? - bne- notufp ; Yes, no fast trap allowed... +ufpIsBBpre: + mtcrf 0xFF,r11 ; Restore CR + mfsprg r11,3 ; Restore R11 + mfsprg r13,2 ; Restore R13 + rfi ; All done, go back... +; +; Normal fast path... +; + +ufpUSuft: bge+ notufp ; Bail if negative... (ARRRGGG -- BRANCH TO A BRANCH!!!!!) mfsprg r11,3 ; Restore R11 mfsprg r3,0 ; Get the per_proc_area mfsprg r13,2 ; Restore R13 - beq- cr1,isvecfp ; This is the facility stat call + bne- cr5,isvecfp ; This is the facility stat call lwz r3,UAW(r3) ; Get the assist word rfi ; All done, scream back... (no need to restore CR or R11, they are volatile) ; isvecfp: lwz r3,spcFlags(r3) ; Get the facility status rfi ; Bail back... ; - .align 5 -notufp: mtcrf 0xC0,r11 ; Restore the used CRs +notufp: mtcrf 0xFF,r11 ; Restore the used CRs li r11,T_SYSTEM_CALL ; Set interrupt code mfsprg r13,1 ; Get the exception save area b .L_exception_entry ; Join common... -scloadmsr: mfsrr1 r13 ; Get the old SRR - rlwinm. r13,r13,0,MSR_PR_BIT,MSR_PR_BIT ; From problem state? - mfsprg r13,0 ; Restore per_proc +uftInKern: cmplwi r0,0x7FF4 ; Ultra fast path loadMSR? bne- notufp ; Someone is trying to cheat... - mtcrf 0xC0,r11 ; Restore CR + mtcrf 0xFF,r11 ; Restore CR lwz r11,pfAvailable(r13) ; Pick up the feature flags mtsrr1 r3 ; Set new MSR mfsprg r13,2 ; Restore R13 @@ -342,26 +399,16 @@ specbrtr: mfsprg r13,0 ; Get the per_proc area stw r2,emfp0+4(r13) ; Save in a scratch area stw r3,emfp0+8(r13) ; Save in a scratch area - lwz r1,spcTRc(r13) ; Pick up the count lis r2,hi16(EXT(pc_trace_buf)) ; Get the top of the buffer - subi r1,r1,1 ; Count down lwz r3,spcTRp(r13) ; Pick up buffer position mr. r1,r1 ; Is it time to count? ori r2,r2,lo16(EXT(pc_trace_buf)) ; Get the bottom of the buffer - cmplwi cr1,r3,4092 ; Set cr1_eq if we should take exception - ble+ spclogpc ; We are logging this one... - cmplwi cr1,r2,0 ; Set cr1_eq false so we do not take an interrupt - b spcskip ; Fly away... - -spclogpc: mfsrr0 r1 ; Get the pc + cmplwi cr1,r3,4092 ; Set cr1_eq if we should take exception + mfsrr0 r1 ; Get the pc stwx r1,r2,r3 ; Save it in the buffer addi r3,r3,4 ; Point to the next slot - li r1,2 ; Number of branches to skip rlwinm r3,r3,0,20,31 ; Wrap the slot at one page stw r3,spcTRp(r13) ; Save the new slot - -spcskip: stw r1,spcTRc(r13) ; Save the new count - lwz r1,emfp0(r13) ; Restore work register lwz r2,emfp0+4(r13) ; Restore work register lwz r3,emfp0+8(r13) ; Restore work register @@ -1296,6 +1343,7 @@ mpwait2x: lwarx r4,0,r8 /* (TEST/DEBUG) */ currbad: lis r23,hi16(EXT(debugbackpocket)) /* (TEST/DEBUG) */ ori r23,r23,lo16(EXT(debugbackpocket)) /* (TEST/DEBUG) */ + lwz r23,0(r23) ; (TEST/DEBUG) stw r23,SVfree(r8) /* (TEST/DEBUG) */ mfsprg r25,1 /* (TEST/DEBUG) */ @@ -1937,6 +1985,33 @@ tempisok: lis r30,HIGH_ADDR(EXT(saveanchor)) /* Get the high part of the anchor stw r0,PP_QUICKFRET(r2) /* Clear quickfret pointer */ ori r30,r30,LOW_ADDR(EXT(saveanchor)) /* Bottom half of the anchor */ dcbt 0,r21 /* Touch in the first thing */ + +#if 0 + li r23,0 ; (TEST/DEBUG) + rlwinm r14,r31,0,0,19 ; (TEST/DEBUG) + lwz r21,SACflags(r14) ; (TEST/DEBUG) + rlwinm r22,r21,24,24,31 ; (TEST/DEBUG) + cmplwi r22,0x00EE ; (TEST/DEBUG) + beq+ nodienodie1 ; (TEST/DEBUG) + +dodiedodie: li r1,0x666 ; (TEST/DEBUG) + BREAKPOINT_TRAP ; (TEST/DEBUG) + +nodienodie1: + mr r23,r19 ; (TEST/DEBUG) + +chkitagain: mr. r23,r23 ; (TEST/DEBUG) + beq nodienodie2 ; (TEST/DEBUG) + rlwinm r14,r23,0,0,19 ; (TEST/DEBUG) + lwz r21,SACflags(r14) ; (TEST/DEBUG) + rlwinm r22,r21,24,24,31 ; (TEST/DEBUG) + cmplwi r22,0x00EE ; (TEST/DEBUG) + bne- dodiedodie ; (TEST/DEBUG) + lwz r23,SAVqfret(r23) ; (TEST/DEBUG) + b chkitagain ; (TEST/DEBUG) + +nodienodie2: +#endif #if TRCSAVE beq- cr5,trkill0 ; (TEST/DEBUG) Do not trace this type @@ -2098,13 +2173,16 @@ donefret: lwz r26,savesrr1(r31) ; Get destination state flags .align 5 gotouser: dcbt r14,r7 ; Touch the segment register contents - lwz r16,PP_LASTPMAP(r7) ; Pick up the last loaded pmap + lwz r9,spcFlags(r2) ; Pick up the special flags + lwz r16,PP_LASTPMAP(r2) ; Pick up the last loaded pmap addi r14,r14,32 ; Second half of pmap segments - lwz r13,PMAP_VFLAGS(r7) ; Get the flags + rlwinm r9,r9,userProtKeybit-2,2,2 ; Isolate the user state protection key lwz r15,PMAP_SPACE(r7) ; Get the primary space + lwz r13,PMAP_VFLAGS(r7) ; Get the flags dcbt r14,r7 ; Touch second page - mtcrf 0x0F,r13 ; Set CRs to correspond to the subordinate spaces oris r15,r15,hi16(SEG_REG_PROT) ; Set segment 0 SR value + mtcrf 0x0F,r13 ; Set CRs to correspond to the subordinate spaces + xor r15,r15,r9 ; Flip to proper segment register key lhz r9,PP_CPU_FLAGS(r2) ; Get the processor flags addis r13,r15,0x0000 ; Get SR0 value @@ -2121,7 +2199,7 @@ nlsr0: mtsr sr0,r13 ; Load up the SR nlsr1: mtsr sr1,r13 ; Load up the SR or r26,r26,r9 ; Flip on the BE bit for special trace if needed - cmplw cr3,r7,r16 ; Are we running the same segs as last time? + cmplw r7,r16 ; Are we running the same segs as last time? addis r13,r15,0x0020 ; Get SR2 value bf 18,nlsr2 ; No alternate here... @@ -2143,6 +2221,8 @@ nlsr14: mtsr sr14,r13 ; Load up the SR beq+ segsdone ; All done if same pmap as last time... + stw r7,PP_LASTPMAP(r2) ; Remember what we just loaded + addis r13,r15,0x0040 ; Get SR4 value bf 20,nlsr4 ; No alternate here... lwz r13,PMAP_SEGS+(4*4)(r7) ; Get SR4 value diff --git a/osfmk/ppc/machine_routines.c b/osfmk/ppc/machine_routines.c index 8333d637c..ad124b421 100644 --- a/osfmk/ppc/machine_routines.c +++ b/osfmk/ppc/machine_routines.c @@ -30,7 +30,6 @@ #include <kern/processor.h> boolean_t get_interrupts_enabled(void); -extern boolean_t set_interrupts_enabled(boolean_t); /* Map memory map IO space */ vm_offset_t @@ -120,10 +119,7 @@ void ml_install_interrupt_handler( per_proc_info[current_cpu].interrupt_handler = handler; per_proc_info[current_cpu].interrupt_refCon = refCon; - per_proc_info[current_cpu].get_interrupts_enabled - = get_interrupts_enabled; - per_proc_info[current_cpu].set_interrupts_enabled - = set_interrupts_enabled; + per_proc_info[current_cpu].interrupts_enabled = TRUE; (void) ml_set_interrupts_enabled(current_state); } @@ -136,10 +132,7 @@ void ml_init_interrupt(void) current_state = ml_get_interrupts_enabled(); current_cpu = cpu_number(); - per_proc_info[current_cpu].get_interrupts_enabled - = get_interrupts_enabled; - per_proc_info[current_cpu].set_interrupts_enabled - = set_interrupts_enabled; + per_proc_info[current_cpu].interrupts_enabled = TRUE; (void) ml_set_interrupts_enabled(current_state); } @@ -170,7 +163,10 @@ boolean_t fake_set_interrupts_enabled(boolean_t enable) /* Get Interrupts Enabled */ boolean_t ml_get_interrupts_enabled(void) { - return(per_proc_info[cpu_number()].get_interrupts_enabled()); + if (per_proc_info[cpu_number()].interrupts_enabled == TRUE) + return(get_interrupts_enabled()); + else + return(fake_get_interrupts_enabled()); } boolean_t get_interrupts_enabled(void) @@ -178,20 +174,16 @@ boolean_t get_interrupts_enabled(void) return((mfmsr() & MASK(MSR_EE)) != 0); } -/* Set Interrupts Enabled */ -boolean_t ml_set_interrupts_enabled(boolean_t enable) -{ - return(per_proc_info[cpu_number()].set_interrupts_enabled(enable)); -} - /* Check if running at interrupt context */ boolean_t ml_at_interrupt_context(void) { - /* - * If running at interrupt context, the current thread won't be - * dispatched on another cpu. There is no need to turn off preemption. - */ - return (per_proc_info[cpu_number()].istackptr == 0); + boolean_t ret; + boolean_t current_state; + + current_state = ml_set_interrupts_enabled(FALSE); + ret = (per_proc_info[cpu_number()].istackptr == 0); + ml_set_interrupts_enabled(current_state); + return(ret); } /* Generate a fake interrupt */ @@ -200,15 +192,9 @@ void ml_cause_interrupt(void) CreateFakeIO(); } -void machine_clock_assist(void) -{ - if (per_proc_info[cpu_number()].get_interrupts_enabled == fake_get_interrupts_enabled) - CreateFakeDEC(); -} - void machine_idle(void) { - if (per_proc_info[cpu_number()].get_interrupts_enabled != fake_get_interrupts_enabled) { + if (per_proc_info[cpu_number()].interrupts_enabled == TRUE) { int cur_decr; machine_idle_ppc(); @@ -324,8 +310,7 @@ void cause_ast_check(processor_t processor) { if ((processor != current_processor()) - && (per_proc_info[processor->slot_num].get_interrupts_enabled - != fake_get_interrupts_enabled)) + && (per_proc_info[processor->slot_num].interrupts_enabled == TRUE)) cpu_signal(processor->slot_num, SIGPast, NULL, NULL); } @@ -374,3 +359,4 @@ be_tracing() int mycpu = cpu_number(); return(per_proc_info[mycpu].cpu_flags & traceBE); } + diff --git a/osfmk/ppc/machine_routines_asm.s b/osfmk/ppc/machine_routines_asm.s index b67ea1091..b8a70201c 100644 --- a/osfmk/ppc/machine_routines_asm.s +++ b/osfmk/ppc/machine_routines_asm.s @@ -248,23 +248,26 @@ LEXT(ml_phys_write) */ ; Force a line boundry here - .align 5 - .globl EXT(set_interrupts_enabled) - -LEXT(set_interrupts_enabled) + .align 5 + .globl EXT(ml_set_interrupts_enabled) + +LEXT(ml_set_interrupts_enabled) + mfsprg r7,0 + lwz r4,PP_INTS_ENABLED(r7) + mr. r4,r4 + beq- EXT(fake_set_interrupts_enabled) mfmsr r5 ; Get the current MSR mr r4,r3 ; Save the old value rlwinm r3,r5,17,31,31 ; Set return value rlwimi r5,r4,15,16,16 ; Insert new EE bit - andi. r7,r5,lo16(MASK(MSR_EE)) ; Interruptions + andi. r8,r5,lo16(MASK(MSR_EE)) ; Interruptions bne CheckPreemption NoPreemption: mtmsr r5 ; Slam enablement blr CheckPreemption: - mfsprg r7,0 lwz r8,PP_NEED_AST(r7) lwz r7,PP_CPU_DATA(r7) li r6,AST_URGENT @@ -281,6 +284,24 @@ CheckPreemption: blr +/* Emulate a decremeter exception + * + * void machine_clock_assist(void) + * + */ + +; Force a line boundry here + .align 5 + .globl EXT(machine_clock_assist) + +LEXT(machine_clock_assist) + + mfsprg r7,0 + lwz r4,PP_INTS_ENABLED(r7) + mr. r4,r4 + beq- EXT(CreateFakeDEC) + blr + /* Set machine into idle power-saving mode. * * void machine_idle_ppc(void) @@ -537,7 +558,7 @@ LEXT(cacheInit) mfsprg r11,2 ; Get CPU specific features mfmsr r7 ; Get the current MSR rlwinm r4,r9,0,dpm+1,doze-1 ; Clear all possible power-saving modes (also disable DPM) - rlwimi r11,r11,pfL23lckb+1,31,31 ; Move pfL23lck to another position (to keep from using non-volatile CRs) + rlwimi r11,r11,pfLClckb+1,31,31 ; Move pfLClck to another position (to keep from using non-volatile CRs) rlwinm r5,r7,0,MSR_DR_BIT+1,MSR_IR_BIT-1 ; Turn off translation rlwinm r5,r5,0,MSR_EE_BIT+1,MSR_EE_BIT-1 ; Turn off interruptions mtcrf 0x87,r11 ; Get the feature flags @@ -565,7 +586,6 @@ cinoDSS: lis r5,hi16(EXT(tlb_system_lock)) ; Get the TLBIE lock ori r5,r5,lo16(EXT(tlb_system_lock)) ; Grab up the bottom part li r6,0 ; Start at 0 - lwarx r2,0,r5 ; ? citlbhang: lwarx r2,0,r5 ; Get the TLBIE lock mr. r2,r2 ; Is it locked? @@ -621,7 +641,74 @@ ciwdl1f: mfspr r8,msscr0 ; Get the control register again ; ciswdl1: lwz r0,pfl1dSize(r12) ; Get the level 1 cache size - rlwinm r2,r0,0,1,30 ; Double it + + bf 31,cisnlck ; Skip if pfLClck not set... + + mfspr r4,msscr0 ; ? + rlwinm r6,r4,0,0,l2pfes-1 ; ? + mtspr msscr0,r6 ; Set it + sync + isync + + mfspr r8,ldstcr ; Save the LDSTCR + li r2,1 ; Get a mask of 0x01 + lis r3,0xFFF0 ; Point to ROM + rlwinm r11,r0,29,3,31 ; Get the amount of memory to handle all indexes + + li r6,0 ; Start here + +cisiniflsh: dcbf r6,r3 ; Flush each line of the range we use + addi r6,r6,32 ; Bump to the next + cmplw r6,r0 ; Have we reached the end? + blt+ cisiniflsh ; Nope, continue initial flush... + + sync ; Make sure it is done + + addi r11,r11,-1 ; Get mask for index wrap + li r6,0 ; Get starting offset + +cislckit: not r5,r2 ; Lock all but 1 way + rlwimi r5,r8,0,0,23 ; Build LDSTCR + mtspr ldstcr,r5 ; Lock a way + sync ; Clear out memory accesses + isync ; Wait for all + + +cistouch: lwzx r10,r3,r6 ; Pick up some trash + addi r6,r6,32 ; Go to the next index + and. r0,r6,r11 ; See if we are about to do next index + bne+ cistouch ; Nope, do more... + + sync ; Make sure it is all done + isync + + sub r6,r6,r11 ; Back up to start + 1 + addi r6,r6,-1 ; Get it right + +cisflush: dcbf r3,r6 ; Flush everything out + addi r6,r6,32 ; Go to the next index + and. r0,r6,r11 ; See if we are about to do next index + bne+ cisflush ; Nope, do more... + + sync ; Make sure it is all done + isync + + + rlwinm. r2,r2,1,24,31 ; Shift to next way + bne+ cislckit ; Do this for all ways... + + mtspr ldstcr,r8 ; Slam back to original + sync + isync + + mtspr msscr0,r4 ; ? + sync + isync + + b cinoL1 ; Go on to level 2... + + +cisnlck: rlwinm r2,r0,0,1,30 ; Double cache size add r0,r0,r2 ; Get 3 times cache size rlwinm r0,r0,26,6,31 ; Get 3/2 number of cache lines lis r3,0xFFF0 ; Dead recon ROM address for now @@ -637,7 +724,8 @@ ciinvdl1: sync ; Make sure all flushes have been committed rlwinm r8,r8,0,dce+1,ice-1 ; Clear cache enables mtspr hid0,r8 ; and turn off L1 cache sync ; Make sure all is done - + isync + ori r8,r8,lo16(icem|dcem|icfim|dcfim) ; Set the HID0 bits for enable, and invalidate sync isync @@ -646,6 +734,7 @@ ciinvdl1: sync ; Make sure all flushes have been committed rlwinm r8,r8,0,dcfi+1,icfi-1 ; Turn off the invalidate bits mtspr hid0,r8 ; Turn off the invalidate (needed for some older machines) sync + cinoL1: ; @@ -665,7 +754,7 @@ cinoL1: mr r10,r3 ; Take a copy now - bf 31,cinol2lck ; Skip if pfL23lck not set... + bf 31,cinol2lck ; Skip if pfLClck not set... oris r10,r10,hi16(l2ionlym|l2donlym) ; Set both instruction- and data-only sync @@ -686,9 +775,24 @@ cihwfl2: mfspr r10,l2cr ; Get back the L2CR ciswfl2: lwz r0,pfl2Size(r12) ; Get the L2 size oris r2,r3,hi16(l2dom) ; Set L2 to data only mode - mtspr l2cr,r2 ; Go into data only mode - sync ; Clean it up - + + b ciswfl2doa ; Branch to next line... + + .align 5 +ciswfl2doc: + mtspr l2cr,r2 ; Disable L2 + sync + isync + b ciswfl2dod ; It is off, go invalidate it... + +ciswfl2doa: + b ciswfl2dob ; Branch to next... + +ciswfl2dob: + sync ; Finish memory stuff + isync ; Stop speculation + b ciswfl2doc ; Jump back up and turn on data only... +ciswfl2dod: rlwinm r0,r0,27,5,31 ; Get the number of lines lis r10,0xFFF0 ; Dead recon ROM for now mtctr r0 ; Set the number of lines @@ -817,7 +921,10 @@ cinol3: ; Invalidate and turn on L1s ; -cinol2a: rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables +cinol2a: + bt 31,cinoexit ; Skip if pfLClck set... + + rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables mtspr hid0,r8 ; Turn off dem caches sync @@ -827,7 +934,8 @@ cinol2a: rlwinm r8,r9,0,dce+1,ice-1 ; Clear the I- and D- cache enables isync mtspr hid0,r8 ; Start the invalidate and turn on L1 cache - mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) + +cinoexit: mtspr hid0,r9 ; Turn off the invalidate (needed for some older machines) and restore entry conditions sync mtmsr r7 ; Restore MSR to entry isync diff --git a/osfmk/ppc/mappings.c b/osfmk/ppc/mappings.c index 192569f7d..d59d912d9 100644 --- a/osfmk/ppc/mappings.c +++ b/osfmk/ppc/mappings.c @@ -78,12 +78,14 @@ extern unsigned int hash_table_size; extern vm_offset_t mem_size; /* * ppc_prot translates from the mach representation of protections to the PPC version. + * We also allow for a direct setting of the protection bits. This extends the mach + * concepts to allow the greater control we need for Virtual Machines (VMM). * Calculation of it like this saves a memory reference - and maybe a couple of microseconds. * It eliminates the used of this table. - * unsigned char ppc_prot[8] = { 0, 3, 2, 2, 3, 3, 2, 2 }; + * unsigned char ppc_prot[16] = { 0, 3, 2, 2, 3, 3, 2, 2, 0, 1, 2, 3, 0, 1, 2, 3 }; */ -#define ppc_prot(p) ((0xAFAC >> (p << 1)) & 3) +#define ppc_prot(p) ((0xE4E4AFAC >> (p << 1)) & 3) /* * About PPC VSID generation: @@ -254,6 +256,66 @@ boolean_t mapping_remove(pmap_t pmap, vm_offset_t va) { /* Remove a single map return TRUE; /* Tell them we did it */ } +/* + * mapping_purge_pmap(struct phys_entry *pp, pmap_t pmap) - release all mappings for this physent for the specified map + * + * This guy releases any mappings that exist for a physical page on a specified map. + * We get the lock on the phys_entry, and hold it through out this whole routine. + * That way, no one can change the queue out from underneath us. We keep fetching + * the physents mapping anchor until it is null, then we're done. + * + * For each mapping, we call the remove routine to remove it from the PTEG hash list and + * decriment the pmap's residency count. Then we release the mapping back to the free list. + * + */ + + +void mapping_purge_pmap(struct phys_entry *pp, pmap_t pmap) { /* Remove all mappings from specified pmap for this physent */ + + mapping *mp, *mp_next, *mpv; + spl_t s; + unsigned int *useadd, *useaddr, uindx; + int i; + + s=splhigh(); /* Don't bother me */ + + if(!hw_lock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK, LockTimeOut)) { /* Lock the physical entry */ + panic("\nmapping_purge_pmap: Timeout attempting to lock physical entry at %08X: %08X %08X\n", + pp, pp->phys_link, pp->pte1); /* Complain about timeout */ + } + + mp = (mapping *)((unsigned int)pp->phys_link & ~PHYS_FLAGS); + + while(mp) { /* Keep going so long as there's another */ + + mpv = hw_cpv(mp); /* Get the virtual address */ + if(mpv->pmap != pmap) { + mp = ((unsigned int)mpv->next & ~PHYS_FLAGS); + continue; + } +#if DEBUG + if(hw_atomic_sub(&mpv->pmap->stats.resident_count, 1) < 0) panic("pmap resident count went negative\n"); +#else + (void)hw_atomic_sub(&mpv->pmap->stats.resident_count, 1); /* Decrement the resident page count */ +#endif + + uindx = ((mpv->PTEv >> 24) & 0x78) | ((mpv->PTEv >> 3) & 7); /* Join seg # and top 2 bits of API */ + useadd = (unsigned int *)&mpv->pmap->pmapUsage[uindx]; /* Point to slot to bump */ + useaddr = (unsigned int *)((unsigned int)useadd & -4); /* Round down to word */ + (void)hw_atomic_sub(useaddr, (useaddr == useadd) ? 0x00010000 : 1); /* Incr the even or odd slot */ + + + + mp_next = (mapping *)((unsigned int)mpv->next & ~PHYS_FLAGS); + hw_rem_map(mp); /* Remove the mapping */ + mapping_free(mpv); /* Add mapping to the free list */ + mp = mp_next; + } + + hw_unlock_bit((unsigned int *)&pp->phys_link, PHYS_LOCK); /* We're done, unlock the physical entry */ + splx(s); + return; +} /* * mapping_purge(struct phys_entry *pp) - release all mappings for this physent to the free list * diff --git a/osfmk/ppc/mappings.h b/osfmk/ppc/mappings.h index ebe99b036..6b780c344 100644 --- a/osfmk/ppc/mappings.h +++ b/osfmk/ppc/mappings.h @@ -90,6 +90,13 @@ typedef struct blokmap { #define MAPPING_NULL ((struct mapping *) 0) +#define mapDirect 0x08 +#define mapRWNA 0x00000000 +#define mapRWRO 0x00000001 +#define mapRWRW 0x00000002 +#define mapRORO 0x00000003 + + typedef struct mappingctl { unsigned int mapclock; /* Mapping allocation lock */ unsigned int mapcrecurse; /* Mapping allocation recursion control */ @@ -141,6 +148,7 @@ extern void mapping_protect_phys(struct phys_entry *pp, vm_prot_t prot, boolea extern void mapping_protect(pmap_t pmap, vm_offset_t vaddr, vm_prot_t prot); /* Change protection of a single mapping to page */ extern mapping *mapping_make(pmap_t pmap, struct phys_entry *pp, vm_offset_t va, vm_offset_t pa, vm_prot_t prot, int attr, boolean_t locked); /* Make an address mapping */ extern void mapping_purge(struct phys_entry *pp); /* Remove all mappings for this physent */ +extern void mapping_purge_pmap(struct phys_entry *pp, pmap_t pmap); /* Remove physent mappings for this pmap */ extern vm_offset_t mapping_p2v(pmap_t pmap, struct phys_entry *pp); /* Finds first virtual mapping of a physical page in a space */ extern void mapping_phys_attr(struct phys_entry *pp, vm_prot_t prot, unsigned int wimg); /* Sets the default physical page attributes */ extern void mapping_block_map_opt(pmap_t pmap, vm_offset_t va, vm_offset_t pa, vm_offset_t bnd, vm_size_t size, vm_prot_t prot, int attr); /* Map a block optimally */ diff --git a/osfmk/ppc/misc.c b/osfmk/ppc/misc.c index 8caaf5d6c..82d0471f4 100644 --- a/osfmk/ppc/misc.c +++ b/osfmk/ppc/misc.c @@ -110,6 +110,8 @@ int copyout_multiple(const char *src, char *dst, vm_size_t count) return copyout(src + first_count, midpoint, count-first_count); } +#define HAVE_ASSEMBLY_BCMP +#ifndef HAVE_ASSEMBLY_BCMP int bcmp( const char *a, const char *b, @@ -125,6 +127,41 @@ int bcmp( return len; } +#endif /* HAVE_ASSEMBLY_BCMP */ + +#define HAVE_ASSEMBLY_MEMCMP +#ifndef HAVE_ASSEMBLY_MEMCMP +int +memcmp(s1, s2, n) + register char *s1, *s2; + register n; +{ + while (--n >= 0) + if (*s1++ != *s2++) + return (*--s1 - *--s2); + return (0); +} +#endif /* HAVE_ASSEMBLY_MEMCMP */ + +#define HAVE_ASSEMBLY_STRLEN +#ifndef HAVE_ASSEMBLY_STRLEN +/* + * Abstract: + * strlen returns the number of characters in "string" preceeding + * the terminating null character. + */ + +size_t +strlen( + register const char *string) +{ + register const char *ret = string; + + while (*string++ != '\0') + continue; + return string - 1 - ret; +} +#endif /* HAVE_ASSEMBLY_STRLEN */ #if DEBUG void regDump(struct ppc_saved_state *state) @@ -168,7 +205,7 @@ void regDump(struct ppc_saved_state *state) } #endif /* DEBUG */ -#ifdef 0 +#if 0 /* * invalidate_cache_for_io * diff --git a/osfmk/ppc/model_dep.c b/osfmk/ppc/model_dep.c index 970e9b156..dbc07fd51 100644 --- a/osfmk/ppc/model_dep.c +++ b/osfmk/ppc/model_dep.c @@ -126,6 +126,7 @@ char env_buf[256]; */ decl_simple_lock_data(, debugger_lock) /* debugger lock */ +decl_simple_lock_data(, pbtlock) /* backtrace print lock */ int debugger_cpu = -1; /* current cpu running debugger */ int debugger_debug = 0; /* Debug debugger */ @@ -137,6 +138,10 @@ int db_run_mode; /* Debugger run mode */ unsigned int debugger_sync = 0; /* Cross processor debugger entry sync */ extern unsigned int NMIss; /* NMI debounce switch */ +extern volatile int panicwait; +volatile unsigned int pbtcnt = 0; +volatile unsigned int pbtcpu = -1; + unsigned int lastTrace; /* Value of low-level exception trace controls */ volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus holding @@ -144,6 +149,8 @@ volatile unsigned int cpus_holding_bkpts; /* counter for number of cpus holding insert back breakpoints) */ void unlock_debugger(void); void lock_debugger(void); +void dump_backtrace(unsigned int stackptr, unsigned int fence); +void dump_savearea(savearea *sv, unsigned int fence); #if !MACH_KDB boolean_t db_breakpoints_inserted = TRUE; @@ -165,7 +172,21 @@ extern int kdp_flag; boolean_t db_im_stepping = 0xFFFFFFFF; /* Remember if we were stepping */ + +char *failNames[] = { + + "Debugging trap", /* failDebug */ + "Corrupt stack", /* failStack */ + "Corrupt mapping tables", /* failMapping */ + "Corrupt context", /* failContext */ + "Unknown failure code" /* Unknown failure code - must always be last */ +}; + +char *invxcption = "Unknown code"; + extern const char version[]; +extern char *trap_type[]; +extern vm_offset_t mem_actual; #if !MACH_KDB void kdb_trap(int type, struct ppc_saved_state *regs); @@ -201,7 +222,8 @@ machine_startup(boot_args *args) if (boot_arg & DB_SLOG) systemLogDiags=TRUE; } - hw_lock_init(&debugger_lock); /* initialized debugger lock */ + hw_lock_init(&debugger_lock); /* initialize debugger lock */ + hw_lock_init(&pbtlock); /* initialize print backtrace lock */ #if MACH_KDB /* @@ -238,6 +260,21 @@ machine_startup(boot_args *args) kernel_preemption_mode = boot_arg; zone_gc_allowed = FALSE; /* XXX: TO BE REMOVED */ } + if (PE_parse_boot_arg("unsafe", &boot_arg)) { + extern int max_unsafe_quanta; + + max_unsafe_quanta = boot_arg; + } + if (PE_parse_boot_arg("poll", &boot_arg)) { + extern int max_poll_quanta; + + max_poll_quanta = boot_arg; + } + if (PE_parse_boot_arg("yield", &boot_arg)) { + extern int sched_poll_yield_shift; + + sched_poll_yield_shift = boot_arg; + } machine_conf(); @@ -318,52 +355,151 @@ void machine_callstack( void print_backtrace(struct ppc_saved_state *ssp) { - unsigned int *stackptr, *raddr, *rstack, trans; + unsigned int stackptr, *raddr, *rstack, trans, fence; int i, frames_cnt, skip_top_frames, frames_max; unsigned int store[8]; /* Buffer for real storage reads */ vm_offset_t backtrace_entries[32]; + thread_act_t *act; + savearea *sv, *svssp; + int cpu; + +/* + * We need this lock to make sure we don't hang up when we double panic on an MP. + */ + + cpu = cpu_number(); /* Just who are we anyways? */ + if(pbtcpu != cpu) { /* Allow recursion */ + hw_atomic_add(&pbtcnt, 1); /* Remember we are trying */ + while(!hw_lock_try(&pbtlock)); /* Spin here until we can get in. If we never do, well, we're crashing anyhow... */ + pbtcpu = cpu; /* Mark it as us */ + } + + svssp = (savearea *)ssp; /* Make this easier */ + sv = 0; + if(current_thread()) sv = (savearea *)current_act()->mact.pcb; /* Find most current savearea if system has started */ + + fence = 0xFFFFFFFF; /* Show we go all the way */ + if(sv) fence = sv->save_r1; /* Stop at previous exception point */ + + if(!svssp) { /* Should we start from stack? */ + printf("Latest stack backtrace for cpu %d:\n", cpu_number()); + __asm__ volatile("mr %0,r1" : "=r" (stackptr)); /* Get current stack */ + dump_backtrace(stackptr, fence); /* Dump the backtrace */ + if(!sv) { /* Leave if no saveareas */ + printf("\nKernel version:\n%s\n",version); /* Print kernel version */ + hw_lock_unlock(&pbtlock); /* Allow another back trace to happen */ + return; + } + } + else { /* Were we passed an exception? */ + fence = 0xFFFFFFFF; /* Show we go all the way */ + if(svssp->save_prev) fence = svssp->save_prev->save_r1; /* Stop at previous exception point */ + + printf("Latest crash info for cpu %d:\n", cpu_number()); + printf(" Exception state (sv=0x%08x)\n", sv); + dump_savearea(svssp, fence); /* Dump this savearea */ + } - printf("backtrace: "); - frames_cnt =0; - - /* Get our stackpointer for backtrace */ - if (ssp==NULL) { - __asm__ volatile("mr %0, r1" : "=r" (stackptr)); - skip_top_frames = 1; - } else { - stackptr = (unsigned int *)(ssp->r1); - skip_top_frames = 0; - backtrace_entries[frames_cnt] = ssp->srr0; - frames_cnt++; - printf("0x%08x ", ssp->srr0); + if(!sv) { /* Leave if no saveareas */ + printf("\nKernel version:\n%s\n",version); /* Print kernel version */ + hw_lock_unlock(&pbtlock); /* Allow another back trace to happen */ + return; } + + printf("Proceeding back via exception chain:\n"); - frames_max = 32-frames_cnt; - for (i = 0; i < frames_max; i++) { + while(sv) { /* Do them all... */ + printf(" Exception state (sv=0x%08x)\n", sv); + if(sv == svssp) { /* Did we dump it already? */ + printf(" previously dumped as \"Latest\" state. skipping...\n"); + } + else { + fence = 0xFFFFFFFF; /* Show we go all the way */ + if(sv->save_prev) fence = sv->save_prev->save_r1; /* Stop at previous exception point */ + dump_savearea(sv, fence); /* Dump this savearea */ + } + + sv = sv->save_prev; /* Back chain */ + } + + printf("\nKernel version:\n%s\n",version); /* Print kernel version */ + + pbtcpu = -1; /* Mark as unowned */ + hw_lock_unlock(&pbtlock); /* Allow another back trace to happen */ + hw_atomic_sub(&pbtcnt, 1); /* Show we are done */ + + while(pbtcnt); /* Wait for completion */ + + return; +} + +void dump_savearea(savearea *sv, unsigned int fence) { + + char *xcode; + + if(sv->save_exception > T_MAX) xcode = invxcption; /* Too big for table */ + else xcode = trap_type[sv->save_exception / 4]; /* Point to the type */ + + printf(" PC=0x%08X; MSR=0x%08x; DAR=0x%08x; DSISR=0x%08x; LR=0x%08x; R1=0x%08x; XCP=0x%08x (%s)\n", + sv->save_srr0, sv->save_srr1, sv->save_dar, sv->save_dsisr, + sv->save_lr, sv->save_r1, sv->save_exception, xcode); + + if(!(sv->save_srr1 & MASK(MSR_PR))) { /* Are we in the kernel? */ + dump_backtrace(sv->save_r1, fence); /* Dump the stack back trace from here if not user state */ + } + + return; +} - if(!stackptr) break; /* No more to get... */ - /* Avoid causing page fault */ - if (!(raddr = LRA(PPC_SID_KERNEL, (void *)((unsigned int)stackptr+FM_LR_SAVE)))) + +#define DUMPFRAMES 32 +#define LRindex 2 + +void dump_backtrace(unsigned int stackptr, unsigned int fence) { + + unsigned int bframes[DUMPFRAMES]; + unsigned int sframe[8], raddr, dumbo; + int i; + + printf(" Backtrace:\n"); + for(i = 0; i < DUMPFRAMES; i++) { /* Dump up to max frames */ + + if(!stackptr || (stackptr == fence)) break; /* Hit stop point or end... */ + + if(stackptr & 0x0000000f) { /* Is stack pointer valid? */ + printf("\n backtrace terminated - unaligned frame address: 0x%08x\n", stackptr); /* No, tell 'em */ break; - ReadReal((unsigned int)raddr, &store[0]); - if (skip_top_frames) - skip_top_frames--; - else { - backtrace_entries[frames_cnt] = store[0]; - frames_cnt++; - printf("0x%08x ",store[0]); } - if (!(raddr = LRA(PPC_SID_KERNEL, (void *)stackptr))) + + raddr = (unsigned int)LRA(PPC_SID_KERNEL, (void *)stackptr); /* Get physical frame address */ + if(!raddr) { /* Is it mapped? */ + printf("\n backtrace terminated - frame not mapped: 0x%08x\n", stackptr); /* No, tell 'em */ break; - ReadReal((unsigned int)raddr, &store[0]); - stackptr=(unsigned int *)store[0]; + } + + if(raddr >= mem_actual) { /* Is it within physical RAM? */ + printf("\n backtrace terminated - frame outside of RAM: v=0x%08x, p=%08X\n", stackptr, raddr); /* No, tell 'em */ + break; + } + + ReadReal(raddr, &sframe[0]); /* Fetch the stack frame */ + + bframes[i] = sframe[LRindex]; /* Save the link register */ + + if(!i) printf(" "); /* Indent first time */ + else if(!(i & 7)) printf("\n "); /* Skip to new line every 8 */ + printf("0x%08x ", bframes[i]); /* Dump the link register */ + + stackptr = sframe[0]; /* Chain back */ } printf("\n"); - - if (frames_cnt) - kmod_dump((vm_offset_t *)&backtrace_entries[0], frames_cnt); + if(i >= DUMPFRAMES) printf(" backtrace continues...\n"); /* Say we terminated early */ + if(i) kmod_dump((vm_offset_t *)&bframes[0], i); /* Show what kmods are in trace */ + } + + void Debugger(const char *message) { @@ -373,7 +509,7 @@ Debugger(const char *message) { spl_t spl; spl = splhigh(); /* No interruptions from here on */ - + /* * backtrace for Debugger() call from panic() if no current debugger * backtrace and return for double panic() call @@ -383,10 +519,10 @@ Debugger(const char *message) { print_backtrace(NULL); if (nestedpanic != 0) { splx(spl); - return; /* Yeah, don't enter again... */ + return; /* Yeah, don't enter again... */ } } - + if (debug_mode && debugger_active[cpu_number()]) { /* Are we already on debugger on this processor? */ splx(spl); return; /* Yeah, don't do it again... */ @@ -400,7 +536,6 @@ Debugger(const char *message) { } printf("\nNo debugger configured - dumping debug information\n"); - printf("\nversion string : %s\n",version); mfdbatu(store[0],0); mfdbatl(store[1],0); mfdbatu(store[2],1); @@ -419,6 +554,40 @@ Debugger(const char *message) { return; } +/* + * Here's where we attempt to get some diagnostic information dumped out + * when the system is really confused. We will try to get into the + * debugger as well. + * + * We are here with interrupts disabled and on the debug stack. The savearea + * that was passed in is NOT chained to the activation. + * + * save_r3 contains the failure reason code. + */ + +void SysChoked(int type, savearea *sv) { /* The system is bad dead */ + + unsigned int failcode; + + mp_disable_preemption(); + disableDebugOuput = FALSE; + debug_mode = TRUE; + + failcode = sv->save_r3; /* Get the failure code */ + if(failcode > failUnknown) failcode = failUnknown; /* Set unknown code code */ + + kprintf("System Failure: cpu=%d; code=%08X (%s)\n", cpu_number(), sv->save_r3, failNames[failcode]); + printf("System Failure: cpu=%d; code=%08X (%s)\n", cpu_number(), sv->save_r3, failNames[failcode]); + + print_backtrace((struct ppc_saved_state *)sv); /* Attempt to print backtrace */ + Call_DebuggerC(type, sv); /* Attempt to get into debugger */ + + if ((current_debugger != NO_CUR_DB)) Call_DebuggerC(type, sv); /* Attempt to get into debugger */ + +} + + + /* * When we get here, interruptions are disabled and we are on the debugger stack * Never, ever, ever, ever enable interruptions from here on diff --git a/osfmk/ppc/pcb.c b/osfmk/ppc/pcb.c index 9aa01672a..45f05dceb 100644 --- a/osfmk/ppc/pcb.c +++ b/osfmk/ppc/pcb.c @@ -176,13 +176,10 @@ switch_context( (long)__builtin_return_address(0)); #endif per_proc_info[cpu_number()].old_thread = old; + per_proc_info[cpu_number()].cpu_flags &= ~traceBE; /* disable branch tracing if on */ assert(old_act->kernel_loaded || active_stacks[cpu_number()] == old_act->thread->kernel_stack); - if(get_preemption_level() != 1) { /* Make sure we are not at wrong preemption level */ - panic("switch_context: Invalid preemption level (%d); old = %08X, cont = %08X, new = %08X\n", - get_preemption_level(), old, continuation, new); - } check_simple_locks(); /* Our context might wake up on another processor, so we must @@ -190,8 +187,8 @@ switch_context( * so that it can be found by the other if needed */ if(real_ncpus > 1) { /* This is potentially slow, so only do when actually SMP */ - fpu_save(); /* Save floating point if used */ - vec_save(); /* Save vector if used */ + fpu_save(old_act); /* Save floating point if used */ + vec_save(old_act); /* Save vector if used */ } #if DEBUG @@ -240,6 +237,9 @@ switch_context( retval = Switch_context(old, continuation, new); assert(retval != (struct thread_shuttle*)NULL); + if (branch_tracing_enabled()) + per_proc_info[cpu_number()].cpu_flags |= traceBE; /* restore branch tracing */ + /* We've returned from having switched context, so we should be * back in the original context. */ @@ -297,9 +297,6 @@ thread_machine_create( sv->save_vrsave = 0; thr_act->mact.pcb = (pcb_t)sv; /* Point to the save area */ - thread->kernel_stack = (int)stack_alloc(thread,start_pos); /* Allocate our kernel stack */ - assert(thread->kernel_stack); /* Make sure we got it */ - #if MACH_ASSERT if (watchacts & WA_PCB) printf("pcb_init(%x) pcb=%x\n", thr_act, sv); @@ -372,8 +369,8 @@ machine_switch_act( * so that it can be found by the other if needed */ if(real_ncpus > 1) { /* This is potentially slow, so only do when actually SMP */ - fpu_save(); /* Save floating point if used */ - vec_save(); /* Save vector if used */ + fpu_save(old); /* Save floating point if used */ + vec_save(old); /* Save vector if used */ } active_stacks[cpu] = thread->kernel_stack; @@ -883,10 +880,12 @@ stack_handoff(thread_t old, stack = stack_detach(old); new->kernel_stack = stack; + per_proc_info[cpu_number()].cpu_flags &= ~traceBE; + #if NCPUS > 1 if (real_ncpus > 1) { - fpu_save(); - vec_save(); + fpu_save(old->top_act); + vec_save(old->top_act); } #endif @@ -907,6 +906,12 @@ stack_handoff(thread_t old, thread_machine_set_current(new); active_stacks[cpu_number()] = new->kernel_stack; per_proc_info[cpu_number()].Uassist = new->top_act->mact.cthread_self; +#if 1 + per_proc_info[cpu_number()].ppbbTaskEnv = new->top_act->mact.bbTaskEnv; + per_proc_info[cpu_number()].spcFlags = new->top_act->mact.specFlags; +#endif + if (branch_tracing_enabled()) + per_proc_info[cpu_number()].cpu_flags |= traceBE; return; } diff --git a/osfmk/ppc/pmap.c b/osfmk/ppc/pmap.c index e7b6e01f8..5b7bc5b87 100644 --- a/osfmk/ppc/pmap.c +++ b/osfmk/ppc/pmap.c @@ -1091,6 +1091,30 @@ pmap_reference(pmap_t pmap) if (pmap != PMAP_NULL) hw_atomic_add(&pmap->ref_count, 1); /* Bump the count */ } +/* + * pmap_remove_some_phys + * + * Removes mappings of the associated page from the specified pmap + * + */ +void pmap_remove_some_phys( + pmap_t pmap, + vm_offset_t pa) +{ + register struct phys_entry *pp; + register struct mapping *mp, *mpv; + + + if (pmap == PMAP_NULL) return; /* Do nothing if no pmap */ + + pp = pmap_find_physentry(pa); /* Get the physent for this page */ + if (pp == PHYS_NULL) return; /* Leave if not in physical RAM */ + + mapping_purge_pmap(pp, pmap); + + return; /* Leave... */ +} + /* * pmap_remove(pmap, s, e) * unmaps all virtual addresses v in the virtual address @@ -2114,14 +2138,11 @@ kern_return_t pmap_nest(pmap_t grand, pmap_t subord, vm_offset_t vaddr, vm_size_ * Note that the following will force the segment registers to be reloaded following * the next interrupt on all processors if they are using the pmap we just changed. * - * This probably isn't needed, but it just feels better to do it. The reason it isn't - * needed is that there is no mapped memory in the grand pmap's segment before we - * nest and we will take a fault if it is accessed. */ for(i=0; i < real_ncpus; i++) { /* Cycle through processors */ - (void)hw_compare_and_store((unsigned int)grand, 0, &per_proc_info[i].userpmap); /* Clear if ours */ + (void)hw_compare_and_store((unsigned int)grandr, 0, &per_proc_info[i].Lastpmap); /* Clear if ours */ } return KERN_SUCCESS; /* Bye, bye, butterfly... */ @@ -2185,13 +2206,13 @@ kern_return_t pmap_unnest(pmap_t grand, vm_offset_t vaddr, vm_size_t size) { mycpu = cpu_number(); /* Who am I? Am I just a dream? */ for(i=0; i < real_ncpus; i++) { /* Cycle through processors */ - if(hw_compare_and_store((unsigned int)grand, 0, &per_proc_info[i].userpmap)) { /* Clear if ours and kick the other guy if he was using it */ + if(hw_compare_and_store((unsigned int)grandr, 0, &per_proc_info[i].Lastpmap)) { /* Clear if ours and kick the other guy if he was using it */ if(i == mycpu) continue; /* Don't diddle ourselves */ tstamp = per_proc_info[i].ruptStamp[1]; /* Save the processor's last interrupt time stamp */ - if(cpu_signal(i, SIGPwake, 0, 0) != KERN_SUCCESS) { /* Make sure we see the pmap change - panic("pmap_unnest: Signal processor (%d) failed\n", i); + if(cpu_signal(i, SIGPwake, 0, 0) != KERN_SUCCESS) { /* Make sure we see the pmap change */ + continue; } - if(!hw_cpu_wcng(tstamp, &per_proc_info[i].ruptStamp[1], LockTimeOut) { /* Wait for the other processors to enter debug */ + if(!hw_cpu_wcng(&per_proc_info[i].ruptStamp[1], tstamp, LockTimeOut)) { /* Wait for the other processors to enter debug */ panic("pmap_unnest: Other processor (%d) did not see interruption request\n", i); } } diff --git a/osfmk/ppc/ppc_init.c b/osfmk/ppc/ppc_init.c index b527cba05..4219840d4 100644 --- a/osfmk/ppc/ppc_init.c +++ b/osfmk/ppc/ppc_init.c @@ -48,33 +48,13 @@ extern const char version[]; extern const char version_variant[]; extern unsigned int intstack_top_ss; /* declared in start.s */ -#if MACH_KDP || MACH_KDB extern unsigned int debstackptr; /* declared in start.s */ extern unsigned int debstack_top_ss; /* declared in start.s */ -#endif /* MACH_KDP || MACH_KDB */ - -unsigned int kernel_seg_regs[] = { - KERNEL_SEG_REG0_VALUE, /* 0 */ - KERNEL_SEG_REG0_VALUE + 1, /* 1 */ - KERNEL_SEG_REG0_VALUE + 2, /* 2 */ - SEG_REG_INVALID, /* 3 */ - SEG_REG_INVALID, /* 4 */ - KERNEL_SEG_REG5_VALUE, /* 5 - I/O segment */ - SEG_REG_INVALID, /* 6 */ - SEG_REG_INVALID, /* 7 */ - KERNEL_SEG_REG8_VALUE, /* 8-F are possible IO space */ - KERNEL_SEG_REG9_VALUE, - KERNEL_SEG_REG10_VALUE, - KERNEL_SEG_REG11_VALUE, - KERNEL_SEG_REG12_VALUE, - KERNEL_SEG_REG13_VALUE, - KERNEL_SEG_REG14_VALUE, /* 14 - A/V video */ - KERNEL_SEG_REG15_VALUE /* 15 - NuBus etc */ -}; extern void thandler(void); /* trap handler */ extern void ihandler(void); /* interrupt handler */ extern void shandler(void); /* syscall handler */ +extern void chandler(void); /* system choke */ extern void fpu_switch(void); /* fp handler */ extern void vec_switch(void); /* vector handler */ extern void atomic_switch_trap(void); /* fast path atomic thread switch */ @@ -118,7 +98,8 @@ void (*exception_handlers[])(void) = { ihandler, /* Software Signal processor (T_SIGP) */ thandler, /* Software Preemption (T_PREEMPT) */ ihandler, /* Software INVALID EXCEPTION (T_CSWITCH) */ - ihandler /* Software Shutdown Context (T_SHUTDOWN) */ + ihandler, /* Software Shutdown Context (T_SHUTDOWN) */ + chandler /* Software System choke (crash) (T_CHOKE) */ }; int pc_trace_buf[1024] = {0}; @@ -142,14 +123,9 @@ void ppc_init(boot_args *args) per_proc_info[0].cpu_flags = 0; per_proc_info[0].istackptr = 0; /* we're on the interrupt stack */ per_proc_info[0].intstack_top_ss = intstack_top_ss; -#if MACH_KDP || MACH_KDB per_proc_info[0].debstackptr = debstackptr; per_proc_info[0].debstack_top_ss = debstack_top_ss; -#endif /* MACH_KDP || MACH_KDB */ - per_proc_info[0].get_interrupts_enabled = - fake_get_interrupts_enabled; - per_proc_info[0].set_interrupts_enabled = - fake_set_interrupts_enabled; + per_proc_info[0].interrupts_enabled = 0; per_proc_info[0].active_kloaded = (unsigned int) &active_kloaded[0]; per_proc_info[0].cpu_data = (unsigned int) diff --git a/osfmk/ppc/ppc_vm_init.c b/osfmk/ppc/ppc_vm_init.c index 29bee412e..cfbaab033 100644 --- a/osfmk/ppc/ppc_vm_init.c +++ b/osfmk/ppc/ppc_vm_init.c @@ -85,8 +85,6 @@ vm_offset_t sectTEXTB; int sectSizeTEXT; vm_offset_t sectDATAB; int sectSizeDATA; -vm_offset_t sectOBJCB; -int sectSizeOBJC; vm_offset_t sectLINKB; int sectSizeLINK; vm_offset_t sectKLDB; @@ -110,7 +108,6 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) vm_offset_t first_phys_avail; vm_offset_t sizeadj, oldstart; -#ifdef __MACHO__ /* Now retrieve addresses for end, edata, and etext * from MACH-O headers. */ @@ -118,8 +115,6 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) &_mh_execute_header, "__TEXT", §SizeTEXT); sectDATAB = (vm_offset_t)getsegdatafromheader( &_mh_execute_header, "__DATA", §SizeDATA); - sectOBJCB = (vm_offset_t)getsegdatafromheader( - &_mh_execute_header, "__OBJC", §SizeOBJC); sectLINKB = (vm_offset_t)getsegdatafromheader( &_mh_execute_header, "__LINKEDIT", §SizeLINK); sectKLDB = (vm_offset_t)getsegdatafromheader( @@ -131,17 +126,15 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) #if DEBUG kprintf("sectTEXT: %x, size: %x\n", sectTEXTB, sectSizeTEXT); kprintf("sectDATA: %x, size: %x\n", sectDATAB, sectSizeDATA); - kprintf("sectOBJC: %x, size: %x\n", sectOBJCB, sectSizeOBJC); kprintf("sectLINK: %x, size: %x\n", sectLINKB, sectSizeLINK); kprintf("sectKLD: %x, size: %x\n", sectKLDB, sectSizeKLD); kprintf("end: %x\n", end); #endif -#endif /* __MACHO__ */ /* Stitch valid memory regions together - they may be contiguous * even though they're not already glued together */ - mem_actual = mem_actual = args->PhysicalDRAM[0].base + args->PhysicalDRAM[0].size; /* Initialize to the first region size */ + mem_actual = args->PhysicalDRAM[0].base + args->PhysicalDRAM[0].size; /* Initialize to the first region size */ addr = 0; /* temp use as pointer to previous memory region... */ for (i = 1; i < kMaxDRAMBanks; i++) { @@ -229,7 +222,6 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) kmapsize = (round_page(exception_end) - trunc_page(exception_entry)) + /* Get size we will map later */ (round_page(sectTEXTB+sectSizeTEXT) - trunc_page(sectTEXTB)) + (round_page(sectDATAB+sectSizeDATA) - trunc_page(sectDATAB)) + - (round_page(sectOBJCB+sectSizeOBJC) - trunc_page(sectOBJCB)) + (round_page(sectLINKB+sectSizeLINK) - trunc_page(sectLINKB)) + (round_page(sectKLDB+sectSizeKLD) - trunc_page(sectKLDB)) + (round_page(static_memory_end) - trunc_page(end)); @@ -245,8 +237,6 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) trunc_page(sectTEXTB), round_page(sectTEXTB+sectSizeTEXT)); kprintf(" sectDATAB: %08X, %08X - %08X\n", trunc_page(sectDATAB), trunc_page(sectDATAB), round_page(sectDATAB+sectSizeDATA)); - kprintf(" sectOBJCB: %08X, %08X - %08X\n", trunc_page(sectOBJCB), - trunc_page(sectOBJCB), round_page(sectOBJCB+sectSizeOBJC)); kprintf(" sectLINKB: %08X, %08X - %08X\n", trunc_page(sectLINKB), trunc_page(sectLINKB), round_page(sectLINKB+sectSizeLINK)); kprintf(" sectKLDB: %08X, %08X - %08X\n", trunc_page(sectKLDB), @@ -260,8 +250,6 @@ void ppc_vm_init(unsigned int mem_limit, boot_args *args) round_page(sectTEXTB+sectSizeTEXT), VM_PROT_READ|VM_PROT_EXECUTE); pmap_map(trunc_page(sectDATAB), trunc_page(sectDATAB), round_page(sectDATAB+sectSizeDATA), VM_PROT_READ|VM_PROT_WRITE); - pmap_map(trunc_page(sectOBJCB), trunc_page(sectOBJCB), - round_page(sectOBJCB+sectSizeOBJC), VM_PROT_READ|VM_PROT_WRITE); /* The KLD and LINKEDIT segments are unloaded in toto after boot completes, diff --git a/osfmk/ppc/proc_reg.h b/osfmk/ppc/proc_reg.h index 68fb49dba..c06e8b993 100644 --- a/osfmk/ppc/proc_reg.h +++ b/osfmk/ppc/proc_reg.h @@ -202,18 +202,6 @@ #define PPC_HASHSIZE_LOG2 11 #define PPC_MIN_MPP 2 /* min # of mappings per phys page */ -/* macros to help decide processor type */ -#define PROCESSOR_VERSION_601 1 -#define PROCESSOR_VERSION_603 3 -#define PROCESSOR_VERSION_604 4 -#define PROCESSOR_VERSION_603e 6 -#define PROCESSOR_VERSION_750 8 -#define PROCESSOR_VERSION_604e 9 -#define PROCESSOR_VERSION_604ev 10 /* ? */ -#define PROCESSOR_VERSION_7400 12 /* ? */ -#define PROCESSOR_VERSION_7410 0x800C /* ? */ -#define PROCESSOR_VERSION_7450 0x8000 /* ? */ - #ifndef ASSEMBLER #ifdef __GNUC__ diff --git a/osfmk/ppc/rtclock.c b/osfmk/ppc/rtclock.c index 9ccae5ae7..a7c215da6 100644 --- a/osfmk/ppc/rtclock.c +++ b/osfmk/ppc/rtclock.c @@ -31,6 +31,8 @@ * real-time clock. */ +#include <libkern/OSTypes.h> + #include <mach/mach_types.h> #include <kern/clock.h> @@ -43,16 +45,6 @@ #include <pexpert/pexpert.h> -/*XXX power management hacks XXX*/ -#include <IOKit/IOReturn.h> -#include <IOKit/IOMessage.h> - -extern void *registerSleepWakeInterest( - void *callback, - void *target, - void *refCon); -/*XXX power management hacks XXX*/ - #include <sys/kdebug.h> int sysclk_config(void); @@ -108,7 +100,7 @@ static struct rtclock { mach_timebase_info_data_t timebase_const; struct rtclock_timer { - AbsoluteTime deadline; + uint64_t deadline; boolean_t is_set; } timer[NCPUS]; @@ -117,7 +109,7 @@ static struct rtclock { timer_call_data_t alarm[NCPUS]; /* debugging */ - AbsoluteTime last_abstime[NCPUS]; + uint64_t last_abstime[NCPUS]; int last_decr[NCPUS]; decl_simple_lock_data(,lock) /* real-time clock device lock */ @@ -125,16 +117,16 @@ static struct rtclock { static boolean_t rtclock_initialized; -static AbsoluteTime rtclock_tick_deadline[NCPUS]; -static AbsoluteTime rtclock_tick_interval; +static uint64_t rtclock_tick_deadline[NCPUS]; +static uint64_t rtclock_tick_interval; static void timespec_to_absolutetime( mach_timespec_t timespec, - AbsoluteTime *result); + uint64_t *result); static int deadline_to_decrementer( - AbsoluteTime deadline, - AbsoluteTime now); + uint64_t deadline, + uint64_t now); static void rtclock_alarm_timer( timer_call_param_t p0, @@ -219,7 +211,7 @@ sysclk_config(void) int sysclk_init(void) { - AbsoluteTime abstime; + uint64_t abstime; int decr, mycpu = cpu_number(); if (mycpu != master_cpu) { @@ -229,8 +221,7 @@ sysclk_init(void) /* Set decrementer and hence our next tick due */ clock_get_uptime(&abstime); rtclock_tick_deadline[mycpu] = abstime; - ADD_ABSOLUTETIME(&rtclock_tick_deadline[mycpu], - &rtclock_tick_interval); + rtclock_tick_deadline[mycpu] += rtclock_tick_interval; decr = deadline_to_decrementer(rtclock_tick_deadline[mycpu], abstime); mtdec(decr); rtclock.last_decr[mycpu] = decr; @@ -246,7 +237,7 @@ sysclk_init(void) /* Set decrementer and our next tick due */ clock_get_uptime(&abstime); rtclock_tick_deadline[mycpu] = abstime; - ADD_ABSOLUTETIME(&rtclock_tick_deadline[mycpu], &rtclock_tick_interval); + rtclock_tick_deadline[mycpu] += rtclock_tick_interval; decr = deadline_to_decrementer(rtclock_tick_deadline[mycpu], abstime); mtdec(decr); rtclock.last_decr[mycpu] = decr; @@ -256,6 +247,9 @@ sysclk_init(void) return (1); } +#define UnsignedWide_to_scalar(x) (*(uint64_t *)(x)) +#define scalar_to_UnsignedWide(x) (*(UnsignedWide *)(x)) + /* * Perform a full 64 bit by 32 bit unsigned multiply, * yielding a 96 bit product. The most significant @@ -264,12 +258,12 @@ sysclk_init(void) */ static void umul_64by32( - AbsoluteTime now64, - natural_t mult32, - AbsoluteTime *result64, - natural_t *result32) + UnsignedWide now64, + uint32_t mult32, + UnsignedWide *result64, + uint32_t *result32) { - natural_t mid, mid2; + uint32_t mid, mid2; asm volatile(" mullw %0,%1,%2" : "=r" (*result32) : @@ -299,11 +293,11 @@ umul_64by32( */ static void umul_64by32to64( - AbsoluteTime now64, - natural_t mult32, - AbsoluteTime *result64) + UnsignedWide now64, + uint32_t mult32, + UnsignedWide *result64) { - natural_t mid, mid2; + uint32_t mid, mid2; asm volatile(" mullw %0,%1,%2" : "=r" (result64->lo) : @@ -328,31 +322,30 @@ umul_64by32to64( * returned as a 64 bit quantity, with the lower * portion as a 32 bit word. */ -static __inline__ -void +static void udiv_96by32( - AbsoluteTime now64, - natural_t now32, - natural_t div32, - AbsoluteTime *result64, - natural_t *result32) + UnsignedWide now64, + uint32_t now32, + uint32_t div32, + UnsignedWide *result64, + uint32_t *result32) { - AbsoluteTime t64; + UnsignedWide t64; if (now64.hi > 0 || now64.lo >= div32) { - AbsoluteTime_to_scalar(result64) = - AbsoluteTime_to_scalar(&now64) / div32; + UnsignedWide_to_scalar(result64) = + UnsignedWide_to_scalar(&now64) / div32; umul_64by32to64(*result64, div32, &t64); - AbsoluteTime_to_scalar(&t64) = - AbsoluteTime_to_scalar(&now64) - AbsoluteTime_to_scalar(&t64); + UnsignedWide_to_scalar(&t64) = + UnsignedWide_to_scalar(&now64) - UnsignedWide_to_scalar(&t64); - *result32 = (((unsigned long long)t64.lo << 32) | now32) / div32; + *result32 = (((uint64_t)t64.lo << 32) | now32) / div32; } else { - AbsoluteTime_to_scalar(result64) = - (((unsigned long long)now64.lo << 32) | now32) / div32; + UnsignedWide_to_scalar(result64) = + (((uint64_t)now64.lo << 32) | now32) / div32; *result32 = result64->lo; result64->lo = result64->hi; @@ -366,31 +359,30 @@ udiv_96by32( * Any higher order bits of the quotient are simply * discarded. */ -static __inline__ -void +static void udiv_96by32to64( - AbsoluteTime now64, - natural_t now32, - natural_t div32, - AbsoluteTime *result64) + UnsignedWide now64, + uint32_t now32, + uint32_t div32, + UnsignedWide *result64) { - AbsoluteTime t64; + UnsignedWide t64; if (now64.hi > 0 || now64.lo >= div32) { - AbsoluteTime_to_scalar(result64) = - AbsoluteTime_to_scalar(&now64) / div32; + UnsignedWide_to_scalar(result64) = + UnsignedWide_to_scalar(&now64) / div32; umul_64by32to64(*result64, div32, &t64); - AbsoluteTime_to_scalar(&t64) = - AbsoluteTime_to_scalar(&now64) - AbsoluteTime_to_scalar(&t64); + UnsignedWide_to_scalar(&t64) = + UnsignedWide_to_scalar(&now64) - UnsignedWide_to_scalar(&t64); result64->hi = result64->lo; - result64->lo = (((unsigned long long)t64.lo << 32) | now32) / div32; + result64->lo = (((uint64_t)t64.lo << 32) | now32) / div32; } else { - AbsoluteTime_to_scalar(result64) = - (((unsigned long long)now64.lo << 32) | now32) / div32; + UnsignedWide_to_scalar(result64) = + (((uint64_t)now64.lo << 32) | now32) / div32; } } @@ -400,52 +392,49 @@ udiv_96by32to64( * and a 32 bit remainder. Any higher order bits * of the quotient are simply discarded. */ -static __inline__ -void +static void udiv_96by32to32and32( - AbsoluteTime now64, - natural_t now32, - natural_t div32, - natural_t *result32, - natural_t *remain32) + UnsignedWide now64, + uint32_t now32, + uint32_t div32, + uint32_t *result32, + uint32_t *remain32) { - AbsoluteTime t64, u64; + UnsignedWide t64, u64; if (now64.hi > 0 || now64.lo >= div32) { - AbsoluteTime_to_scalar(&t64) = - AbsoluteTime_to_scalar(&now64) / div32; + UnsignedWide_to_scalar(&t64) = + UnsignedWide_to_scalar(&now64) / div32; umul_64by32to64(t64, div32, &t64); - AbsoluteTime_to_scalar(&t64) = - AbsoluteTime_to_scalar(&now64) - AbsoluteTime_to_scalar(&t64); + UnsignedWide_to_scalar(&t64) = + UnsignedWide_to_scalar(&now64) - UnsignedWide_to_scalar(&t64); - AbsoluteTime_to_scalar(&t64) = - ((unsigned long long)t64.lo << 32) | now32; + UnsignedWide_to_scalar(&t64) = ((uint64_t)t64.lo << 32) | now32; - AbsoluteTime_to_scalar(&u64) = - AbsoluteTime_to_scalar(&t64) / div32; + UnsignedWide_to_scalar(&u64) = + UnsignedWide_to_scalar(&t64) / div32; *result32 = u64.lo; umul_64by32to64(u64, div32, &u64); - *remain32 = AbsoluteTime_to_scalar(&t64) - - AbsoluteTime_to_scalar(&u64); + *remain32 = UnsignedWide_to_scalar(&t64) - + UnsignedWide_to_scalar(&u64); } else { - AbsoluteTime_to_scalar(&t64) = - ((unsigned long long)now64.lo << 32) | now32; + UnsignedWide_to_scalar(&t64) = ((uint64_t)now64.lo << 32) | now32; - AbsoluteTime_to_scalar(&u64) = - AbsoluteTime_to_scalar(&t64) / div32; + UnsignedWide_to_scalar(&u64) = + UnsignedWide_to_scalar(&t64) / div32; *result32 = u64.lo; umul_64by32to64(u64, div32, &u64); - *remain32 = AbsoluteTime_to_scalar(&t64) - - AbsoluteTime_to_scalar(&u64); + *remain32 = UnsignedWide_to_scalar(&t64) - + UnsignedWide_to_scalar(&u64); } } @@ -454,22 +443,21 @@ udiv_96by32to32and32( * for converting the device's machine dependent time value * into a canonical mach_timespec_t value. * - * SMP configurations - *this currently assumes that the processor - * clocks will be synchronised* + * SMP configurations - *the processor clocks are synchronised* */ kern_return_t sysclk_gettime_internal( mach_timespec_t *time) /* OUT */ { - AbsoluteTime now; - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + UnsignedWide now; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; numer = rtclock.timebase_const.numer; denom = rtclock.timebase_const.denom; - clock_get_uptime(&now); + clock_get_uptime((uint64_t *)&now); umul_64by32(now, numer, &t64, &t32); @@ -485,10 +473,10 @@ kern_return_t sysclk_gettime( mach_timespec_t *time) /* OUT */ { - AbsoluteTime now; - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + UnsignedWide now; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; spl_t s; LOCK_RTC(s); @@ -496,7 +484,7 @@ sysclk_gettime( denom = rtclock.timebase_const.denom; UNLOCK_RTC(s); - clock_get_uptime(&now); + clock_get_uptime((uint64_t *)&now); umul_64by32(now, numer, &t64, &t32); @@ -546,7 +534,7 @@ void sysclk_setalarm( mach_timespec_t *deadline) { - AbsoluteTime abstime; + uint64_t abstime; timespec_to_absolutetime(*deadline, &abstime); timer_call_enter(&rtclock.alarm[cpu_number()], abstime); @@ -662,12 +650,14 @@ clock_adjust_calendar( UNLOCK_RTC(s); } -static void -calend_setup_internal( - long seconds) +void +clock_initialize_calendar(void) { - mach_timespec_t curr_time; + mach_timespec_t curr_time; + long seconds = PEGetGMTTimeOfDay(); + spl_t s; + LOCK_RTC(s); (void) sysclk_gettime_internal(&curr_time); if (curr_time.tv_nsec < 500*USEC_PER_SEC) rtclock.calend_offset.tv_sec = seconds; @@ -676,58 +666,6 @@ calend_setup_internal( rtclock.calend_offset.tv_nsec = 0; SUB_MACH_TIMESPEC(&rtclock.calend_offset, &curr_time); rtclock.calend_is_set = TRUE; -} - -static thread_call_t calend_wakeup_call; -static thread_call_data_t calend_wakeup_call_data; - -static void -calend_wakeup_resynch( - thread_call_param_t p0, - thread_call_param_t p1) -{ - long seconds = PEGetGMTTimeOfDay(); - spl_t s; - - LOCK_RTC(s); - calend_setup_internal(seconds); - UNLOCK_RTC(s); -} - -static IOReturn -calend_sleep_wake_notif( - void *target, - void *refCon, - UInt32 messageType, - void *provider, - void *messageArg, - vm_size_t argSize) -{ - if (messageType != kIOMessageSystemHasPoweredOn) - return (kIOReturnUnsupported); - - if (calend_wakeup_call != NULL) - thread_call_enter(calend_wakeup_call); - - return (kIOReturnSuccess); -} - -void -clock_initialize_calendar(void) -{ - long seconds; - spl_t s; - - thread_call_setup(&calend_wakeup_call_data, calend_wakeup_resynch, NULL); - calend_wakeup_call = &calend_wakeup_call_data; - - registerSleepWakeInterest(calend_sleep_wake_notif, NULL, NULL); - - seconds = PEGetGMTTimeOfDay(); - - LOCK_RTC(s); - if (!rtclock.calend_is_set) - calend_setup_internal(seconds); UNLOCK_RTC(s); } @@ -758,9 +696,9 @@ clock_timebase_info( void clock_set_timer_deadline( - AbsoluteTime deadline) + uint64_t deadline) { - AbsoluteTime abstime; + uint64_t abstime; int decr, mycpu; struct rtclock_timer *mytimer; spl_t s; @@ -772,18 +710,17 @@ clock_set_timer_deadline( rtclock.last_abstime[mycpu] = abstime; mytimer->deadline = deadline; mytimer->is_set = TRUE; - if ( CMP_ABSOLUTETIME(&mytimer->deadline, - &rtclock_tick_deadline[mycpu]) < 0) { + if ( mytimer->deadline < rtclock_tick_deadline[mycpu] ) { decr = deadline_to_decrementer(mytimer->deadline, abstime); if ( rtclock_decrementer_min != 0 && rtclock_decrementer_min < (natural_t)decr ) decr = rtclock_decrementer_min; - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) - | DBG_FUNC_NONE, decr, 2, 0, 0, 0); - mtdec(decr); rtclock.last_decr[mycpu] = decr; + + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) + | DBG_FUNC_NONE, decr, 2, 0, 0, 0); } splx(s); } @@ -819,7 +756,7 @@ rtclock_intr( struct ppc_saved_state *ssp, spl_t old_spl) { - AbsoluteTime abstime; + uint64_t abstime; int decr[3], mycpu = cpu_number(); struct rtclock_timer *mytimer = &rtclock.timer[mycpu]; @@ -835,7 +772,7 @@ rtclock_intr( clock_get_uptime(&abstime); rtclock.last_abstime[mycpu] = abstime; - if (CMP_ABSOLUTETIME(&rtclock_tick_deadline[mycpu], &abstime) <= 0) { + if ( rtclock_tick_deadline[mycpu] <= abstime ) { clock_deadline_for_periodic_event(rtclock_tick_interval, abstime, &rtclock_tick_deadline[mycpu]); hertz_tick(USER_MODE(ssp->srr1), ssp->srr0); @@ -843,8 +780,8 @@ rtclock_intr( clock_get_uptime(&abstime); rtclock.last_abstime[mycpu] = abstime; - if (mytimer->is_set && - CMP_ABSOLUTETIME(&mytimer->deadline, &abstime) <= 0) { + if ( mytimer->is_set && + mytimer->deadline <= abstime ) { mytimer->is_set = FALSE; (*rtclock.timer_expire)(abstime); } @@ -863,11 +800,11 @@ rtclock_intr( rtclock_decrementer_min < (natural_t)decr[1] ) decr[1] = rtclock_decrementer_min; - KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) - | DBG_FUNC_NONE, decr[1], 3, 0, 0, 0); - mtdec(decr[1]); rtclock.last_decr[mycpu] = decr[1]; + + KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 1) + | DBG_FUNC_NONE, decr[1], 3, 0, 0, 0); } static void @@ -884,9 +821,10 @@ rtclock_alarm_timer( void clock_get_uptime( - AbsoluteTime *result) + uint64_t *result0) { - natural_t hi, lo, hic; + UnsignedWide *result = (UnsignedWide *)result0; + uint32_t hi, lo, hic; do { asm volatile(" mftbu %0" : "=r" (hi)); @@ -900,16 +838,15 @@ clock_get_uptime( static int deadline_to_decrementer( - AbsoluteTime deadline, - AbsoluteTime now) + uint64_t deadline, + uint64_t now) { uint64_t delt; - if (CMP_ABSOLUTETIME(&deadline, &now) <= 0) + if (deadline <= now) return DECREMENTER_MIN; else { - delt = AbsoluteTime_to_scalar(&deadline) - - AbsoluteTime_to_scalar(&now); + delt = deadline - now; return (delt >= (DECREMENTER_MAX + 1))? DECREMENTER_MAX: ((delt >= (DECREMENTER_MIN + 1))? (delt - 1): DECREMENTER_MIN); } @@ -918,11 +855,12 @@ deadline_to_decrementer( static void timespec_to_absolutetime( mach_timespec_t timespec, - AbsoluteTime *result) + uint64_t *result0) { - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + UnsignedWide *result = (UnsignedWide *)result0; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; spl_t s; LOCK_RTC(s); @@ -938,7 +876,7 @@ timespec_to_absolutetime( "=r" (t64.hi) : "r" (timespec.tv_sec), "r" (NSEC_PER_SEC)); - AbsoluteTime_to_scalar(&t64) += timespec.tv_nsec; + UnsignedWide_to_scalar(&t64) += timespec.tv_nsec; umul_64by32(t64, denom, &t64, &t32); @@ -950,28 +888,29 @@ timespec_to_absolutetime( void clock_interval_to_deadline( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result) + uint32_t interval, + uint32_t scale_factor, + uint64_t *result) { - AbsoluteTime abstime; + uint64_t abstime; clock_get_uptime(result); clock_interval_to_absolutetime_interval(interval, scale_factor, &abstime); - ADD_ABSOLUTETIME(result, &abstime); + *result += abstime; } void clock_interval_to_absolutetime_interval( - natural_t interval, - natural_t scale_factor, - AbsoluteTime *result) -{ - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + uint32_t interval, + uint32_t scale_factor, + uint64_t *result0) +{ + UnsignedWide *result = (UnsignedWide *)result0; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; spl_t s; LOCK_RTC(s); @@ -996,22 +935,22 @@ clock_interval_to_absolutetime_interval( void clock_absolutetime_interval_to_deadline( - AbsoluteTime abstime, - AbsoluteTime *result) + uint64_t abstime, + uint64_t *result) { clock_get_uptime(result); - ADD_ABSOLUTETIME(result, &abstime); + *result += abstime; } void absolutetime_to_nanoseconds( - AbsoluteTime abstime, - UInt64 *result) + uint64_t abstime, + uint64_t *result) { - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; spl_t s; LOCK_RTC(s); @@ -1019,19 +958,21 @@ absolutetime_to_nanoseconds( denom = rtclock.timebase_const.denom; UNLOCK_RTC(s); - umul_64by32(abstime, numer, &t64, &t32); + UnsignedWide_to_scalar(&t64) = abstime; + + umul_64by32(t64, numer, &t64, &t32); udiv_96by32to64(t64, t32, denom, (void *)result); } void nanoseconds_to_absolutetime( - UInt64 nanoseconds, - AbsoluteTime *result) + uint64_t nanoseconds, + uint64_t *result) { - AbsoluteTime t64; - natural_t t32; - natural_t numer, denom; + UnsignedWide t64; + uint32_t t32; + uint32_t numer, denom; spl_t s; LOCK_RTC(s); @@ -1039,11 +980,11 @@ nanoseconds_to_absolutetime( denom = rtclock.timebase_const.denom; UNLOCK_RTC(s); - AbsoluteTime_to_scalar(&t64) = nanoseconds; + UnsignedWide_to_scalar(&t64) = nanoseconds; umul_64by32(t64, denom, &t64, &t32); - udiv_96by32to64(t64, t32, numer, result); + udiv_96by32to64(t64, t32, numer, (void *)result); } /* @@ -1051,32 +992,32 @@ nanoseconds_to_absolutetime( */ void delay_for_interval( - natural_t interval, - natural_t scale_factor) + uint32_t interval, + uint32_t scale_factor) { - AbsoluteTime now, end; + uint64_t now, end; clock_interval_to_deadline(interval, scale_factor, &end); do { clock_get_uptime(&now); - } while (CMP_ABSOLUTETIME(&now, &end) < 0); + } while (now < end); } void clock_delay_until( - AbsoluteTime deadline) + uint64_t deadline) { - AbsoluteTime now; + uint64_t now; do { clock_get_uptime(&now); - } while (CMP_ABSOLUTETIME(&now, &deadline) < 0); + } while (now < deadline); } void delay( - int usec) + int usec) { delay_for_interval((usec < 0)? -usec: usec, NSEC_PER_USEC); } diff --git a/osfmk/ppc/savearea.h b/osfmk/ppc/savearea.h index e98ada3c0..a8b4e180f 100644 --- a/osfmk/ppc/savearea.h +++ b/osfmk/ppc/savearea.h @@ -34,9 +34,11 @@ struct savearea *save_alloc(void); /* Obtains a savearea and allocates blocks struct savearea *save_cpv(struct savearea *); /* Converts a physical savearea address to virtual */ unsigned int *save_deb(unsigned int *msr); /* Finds virtual of first free block and disableds interrupts */ void save_ret(struct savearea *); /* Returns a savearea to the free list */ +#if DEBUG void save_free_dump(void); /* Dump the free chain */ void DumpTheSave(struct savearea *); /* Prints out a savearea */ void DumpBackChain(struct savearea *save); /* Dumps a backchain */ +#endif #endif /* _PPC_SAVEAREA_H_ */ diff --git a/osfmk/ppc/start.s b/osfmk/ppc/start.s index c2e58c929..13bd883f9 100644 --- a/osfmk/ppc/start.s +++ b/osfmk/ppc/start.s @@ -47,7 +47,19 @@ #define bootCPU 10 #define firstInit 9 #define firstBoot 8 - + +/* Defines for PVRs */ +#define PROCESSOR_VERSION_601 1 +#define PROCESSOR_VERSION_603 3 +#define PROCESSOR_VERSION_604 4 +#define PROCESSOR_VERSION_603e 6 +#define PROCESSOR_VERSION_750 8 +#define PROCESSOR_VERSION_604e 9 +#define PROCESSOR_VERSION_604ev 10 /* ? */ +#define PROCESSOR_VERSION_7400 12 /* ? */ +#define PROCESSOR_VERSION_7410 0x800C /* ? */ +#define PROCESSOR_VERSION_7450 0x8000 /* ? */ + /* * Interrupt and bootup stack for initial processor */ @@ -82,17 +94,17 @@ EXT(FixedStackEnd): .align ALIGN .globl EXT(intstack_top_ss) EXT(intstack_top_ss): - .long EXT(intstack)+INTSTACK_SIZE-SS_SIZE /* intstack_top_ss points to the top of interrupt stack */ + .long EXT(intstack)+INTSTACK_SIZE-FM_SIZE /* intstack_top_ss points to the top of interrupt stack */ .align ALIGN .globl EXT(debstack_top_ss) EXT(debstack_top_ss): - .long EXT(debstack)+KERNEL_STACK_SIZE-SS_SIZE /* debstack_top_ss points to the top of debug stack */ + .long EXT(debstack)+KERNEL_STACK_SIZE-FM_SIZE /* debstack_top_ss points to the top of debug stack */ .globl EXT(debstackptr) EXT(debstackptr): - .long EXT(debstack)+KERNEL_STACK_SIZE-SS_SIZE + .long EXT(debstack)+KERNEL_STACK_SIZE-FM_SIZE #endif /* MACH_KDP || MACH_KDB */ @@ -542,9 +554,14 @@ i7450hl3: cmplwi cr0,r13,0 ; No L3 if L3CR is zero b init7450fin ; Return.... init7450none: - rlwinm r17,r17,0,pfL3fab+1,pfL3b-1 ; No 3rd level cache or assist + rlwinm r17,r17,0,pfL3fab+1,pfL3b-1 ; No 3rd level cache or assist + rlwinm r11,r17,pfWillNapb-pfCanNapb,pfCanNapb,pfCanNapb ; Set pfCanNap if pfWillNap is set + or r17,r17,r11 -init7450fin: mfspr r11,hid0 ; Get the current HID0 +init7450fin: + rlwinm r17,r17,0,pfWillNapb+1,pfWillNapb-1 ; Make sure pfWillNap is not set + + mfspr r11,hid0 ; Get the current HID0 stw r11,pfHID0(r30) ; Save the HID0 value mfspr r11,hid1 ; Get the current HID1 stw r11,pfHID1(r30) ; Save the HID1 value @@ -556,6 +573,8 @@ init7450fin: mfspr r11,hid0 ; Get the current HID0 stw r11,pfICTRL(r30) ; Save the ICTRL value mfspr r11,ldstcr ; Get the ldstcr register stw r11,pfLDSTCR(r30) ; Save the LDSTCR value + mfspr r11,ldstdb ; Get the ldstdb register + stw r11,pfLDSTDB(r30) ; Save the LDSTDB value blr ; Return.... @@ -582,6 +601,11 @@ i7450nb: lwz r11,pfHID0(r30) ; Get HID0 mtspr ldstcr,r11 ; Set the LDSTCR isync sync + lwz r11,pfLDSTDB(r30) ; Get LDSTDB + sync + mtspr ldstdb,r11 ; Set the LDSTDB + isync + sync blr @@ -741,6 +765,7 @@ processor_types: .long 32*1024 .long 32*1024 + ; 7400 (generic) .align 2 @@ -792,7 +817,7 @@ processor_types: .long 0xFFFFFF00 ; Just revisions 1.xx .short PROCESSOR_VERSION_7450 .short 0x0100 - .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfL23lck | pfL1nnc | pfL1i | pfL1d | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa + .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfLClck | pfL1nnc | pfL1i | pfL1d | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa .long init7450 .long CPU_SUBTYPE_POWERPC_7450 .long 105 @@ -801,13 +826,28 @@ processor_types: .long 32*1024 .long 32*1024 -; 7450 (>=2) +; 7450 (2.0) + + .align 2 + .long 0xFFFFFFFF ; Just revision 2.0 + .short PROCESSOR_VERSION_7450 + .short 0x0200 + .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfLClck | pfL1i | pfL1d | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa + .long init7450 + .long CPU_SUBTYPE_POWERPC_7450 + .long 105 + .long 90 + .long 32 + .long 32*1024 + .long 32*1024 + +; 7450 (2.1) .align 2 .long 0xFFFF0000 ; All other revisions .short PROCESSOR_VERSION_7450 .short 0 - .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfL23lck | pfL1i | pfL1d | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa + .long pfFloat | pfAltivec | pfSMPcap | pfCanSleep | pfNoMSRir | pfWillNap | pfLClck | pfL1i | pfL1d | pfL2 | pfL2fa | pfL2i | pfL3 | pfL3fa .long init7450 .long CPU_SUBTYPE_POWERPC_7450 .long 105 @@ -816,6 +856,7 @@ processor_types: .long 32*1024 .long 32*1024 + ; Default dumb loser machine .align 2 diff --git a/osfmk/ppc/status.c b/osfmk/ppc/status.c index aed0b63e6..f716068bc 100644 --- a/osfmk/ppc/status.c +++ b/osfmk/ppc/status.c @@ -42,6 +42,8 @@ extern unsigned int killprint; extern double FloatInit; extern unsigned long QNaNbarbarian[4]; extern void thread_bootstrap_return(void); +extern struct Saveanchor saveanchor; +extern int real_ncpus; /* Number of actual CPUs */ struct ppc_saved_state * get_user_regs(thread_act_t); @@ -54,7 +56,8 @@ thread_userstack( int, thread_state_t, unsigned int, - vm_offset_t * + vm_offset_t *, + int * ); kern_return_t @@ -70,6 +73,7 @@ unsigned int get_msr_exportmask(void); unsigned int get_msr_nbits(void); unsigned int get_msr_rbits(void); void thread_set_child(thread_act_t child, int pid); +void thread_set_parent(thread_act_t parent, int pid); /* * Maps state flavor to number of words in the state: @@ -240,7 +244,7 @@ act_machine_get_state( return KERN_INVALID_ARGUMENT; } - fpu_save(); /* Just in case it's live, save it */ + fpu_save(thr_act); /* Just in case it's live, save it */ fs = (struct ppc_float_state *) tstate; /* Point to destination */ @@ -274,7 +278,7 @@ act_machine_get_state( return KERN_INVALID_ARGUMENT; } - vec_save(); /* Just in case it's live, save it */ + vec_save(thr_act); /* Just in case it's live, save it */ vs = (struct ppc_vector_state *) tstate; /* Point to destination */ @@ -492,7 +496,7 @@ act_machine_set_state( if(!kernel_act) sv->save_srr1 |= MSR_EXPORT_MASK_SET; /* If not a kernel guy, force the magic bits on */ - sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_FP)); /* Make sure we don't enable the floating point unit */ + sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make sure we don't enable the floating point unit */ if(isnew) { /* Is it a new one? */ sv->save_dar = 0; /* Yes, these need initialization also */ @@ -538,6 +542,15 @@ act_machine_set_state( sv = (savearea *)thr_act->mact.FPU_pcb; /* Get the top savearea on the stack */ osv = 0; /* Set no user savearea yet */ + if(sv && (sv->save_level_fp == 1)) { /* Is the first savearea invalid? */ + thr_act->mact.FPU_pcb = (pcb_t)sv->save_prev_float; /* Yes, clean it out */ + sv->save_flags &= ~SAVfpuvalid; /* Clear the floating point flag */ + if(!(sv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(sv); /* Nope, release it */ + } + sv = (savearea *)thr_act->mact.FPU_pcb; /* Get the new top savearea on the stack */ + } + while(sv) { /* Find the user context */ if(!(sv->save_level_fp)) { /* Are we looking at the user context? */ break; /* Outta here */ @@ -599,7 +612,6 @@ act_machine_set_state( usv->save_xfpscrpad = sv->save_fpscr_pad; /* Copy the pad value to normal */ usv->save_xfpscr = sv->save_fpscr; /* Copy the fpscr value to normal */ - return KERN_SUCCESS; @@ -615,6 +627,15 @@ act_machine_set_state( sv = (savearea *)thr_act->mact.VMX_pcb; /* Get the top savearea on the stack */ osv = 0; /* Set no user savearea yet */ + if(sv && (sv->save_level_vec == 1)) { /* Is the first savearea invalid? */ + thr_act->mact.VMX_pcb = (pcb_t)sv->save_prev_vector; /* Yes, clean it out */ + sv->save_flags &= ~SAVvmxvalid; /* Clear the floating point flag */ + if(!(sv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(sv); /* Nope, release it */ + } + sv = (savearea *)thr_act->mact.VMX_pcb; /* Get the new top savearea on the stack */ + } + while(sv) { /* Find the user context */ if(!(sv->save_level_vec)) { /* Are we looking at the user context? */ break; /* Outta here */ @@ -694,8 +715,8 @@ void act_thread_dup(thread_act_t old, thread_act_t new) { savearea *sv, *osv, *fsv; unsigned int spc, i, *srs; - fpu_save(); /* Make certain floating point state is all saved */ - vec_save(); /* Make certain the vector state is all saved */ + fpu_save(old); /* Make certain floating point state is all saved */ + vec_save(old); /* Make certain the vector state is all saved */ osv = (savearea *)new->mact.pcb; /* Get the top savearea on the stack */ sv = 0; /* Set no new user savearea yet */ @@ -755,6 +776,8 @@ void act_thread_dup(thread_act_t old, thread_act_t new) { sv->save_prev_float = (savearea *)0; /* Clear the back chain */ sv->save_prev_vector = (savearea *)0; /* Clear the back chain */ + sv->save_level_fp = 0; /* Set the level for FP */ + sv->save_level_vec = 0; /* Set the level for vector */ sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make certain that floating point and vector are turned off */ @@ -896,7 +919,8 @@ thread_userstack( int flavor, thread_state_t tstate, unsigned int count, - vm_offset_t *user_stack + vm_offset_t *user_stack, + int *customstack ) { struct ppc_thread_state *state; @@ -906,6 +930,8 @@ thread_userstack( */ if (*user_stack == 0) *user_stack = USRSTACK; + if (customstack) + *customstack = 0; switch (flavor) { case PPC_THREAD_STATE: @@ -918,6 +944,10 @@ thread_userstack( * If a valid user stack is specified, use it. */ *user_stack = state->r1 ? state->r1: USRSTACK; + + if (customstack && state->r1) + *customstack = 1; + break; default : return (KERN_INVALID_ARGUMENT); @@ -986,3 +1016,286 @@ void thread_set_child(thread_act_t child, int pid) child_state->r3 = pid; child_state->r4 = 1; } +void thread_set_parent(thread_act_t parent, int pid) +{ + struct ppc_saved_state *parent_state; + + parent_state = find_user_regs(parent); + + parent_state->r3 = pid; + parent_state->r4 = 0; +} + +/* + * Saves the complete context (general, floating point, and vector) of the current activation. + * We will collect everything into one savearea and pass that back. + * + * The savearea is made to look like it belongs to the source activation. This needs to + * be adjusted when these contexts are attached to a new activation. + * + */ + +void *act_thread_csave(void) { + + savearea *sv, *osv, *fsv; + unsigned int spc, i, *srs; + + thread_act_t act; + + fpu_save(current_act()); /* Make certain floating point state is all saved */ + vec_save(current_act()); /* Make certain the vector state is all saved */ + + sv = save_alloc(); /* Get a fresh save area */ + hw_atomic_add(&saveanchor.saveneed, 1); /* Account for the extra saveareas "need" */ + + act = current_act(); /* Find ourselves */ + + sv->save_flags |= SAVattach; /* Say that it is in use */ + sv->save_act = act; /* Point to the activation */ + + spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */ + + srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */ + for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */ + srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SR */ + } + + sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */ + + osv = (savearea *)(act->mact.pcb); /* Start with the normal savearea */ + fsv = 0; /* Assume none */ + while(osv) { /* Find the user context */ + if(osv->save_srr1 & MASK(MSR_PR)) { /* Are we looking at the user context? */ + fsv = osv; /* Remember what we found */ + break; /* Outta here */ + } + osv = osv->save_prev; /* Back chain */ + } + + if(!fsv) { /* Did we find one? */ + for(i=0; i < 32; i+=2) { /* Fill up with defaults */ + ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0]; + ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1]; + } + sv->save_cr = 0; + sv->save_xer = 0; + sv->save_lr = ((unsigned int *)&FloatInit)[0]; + sv->save_ctr = ((unsigned int *)&FloatInit)[1]; + sv->save_srr0 = ((unsigned int *)&FloatInit)[0]; + sv->save_srr1 = MSR_EXPORT_MASK_SET; + sv->save_mq = 0; + sv->save_vrsave = 0; /* VRSAVE register (Altivec only) */ + sv->save_xfpscrpad = 0; /* Start with a clear fpscr */ + sv->save_xfpscr = 0; /* Start with a clear fpscr */ + } + else { /* We did find one, copy it */ + bcopy((char *)&fsv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */ + sv->save_xfpscrpad = osv->save_xfpscrpad; /* Copy the pad value to old */ + sv->save_xfpscr = osv->save_xfpscr; /* Copy the fpscr value to old */ + } + + + sv->save_prev = (savearea *)0xDEBB1ED0; /* Eye catcher for debug */ + sv->save_prev_float = (savearea *)0xE5DA11A5; /* Eye catcher for debug */ + sv->save_prev_vector = (savearea *)0; /* Clear */ + sv->save_level_fp = 0; /* Set the level for FP */ + sv->save_level_vec = 0; /* Set the level for vector */ + + sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC)); /* Make certain that floating point and vector are turned off */ + + fsv = (savearea *)act->mact.FPU_pcb; /* Get the start of the floating point chain */ + while(fsv) { /* Look until the end or we find it */ + if(!(fsv->save_level_fp)) { /* Is the the user state stuff? (the level is 0 if so) */ + sv->save_flags |= SAVfpuvalid; /* Show we have it */ + bcopy((char *)&fsv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */ + break; /* Done, everything else is all set up... */ + } + fsv = fsv->save_prev_float; /* Try the previous one */ + } + + fsv = (savearea *)act->mact.VMX_pcb; /* Get the start of the vector chain */ + while(fsv) { /* Look until the end or we find it */ + if(!(fsv->save_level_vec)) { /* Is the the user state stuff? (the level is 0 if so) */ + sv->save_flags |= SAVvmxvalid; /* Show we have it */ + bcopy((char *)&fsv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */ + break; /* Done, everything else is all set up... */ + } + fsv = fsv->save_prev_vector; /* Try the previous one */ + } + + return (void *)sv; /* Bye bye... */ +} + + + +/* + * Attaches saved user state context to an activation. We will replace any + * user state context with what is passed in. The saved context consists of a + * savearea that was setup by + * We will collect everything into one savearea and pass that back. + * + * The savearea is made to look like it belongs to the source activation. This needs to + * be adjusted when these contexts are attached to a new activation. + * + */ + +void act_thread_catt(void *ctx) { + + savearea *sv, *osv, *fsv, *psv; + unsigned int spc, i, *srs; + thread_act_t act; + + sv = (savearea *)ctx; /* Make this easier for C */ + + if((sv->save_prev != (savearea *)0xDEBB1ED0) || (sv->save_prev_float != (savearea *)0xE5DA11A5)) { /* See if valid savearea */ + panic("act_thread_catt: attempt to attach invalid context savearea - %08X\n", sv); /* Die */ + } + + act = current_act(); /* Find ourselves */ + +/* + * This next bit insures that any live facility context for this thread is discarded on every processor + * that may have it. + * + * Note that this will not be good if the activation has any kernel fp or vec contexts that are live. + * We won't worry about it because it would be silly to call this if we are a kernel task using altivec + * or floating point...... + */ + + for(i=0; i < real_ncpus; i++) { /* Cycle through processors */ + (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */ + (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].VMX_thread); /* Clear if ours */ + } + + +/* + * Now we make the savearea look like we own it + */ + + sv->save_prev = (savearea *)0; /* Clear */ + sv->save_prev_float = (savearea *)0; /* Clear */ + sv->save_prev_vector = (savearea *)0; /* Clear */ + sv->save_act = act; /* Point to the activation */ + + spc=(unsigned int)act->map->pmap->space; /* Get the space we're in */ + + srs=(unsigned int *)&sv->save_sr0; /* Point to the SRs */ + for(i=0; i < 16; i++) { /* Fill in the SRs for the new context */ + srs[i] = SEG_REG_PROT | (i<<20) | spc; /* Set the SRs */ + } + + sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc; /* Make sure the copyin is set */ + + osv = (savearea *)act->mact.VMX_pcb; /* Get the top vector savearea */ + + if(osv && (osv->save_level_vec == 1)) { /* Is the first one a special dummy one? */ + psv = osv; /* Yes, remember it */ + osv = osv->save_prev_vector; /* Step to the next */ + (savearea *)act->mact.VMX_pcb = osv; /* Dequeue it */ + psv->save_flags &= ~SAVvmxvalid; /* Clear the VMX flag */ + if(!(psv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(psv); /* Nope, release it */ + } + } + + psv = 0; + while(osv) { /* Any VMX saved state? */ + if(!(osv->save_level_vec)) break; /* Leave if this is user state */ + psv = osv; /* Save previous savearea address */ + osv = osv->save_prev_vector; /* Get one underneath our's */ + } + + if(osv) { /* Did we find one? */ + if(psv) psv->save_prev_vector = 0; /* Yes, clear pointer to it (it should always be last) or */ + else act->mact.VMX_pcb = 0; /* to the start if the only one */ + + osv->save_flags &= ~SAVvmxvalid; /* Clear the VMX flag */ + if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(osv); /* Nope, release it */ + } + } + + if(sv->save_flags & SAVvmxvalid) { /* Are we adding Altivec context? */ + if(psv) psv->save_prev_vector = sv; /* Yes, chain us to the end or */ + else act->mact.VMX_pcb = (pcb_t)sv; /* to the start if the only one */ + } + + osv = (savearea *)act->mact.FPU_pcb; /* Get the top floating point savearea */ + + if(osv && (osv->save_level_fp == 1)) { /* Is the first one a special dummy one? */ + psv = osv; /* Yes, remember it */ + osv = osv->save_prev_float; /* Step to the next */ + (savearea *)act->mact.FPU_pcb = osv; /* Dequeue it */ + psv->save_flags &= ~SAVfpuvalid; /* Clear the float flag */ + if(!(psv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(psv); /* Nope, release it */ + } + } + + psv = 0; + while(osv) { /* Any floating point saved state? */ + if(!(osv->save_level_fp)) break; /* Leave if this is user state */ + psv = osv; /* Save previous savearea address */ + osv = osv->save_prev_float; /* Get one underneath our's */ + } + + if(osv) { /* Did we find one? */ + if(psv) psv->save_prev_float = 0; /* Yes, clear pointer to it (it should always be last) or */ + else act->mact.FPU_pcb = 0; /* to the start if the only one */ + + osv->save_flags &= ~SAVfpuvalid; /* Clear the floating point flag */ + if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(osv); /* Nope, release it */ + } + } + + if(sv->save_flags & SAVfpuvalid) { /* Are we adding floating point context? */ + if(psv) psv->save_prev_float = sv; /* Yes, chain us to the end or */ + else act->mact.FPU_pcb = (pcb_t)sv; /* to the start if the only one */ + } + + osv = (savearea *)act->mact.pcb; /* Get the top general savearea */ + psv = 0; + while(osv) { /* Any floating point saved state? */ + if(osv->save_srr1 & MASK(MSR_PR)) break; /* Leave if this is user state */ + psv = osv; /* Save previous savearea address */ + osv = osv->save_prev; /* Get one underneath our's */ + } + + if(osv) { /* Did we find one? */ + if(psv) psv->save_prev = 0; /* Yes, clear pointer to it (it should always be last) or */ + else act->mact.pcb = 0; /* to the start if the only one */ + + osv->save_flags &= ~SAVattach; /* Clear the attached flag */ + if(!(osv->save_flags & SAVinuse)) { /* Anyone left with this one? */ + save_release(osv); /* Nope, release it */ + } + } + + if(psv) psv->save_prev = sv; /* Chain us to the end or */ + else act->mact.pcb = (pcb_t)sv; /* to the start if the only one */ + + hw_atomic_sub(&saveanchor.saveneed, 1); /* Unaccount for the savearea we think we "need" */ +} + + + +/* + * Releases saved context. We need this because the saved context is opague. + * be adjusted when these contexts are attached to a new activation. + * + */ + +void act_thread_cfree(void *ctx) { + + if((((savearea *)ctx)->save_prev != (savearea *)0xDEBB1ED0) || + (((savearea *)ctx)->save_prev_float != (savearea *)0xE5DA11A5)) { /* See if valid savearea */ + panic("act_thread_cfree: attempt to free invalid context savearea - %08X\n", ctx); /* Die */ + } + + ((savearea *)ctx)->save_flags = 0; /* Clear all flags since we release this in any case */ + save_release((savearea *)ctx); /* Release this one */ + hw_atomic_sub(&saveanchor.saveneed, 1); /* Unaccount for the savearea we think we "need" */ + + return; +} diff --git a/osfmk/ppc/thread_act.h b/osfmk/ppc/thread_act.h index 30bf02c8e..09e3097c5 100644 --- a/osfmk/ppc/thread_act.h +++ b/osfmk/ppc/thread_act.h @@ -34,15 +34,11 @@ #include <kern/lock.h> #include <kern/clock.h> - /* * Kernel state structure * * This holds the kernel state that is saved and restored across context - * switches. This is kept at the top of the kernel stack. - * - * XXX Some state is saved only because it is not saved on entry to the - * kernel from user mode. This needs to be straightened out. + * switches. */ /* @@ -93,12 +89,12 @@ typedef struct MachineThrAct { unsigned int VMX_cpu; /* The last processor to enable vector */ struct vmmCntrlEntry *vmmCEntry; /* Pointer current emulation context or 0 */ struct vmmCntrlTable *vmmControl; /* Pointer to virtual machine monitor control table */ - AbsoluteTime qactTimer; /* Time thread needs to interrupt. This is a single-shot timer. Zero is unset */ + uint64_t qactTimer; /* Time thread needs to interrupt. This is a single-shot timer. Zero is unset */ unsigned int ksp; /* points to TOP OF STACK or zero */ unsigned int bbDescAddr; /* Points to Blue Box Trap descriptor area in kernel (page aligned) */ unsigned int bbUserDA; /* Points to Blue Box Trap descriptor area in user (page aligned) */ unsigned int bbTableStart; /* Points to Blue Box Trap dispatch area in user */ - unsigned int bbPendRupt; /* Number of pending Blue Box interruptions */ + unsigned int emPendRupts; /* Number of pending emulated interruptions */ unsigned int bbTaskID; /* Opaque task ID for Blue Box threads */ unsigned int bbTaskEnv; /* Opaque task data reference for Blue Box threads */ unsigned int specFlags; /* Special flags */ @@ -108,20 +104,31 @@ typedef struct MachineThrAct { #define ignoreZeroFaultbit 0 #define floatUsedbit 1 #define vectorUsedbit 2 -#define bbNoMachSCbit 3 #define runningVMbit 4 #define floatCngbit 5 #define vectorCngbit 6 #define timerPopbit 7 +#define userProtKeybit 8 +/* NOTE: Do not move or assign bit 31 without changing exception vector ultra fast path code */ +#define bbThreadbit 28 +#define bbNoMachSCbit 29 +#define bbPreemptivebit 30 +#define spfReserved1 31 /* See note above */ #define ignoreZeroFault (1<<(31-ignoreZeroFaultbit)) #define floatUsed (1<<(31-floatUsedbit)) #define vectorUsed (1<<(31-vectorUsedbit)) -#define bbNoMachSC (1<<(31-bbNoMachSCbit)) #define runningVM (1<<(31-runningVMbit)) #define floatCng (1<<(31-floatCngbit)) #define vectorCng (1<<(31-vectorCngbit)) #define timerPop (1<<(31-timerPopbit)) +#define userProtKey (1<<(31-userProtKeybit)) +#define bbThread (1<<(31-bbThreadbit)) +#define bbNoMachSC (1<<(31-bbNoMachSCbit)) +#define bbPreemptive (1<<(31-bbPreemptivebit)) + +#define fvChkb 0 +#define fvChk 0x80000000 #ifdef MACH_BSD unsigned long cthread_self; /* for use of cthread package */ @@ -132,4 +139,8 @@ typedef struct MachineThrAct { extern struct ppc_saved_state * find_user_regs(thread_act_t act); extern struct ppc_float_state * find_user_fpu(thread_act_t act); +extern void *act_thread_csave(void); +extern void act_thread_catt(void *ctx); +extern void act_thread_cfree(void *ctx); + #endif /* _PPC_THREAD_ACT_H_ */ diff --git a/osfmk/ppc/trap.c b/osfmk/ppc/trap.c index 3b0fbddb8..05209b387 100644 --- a/osfmk/ppc/trap.c +++ b/osfmk/ppc/trap.c @@ -132,7 +132,7 @@ struct ppc_saved_state *trap(int trapno, switch (trapno) { case T_PREEMPT: /* Handle a preempt trap */ - ast_taken(FALSE, AST_URGENT, FALSE); + ast_taken(AST_PREEMPT, FALSE); break; case T_RESET: /* Reset interruption */ @@ -361,7 +361,7 @@ struct ppc_saved_state *trap(int trapno, ml_set_interrupts_enabled(FALSE); /* Turn off interruptions */ - panic("Unexpected user state trap(cpu %d): %08X DSISR=0x%08X DAR=0x%08X PC=0x%08X, MSR=0x%08X\n", + panic("Unexpected user state trap(cpu %d): 0x%08x DSISR=0x%08x DAR=0x%08x PC=0x%08x, MSR=0x%08x\n", cpu_number(), trapno, dsisr, dar, ssp->srr0, ssp->srr1); break; @@ -370,7 +370,7 @@ struct ppc_saved_state *trap(int trapno, kprintf("*** Reset exception ignored; srr0 = %08X, srr1 = %08X\n", ssp->srr0, ssp->srr1); #else - panic("Unexpected Reset exception: srr0 = %08X, srr1 = %08X\n", + panic("Unexpected Reset exception: srr0 = %0x08x, srr1 = %0x08x\n", ssp->srr0, ssp->srr1); #endif break; /* We just ignore these */ @@ -399,7 +399,7 @@ struct ppc_saved_state *trap(int trapno, case T_PROGRAM: if (ssp->srr1 & MASK(SRR1_PRG_FE)) { - fpu_save(); + fpu_save(thr_act); UPDATE_PPC_EXCEPTION_STATE; exception = EXC_ARITHMETIC; code = EXC_ARITHMETIC; @@ -482,7 +482,7 @@ struct ppc_saved_state *trap(int trapno, case T_AST: ml_set_interrupts_enabled(FALSE); - ast_taken(FALSE, AST_ALL, intr); + ast_taken(AST_ALL, intr); break; } @@ -555,7 +555,7 @@ struct ppc_saved_state *trap(int trapno, ml_set_interrupts_enabled(FALSE); if (USER_MODE(ssp->srr1)) while (ast_needed(cpu_number())) { - ast_taken(FALSE, AST_ALL, intr); + ast_taken(AST_ALL, intr); ml_set_interrupts_enabled(FALSE); } @@ -650,40 +650,45 @@ doexception( } char *trap_type[] = { - "0x000 Interrupt in vain", - "0x100 System reset", - "0x200 Machine check", - "0x300 Data access", - "0x400 Instruction access", - "0x500 External interrupt", - "0x600 Alignment", - "0x700 Program", - "0x800 Floating point", - "0x900 Decrementer", - "0xA00 I/O controller interface", - "0xB00 INVALID EXCEPTION", - "0xC00 System call exception", - "0xD00 Trace", - "0xE00 FP assist", - "0xF20 VMX", - "0xF00 INVALID EXCEPTION", - "0x1000 Instruction PTE miss", - "0x1100 Data load PTE miss", - "0x1200 Data store PTE miss", - "0x1300 Instruction Breakpoint", - "0x1400 System Management", - "0x1500 INVALID EXCEPTION", - "0x1600 Altivec Assist", - "0x1700 INVALID EXCEPTION", - "0x1800 INVALID EXCEPTION", - "0x1900 INVALID EXCEPTION", - "0x1A00 INVALID EXCEPTION", - "0x1B00 INVALID EXCEPTION", - "0x1C00 INVALID EXCEPTION", - "0x1D00 INVALID EXCEPTION", - "0x1E00 INVALID EXCEPTION", - "0x1F00 INVALID EXCEPTION", - "0x2000 Run Mode/Trace" + "Unknown", + "0x100 - System reset", + "0x200 - Machine check", + "0x300 - Data access", + "0x400 - Inst access", + "0x500 - Ext int", + "0x600 - Alignment", + "0x700 - Program", + "0x800 - Floating point", + "0x900 - Decrementer", + "0xA00 - n/a", + "0xB00 - n/a", + "0xC00 - System call", + "0xD00 - Trace", + "0xE00 - FP assist", + "0xF00 - Perf mon", + "0xF20 - VMX", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "0x1300 - Inst bkpnt", + "0x1400 - Sys mgmt", + "0x1600 - Altivec Assist", + "0x1700 - Thermal", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "INVALID EXCEPTION", + "0x2000 - Run Mode/Trace", + "Signal Processor", + "Preemption", + "Context Switch", + "Shutdown", + "System Failure" }; int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); @@ -708,9 +713,8 @@ void unresolved_kernel_trap(int trapno, if (message == NULL) message = trap_name; - printf("\n\nUnresolved kernel trap(cpu %d): %s DSISR=0x%08x DAR=0x%08x PC=0x%08x, MSR=0x%08X\n" - "generating stack backtrace prior to panic:\n\n", - cpu_number(), trap_name, dsisr, dar, ssp->srr0, ssp->srr1); + printf("\n\nUnresolved kernel trap(cpu %d): %s DAR=0x%08x PC=0x%08x\n", + cpu_number(), trap_name, dar, ssp->srr0); print_backtrace(ssp); diff --git a/osfmk/ppc/vmachmon.c b/osfmk/ppc/vmachmon.c index 383e62ac8..d46f6e1da 100644 --- a/osfmk/ppc/vmachmon.c +++ b/osfmk/ppc/vmachmon.c @@ -36,6 +36,7 @@ #include <kern/host.h> #include <kern/task.h> #include <kern/thread.h> +#include <kern/thread_act.h> #include <ppc/exception.h> #include <ppc/mappings.h> #include <ppc/thread_act.h> @@ -182,13 +183,18 @@ int vmm_init_context(struct savearea *save) return 1; } - /* If the client is requesting a newer major version than */ - /* we currently support, we'll have to fail. In the future, */ - /* we can add new major versions and support the older ones. */ + /* Make sure that the version requested is supported */ version = save->save_r3; /* Pick up passed in version */ - if ((version >> 16) > (kVmmCurrentVersion >> 16)) { + if (((version >> 16) < kVmmMinMajorVersion) || ((version >> 16) > (kVmmCurrentVersion >> 16))) { + save->save_r3 = KERN_FAILURE; /* Return failure */ + return 1; } - + + if((version & 0xFFFF) > kVmmCurMinorVersion) { /* Check for valid minor */ + save->save_r3 = KERN_FAILURE; /* Return failure */ + return 1; + } + act = current_act(); /* Pick up our activation */ ml_set_interrupts_enabled(TRUE); /* This can take a bit of time so pass interruptions */ @@ -440,6 +446,7 @@ void vmm_tear_down_all(thread_act_t act) { return; } + save->save_exception = kVmmBogusContext*4; /* Indicate that this context is bogus now */ s = splhigh(); /* Make sure interrupts are off */ vmm_force_exit(act, save); /* Force and exit from VM state */ splx(s); /* Restore interrupts */ @@ -486,9 +493,9 @@ void vmm_tear_down_all(thread_act_t act) { ** act - pointer to current thread activation ** index - index of vmm state for this page ** va - virtual address within the client's address -** space (must be page aligned) +** space ** ava - virtual address within the alternate address -** space (must be page aligned) +** space ** prot - protection flags ** ** Note that attempted mapping of areas in nested pmaps (shared libraries) or block mapped @@ -546,7 +553,12 @@ kern_return_t vmm_map_page( if(mp) { /* We found it... */ mpv = hw_cpv(mp); /* Convert mapping block to virtual */ - if(!(mpv->PTEr & 1)) break; /* If we are not write protected, we are ok... */ + + if(!mpv->physent) return KERN_FAILURE; /* If there is no physical entry (e.g., I/O area), we won't map it */ + + if(!(mpv->PTEr & 1)) break; /* If we are writable go ahead and map it... */ + + hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* Unlock the map before we try to fault the write bit on */ } ml_set_interrupts_enabled(TRUE); /* Enable interruptions */ @@ -555,11 +567,6 @@ kern_return_t vmm_map_page( if (ret != KERN_SUCCESS) return KERN_FAILURE; /* There isn't a page there, return... */ } - - if(!mpv->physent) { /* Is this an I/O area, e.g., framebuffer? */ - return KERN_FAILURE; /* Yes, we won't map it... */ - } - /* * Now we make a mapping using all of the attributes of the source page except for protection. * Also specify that the physical entry is locked. @@ -576,6 +583,43 @@ kern_return_t vmm_map_page( } +/*----------------------------------------------------------------------- +** vmm_map_execute +** +** This function maps a page from within the client's logical +** address space into the alternate address space of the +** Virtual Machine Monitor context and then directly starts executing. +** +** See description of vmm_map_page for details. +** +** Outputs: +** Normal exit is to run the VM. Abnormal exit is triggered via a +** non-KERN_SUCCESS return from vmm_map_page or later during the +** attempt to transition into the VM. +-----------------------------------------------------------------------*/ + +vmm_return_code_t vmm_map_execute( + thread_act_t act, + vmm_thread_index_t index, + vm_offset_t cva, + vm_offset_t ava, + vm_prot_t prot) +{ + kern_return_t ret; + vmmCntrlEntry *CEntry; + + CEntry = vmm_get_entry(act, index); /* Get and validate the index */ + + if (CEntry == NULL) return kVmmBogusContext; /* Return bogus context */ + + ret = vmm_map_page(act, index, cva, ava, prot); /* Go try to map the page on in */ + + if(ret == KERN_SUCCESS) vmm_execute_vm(act, index); /* Return was ok, launch the VM */ + + return kVmmInvalidAddress; /* We had trouble mapping in the page */ + +} + /*----------------------------------------------------------------------- ** vmm_get_page_mapping ** @@ -754,6 +798,93 @@ boolean_t vmm_get_page_dirty_flag( return (RC & 1); /* Return the change bit */ } + +/*----------------------------------------------------------------------- +** vmm_protect_page +** +** This function sets the protection bits of a mapped page +** +** Inputs: +** act - pointer to current thread activation +** index - index of vmm state for this page +** va - virtual address within the vmm's address +** space +** prot - Protection flags +** +** Outputs: +** none +** Protection bits of the mapping are modifed +** +-----------------------------------------------------------------------*/ + +kern_return_t vmm_protect_page( + thread_act_t act, + vmm_thread_index_t index, + vm_offset_t va, + vm_prot_t prot) +{ + vmmCntrlEntry *CEntry; + register mapping *mpv, *mp; + unsigned int RC; + + CEntry = vmm_get_entry(act, index); /* Convert index to entry */ + if (CEntry == NULL) return KERN_FAILURE; /* Either this isn't vmm thread or the index is bogus */ + + mp = hw_lock_phys_vir(CEntry->vmmPmap->space, va); /* Look up the mapping */ + if((unsigned int)mp & 1) { /* Did we timeout? */ + panic("vmm_protect_page: timeout locking physical entry for virtual address (%08X)\n", va); /* Yeah, scream about it! */ + return 1; /* Bad hair day, return dirty... */ + } + if(!mp) return KERN_SUCCESS; /* Not mapped, just return... */ + + hw_prot_virt(mp, prot); /* Set the protection */ + + mpv = hw_cpv(mp); /* Convert mapping block to virtual */ + hw_unlock_bit((unsigned int *)&mpv->physent->phys_link, PHYS_LOCK); /* We're done, unlock the physical entry */ + + CEntry->vmmLastMap = va & -PAGE_SIZE; /* Remember the last mapping we changed */ + CEntry->vmmFlags |= vmmMapDone; /* Set that we did a map operation */ + + return KERN_SUCCESS; /* Return */ +} + + +/*----------------------------------------------------------------------- +** vmm_protect_execute +** +** This function sets the protection bits of a mapped page +** and then directly starts executing. +** +** See description of vmm_protect_page for details. +** +** Outputs: +** Normal exit is to run the VM. Abnormal exit is triggered via a +** non-KERN_SUCCESS return from vmm_map_page or later during the +** attempt to transition into the VM. +-----------------------------------------------------------------------*/ + +vmm_return_code_t vmm_protect_execute( + thread_act_t act, + vmm_thread_index_t index, + vm_offset_t va, + vm_prot_t prot) +{ + kern_return_t ret; + vmmCntrlEntry *CEntry; + + CEntry = vmm_get_entry(act, index); /* Get and validate the index */ + + if (CEntry == NULL) return kVmmBogusContext; /* Return bogus context */ + + ret = vmm_protect_page(act, index, va, prot); /* Go try to change access */ + + if(ret == KERN_SUCCESS) vmm_execute_vm(act, index); /* Return was ok, launch the VM */ + + return kVmmInvalidAddress; /* We had trouble of some kind (shouldn't happen) */ + +} + + /*----------------------------------------------------------------------- ** vmm_get_float_state ** @@ -904,8 +1035,7 @@ kern_return_t vmm_set_timer( CEntry = vmm_get_entry(act, index); /* Convert index to entry */ if (CEntry == NULL) return KERN_FAILURE; /* Either this isn't vmm thread or the index is bogus */ - CEntry->vmmTimer.hi = timerhi; /* Set the high order part */ - CEntry->vmmTimer.lo = timerlo; /* Set the low order part */ + CEntry->vmmTimer = ((uint64_t)timerhi << 32) | timerlo; vmm_timer_pop(act); /* Go adjust all of the timer stuff */ return KERN_SUCCESS; /* Leave now... */ @@ -938,8 +1068,8 @@ kern_return_t vmm_get_timer( CEntry = vmm_get_entry(act, index); /* Convert index to entry */ if (CEntry == NULL) return KERN_FAILURE; /* Either this isn't vmm thread or the index is bogus */ - CEntry->vmmContextKern->return_params[0] = CEntry->vmmTimer.hi; /* Return the last timer value */ - CEntry->vmmContextKern->return_params[1] = CEntry->vmmTimer.lo; /* Return the last timer value */ + CEntry->vmmContextKern->return_params[0] = (CEntry->vmmTimer >> 32); /* Return the last timer value */ + CEntry->vmmContextKern->return_params[1] = (uint32_t)CEntry->vmmTimer; /* Return the last timer value */ return KERN_SUCCESS; } @@ -969,17 +1099,16 @@ void vmm_timer_pop( vmmCntrlEntry *CEntry; vmmCntrlTable *CTable; int cvi, any; - AbsoluteTime now, soonest; + uint64_t now, soonest; savearea *sv; if(!((unsigned int)act->mact.vmmControl & 0xFFFFFFFE)) { /* Are there any virtual machines? */ panic("vmm_timer_pop: No virtual machines defined; act = %08X\n", act); } - soonest.hi = 0xFFFFFFFF; /* Max time */ - soonest.lo = 0xFFFFFFFF; /* Max time */ + soonest = 0xFFFFFFFFFFFFFFFFULL; /* Max time */ - clock_get_uptime((AbsoluteTime *)&now); /* What time is it? */ + clock_get_uptime(&now); /* What time is it? */ CTable = act->mact.vmmControl; /* Make this easier */ any = 0; /* Haven't found a running unexpired timer yet */ @@ -988,13 +1117,13 @@ void vmm_timer_pop( if(!(CTable->vmmc[cvi].vmmFlags & vmmInUse)) continue; /* Do not check if the entry is empty */ - if(!(CTable->vmmc[cvi].vmmTimer.hi | CTable->vmmc[cvi].vmmTimer.hi)) { /* Is the timer reset? */ + if(CTable->vmmc[cvi].vmmTimer == 0) { /* Is the timer reset? */ CTable->vmmc[cvi].vmmFlags &= ~vmmTimerPop; /* Clear timer popped */ CTable->vmmc[cvi].vmmContextKern->vmmStat &= ~vmmTimerPop; /* Clear timer popped */ continue; /* Check next */ } - if (CMP_ABSOLUTETIME(&CTable->vmmc[cvi].vmmTimer, &now) <= 0) { + if (CTable->vmmc[cvi].vmmTimer <= now) { CTable->vmmc[cvi].vmmFlags |= vmmTimerPop; /* Set timer popped here */ CTable->vmmc[cvi].vmmContextKern->vmmStat |= vmmTimerPop; /* Set timer popped here */ if((unsigned int)&CTable->vmmc[cvi] == (unsigned int)act->mact.vmmCEntry) { /* Is this the running VM? */ @@ -1002,7 +1131,7 @@ void vmm_timer_pop( if(!sv) { /* Did we find something? */ panic("vmm_timer_pop: no user context; act = %08X\n", act); } - sv->save_exception = T_IN_VAIN; /* Indicate that this is a null exception */ + sv->save_exception = kVmmReturnNull*4; /* Indicate that this is a null exception */ vmm_force_exit(act, sv); /* Intercept a running VM */ } continue; /* Check the rest */ @@ -1014,19 +1143,175 @@ void vmm_timer_pop( any = 1; /* Show we found an active unexpired timer */ - if (CMP_ABSOLUTETIME(&CTable->vmmc[cvi].vmmTimer, &soonest) < 0) { - soonest.hi = CTable->vmmc[cvi].vmmTimer.hi; /* Set high order lowest timer */ - soonest.lo = CTable->vmmc[cvi].vmmTimer.lo; /* Set low order lowest timer */ - } + if (CTable->vmmc[cvi].vmmTimer < soonest) + soonest = CTable->vmmc[cvi].vmmTimer; } if(any) { - if (!(act->mact.qactTimer.hi | act->mact.qactTimer.lo) || - (CMP_ABSOLUTETIME(&soonest, &act->mact.qactTimer) <= 0)) { - act->mact.qactTimer.hi = soonest.hi; /* Set high order lowest timer */ - act->mact.qactTimer.lo = soonest.lo; /* Set low order lowest timer */ + if (act->mact.qactTimer == 0 || soonest <= act->mact.qactTimer) + act->mact.qactTimer = soonest; /* Set lowest timer */ + } + + return; +} + + + +/*----------------------------------------------------------------------- +** vmm_stop_vm +** +** This function prevents the specified VM(s) to from running. +** If any is currently executing, the execution is intercepted +** with a code of kVmmStopped. Note that execution of the VM is +** blocked until a vmmExecuteVM is called with the start flag set to 1. +** This provides the ability for a thread to stop execution of a VM and +** insure that it will not be run until the emulator has processed the +** "virtual" interruption. +** +** Inputs: +** vmmask - 32 bit mask corresponding to the VMs to put in stop state +** NOTE: if this mask is all 0s, any executing VM is intercepted with +* a kVmmStopped (but not marked stopped), otherwise this is a no-op. Also note that there +** note that there is a potential race here and the VM may not stop. +** +** Outputs: +** kernel return code indicating success +** or if no VMs are enabled, an invalid syscall exception. +-----------------------------------------------------------------------*/ + +int vmm_stop_vm(struct savearea *save) +{ + + thread_act_t act; + vmmCntrlTable *CTable; + int cvi, i; + task_t task; + thread_act_t fact; + unsigned int vmmask; + ReturnHandler *stopapc; + + ml_set_interrupts_enabled(TRUE); /* This can take a bit of time so pass interruptions */ + + task = current_task(); /* Figure out who we are */ + + task_lock(task); /* Lock our task */ + + fact = (thread_act_t)task->thr_acts.next; /* Get the first activation on task */ + act = 0; /* Pretend we didn't find it yet */ + + for(i = 0; i < task->thr_act_count; i++) { /* All of the activations */ + if(fact->mact.vmmControl) { /* Is this a virtual machine monitor? */ + act = fact; /* Yeah... */ + break; /* Bail the loop... */ + } + fact = (thread_act_t)fact->thr_acts.next; /* Go to the next one */ + } + + if(!((unsigned int)act)) { /* See if we have VMMs yet */ + task_unlock(task); /* No, unlock the task */ + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + return 0; /* Go generate a syscall exception */ + } + + act_lock_thread(act); /* Make sure this stays 'round */ + task_unlock(task); /* Safe to release now */ + + CTable = act->mact.vmmControl; /* Get the pointer to the table */ + + if(!((unsigned int)CTable & -2)) { /* Are there any all the way up yet? */ + act_unlock_thread(act); /* Unlock the activation */ + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + return 0; /* Go generate a syscall exception */ + } + + if(!(vmmask = save->save_r3)) { /* Get the stop mask and check if all zeros */ + act_unlock_thread(act); /* Unlock the activation */ + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + save->save_r3 = KERN_SUCCESS; /* Set success */ + return 1; /* Return... */ + } + + for(cvi = 0; cvi < kVmmMaxContextsPerThread; cvi++) { /* Search slots */ + if((0x80000000 & vmmask) && (CTable->vmmc[cvi].vmmFlags & vmmInUse)) { /* See if we need to stop and if it is in use */ + hw_atomic_or(&CTable->vmmc[cvi].vmmFlags, vmmXStop); /* Set this one to stop */ + } + vmmask = vmmask << 1; /* Slide mask over */ + } + + if(hw_compare_and_store(0, 1, &act->mact.emPendRupts)) { /* See if there is already a stop pending and lock out others if not */ + act_unlock_thread(act); /* Already one pending, unlock the activation */ + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + save->save_r3 = KERN_SUCCESS; /* Say we did it... */ + return 1; /* Leave */ + } + + if(!(stopapc = (ReturnHandler *)kalloc(sizeof(ReturnHandler)))) { /* Get a return handler control block */ + act->mact.emPendRupts = 0; /* No memory, say we have given up request */ + act_unlock_thread(act); /* Unlock the activation */ + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + save->save_r3 = KERN_RESOURCE_SHORTAGE; /* No storage... */ + return 1; /* Return... */ + } + + ml_set_interrupts_enabled(FALSE); /* Disable interruptions for now */ + + stopapc->handler = vmm_interrupt; /* Set interruption routine */ + + stopapc->next = act->handlers; /* Put our interrupt at the start of the list */ + act->handlers = stopapc; /* Point to us */ + + act_set_apc(act); /* Set an APC AST */ + ml_set_interrupts_enabled(TRUE); /* Enable interruptions now */ + + act_unlock_thread(act); /* Unlock the activation */ + + ml_set_interrupts_enabled(FALSE); /* Set back interruptions */ + save->save_r3 = KERN_SUCCESS; /* Hip, hip, horay... */ + return 1; +} + +/*----------------------------------------------------------------------- +** vmm_interrupt +** +** This function is executed asynchronously from an APC AST. +** It is to be used for anything that needs to interrupt a running VM. +** This include any kind of interruption generation (other than timer pop) +** or entering the stopped state. +** +** Inputs: +** ReturnHandler *rh - the return handler control block as required by the APC. +** thread_act_t act - the activation +** +** Outputs: +** Whatever needed to be done is done. +-----------------------------------------------------------------------*/ + +void vmm_interrupt(ReturnHandler *rh, thread_act_t act) { + + vmmCntrlTable *CTable; + savearea *sv; + boolean_t inter; + + + + kfree((vm_offset_t)rh, sizeof(ReturnHandler)); /* Release the return handler block */ + + inter = ml_set_interrupts_enabled(FALSE); /* Disable interruptions for now */ + + act->mact.emPendRupts = 0; /* Say that there are no more interrupts pending */ + CTable = act->mact.vmmControl; /* Get the pointer to the table */ + + if(!((unsigned int)CTable & -2)) return; /* Leave if we aren't doing VMs any more... */ + + if(act->mact.vmmCEntry && (act->mact.vmmCEntry->vmmFlags & vmmXStop)) { /* Do we need to stop the running guy? */ + sv = (savearea *)find_user_regs(act); /* Get the user state registers */ + if(!sv) { /* Did we find something? */ + panic("vmm_interrupt: no user context; act = %08X\n", act); } + sv->save_exception = kVmmStopped*4; /* Set a "stopped" exception */ + vmm_force_exit(act, sv); /* Intercept a running VM */ } + ml_set_interrupts_enabled(inter); /* Put interrupts back to what they were */ return; } diff --git a/osfmk/ppc/vmachmon.h b/osfmk/ppc/vmachmon.h index 4c5ed7f6c..2d7294888 100644 --- a/osfmk/ppc/vmachmon.h +++ b/osfmk/ppc/vmachmon.h @@ -84,14 +84,21 @@ typedef struct vmm_processor_state_t { typedef unsigned long vmm_return_code_t; typedef unsigned long vmm_thread_index_t; + enum { - kVmmCurrentVersion = 0x00010000 + kVmmCurMajorVersion = 0x0001, + kVmmCurMinorVersion = 0x0002, + kVmmMinMajorVersion = 0x0001, }; +#define kVmmCurrentVersion ((kVmmCurMajorVersion << 16) | kVmmCurMinorVersion) typedef unsigned long vmm_features_t; enum { - kVmmFeature_LittleEndian = 0x00000001 + kVmmFeature_LittleEndian = 0x00000001, + kVmmFeature_Stop = 0x00000002, + kVmmFeature_ExtendedMapping = 0x00000004, }; +#define kVmmCurrentFeatures (kVmmFeature_LittleEndian | kVmmFeature_Stop | kVmmFeature_ExtendedMapping) typedef unsigned long vmm_version_t; @@ -109,6 +116,10 @@ typedef struct vmm_state_page_t { #define vmmVectVRallb 2 #define vmmVectVAss 0x10000000 #define vmmVectVAssb 3 +#define vmmXStart 0x08000000 +#define vmmXStartb 4 +#define vmmKey 0x04000000 +#define vmmKeyb 5 vmm_return_code_t return_code; unsigned long return_params[4]; unsigned long gas[7]; /* For alignment */ @@ -134,11 +145,15 @@ enum { kVmmGetVectorState, kVmmSetTimer, kVmmGetTimer, - kVmmExecuteVM + kVmmExecuteVM, + kVmmProtectPage, + kVmmMapExecute, + kVmmProtectExecute, }; #define kVmmReturnNull 0 #define kVmmBogusContext 1 +#define kVmmStopped 2 #define kVmmReturnDataPageFault 3 #define kVmmReturnInstrPageFault 4 #define kVmmReturnAlignmentFault 6 @@ -146,7 +161,29 @@ enum { #define kVmmReturnSystemCall 12 #define kVmmReturnTraceException 13 #define kVmmAltivecAssist 22 +#define kVmmInvalidAddress 4096 +/* + * Storage Extended Protection modes + * Notes: + * To keep compatibility, vmmKey and the PPC key have reversed meanings, + * i.e., vmmKey 0 is PPC key 1 and vice versa. + * + * vmmKey Notes + * Mode 0 1 + * + * kVmmProtNARW not accessible read/write VM_PROT_NONE (not settable via VM calls) + * kVmmProtRORW read only read/write + * kVmmProtRWRW read/write read/write VM_PROT_WRITE or (VM_PROT_WRITE | VM_PROT_READ) + * kVmmProtRORO read only read only VM_PROT_READ + + */ + +#define kVmmProtXtnd 0x00000008 +#define kVmmProtNARW (kVmmProtXtnd | 0x00000000) +#define kVmmProtRORW (kVmmProtXtnd | 0x00000001) +#define kVmmProtRWRW (kVmmProtXtnd | 0x00000002) +#define kVmmProtRORO (kVmmProtXtnd | 0x00000003) /************************************************************************************* Internal Emulation Types @@ -154,10 +191,6 @@ enum { #define kVmmMaxContextsPerThread 32 -enum { - kVmmCurrentFeatures = kVmmFeature_LittleEndian -}; - typedef struct vmmCntrlEntry { /* Virtual Machine Monitor control table entry */ unsigned int vmmFlags; /* Assorted control flags */ #define vmmInUse 0x80000000 @@ -170,6 +203,8 @@ typedef struct vmmCntrlEntry { /* Virtual Machine Monitor control table ent #define vmmTimerPopb 3 #define vmmMapDone 0x08000000 #define vmmMapDoneb 4 +#define vmmXStop 0x00800000 +#define vmmXStopb 8 #define vmmSpfSave 0x000000FF #define vmmSpfSaveb 24 pmap_t vmmPmap; /* pmap for alternate context's view of task memory */ @@ -179,7 +214,7 @@ typedef struct vmmCntrlEntry { /* Virtual Machine Monitor control table ent unsigned int vmmFPU_cpu; /* CPU saved fp context is valid on */ pcb_t vmmVMX_pcb; /* Saved vector context */ unsigned int vmmVMX_cpu; /* CPU saved vector context is valid on */ - AbsoluteTime vmmTimer; /* Last set timer value. Zero means unset */ + uint64_t vmmTimer; /* Last set timer value. Zero means unset */ vm_offset_t vmmLastMap; /* Last vaddr mapping into virtual machine */ } vmmCntrlEntry; @@ -188,6 +223,7 @@ typedef struct vmmCntrlTable { /* Virtual Machine Monitor Control table */ } vmmCntrlTable; /* function decls for kernel level routines... */ +extern void vmm_execute_vm(thread_act_t act, vmm_thread_index_t index); extern vmmCntrlEntry *vmm_get_entry(thread_act_t act, vmm_thread_index_t index); extern kern_return_t vmm_tear_down_context(thread_act_t act, vmm_thread_index_t index); extern kern_return_t vmm_get_float_state(thread_act_t act, vmm_thread_index_t index); @@ -197,6 +233,12 @@ extern kern_return_t vmm_get_timer(thread_act_t act, vmm_thread_index_t index); extern void vmm_tear_down_all(thread_act_t act); extern kern_return_t vmm_map_page(thread_act_t act, vmm_thread_index_t hindex, vm_offset_t cva, vm_offset_t ava, vm_prot_t prot); +extern vmm_return_code_t vmm_map_execute(thread_act_t act, vmm_thread_index_t hindex, vm_offset_t cva, + vm_offset_t ava, vm_prot_t prot); +extern kern_return_t vmm_protect_page(thread_act_t act, vmm_thread_index_t hindex, vm_offset_t va, + vm_prot_t prot); +extern vmm_return_code_t vmm_protect_execute(thread_act_t act, vmm_thread_index_t hindex, vm_offset_t va, + vm_prot_t prot); extern vm_offset_t vmm_get_page_mapping(thread_act_t act, vmm_thread_index_t index, vm_offset_t va); extern kern_return_t vmm_unmap_page(thread_act_t act, vmm_thread_index_t index, vm_offset_t va); @@ -209,7 +251,9 @@ extern int vmm_init_context(struct savearea *); extern int vmm_dispatch(struct savearea *); extern int vmm_exit(thread_act_t act, struct savearea *); extern void vmm_force_exit(thread_act_t act, struct savearea *); -void vmm_timer_pop(thread_act_t act); +extern int vmm_stop_vm(struct savearea *save); +extern void vmm_timer_pop(thread_act_t act); +extern void vmm_interrupt(ReturnHandler *rh, thread_act_t act); #endif diff --git a/osfmk/ppc/vmachmon_asm.s b/osfmk/ppc/vmachmon_asm.s index a1039dceb..4b7e482b5 100644 --- a/osfmk/ppc/vmachmon_asm.s +++ b/osfmk/ppc/vmachmon_asm.s @@ -67,6 +67,9 @@ LEXT(vmm_dispatch_table) .long EXT(vmm_set_timer) ; Sets a timer value .long EXT(vmm_get_timer) ; Gets a timer value .long EXT(switchIntoVM) ; Switches to the VM context + .long EXT(vmm_protect_page) ; Sets protection values for a page + .long EXT(vmm_map_execute) ; Maps a page an launches VM + .long EXT(vmm_protect_execute) ; Sets protection values for a page and launches VM .set vmm_count,(.-EXT(vmm_dispatch_table))/4 ; Get the top number @@ -103,7 +106,7 @@ LEXT(vmm_dispatch) li r3,1 ; Set normal return with check for AST b EXT(ppcscret) ; Go back to handler... -vmmBogus: eqv r3,r3,r3 ; Bogus selector, treat like a bogus system call +vmmBogus: li r3,0 ; Bogus selector, treat like a bogus system call b EXT(ppcscret) ; Go back to handler... @@ -122,8 +125,8 @@ LEXT(vmm_get_version_sel) ; Selector based version of get version LEXT(vmm_get_features_sel) ; Selector based version of get features - lis r3,hi16(EXT(vmm_get_features_sel)) - ori r3,r3,lo16(EXT(vmm_get_features_sel)) + lis r3,hi16(EXT(vmm_get_features)) + ori r3,r3,lo16(EXT(vmm_get_features)) b selcomm @@ -132,8 +135,12 @@ LEXT(vmm_get_features_sel) ; Selector based version of get features LEXT(vmm_init_context_sel) ; Selector based version of init context - lis r3,hi16(EXT(vmm_init_context_sel)) - ori r3,r3,lo16(EXT(vmm_init_context_sel)) + lwz r4,saver4(r30) ; Get the passed in version + lwz r5,saver5(r30) ; Get the passed in comm area + lis r3,hi16(EXT(vmm_init_context)) + stw r4,saver3(r30) ; Cheat and move this parameter over + ori r3,r3,lo16(EXT(vmm_init_context)) + stw r5,saver4(r30) ; Cheat and move this parameter over selcomm: mtlr r3 ; Set the real routine address mr r3,r30 ; Pass in the savearea @@ -150,6 +157,10 @@ selcomm: mtlr r3 ; Set the real routine address * Then we will setup the new address space to run with, and anything else that is normally part * of a context switch. * + * The vmm_execute_vm entry point is for the fused vmm_map_execute and vmm_protect_execute + * calls. This is called, but never returned from. We always go directly back to the + * user from here. + * * Still need to figure out final floats and vectors. For now, we will go brute * force and when we go into the VM, we will force save any normal floats and * vectors. Then we will hide them and swap the VM copy (if any) into the normal @@ -159,10 +170,21 @@ selcomm: mtlr r3 ; Set the real routine address * */ + + .align 5 + .globl EXT(vmm_execute_vm) + +LEXT(vmm_execute_vm) + + lwz r30,ACT_MACT_PCB(r3) ; Restore the savearea pointer because it could be trash here + b EXT(switchIntoVM) ; Join common... + + .align 5 .globl EXT(switchIntoVM) LEXT(switchIntoVM) + lwz r5,vmmControl(r3) ; Pick up the control table address subi r4,r4,1 ; Switch to zero offset rlwinm. r2,r5,0,0,30 ; Is there a context there? (Note: we will ignore bit 31 so that we @@ -185,12 +207,35 @@ swvmmBogus: li r2,kVmmBogusContext ; Set bogus index return ; ; Here we check for any immediate intercepts. So far, the only -; one of these is a timer pop. We will not dispatch if the timer has -; already popped. They need to either reset the timer (i.e. set timer -; to 0) or to set a future time. +; two of these are a timer pop and and external stop. We will not dispatch if +; either is true. They need to either reset the timer (i.e. set timer +; to 0) or to set a future time, or if it is external stop, set the vmmXStopRst flag. ; swvmChkIntcpt: + lwz r6,vmmCntrl(r5) ; Get the control field + rlwinm. r7,r6,0,vmmXStartb,vmmXStartb ; Clear all but start bit + beq+ swvmChkStop ; Do not reset stop + andc r6,r6,r7 ; Clear it + li r8,vmmFlags ; Point to the flags + stw r6,vmmCntrl(r5) ; Set the control field + +swvmtryx: lwarx r4,r8,r2 ; Pick up the flags + rlwinm r4,r4,0,vmmXStopb+1,vmmXStopb-1 ; Clear the stop bit + stwcx. r4,r8,r2 ; Save the updated field + bne- swvmtryx ; Try again... + +swvmChkStop: + rlwinm. r26,r4,0,vmmXStopb,vmmXStopb ; Is this VM stopped? + beq+ swvmNoStop ; Nope... + + li r2,kVmmStopped ; Set stopped return + li r3,1 ; Set normal return with check for AST + stw r2,saver3(r30) ; Pass back the return code + stw r2,return_code(r5) ; Save the exit code + b EXT(ppcscret) ; Go back to handler... + +swvmNoStop: rlwinm. r26,r4,0,vmmTimerPopb,vmmTimerPopb ; Did the timer pop? beq+ swvmDoSwitch ; No... @@ -254,8 +299,11 @@ swvmDoSwitch: stw r20,saveexception(r30) ; Say we need to emulate a DSI stw r2,savedsisr(r30) ; Pretend we have a PTE miss -swvmNoMap: rlwimi r15,r17,32-(floatCngbit-vmmFloatCngdb),floatCngbit,vectorCngbit ; Shift and insert changed bits +swvmNoMap: lwz r20,vmmContextKern(r27) ; Get the comm area + rlwimi r15,r17,32-(floatCngbit-vmmFloatCngdb),floatCngbit,vectorCngbit ; Shift and insert changed bits + lwz r20,vmmCntrl(r20) ; Get the control flags rlwimi r17,r11,8,24,31 ; Save the old spf flags + rlwimi r15,r20,32+vmmKeyb-userProtKeybit,userProtKeybit,userProtKeybit ; Set the protection key stw r15,spcFlags(r10) ; Set per_proc copy of the special flags stw r15,ACT_MACT_SPF(r26) ; Get the special flags @@ -263,9 +311,9 @@ swvmNoMap: rlwimi r15,r17,32-(floatCngbit-vmmFloatCngdb),floatCngbit,vectorCngbi bl swapCtxt ; First, swap the general register state - lwz r17,vmmContextKern(r27) ; Get the comm area + lwz r17,vmmContextKern(r27) ; Get the comm area back - lwz r15,vmmCntrl(r17) ; Get the control flags + lwz r15,vmmCntrl(r17) ; Get the control flags again rlwinm. r0,r15,0,vmmFloatLoadb,vmmFloatLoadb ; Are there new floating point values? li r14,vmmppcFPRs ; Get displacement to the new values @@ -365,7 +413,9 @@ swvmNoNewVects: ; vmmxcng: mflr r21 ; Save the return point + mr r3,r26 ; Pass in the activation bl EXT(fpu_save) ; Save any floating point context + mr r3,r26 ; Pass in the activation bl EXT(vec_save) ; Save any vector point context lis r10,hi16(EXT(per_proc_info)) ; Get top of first per_proc @@ -461,6 +511,7 @@ LEXT(vmm_exit) rlwinm r11,r11,0,runningVMbit+1,runningVMbit-1 ; Clear the "in VM" flag stw r0,vmmCEntry(r16) ; Clear pointer to active context stw r19,vmmFlags(r2) ; Set the status flags + rlwinm r11,r11,0,userProtKeybit+1,userProtKeybit-1 ; Set back to normal protection key mfsprg r10,0 ; Get the per_proc block stw r11,ACT_MACT_SPF(r16) ; Get the special flags stw r11,spcFlags(r10) ; Set per_proc copy of the special flags @@ -516,6 +567,7 @@ LEXT(vmm_force_exit) cmplw r9,r11 ; Check if we were in a vm lwz r3,VMMAP_PMAP(r12) ; Get the pmap for the activation beq- vfeNotRun ; We were not in a vm.... + rlwinm r9,r9,0,userProtKeybit+1,userProtKeybit-1 ; Set back to normal protection key stw r0,vmmCEntry(r26) ; Clear pointer to active context mfsprg r10,0 ; Get the per_proc block stw r9,ACT_MACT_SPF(r26) ; Get the special flags @@ -532,7 +584,8 @@ LEXT(vmm_force_exit) stw r19,vmmStat(r5) ; Save the changed and popped flags bl swapCtxt ; Exchange the VM context for the emulator one - li r8,kVmmReturnNull ; Set a null return when we force an intercept + lwz r8,saveexception(r30) ; Pick up the exception code + rlwinm r8,r8,30,24,31 ; Convert exception to return code stw r8,saver3(r30) ; Set the return code as the return value also diff --git a/osfmk/vm/bsd_vm.c b/osfmk/vm/bsd_vm.c index 6c4a68dc7..01f6ffdef 100644 --- a/osfmk/vm/bsd_vm.c +++ b/osfmk/vm/bsd_vm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -33,8 +33,12 @@ #include <ipc/ipc_port.h> #include <ipc/ipc_space.h> #include <kern/thread.h> +#include <vm/memory_object.h> #include <vm/vm_pageout.h> +#include <libkern/OSAtomic.h> + +#include <default_pager/default_pager_types.h> /* BSD VM COMPONENT INTERFACES */ int @@ -89,27 +93,13 @@ int vnode_pager_workaround; typedef int vnode_port_t; typedef struct vnode_pager { - ipc_port_t pager; /* pager */ - ipc_port_t pager_handle; /* pager handle */ - ipc_port_t vm_obj_handle; /* memory object's control handle */ - vnode_port_t vnode_handle; /* vnode handle */ + int *pager; /* pager workaround pointer */ + unsigned int pager_ikot; /* JMM: fake ip_kotype() */ + unsigned int ref_count; /* reference count */ + memory_object_control_t control_handle; /* mem object control handle */ + vnode_port_t vnode_handle; /* vnode handle */ } *vnode_pager_t; -typedef struct vnode_port_entry { - queue_chain_t links; /* queue links */ - ipc_port_t name; /* port name */ - vnode_pager_t pager_rec; /* pager record */ -} *vnode_port_entry_t; - - -#define VNODE_PORT_HASH_COUNT 127 -#define vnode_port_hash(name_port) \ - (((int)(name_port) & 0xffffff) % VNODE_PORT_HASH_COUNT) - -queue_head_t vnode_port_hashtable[VNODE_PORT_HASH_COUNT]; -zone_t vnode_port_hash_zone; -decl_simple_lock_data(,vnode_port_hash_lock) - ipc_port_t trigger_name_to_port( @@ -123,49 +113,51 @@ void vnode_pager_alloc_map( void); -ipc_port_t +memory_object_t vnode_pager_setup( vnode_port_t, - ipc_port_t); + memory_object_t); -ipc_port_t -vnode_pager_lookup( - vnode_port_t, - ipc_port_t); kern_return_t vnode_pager_init( - ipc_port_t, - ipc_port_t, + memory_object_t, + memory_object_control_t, vm_size_t); +kern_return_t +vnode_pager_get_object_size( + memory_object_t, + memory_object_offset_t *); + kern_return_t vnode_pager_data_request( - ipc_port_t, - ipc_port_t, - vm_object_offset_t, + memory_object_t, + memory_object_offset_t, vm_size_t, vm_prot_t); kern_return_t vnode_pager_data_return( - ipc_port_t, - ipc_port_t, - vm_object_offset_t, - pointer_t, + memory_object_t, + memory_object_offset_t, vm_size_t, boolean_t, boolean_t); +kern_return_t +vnode_pager_data_initialize( + memory_object_t, + memory_object_offset_t, + vm_size_t); + void -vnode_pager_no_senders( - ipc_port_t, - mach_port_mscount_t); +vnode_pager_deallocate( + memory_object_t); kern_return_t vnode_pager_terminate( - ipc_port_t, - ipc_port_t); + memory_object_t); kern_return_t vnode_pager_cluster_read( @@ -179,14 +171,6 @@ vnode_pager_cluster_write( vm_object_offset_t, vm_size_t); -kern_return_t -memory_object_change_attributes( - vm_object_t, - memory_object_flavor_t, - memory_object_info_t, - mach_msg_type_number_t, - ipc_port_t, - mach_msg_type_name_t); int vnode_pagein( @@ -207,25 +191,17 @@ vnode_pageout( int, int *); +vm_object_offset_t +vnode_pager_get_filesize( + vnode_port_t); + vnode_pager_t vnode_object_create( vnode_port_t vp); -void -vnode_port_hash_init(void); - -void -vnode_port_hash_insert( - ipc_port_t, - vnode_pager_t); - vnode_pager_t -vnode_port_hash_lookup( - ipc_port_t); - -void -vnode_port_hash_delete( - ipc_port_t); +vnode_pager_lookup( + memory_object_t); void vnode_pager_release_from_cache( @@ -269,23 +245,40 @@ macx_triggers( mach_port_t trigger_name) { kern_return_t kr; - ipc_port_t default_pager_port = MACH_PORT_NULL; + memory_object_default_t default_pager; ipc_port_t trigger_port; + default_pager = MEMORY_OBJECT_DEFAULT_NULL; kr = host_default_memory_manager(host_priv_self(), - &default_pager_port, 0); + &default_pager, 0); if(kr != KERN_SUCCESS) { return EINVAL; } - trigger_port = trigger_name_to_port(trigger_name); - if(trigger_port == NULL) { - return EINVAL; + if (flags & HI_WAT_ALERT) { + trigger_port = trigger_name_to_port(trigger_name); + if(trigger_port == NULL) { + return EINVAL; + } + /* trigger_port is locked and active */ + ipc_port_make_send_locked(trigger_port); + /* now unlocked */ + default_pager_triggers(default_pager, + hi_water, low_water, + HI_WAT_ALERT, trigger_port); + } + + if (flags & LO_WAT_ALERT) { + trigger_port = trigger_name_to_port(trigger_name); + if(trigger_port == NULL) { + return EINVAL; + } + /* trigger_port is locked and active */ + ipc_port_make_send_locked(trigger_port); + /* and now its unlocked */ + default_pager_triggers(default_pager, + hi_water, low_water, + LO_WAT_ALERT, trigger_port); } - /* trigger_port is locked and active */ - ip_unlock(trigger_port); - default_pager_triggers(default_pager_port, - hi_water, low_water, flags, trigger_port); - ipc_port_make_send(trigger_port); /* * Set thread scheduling priority and policy for the current thread @@ -340,100 +333,47 @@ vnode_pager_bootstrap(void) size = (vm_size_t) sizeof(struct vnode_pager); vnode_pager_zone = zinit(size, (vm_size_t) MAX_VNODE*size, PAGE_SIZE, "vnode pager structures"); - vnode_port_hash_init(); - return; } /* * */ -ipc_port_t +memory_object_t vnode_pager_setup( vnode_port_t vp, - ipc_port_t pager) + memory_object_t pager) { vnode_pager_t vnode_object; - kern_return_t kr; - ipc_port_t previous; - - if (pager && - (vnode_object = vnode_port_hash_lookup(pager))) { - if (vnode_object->vnode_handle == vp) - return(pager); - } vnode_object = vnode_object_create(vp); if (vnode_object == VNODE_PAGER_NULL) panic("vnode_pager_setup: vnode_object_create() failed"); - - vnode_object->pager = ipc_port_alloc_kernel(); - assert (vnode_object->pager != IP_NULL); - pager_mux_hash_insert(vnode_object->pager, - (rpc_subsystem_t)&vnode_pager_workaround); - - vnode_object->pager_handle = ipc_port_make_send(vnode_object->pager); - - vnode_port_hash_insert(vnode_object->pager_handle, vnode_object); - - ipc_port_make_sonce(vnode_object->pager); - ip_lock(vnode_object->pager); /* unlocked in nsrequest below */ - ipc_port_nsrequest(vnode_object->pager, 1, vnode_object->pager, &previous); - - PAGER_DEBUG(PAGER_INIT, ("vnode_pager_setup: vp %x pager %x vnode_pager %x\n", vp, vnode_object->pager_handle, vnode_object)); - - ubc_setpager( vp, vnode_object->pager_handle); - return(vnode_object->pager_handle); -} - -/* - * - */ -ipc_port_t -vnode_pager_lookup( - vnode_port_t vp, - ipc_port_t pager) -{ - vnode_pager_t vnode_object; - kern_return_t kr; - - if (pager && - (vnode_object = vnode_port_hash_lookup(pager))) { - if (vnode_object->vnode_handle == vp) - return(vnode_object->vm_obj_handle); - else - return NULL; - } - else - return NULL; + return((memory_object_t)vnode_object); } /* * */ kern_return_t -vnode_pager_init(ipc_port_t pager, - ipc_port_t pager_request, +vnode_pager_init(memory_object_t mem_obj, + memory_object_control_t control, vm_size_t pg_size) { vnode_pager_t vnode_object; kern_return_t kr; memory_object_attr_info_data_t attributes; - vm_object_t vm_object; PAGER_DEBUG(PAGER_ALL, ("vnode_pager_init: %x, %x, %x\n", pager, pager_request, pg_size)); - vnode_object = vnode_port_hash_lookup(pager); - if (vnode_object == VNODE_PAGER_NULL) - panic("vnode_pager_init: lookup failed"); - - vnode_object->vm_obj_handle = pager_request; + if (control == MEMORY_OBJECT_CONTROL_NULL) + return KERN_INVALID_ARGUMENT; - vm_object = vm_object_lookup(pager_request); + vnode_object = vnode_pager_lookup(mem_obj); - if (vm_object == VM_OBJECT_NULL) - panic("vnode_pager_init: vm_object_lookup() failed"); + memory_object_control_reference(control); + vnode_object->control_handle = control; attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY; /* attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));*/ @@ -442,11 +382,10 @@ vnode_pager_init(ipc_port_t pager, attributes.temporary = TRUE; kr = memory_object_change_attributes( - vm_object, + control, MEMORY_OBJECT_ATTRIBUTE_INFO, (memory_object_info_t) &attributes, - MEMORY_OBJECT_ATTR_INFO_COUNT, - MACH_PORT_NULL, 0); + MEMORY_OBJECT_ATTR_INFO_COUNT); if (kr != KERN_SUCCESS) panic("vnode_pager_init: memory_object_change_attributes() failed"); @@ -458,47 +397,71 @@ vnode_pager_init(ipc_port_t pager, */ kern_return_t vnode_pager_data_return( - ipc_port_t mem_obj, - ipc_port_t control_port, - vm_object_offset_t offset, - pointer_t addr, + memory_object_t mem_obj, + memory_object_offset_t offset, vm_size_t data_cnt, boolean_t dirty, boolean_t kernel_copy) { register vnode_pager_t vnode_object; - vnode_object = vnode_port_hash_lookup(mem_obj); - if (vnode_object == VNODE_PAGER_NULL) - panic("vnode_pager_data_return: lookup failed"); + vnode_object = vnode_pager_lookup(mem_obj); vnode_pager_cluster_write(vnode_object, offset, data_cnt); return KERN_SUCCESS; } +kern_return_t +vnode_pager_data_initialize( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t data_cnt) +{ + return KERN_FAILURE; +} + +kern_return_t +vnode_pager_data_unlock( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t size, + vm_prot_t desired_access) +{ + return KERN_FAILURE; +} + +kern_return_t +vnode_pager_get_object_size( + memory_object_t mem_obj, + memory_object_offset_t *length) +{ + vnode_pager_t vnode_object; + + vnode_object = vnode_pager_lookup(mem_obj); + + *length = vnode_pager_get_filesize(vnode_object->vnode_handle); + return KERN_SUCCESS; +} + /* * */ kern_return_t vnode_pager_data_request( - ipc_port_t mem_obj, - ipc_port_t mem_obj_control, - vm_object_offset_t offset, + memory_object_t mem_obj, + memory_object_offset_t offset, vm_size_t length, vm_prot_t protection_required) { register vnode_pager_t vnode_object; - PAGER_DEBUG(PAGER_ALL, ("vnode_pager_data_request: %x, %x, %x, %x, %x\n", mem_obj, mem_obj_control, offset, length, protection_required)); + PAGER_DEBUG(PAGER_ALL, ("vnode_pager_data_request: %x, %x, %x, %x\n", mem_obj, offset, length, protection_required)); - vnode_object = vnode_port_hash_lookup(mem_obj); + vnode_object = vnode_pager_lookup(mem_obj); - PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pager_data_request: %x, %x, %x, %x, %x, vnode_object %x\n", mem_obj, mem_obj_control, offset, length, protection_required, vnode_object)); + PAGER_DEBUG(PAGER_PAGEIN, ("vnode_pager_data_request: %x, %x, %x, %x, vnode_object %x\n", mem_obj, offset, length, protection_required, vnode_object)); - if (vnode_object == VNODE_PAGER_NULL) - panic("vnode_pager_data_request: lookup failed"); - vnode_pager_cluster_read(vnode_object, offset, length); return KERN_SUCCESS; @@ -508,28 +471,36 @@ vnode_pager_data_request( * */ void -vnode_pager_no_senders( - ipc_port_t mem_obj, - mach_port_mscount_t mscount) -{ +vnode_pager_reference( + memory_object_t mem_obj) +{ register vnode_pager_t vnode_object; + unsigned int prev_ref_count; - PAGER_DEBUG(PAGER_ALL, ("vnode_pager_nosenders: %x, %x\n", mem_obj, mscount)); + vnode_object = vnode_pager_lookup(mem_obj); + prev_ref_count = OSIncrementAtomic((UInt32 *)&vnode_object->ref_count); + assert(prev_ref_count > 0); +} - vnode_object = vnode_port_hash_lookup(mem_obj); - if (vnode_object == VNODE_PAGER_NULL) - panic("vnode_pager_no_senders: lookup failed"); +/* + * + */ +void +vnode_pager_deallocate( + memory_object_t mem_obj) +{ + register vnode_pager_t vnode_object; - assert(vnode_object->pager_handle == mem_obj); + PAGER_DEBUG(PAGER_ALL, ("vnode_pager_deallocate: %x\n", mem_obj)); - pager_mux_hash_delete((ipc_port_t) vnode_object->pager_handle); - ipc_port_dealloc_kernel(vnode_object->pager); - vnode_port_hash_delete(vnode_object->pager_handle); - if (vnode_object->vnode_handle != (vnode_port_t) NULL) { - vnode_pager_vrele(vnode_object->vnode_handle); - } - zfree(vnode_pager_zone, (vm_offset_t) vnode_object); + vnode_object = vnode_pager_lookup(mem_obj); + if (OSDecrementAtomic((UInt32 *)&vnode_object->ref_count) == 1) { + if (vnode_object->vnode_handle != (vnode_port_t) NULL) { + vnode_pager_vrele(vnode_object->vnode_handle); + } + zfree(vnode_pager_zone, (vm_offset_t) vnode_object); + } return; } @@ -538,50 +509,52 @@ vnode_pager_no_senders( */ kern_return_t vnode_pager_terminate( - ipc_port_t mem_obj, - ipc_port_t mem_obj_control) + memory_object_t mem_obj) { - register vnode_pager_t vnode_object; + PAGER_DEBUG(PAGER_ALL, ("vnode_pager_terminate: %x\n", mem_obj)); - PAGER_DEBUG(PAGER_ALL, ("vnode_pager_terminate: %x, %x\n", mem_obj, mem_obj_control)); - - vnode_object = vnode_port_hash_lookup(mem_obj); - if (vnode_object == VNODE_PAGER_NULL) - panic("vnode_pager_terminate: lookup failed"); + return(KERN_SUCCESS); +} - assert(vnode_object->pager_handle == mem_obj); +/* + * + */ +kern_return_t +vnode_pager_synchronize( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t length, + vm_sync_t sync_flags) +{ + register vnode_pager_t vnode_object; - /* release extra send right created by the fact that the caller */ - /* of vnode_pager_setup does not establish a mapping between a */ - /* cache object and the mem_obj (AMO). When a subsequent vm_map */ - /* is done, vm_map will bump the send right count */ - ipc_port_release_send(mem_obj); + PAGER_DEBUG(PAGER_ALL, ("vnode_pager_synchronize: %x\n", mem_obj)); - /* release a send right because terminate is called directly and */ - /* not through IPC, the right won't disappear quietly */ - ipc_port_release_send(mem_obj); + vnode_object = vnode_pager_lookup(mem_obj); - ipc_port_dealloc_kernel(mem_obj_control); + memory_object_synchronize_completed(vnode_object->control_handle, offset, length); - return(KERN_SUCCESS); + return (KERN_SUCCESS); } /* * */ kern_return_t -vnode_pager_synchronize( - ipc_port_t pager, - ipc_port_t pager_request, - vm_object_offset_t offset, - vm_offset_t length, - vm_sync_t sync_flags) +vnode_pager_unmap( + memory_object_t mem_obj) { - memory_object_synchronize_completed(vm_object_lookup(pager_request), offset, length); + register vnode_pager_t vnode_object; - return (KERN_SUCCESS); + PAGER_DEBUG(PAGER_ALL, ("vnode_pager_unmap: %x\n", mem_obj)); + + vnode_object = vnode_pager_lookup(mem_obj); + + ubc_unmap(vnode_object->vnode_handle); + return KERN_SUCCESS; } + /* * */ @@ -603,7 +576,37 @@ vnode_pager_cluster_write( while (cnt) { - kret = vnode_pageout(vnode_object->vnode_handle, (upl_t )NULL, (vm_offset_t)NULL, offset, size, 0, &local_error); + kret = vnode_pageout(vnode_object->vnode_handle, + (upl_t )NULL, (vm_offset_t)NULL, + offset, size, 0, &local_error); +/* + if(kret == PAGER_ABSENT) { + Need to work out the defs here, 1 corresponds to + PAGER_ABSENT defined in bsd/vm/vm_pager.h However, + we should not be including that file here it is a + layering violation. +*/ + if(kret == 1) { + int uplflags; + upl_t upl = NULL; + int count = 0; + kern_return_t kr; + + uplflags = (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE | + UPL_SET_INTERNAL | UPL_COPYOUT_FROM); + count = 0; + kr = memory_object_upl_request( + vnode_object->control_handle, + offset, size, &upl, NULL, &count, uplflags); + if(kr != KERN_SUCCESS) { + panic("vnode_pager_cluster_write: upl request failed\n"); + } + upl_abort(upl, 0); + upl_deallocate(upl); + + error = 0; + local_error = 0; + } if (local_error != 0) { error = local_error; @@ -611,6 +614,7 @@ vnode_pager_cluster_write( } cnt -= size; offset += size; + size = (cnt < (PAGE_SIZE*32)) ? cnt : (PAGE_SIZE*32); /* effective min */ } #if 0 if (error != 0) @@ -633,25 +637,39 @@ vnode_pager_cluster_read( int error = 0; int local_error = 0; int kret; - int size; if(cnt & PAGE_MASK) { panic("vs_cluster_read: cnt not a multiple of PAGE_SIZE"); } - size = PAGE_SIZE; - - while (cnt) { - - kret = vnode_pagein(vnode_object->vnode_handle, (upl_t)NULL, (vm_offset_t)NULL, offset, size, 0, &local_error); - - if (local_error != 0) { - error = local_error; - local_error = 0; - } - cnt -= size; - offset += size; + kret = vnode_pagein(vnode_object->vnode_handle, (upl_t)NULL, (vm_offset_t)NULL, offset, cnt, 2, &local_error); +/* + if(kret == PAGER_ABSENT) { + Need to work out the defs here, 1 corresponds to PAGER_ABSENT + defined in bsd/vm/vm_pager.h However, we should not be including + that file here it is a layering violation. +*/ + if(kret == 1) { + int uplflags; + upl_t upl = NULL; + int count = 0; + kern_return_t kr; + + uplflags = (UPL_NO_SYNC | + UPL_CLEAN_IN_PLACE | UPL_SET_INTERNAL); + count = 0; + kr = memory_object_upl_request( + vnode_object->control_handle, offset, cnt, + &upl, NULL, &count, uplflags); + if(kr != KERN_SUCCESS) { + panic("vnode_pager_cluster_read: upl request failed\n"); + } + upl_abort(upl, 0); + upl_deallocate(upl); + + error = 1; } + if (error != 0) return(KERN_FAILURE); @@ -668,7 +686,7 @@ vnode_pager_release_from_cache( int *cnt) { memory_object_free_from_cache( - &realhost, (int)&vnode_pager_workaround, cnt); + &realhost, &vnode_pager_workaround, cnt); } /* @@ -683,109 +701,34 @@ vnode_object_create( vnode_object = (struct vnode_pager *) zalloc(vnode_pager_zone); if (vnode_object == VNODE_PAGER_NULL) return(VNODE_PAGER_NULL); - vnode_object->pager_handle = IP_NULL; - vnode_object->vm_obj_handle = IP_NULL; - vnode_object->vnode_handle = vp; - - return(vnode_object); -} - -/* - * - */ -void -vnode_port_hash_init(void) -{ - register vm_size_t size; - register int i; - - - size = (vm_size_t) sizeof(struct vnode_port_entry); - - vnode_port_hash_zone = zinit(size, - (vm_size_t) MAX_VNODE * size, - PAGE_SIZE, "vnode_pager port hash"); - - for (i = 0; i < VNODE_PORT_HASH_COUNT; i++) - queue_init(&vnode_port_hashtable[i]); - - simple_lock_init(&vnode_port_hash_lock,ETAP_NO_TRACE); -} - -/* - * - */ -void -vnode_port_hash_insert( - ipc_port_t name_port, - vnode_pager_t rec) -{ - register vnode_port_entry_t new_entry; - new_entry = (vnode_port_entry_t) zalloc(vnode_port_hash_zone); /* - * TODO: Delete the following check once MAX_VNODE is removed + * The vm_map call takes both named entry ports and raw memory + * objects in the same parameter. We need to make sure that + * vm_map does not see this object as a named entry port. So, + * we reserve the second word in the object for a fake ip_kotype + * setting - that will tell vm_map to use it as a memory object. */ - if (!new_entry) - panic("vnode_port_hash_insert: no space"); - new_entry->name = name_port; - new_entry->pager_rec = rec; - - simple_lock(&vnode_port_hash_lock); - queue_enter(&vnode_port_hashtable[vnode_port_hash(name_port)], - new_entry, vnode_port_entry_t, links); - simple_unlock(&vnode_port_hash_lock); + vnode_object->pager = &vnode_pager_workaround; + vnode_object->pager_ikot = IKOT_MEMORY_OBJECT; + vnode_object->ref_count = 1; + vnode_object->control_handle = MEMORY_OBJECT_CONTROL_NULL; + vnode_object->vnode_handle = vp; + + return(vnode_object); } /* * */ vnode_pager_t -vnode_port_hash_lookup( - ipc_port_t name_port) +vnode_pager_lookup( + memory_object_t name) { - register queue_t bucket; - register vnode_port_entry_t entry; - vnode_pager_t rec; - - bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)]; - - simple_lock(&vnode_port_hash_lock); - entry = (vnode_port_entry_t) queue_first(bucket); - while (!queue_end(bucket,&entry->links)) { - if (entry->name == name_port) { - rec = entry->pager_rec; - simple_unlock(&vnode_port_hash_lock); - return(rec); - } - entry = (vnode_port_entry_t)queue_next(&entry->links); - } - simple_unlock(&vnode_port_hash_lock); - return(VNODE_PAGER_NULL); -} + vnode_pager_t vnode_object; -/* - * - */ -void -vnode_port_hash_delete( - ipc_port_t name_port) -{ - register queue_t bucket; - register vnode_port_entry_t entry; - - bucket = (queue_t) &vnode_port_hashtable[vnode_port_hash(name_port)]; - - simple_lock(&vnode_port_hash_lock); - entry = (vnode_port_entry_t) queue_first(bucket); - while (!queue_end(bucket,&entry->links)) { - if (entry->name == name_port) { - queue_remove(bucket, entry, vnode_port_entry_t,links); - simple_unlock(&vnode_port_hash_lock); - zfree(vnode_port_hash_zone, (vm_offset_t) entry); - return; - } - entry = (vnode_port_entry_t)queue_next(&entry->links); - } - simple_unlock(&vnode_port_hash_lock); + vnode_object = (vnode_pager_t)name; + assert(vnode_object->pager == &vnode_pager_workaround); + return (vnode_object); } + diff --git a/osfmk/vm/device_vm.c b/osfmk/vm/device_vm.c new file mode 100644 index 000000000..c7fdc88bc --- /dev/null +++ b/osfmk/vm/device_vm.c @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ + +#include <sys/errno.h> +#include <kern/host.h> +#include <mach/mach_types.h> +#include <vm/vm_map.h> +#include <vm/vm_kern.h> +#include <vm/vm_pageout.h> +#include <mach/kern_return.h> +#include <mach/memory_object_types.h> +#include <mach/port.h> +#include <mach/policy.h> +#include <ipc/ipc_port.h> +#include <ipc/ipc_space.h> +#include <kern/thread.h> +#include <device/device_port.h> +#include <vm/vm_pageout.h> + +#include <libkern/OSAtomic.h> + + +/* Device VM COMPONENT INTERFACES */ + + +/* + * Device PAGER + */ + + +/* until component support available */ + + + +/* until component support available */ +int device_pager_workaround; + +typedef int device_port_t; + +typedef struct device_pager { + int *pager; /* pager workaround pointer */ + unsigned int pager_ikot; /* fake ip_kotype() */ + unsigned int ref_count; /* reference count */ + memory_object_control_t control_handle; /* mem object's cntrl handle */ + device_port_t device_handle; /* device_handle */ + vm_size_t size; + int flags; +} *device_pager_t; + + + +void +device_pager_bootstrap( + void); + + +memory_object_t +device_pager_setup( + memory_object_t, + int, + vm_size_t, + int); + +device_pager_t +device_pager_lookup( + memory_object_t); + +kern_return_t +device_pager_init( + memory_object_t, + memory_object_control_t, + vm_size_t); + + +kern_return_t +device_pager_data_request( + memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_prot_t); + +kern_return_t +device_pager_data_return( + memory_object_t, + memory_object_offset_t, + vm_size_t, + boolean_t, + boolean_t); + +void +device_pager_reference( + memory_object_t); + +void +device_pager_deallocate( + memory_object_t); + +kern_return_t +device_pager_data_initialize( + memory_object_t, + memory_object_offset_t, + vm_size_t); + +kern_return_t +device_pager_data_unlock( + memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_prot_t); + +kern_return_t +device_pager_terminate( + memory_object_t); + +kern_return_t +device_pager_synchronize( + memory_object_t, + memory_object_offset_t, + vm_offset_t, + vm_sync_t); + +kern_return_t +device_pager_unmap( + memory_object_t); + +device_pager_t +device_object_create(void); + +zone_t device_pager_zone; + + +#define DEVICE_PAGER_NULL ((device_pager_t) 0) + + +#define MAX_DNODE 10000 + + + + + +/* + * + */ +void +device_pager_bootstrap(void) +{ + register vm_size_t size; + + size = (vm_size_t) sizeof(struct device_pager); + device_pager_zone = zinit(size, (vm_size_t) MAX_DNODE*size, + PAGE_SIZE, "device node pager structures"); + + return; +} + +/* + * + */ +memory_object_t +device_pager_setup( + memory_object_t device, + int device_handle, + vm_size_t size, + int flags) +{ + device_pager_t device_object; + + device_object = device_object_create(); + if (device_object == DEVICE_PAGER_NULL) + panic("device_pager_setup: device_object_create() failed"); + + device_object->device_handle = device_handle; + device_object->size = size; + device_object->flags = 0; + if(flags & DEVICE_PAGER_CONTIGUOUS) { + device_object->flags |= DEVICE_PAGER_CONTIGUOUS; + } + if(flags & DEVICE_PAGER_NOPHYSCACHE) { + device_object->flags |= DEVICE_PAGER_NOPHYSCACHE; + } + + return((memory_object_t)device_object); +} + +/* + * + */ +kern_return_t +device_pager_populate_object( + memory_object_t device, + memory_object_offset_t offset, + vm_offset_t phys_addr, + vm_size_t size) +{ + device_pager_t device_object; + vm_object_t vm_object; + kern_return_t kr; + upl_t upl; + ipc_port_t previous; + + device_object = device_pager_lookup(device); + if(device_object == DEVICE_PAGER_NULL) + return KERN_FAILURE; + + vm_object = (vm_object_t)memory_object_control_to_vm_object( + device_object->control_handle); + if(vm_object == NULL) + return KERN_FAILURE; + + kr = vm_object_populate_with_private( + vm_object, offset, phys_addr, size); + if(kr != KERN_SUCCESS) + return kr; + + if(!vm_object->phys_contiguous) { + int null_size = 0; + kr = vm_object_upl_request(vm_object, + (vm_object_offset_t)offset, size, &upl, NULL, + &null_size, (UPL_NO_SYNC | UPL_CLEAN_IN_PLACE)); + + if(kr != KERN_SUCCESS) + panic("device_pager_populate_object: list_req failed"); + + upl_commit(upl, NULL); + upl_deallocate(upl); + } + + + return kr; +} + +/* + * + */ +device_pager_t +device_pager_lookup( + memory_object_t name) +{ + device_pager_t device_object; + + device_object = (device_pager_t)name; + assert(device_object->pager == &device_pager_workaround); + return (device_object); +} + +/* + * + */ +kern_return_t +device_pager_init(memory_object_t mem_obj, + memory_object_control_t control, + vm_size_t pg_size) +{ + device_pager_t device_object; + kern_return_t kr; + memory_object_attr_info_data_t attributes; + + vm_object_t vm_object; + + + if (control == MEMORY_OBJECT_CONTROL_NULL) + return KERN_INVALID_ARGUMENT; + + device_object = device_pager_lookup(mem_obj); + + memory_object_control_reference(control); + device_object->control_handle = control; + + +/* The following settings should be done through an expanded change */ +/* attributes call */ + + vm_object = (vm_object_t)memory_object_control_to_vm_object(control); + vm_object_lock(vm_object); + vm_object->private = TRUE; + if(device_object->flags & DEVICE_PAGER_CONTIGUOUS) + vm_object->phys_contiguous = TRUE; + if(device_object->flags & DEVICE_PAGER_NOPHYSCACHE) + vm_object->nophyscache = TRUE; + vm_object_unlock(vm_object); + + + attributes.copy_strategy = MEMORY_OBJECT_COPY_DELAY; + /* attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));*/ + attributes.cluster_size = (1 << (PAGE_SHIFT)); + attributes.may_cache_object = FALSE; + attributes.temporary = TRUE; + + kr = memory_object_change_attributes( + control, + MEMORY_OBJECT_ATTRIBUTE_INFO, + (memory_object_info_t) &attributes, + MEMORY_OBJECT_ATTR_INFO_COUNT); + if (kr != KERN_SUCCESS) + panic("device_pager_init: memory_object_change_attributes() failed"); + + return(KERN_SUCCESS); +} + +/* + * + */ +kern_return_t +device_pager_data_return( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t data_cnt, + boolean_t dirty, + boolean_t kernel_copy) +{ + device_pager_t device_object; + + device_object = device_pager_lookup(mem_obj); + if (device_object == DEVICE_PAGER_NULL) + panic("device_pager_data_return: lookup failed"); + + return device_data_action(device_object->device_handle, device_object, + VM_PROT_READ | VM_PROT_WRITE, offset, data_cnt); +} + +/* + * + */ +kern_return_t +device_pager_data_request( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t length, + vm_prot_t protection_required) +{ + device_pager_t device_object; + + device_object = device_pager_lookup(mem_obj); + + if (device_object == DEVICE_PAGER_NULL) + panic("device_pager_data_request: lookup failed"); + + device_data_action(device_object->device_handle, device_object, + VM_PROT_READ, offset, length); + return KERN_SUCCESS; +} + +/* + * + */ +void +device_pager_reference( + memory_object_t mem_obj) +{ + device_pager_t device_object; + unsigned int prev_ref_count; + + device_object = device_pager_lookup(mem_obj); + prev_ref_count = OSIncrementAtomic((UInt32 *)&device_object->ref_count); + assert(prev_ref_count > 0); +} + +/* + * + */ +void +device_pager_deallocate( + memory_object_t mem_obj) +{ + device_pager_t device_object; + + device_object = device_pager_lookup(mem_obj); + + if (OSDecrementAtomic((UInt32 *)&device_object->ref_count) == 1) { + if (device_object->device_handle != (device_port_t) NULL) { + device_close(device_object->device_handle); + } + zfree(device_pager_zone, (vm_offset_t) device_object); + } + return; +} + +kern_return_t +device_pager_data_initialize( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t data_cnt) +{ + return KERN_FAILURE; +} + +kern_return_t +device_pager_data_unlock( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_size_t size, + vm_prot_t desired_access) +{ + return KERN_FAILURE; +} + +device_pager_terminate( + memory_object_t mem_obj) +{ + return KERN_SUCCESS; +} + + + +/* + * + */ +kern_return_t +device_pager_synchronize( + memory_object_t mem_obj, + memory_object_offset_t offset, + vm_offset_t length, + vm_sync_t sync_flags) +{ + device_pager_t device_object; + + device_object = device_pager_lookup(mem_obj); + + memory_object_synchronize_completed( + device_object->control_handle, offset, length); + + return KERN_SUCCESS; +} + +/* + * + */ +kern_return_t +device_pager_unmap( + memory_object_t mem_obj) +{ + return KERN_SUCCESS; +} + + + +/* + * + */ +device_pager_t +device_object_create() +{ + register device_pager_t device_object; + + device_object = (struct device_pager *) zalloc(device_pager_zone); + if (device_object == DEVICE_PAGER_NULL) + return(DEVICE_PAGER_NULL); + device_object->pager = &device_pager_workaround; + device_object->pager_ikot = IKOT_MEMORY_OBJECT; + device_object->ref_count = 1; + device_object->control_handle = MEMORY_OBJECT_CONTROL_NULL; + + + return(device_object); +} + diff --git a/osfmk/vm/memory_object.c b/osfmk/vm/memory_object.c index 6c51bdcb9..90de30229 100644 --- a/osfmk/vm/memory_object.c +++ b/osfmk/vm/memory_object.c @@ -56,11 +56,6 @@ * External memory management interface control functions. */ -#ifdef MACH_BSD -/* THIS code should be removed when the component merge is completed */ -extern int vnode_pager_workaround; -#endif - #include <advisory_pageout.h> /* @@ -70,50 +65,50 @@ extern int vnode_pager_workaround; #include <mach/std_types.h> /* For pointer_t */ #include <mach/mach_types.h> +#include <mach/mig.h> #include <mach/kern_return.h> #include <mach/memory_object.h> #include <mach/memory_object_default.h> #include <mach/memory_object_control_server.h> -#include <mach/mach_host_server.h> +#include <mach/host_priv_server.h> #include <mach/boolean.h> #include <mach/vm_prot.h> #include <mach/message.h> -#include <vm/vm_object.h> -#include <vm/vm_fault.h> /* * Implementation dependencies: */ #include <string.h> /* For memcpy() */ +#include <kern/xpr.h> +#include <kern/host.h> +#include <kern/thread.h> /* For current_thread() */ +#include <kern/ipc_mig.h> +#include <kern/misc_protos.h> + +#include <vm/vm_object.h> +#include <vm/vm_fault.h> #include <vm/memory_object.h> #include <vm/vm_page.h> #include <vm/vm_pageout.h> #include <vm/pmap.h> /* For pmap_clear_modify */ -#include <kern/xpr.h> -#include <kern/thread.h> /* For current_thread() */ -#include <kern/host.h> #include <vm/vm_kern.h> /* For kernel_map, vm_move */ #include <vm/vm_map.h> /* For vm_map_pageable */ -#include <ipc/ipc_port.h> -#include <ipc/ipc_space.h> - -#include <kern/misc_protos.h> #if MACH_PAGEMAP #include <vm/vm_external.h> #endif /* MACH_PAGEMAP */ -ipc_port_t memory_manager_default = IP_NULL; -vm_size_t memory_manager_default_cluster = 0; -decl_mutex_data(,memory_manager_default_lock) +memory_object_default_t memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL; +vm_size_t memory_manager_default_cluster = 0; +decl_mutex_data(, memory_manager_default_lock) /* * Forward ref to file-local function: */ boolean_t -memory_object_update(vm_object_t, vm_object_offset_t, +vm_object_update(vm_object_t, vm_object_offset_t, vm_size_t, memory_object_return_t, int, vm_prot_t); @@ -248,13 +243,13 @@ memory_object_lock_page( */ if (prot != VM_PROT_NO_CHANGE) { + if ((m->page_lock ^ prot) & prot) { + pmap_page_protect(m->phys_addr, VM_PROT_ALL & ~prot); + } #if 0 /* code associated with the vestigial * memory_object_data_unlock */ - if ((m->page_lock ^ prot) & prot) { - pmap_page_protect(m->phys_addr, VM_PROT_ALL & ~prot); - } m->page_lock = prot; m->lock_supplied = TRUE; if (prot != VM_PROT_NONE) @@ -329,6 +324,7 @@ memory_object_lock_page( return(MEMORY_OBJECT_LOCK_RESULT_DONE); } + #define LIST_REQ_PAGEOUT_PAGES(object, data_cnt, action, po) \ MACRO_BEGIN \ \ @@ -337,107 +333,15 @@ MACRO_BEGIN \ \ vm_object_unlock(object); \ \ - if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == \ - ((rpc_subsystem_t) &vnode_pager_workaround)) { \ - (void) vnode_pager_data_return(object->pager, \ - object->pager_request, \ - po, \ - POINTER_T(0), \ - data_cnt, \ - (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \ - !should_flush); \ - } else { \ (void) memory_object_data_return(object->pager, \ - object->pager_request, \ po, \ - POINTER_T(0), \ data_cnt, \ (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \ !should_flush); \ - } \ \ vm_object_lock(object); \ - \ MACRO_END -#ifdef MACH_BSD -#define PAGEOUT_PAGES(object, new_object, new_offset, action, po) \ -MACRO_BEGIN \ - \ - vm_map_copy_t copy; \ - register int i; \ - register vm_page_t hp; \ - \ - vm_object_unlock(object); \ - \ - (void) vm_map_copyin_object(new_object, 0, new_offset, ©); \ - \ - if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == \ - ((rpc_subsystem_t) &vnode_pager_workaround)) { \ - (void) vnode_pager_data_return(object->pager, \ - object->pager_request, \ - po, \ - POINTER_T(copy), \ - new_offset, \ - (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \ - !should_flush); \ - } else { \ - (void) memory_object_data_return(object->pager, \ - object->pager_request, \ - po, \ - POINTER_T(copy), \ - new_offset, \ - (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \ - !should_flush); \ - } \ - \ - vm_object_lock(object); \ - \ - for (i = 0; i < atop(new_offset); i++) { \ - hp = holding_pages[i]; \ - if (hp != VM_PAGE_NULL) { \ - vm_object_paging_end(object); \ - VM_PAGE_FREE(hp); \ - } \ - } \ - \ - new_object = VM_OBJECT_NULL; \ -MACRO_END -#else -#define PAGEOUT_PAGES(object, new_object, new_offset, action, po) \ -MACRO_BEGIN \ - \ - vm_map_copy_t copy; \ - register int i; \ - register vm_page_t hp; \ - \ - vm_object_unlock(object); \ - \ - (void) vm_map_copyin_object(new_object, 0, new_offset, ©); \ - \ - (void) memory_object_data_return( \ - object->pager, \ - object->pager_request, \ - po, \ - POINTER_T(copy), \ - new_offset, \ - (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN), \ - !should_flush); \ - \ - vm_object_lock(object); \ - \ - for (i = 0; i < atop(new_offset); i++) { \ - hp = holding_pages[i]; \ - if (hp != VM_PAGE_NULL) { \ - vm_object_paging_end(object); \ - VM_PAGE_FREE(hp); \ - } \ - } \ - \ - new_object = VM_OBJECT_NULL; \ -MACRO_END -#endif - /* * Routine: memory_object_lock_request [user interface] * @@ -465,68 +369,107 @@ MACRO_END kern_return_t memory_object_lock_request( - register vm_object_t object, - register vm_object_offset_t offset, - register vm_object_size_t size, + memory_object_control_t control, + memory_object_offset_t offset, + memory_object_size_t size, memory_object_return_t should_return, int flags, - vm_prot_t prot, - ipc_port_t reply_to, - mach_msg_type_name_t reply_to_type) + vm_prot_t prot) { + vm_object_t object; vm_object_offset_t original_offset = offset; boolean_t should_flush=flags & MEMORY_OBJECT_DATA_FLUSH; XPR(XPR_MEMORY_OBJECT, - "m_o_lock_request, obj 0x%X off 0x%X size 0x%X flags %X prot %X\n", - (integer_t)object, offset, size, + "m_o_lock_request, control 0x%X off 0x%X size 0x%X flags %X prot %X\n", + (integer_t)control, offset, size, (((should_return&1)<<1)|should_flush), prot); /* * Check for bogus arguments. */ + object = memory_object_control_to_vm_object(control); if (object == VM_OBJECT_NULL) return (KERN_INVALID_ARGUMENT); - if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE) { - vm_object_deallocate(object); + if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE) return (KERN_INVALID_ARGUMENT); - } size = round_page(size); /* * Lock the object, and acquire a paging reference to - * prevent the memory_object and control ports from - * being destroyed. + * prevent the memory_object reference from being released. */ - vm_object_lock(object); vm_object_paging_begin(object); offset -= object->paging_offset; - (void)memory_object_update(object, + (void)vm_object_update(object, offset, size, should_return, flags, prot); - if (IP_VALID(reply_to)) { - vm_object_unlock(object); - - /* consumes our naked send-once/send right for reply_to */ - (void) memory_object_lock_completed(reply_to, reply_to_type, - object->pager_request, original_offset, size); - - vm_object_lock(object); - } - vm_object_paging_end(object); vm_object_unlock(object); - vm_object_deallocate(object); return (KERN_SUCCESS); } /* - * Routine: memory_object_sync + * memory_object_release_name: [interface] + * + * Enforces name semantic on memory_object reference count decrement + * This routine should not be called unless the caller holds a name + * reference gained through the memory_object_named_create or the + * memory_object_rename call. + * If the TERMINATE_IDLE flag is set, the call will return if the + * reference count is not 1. i.e. idle with the only remaining reference + * being the name. + * If the decision is made to proceed the name field flag is set to + * false and the reference count is decremented. If the RESPECT_CACHE + * flag is set and the reference count has gone to zero, the + * memory_object is checked to see if it is cacheable otherwise when + * the reference count is zero, it is simply terminated. + */ + +kern_return_t +memory_object_release_name( + memory_object_control_t control, + int flags) +{ + vm_object_t object; + + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); + + return vm_object_release_name(object, flags); +} + + + +/* + * Routine: memory_object_destroy [user interface] + * Purpose: + * Shut down a memory object, despite the + * presence of address map (or other) references + * to the vm_object. + */ +kern_return_t +memory_object_destroy( + memory_object_control_t control, + kern_return_t reason) +{ + vm_object_t object; + + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); + + return (vm_object_destroy(object, reason)); +} + +/* + * Routine: vm_object_sync * * Kernel internal function to synch out pages in a given * range within an object to its memory manager. Much the @@ -550,17 +493,17 @@ memory_object_lock_request( */ boolean_t -memory_object_sync( +vm_object_sync( vm_object_t object, vm_object_offset_t offset, - vm_object_size_t size, + vm_size_t size, boolean_t should_flush, boolean_t should_return) { boolean_t rv; - XPR(XPR_MEMORY_OBJECT, - "m_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n", + XPR(XPR_VM_OBJECT, + "vm_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n", (integer_t)object, offset, size, should_flush, should_return); /* @@ -571,7 +514,7 @@ memory_object_sync( vm_object_lock(object); vm_object_paging_begin(object); - rv = memory_object_update(object, offset, size, + rv = vm_object_update(object, offset, size, (should_return) ? MEMORY_OBJECT_RETURN_ALL : MEMORY_OBJECT_RETURN_NONE, @@ -586,14 +529,14 @@ memory_object_sync( } /* - * Routine: memory_object_update + * Routine: vm_object_update * Description: - * Work function for m_o_lock_request(), m_o_sync(). + * Work function for m_o_lock_request(), vm_o_sync(). * * Called with object locked and paging ref taken. */ kern_return_t -memory_object_update( +vm_object_update( register vm_object_t object, register vm_object_offset_t offset, register vm_size_t size, @@ -613,9 +556,7 @@ memory_object_update( boolean_t data_returned = FALSE; boolean_t update_cow; boolean_t should_flush = flags & MEMORY_OBJECT_DATA_FLUSH; -#ifndef NOT_LIST_REQ boolean_t pending_pageout = FALSE; -#endif /* * To avoid blocking while scanning for pages, save @@ -702,7 +643,7 @@ memory_object_update( (int *)0, &error, FALSE, - FALSE)) { + FALSE, NULL, 0)) { case VM_FAULT_SUCCESS: if(top_page) { @@ -906,17 +847,10 @@ BYPASS_COW_COPYIN: * We have completed the scan for applicable pages. * Clean any pages that have been saved. */ -#ifdef NOT_LIST_REQ - if (new_object != VM_OBJECT_NULL) { - PAGEOUT_PAGES(object, new_object, new_offset, pageout_action, - paging_offset); - } -#else if (pending_pageout) { LIST_REQ_PAGEOUT_PAGES(object, data_cnt, pageout_action, paging_offset); } -#endif return (data_returned); } @@ -933,11 +867,12 @@ BYPASS_COW_COPYIN: kern_return_t memory_object_synchronize_completed( - vm_object_t object, - vm_object_offset_t offset, - vm_offset_t length) + memory_object_control_t control, + memory_object_offset_t offset, + vm_offset_t length) { - msync_req_t msr; + vm_object_t object; + msync_req_t msr; XPR(XPR_MEMORY_OBJECT, "m_o_sync_completed, object 0x%X, offset 0x%X length 0x%X\n", @@ -947,9 +882,9 @@ memory_object_synchronize_completed( * Look for bogus arguments */ - if (object == VM_OBJECT_NULL) { - return KERN_INVALID_ARGUMENT; - } + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); vm_object_lock(object); @@ -965,7 +900,6 @@ memory_object_synchronize_completed( if (queue_end(&object->msr_q, (queue_entry_t)msr)) { vm_object_unlock(object); - vm_object_deallocate(object); return KERN_INVALID_ARGUMENT; } @@ -974,13 +908,12 @@ memory_object_synchronize_completed( msr->flag = VM_MSYNC_DONE; msr_unlock(msr); thread_wakeup((event_t) msr); - vm_object_deallocate(object); return KERN_SUCCESS; }/* memory_object_synchronize_completed */ - -kern_return_t -memory_object_set_attributes_common( + +static kern_return_t +vm_object_set_attributes_common( vm_object_t object, boolean_t may_cache, memory_object_copy_strategy_t copy_strategy, @@ -1007,15 +940,13 @@ memory_object_set_attributes_common( case MEMORY_OBJECT_COPY_DELAY: break; default: - vm_object_deallocate(object); return(KERN_INVALID_ARGUMENT); } #if !ADVISORY_PAGEOUT - if (silent_overwrite || advisory_pageout) { - vm_object_deallocate(object); + if (silent_overwrite || advisory_pageout) return(KERN_INVALID_ARGUMENT); - } + #endif /* !ADVISORY_PAGEOUT */ if (may_cache) may_cache = TRUE; @@ -1029,10 +960,8 @@ memory_object_set_attributes_common( * and be a power of 2 number of pages. */ if ((cluster_size & (PAGE_SIZE-1)) || - ((pages_per_cluster-1) & pages_per_cluster)) { - vm_object_deallocate(object); + ((pages_per_cluster-1) & pages_per_cluster)) return KERN_INVALID_ARGUMENT; - } } vm_object_lock(object); @@ -1066,8 +995,6 @@ memory_object_set_attributes_common( vm_object_unlock(object); - vm_object_deallocate(object); - return(KERN_SUCCESS); } @@ -1076,31 +1003,32 @@ memory_object_set_attributes_common( * * XXX This routine cannot be completed until the vm_msync, clean * in place, and cluster work is completed. See ifdef notyet - * below and note that memory_object_set_attributes_common() + * below and note that vm_object_set_attributes_common() * may have to be expanded. */ kern_return_t memory_object_change_attributes( - vm_object_t object, - memory_object_flavor_t flavor, - memory_object_info_t attributes, - mach_msg_type_number_t count, - ipc_port_t reply_to, - mach_msg_type_name_t reply_to_type) + memory_object_control_t control, + memory_object_flavor_t flavor, + memory_object_info_t attributes, + mach_msg_type_number_t count) { - kern_return_t result = KERN_SUCCESS; - boolean_t temporary; - boolean_t may_cache; - boolean_t invalidate; + vm_object_t object; + kern_return_t result = KERN_SUCCESS; + boolean_t temporary; + boolean_t may_cache; + boolean_t invalidate; vm_size_t cluster_size; memory_object_copy_strategy_t copy_strategy; - boolean_t silent_overwrite; + boolean_t silent_overwrite; boolean_t advisory_pageout; + object = memory_object_control_to_vm_object(control); if (object == VM_OBJECT_NULL) - return(KERN_INVALID_ARGUMENT); + return (KERN_INVALID_ARGUMENT); vm_object_lock(object); + temporary = object->temporary; may_cache = object->can_persist; copy_strategy = object->copy_strategy; @@ -1209,10 +1137,8 @@ memory_object_change_attributes( break; } - if (result != KERN_SUCCESS) { - vm_object_deallocate(object); + if (result != KERN_SUCCESS) return(result); - } if (copy_strategy == MEMORY_OBJECT_COPY_TEMPORARY) { copy_strategy = MEMORY_OBJECT_COPY_DELAY; @@ -1222,45 +1148,31 @@ memory_object_change_attributes( } /* - * Do the work and throw away our object reference. It - * is important that the object reference be deallocated - * BEFORE sending the reply. The whole point of the reply - * is that it shows up after the terminate message that - * may be generated by setting the object uncacheable. - * * XXX may_cache may become a tri-valued variable to handle * XXX uncache if not in use. */ - result = memory_object_set_attributes_common(object, + return (vm_object_set_attributes_common(object, may_cache, copy_strategy, temporary, cluster_size, silent_overwrite, - advisory_pageout); - - if (IP_VALID(reply_to)) { - /* consumes our naked send-once/send right for reply_to */ - (void) memory_object_change_completed(reply_to, reply_to_type, - object->alive ? - object->pager_request : PAGER_REQUEST_NULL, - flavor); - } - - return(result); + advisory_pageout)); } kern_return_t memory_object_get_attributes( - vm_object_t object, + memory_object_control_t control, memory_object_flavor_t flavor, memory_object_info_t attributes, /* pointer to OUT array */ mach_msg_type_number_t *count) /* IN/OUT */ { - kern_return_t ret = KERN_SUCCESS; + kern_return_t ret = KERN_SUCCESS; + vm_object_t object; - if (object == VM_OBJECT_NULL) - return(KERN_INVALID_ARGUMENT); + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); vm_object_lock(object); @@ -1370,30 +1282,90 @@ memory_object_get_attributes( vm_object_unlock(object); - vm_object_deallocate(object); - return(ret); } -int vm_stat_discard_cleared_reply = 0; -int vm_stat_discard_cleared_unset = 0; -int vm_stat_discard_cleared_too_late = 0; +/* + * Routine: memory_object_upl_request [interface] + * Purpose: + * Cause the population of a portion of a vm_object. + * Depending on the nature of the request, the pages + * returned may be contain valid data or be uninitialized. + * + */ -/* - * vm_set_default_memory_manager(): - * [Obsolete] +kern_return_t +memory_object_upl_request( + memory_object_control_t control, + memory_object_offset_t offset, + vm_size_t size, + upl_t *upl_ptr, + upl_page_info_array_t user_page_list, + unsigned int *page_list_count, + int cntrl_flags) +{ + vm_object_t object; + + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); + + return vm_object_upl_request(object, + offset, + size, + upl_ptr, + user_page_list, + page_list_count, + cntrl_flags); +} + +/* + * Routine: memory_object_super_upl_request [interface] + * Purpose: + * Cause the population of a portion of a vm_object + * in much the same way as memory_object_upl_request. + * Depending on the nature of the request, the pages + * returned may be contain valid data or be uninitialized. + * However, the region may be expanded up to the super + * cluster size provided. */ + kern_return_t -vm_set_default_memory_manager( - host_t host, - ipc_port_t *default_manager) +memory_object_super_upl_request( + memory_object_control_t control, + memory_object_offset_t offset, + vm_size_t size, + vm_size_t super_cluster, + upl_t *upl, + upl_page_info_t *user_page_list, + unsigned int *page_list_count, + int cntrl_flags) { - return(host_default_memory_manager(host_priv_self(), default_manager, 4*PAGE_SIZE)); + vm_object_t object; + + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); + + return vm_object_super_upl_request(object, + offset, + size, + super_cluster, + upl, + user_page_list, + page_list_count, + cntrl_flags); } +int vm_stat_discard_cleared_reply = 0; +int vm_stat_discard_cleared_unset = 0; +int vm_stat_discard_cleared_too_late = 0; + + + /* - * Routine: host_default_memory_manager + * Routine: host_default_memory_manager [interface] * Purpose: * set/get the default memory manager port and default cluster * size. @@ -1402,13 +1374,13 @@ vm_set_default_memory_manager( */ kern_return_t host_default_memory_manager( - host_priv_t host_priv, - ipc_port_t *default_manager, - vm_size_t cluster_size) + host_priv_t host_priv, + memory_object_default_t *default_manager, + vm_size_t cluster_size) { - ipc_port_t current_manager; - ipc_port_t new_manager; - ipc_port_t returned_manager; + memory_object_default_t current_manager; + memory_object_default_t new_manager; + memory_object_default_t returned_manager; if (host_priv == HOST_PRIV_NULL) return(KERN_INVALID_HOST); @@ -1419,21 +1391,25 @@ host_default_memory_manager( mutex_lock(&memory_manager_default_lock); current_manager = memory_manager_default; - if (new_manager == IP_NULL) { + if (new_manager == MEMORY_OBJECT_DEFAULT_NULL) { /* * Retrieve the current value. */ - - returned_manager = ipc_port_copy_send(current_manager); + memory_object_default_reference(current_manager); + returned_manager = current_manager; } else { /* * Retrieve the current value, * and replace it with the supplied value. - * We consume the supplied naked send right. + * We return the old reference to the caller + * but we have to take a reference on the new + * one. */ returned_manager = current_manager; memory_manager_default = new_manager; + memory_object_default_reference(new_manager); + if (cluster_size % PAGE_SIZE != 0) { #if 0 mutex_unlock(&memory_manager_default_lock); @@ -1466,62 +1442,27 @@ host_default_memory_manager( * valid (not IP_NULL or IP_DEAD). */ -ipc_port_t +__private_extern__ memory_object_default_t memory_manager_default_reference( vm_size_t *cluster_size) { - ipc_port_t current_manager; + memory_object_default_t current_manager; mutex_lock(&memory_manager_default_lock); - - while (current_manager = ipc_port_copy_send(memory_manager_default), - !IP_VALID(current_manager)) { + current_manager = memory_manager_default; + while (current_manager == MEMORY_OBJECT_DEFAULT_NULL) { thread_sleep_mutex((event_t) &memory_manager_default, &memory_manager_default_lock, THREAD_UNINT); mutex_lock(&memory_manager_default_lock); + current_manager = memory_manager_default; } + memory_object_default_reference(current_manager); *cluster_size = memory_manager_default_cluster; - mutex_unlock(&memory_manager_default_lock); return current_manager; } -/* - * Routine: memory_manager_default_port - * Purpose: - * Returns true if the receiver for the port - * is the default memory manager. - * - * This is a hack to let ds_read_done - * know when it should keep memory wired. - */ - -boolean_t -memory_manager_default_port( - ipc_port_t port) -{ - ipc_port_t current; - boolean_t result; - - mutex_lock(&memory_manager_default_lock); - current = memory_manager_default; - if (IP_VALID(current)) { - /* - * There is no point in bothering to lock - * both ports, which would be painful to do. - * If the receive rights are moving around, - * we might be inaccurate. - */ - - result = port->ip_receiver == current->ip_receiver; - } else - result = FALSE; - mutex_unlock(&memory_manager_default_lock); - - return result; -} - /* * Routine: memory_manager_default_check * @@ -1534,14 +1475,14 @@ memory_manager_default_port( * but only the first time. * */ -kern_return_t +__private_extern__ kern_return_t memory_manager_default_check(void) { - ipc_port_t current; + memory_object_default_t current; mutex_lock(&memory_manager_default_lock); current = memory_manager_default; - if (!IP_VALID(current)) { + if (current == MEMORY_OBJECT_DEFAULT_NULL) { static boolean_t logged; /* initialized to 0 */ boolean_t complain = !logged; logged = TRUE; @@ -1555,10 +1496,10 @@ memory_manager_default_check(void) } } -void +__private_extern__ void memory_manager_default_init(void) { - memory_manager_default = IP_NULL; + memory_manager_default = MEMORY_OBJECT_DEFAULT_NULL; mutex_init(&memory_manager_default_lock, ETAP_VM_MEMMAN); } @@ -1646,17 +1587,42 @@ memory_object_deactivate_pages( kern_return_t memory_object_page_op( - vm_object_t object, - vm_object_offset_t offset, - int ops, - vm_offset_t *phys_entry, - int *flags) + memory_object_control_t control, + memory_object_offset_t offset, + int ops, + vm_offset_t *phys_entry, + int *flags) { - vm_page_t dst_page; + vm_object_t object; + vm_page_t dst_page; + + + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); vm_object_lock(object); + if(ops & UPL_POP_PHYSICAL) { + if(object->phys_contiguous) { + if (phys_entry) { + *phys_entry = (vm_offset_t) + object->shadow_offset; + } + vm_object_unlock(object); + return KERN_SUCCESS; + } else { + vm_object_unlock(object); + return KERN_INVALID_OBJECT; + } + } + while(TRUE) { + if(object->phys_contiguous) { + vm_object_unlock(object); + return KERN_INVALID_OBJECT; + } + if((dst_page = vm_page_lookup(object,offset)) == VM_PAGE_NULL) { vm_object_unlock(object); return KERN_FAILURE; @@ -1664,7 +1630,8 @@ memory_object_page_op( /* Sync up on getting the busy bit */ if((dst_page->busy || dst_page->cleaning) && - (((ops & UPL_POP_SET) && (ops & UPL_POP_BUSY)) || (ops & UPL_POP_DUMP))) { + (((ops & UPL_POP_SET) && + (ops & UPL_POP_BUSY)) || (ops & UPL_POP_DUMP))) { /* someone else is playing with the page, we will */ /* have to wait */ PAGE_ASSERT_WAIT(dst_page, THREAD_UNINT); @@ -1733,4 +1700,461 @@ memory_object_page_op( } +static zone_t mem_obj_control_zone; + +__private_extern__ void +memory_object_control_bootstrap(void) +{ + int i; + + i = (vm_size_t) sizeof (struct memory_object_control); + mem_obj_control_zone = zinit (i, 8192*i, 4096, "mem_obj_control"); + return; +} + +__private_extern__ memory_object_control_t +memory_object_control_allocate( + vm_object_t object) +{ + memory_object_control_t control; + + control = (memory_object_control_t)zalloc(mem_obj_control_zone); + if (control != MEMORY_OBJECT_CONTROL_NULL) + control->object = object; + return (control); +} + +__private_extern__ void +memory_object_control_collapse( + memory_object_control_t control, + vm_object_t object) +{ + assert((control->object != VM_OBJECT_NULL) && + (control->object != object)); + control->object = object; +} + +__private_extern__ vm_object_t +memory_object_control_to_vm_object( + memory_object_control_t control) +{ + if (control == MEMORY_OBJECT_CONTROL_NULL) + return VM_OBJECT_NULL; + + return (control->object); +} + +memory_object_control_t +convert_port_to_mo_control( + mach_port_t port) +{ + return MEMORY_OBJECT_CONTROL_NULL; +} + + +mach_port_t +convert_mo_control_to_port( + memory_object_control_t control) +{ + return MACH_PORT_NULL; +} + +void +memory_object_control_reference( + memory_object_control_t control) +{ + return; +} + +/* + * We only every issue one of these references, so kill it + * when that gets released (should switch the real reference + * counting in true port-less EMMI). + */ +void +memory_object_control_deallocate( + memory_object_control_t control) +{ + zfree(mem_obj_control_zone, (vm_offset_t)control); +} + +void +memory_object_control_disable( + memory_object_control_t control) +{ + assert(control->object != VM_OBJECT_NULL); + control->object = VM_OBJECT_NULL; +} + +void +memory_object_default_reference( + memory_object_default_t dmm) +{ + ipc_port_make_send(dmm); +} + +void +memory_object_default_deallocate( + memory_object_default_t dmm) +{ + ipc_port_release_send(dmm); +} + +memory_object_t +convert_port_to_memory_object( + mach_port_t port) +{ + return (MEMORY_OBJECT_NULL); +} + + +mach_port_t +convert_memory_object_to_port( + memory_object_t object) +{ + return (MACH_PORT_NULL); +} + +#ifdef MACH_BSD +/* remove after component interface available */ +extern int vnode_pager_workaround; +extern int device_pager_workaround; +#endif + + +/* Routine memory_object_reference */ +void memory_object_reference( + memory_object_t memory_object) +{ +extern void dp_memory_object_reference(memory_object_t); + +#ifdef MACH_BSD + extern void vnode_pager_reference(memory_object_t); + extern void device_pager_reference(memory_object_t); + + if(memory_object->pager == &vnode_pager_workaround) { + vnode_pager_reference(memory_object); + } else if(memory_object->pager == &device_pager_workaround) { + device_pager_reference(memory_object); + } else +#endif + dp_memory_object_reference(memory_object); +} + +/* Routine memory_object_deallocate */ +void memory_object_deallocate( + memory_object_t memory_object) +{ +extern void dp_memory_object_deallocate(memory_object_t); + +#ifdef MACH_BSD + extern void vnode_pager_deallocate(memory_object_t); + extern void device_pager_deallocate(memory_object_t); + + if(memory_object->pager == &vnode_pager_workaround) { + vnode_pager_deallocate(memory_object); + } else if(memory_object->pager == &device_pager_workaround) { + device_pager_deallocate(memory_object); + } else +#endif + dp_memory_object_deallocate(memory_object); +} + + +/* Routine memory_object_init */ +kern_return_t memory_object_init +( + memory_object_t memory_object, + memory_object_control_t memory_control, + vm_size_t memory_object_page_size +) +{ +extern kern_return_t dp_memory_object_init(memory_object_t, + memory_object_control_t, + vm_size_t); +#ifdef MACH_BSD +extern kern_return_t vnode_pager_init(memory_object_t, + memory_object_control_t, + vm_size_t); +extern kern_return_t device_pager_init(memory_object_t, + memory_object_control_t, + vm_size_t); + + if(memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_init(memory_object, + memory_control, + memory_object_page_size); + } else if(memory_object->pager == &device_pager_workaround) { + return device_pager_init(memory_object, + memory_control, + memory_object_page_size); + } else +#endif + return dp_memory_object_init(memory_object, + memory_control, + memory_object_page_size); +} + +/* Routine memory_object_terminate */ +kern_return_t memory_object_terminate +( + memory_object_t memory_object +) +{ +extern kern_return_t dp_memory_object_terminate(memory_object_t); + +#ifdef MACH_BSD +extern kern_return_t vnode_pager_terminate(memory_object_t); +extern kern_return_t device_pager_terminate(memory_object_t); + + if(memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_terminate(memory_object); + } else if(memory_object->pager == &device_pager_workaround) { + return device_pager_terminate(memory_object); + } else +#endif + return dp_memory_object_terminate(memory_object); +} + +/* Routine memory_object_data_request */ +kern_return_t memory_object_data_request +( + memory_object_t memory_object, + memory_object_offset_t offset, + vm_size_t length, + vm_prot_t desired_access +) +{ +extern kern_return_t dp_memory_object_data_request(memory_object_t, + memory_object_offset_t, vm_size_t, vm_prot_t); + +#ifdef MACH_BSD +extern kern_return_t vnode_pager_data_request(memory_object_t, + memory_object_offset_t, vm_size_t, vm_prot_t); +extern kern_return_t device_pager_data_request(memory_object_t, + memory_object_offset_t, vm_size_t, vm_prot_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_data_request(memory_object, + offset, + length, + desired_access); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_data_request(memory_object, + offset, + length, + desired_access); + } else +#endif + return dp_memory_object_data_request(memory_object, + offset, + length, + desired_access); +} + +/* Routine memory_object_data_return */ +kern_return_t memory_object_data_return +( + memory_object_t memory_object, + memory_object_offset_t offset, + vm_size_t size, + boolean_t dirty, + boolean_t kernel_copy +) +{ + extern kern_return_t dp_memory_object_data_return(memory_object_t, + memory_object_offset_t, + vm_size_t, + boolean_t, + boolean_t); +#ifdef MACH_BSD + extern kern_return_t vnode_pager_data_return(memory_object_t, + memory_object_offset_t, + vm_size_t, + boolean_t, + boolean_t); + extern kern_return_t device_pager_data_return(memory_object_t, + memory_object_offset_t, + vm_size_t, + boolean_t, + boolean_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_data_return(memory_object, + offset, + size, + dirty, + kernel_copy); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_data_return(memory_object, + offset, + size, + dirty, + kernel_copy); + } else +#endif + return dp_memory_object_data_return(memory_object, + offset, + size, + dirty, + kernel_copy); +} + +/* Routine memory_object_data_initialize */ +kern_return_t memory_object_data_initialize +( + memory_object_t memory_object, + memory_object_offset_t offset, + vm_size_t size +) +{ + + extern kern_return_t dp_memory_object_data_initialize(memory_object_t, + memory_object_offset_t, + vm_size_t); +#ifdef MACH_BSD + extern kern_return_t vnode_pager_data_initialize(memory_object_t, + memory_object_offset_t, + vm_size_t); + extern kern_return_t device_pager_data_initialize(memory_object_t, + memory_object_offset_t, + vm_size_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_data_initialize(memory_object, + offset, + size); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_data_initialize(memory_object, + offset, + size); + } else +#endif + return dp_memory_object_data_initialize(memory_object, + offset, + size); +} + +/* Routine memory_object_data_unlock */ +kern_return_t memory_object_data_unlock +( + memory_object_t memory_object, + memory_object_offset_t offset, + vm_size_t size, + vm_prot_t desired_access +) +{ + extern kern_return_t dp_memory_object_data_unlock(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_prot_t); +#ifdef MACH_BSD + extern kern_return_t vnode_pager_data_unlock(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_prot_t); + extern kern_return_t device_pager_data_unlock(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_prot_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_data_unlock(memory_object, + offset, + size, + desired_access); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_data_unlock(memory_object, + offset, + size, + desired_access); + } else +#endif + return dp_memory_object_data_unlock(memory_object, + offset, + size, + desired_access); + +} + +/* Routine memory_object_synchronize */ +kern_return_t memory_object_synchronize +( + memory_object_t memory_object, + memory_object_offset_t offset, + vm_size_t size, + vm_sync_t sync_flags +) +{ + extern kern_return_t dp_memory_object_data_synchronize(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_sync_t); +#ifdef MACH_BSD + extern kern_return_t vnode_pager_data_synchronize(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_sync_t); + extern kern_return_t device_pager_data_synchronize(memory_object_t, + memory_object_offset_t, + vm_size_t, + vm_sync_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_synchronize( + memory_object, + offset, + size, + sync_flags); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_synchronize( + memory_object, + offset, + size, + sync_flags); + } else +#endif + return dp_memory_object_synchronize( + memory_object, + offset, + size, + sync_flags); +} + +/* Routine memory_object_unmap */ +kern_return_t memory_object_unmap +( + memory_object_t memory_object +) +{ + extern kern_return_t dp_memory_object_unmap(memory_object_t); +#ifdef MACH_BSD + extern kern_return_t vnode_pager_unmap(memory_object_t); + extern kern_return_t device_pager_unmap(memory_object_t); + + if (memory_object->pager == &vnode_pager_workaround) { + return vnode_pager_unmap(memory_object); + } else if (memory_object->pager == &device_pager_workaround) { + return device_pager_unmap(memory_object); + } else +#endif + return dp_memory_object_unmap(memory_object); +} + +/* Routine memory_object_create */ +kern_return_t memory_object_create +( + memory_object_default_t default_memory_manager, + vm_size_t new_memory_object_size, + memory_object_t *new_memory_object +) +{ +extern kern_return_t default_pager_memory_object_create(memory_object_default_t, + vm_size_t, + memory_object_t *); + + return default_pager_memory_object_create(default_memory_manager, + new_memory_object_size, + new_memory_object); +} diff --git a/osfmk/vm/memory_object.h b/osfmk/vm/memory_object.h index d5e897ef0..a169bd3c3 100644 --- a/osfmk/vm/memory_object.h +++ b/osfmk/vm/memory_object.h @@ -56,46 +56,54 @@ #include <mach_pagemap.h> #include <mach/boolean.h> +#include <mach/mach_types.h> +#include <mach/memory_object_types.h> #include <ipc/ipc_types.h> -extern kern_return_t memory_object_set_attributes_common( - vm_object_t object, - boolean_t may_cache, - memory_object_copy_strategy_t copy_strategy, - boolean_t temporary, - vm_size_t cluster_size, - boolean_t silent_overwrite, - boolean_t advisory_pageout); +__private_extern__ +memory_object_default_t memory_manager_default_reference( + vm_size_t *cluster_size); -extern boolean_t memory_object_sync ( - vm_object_t object, - vm_object_offset_t offset, - vm_object_size_t size, - boolean_t should_flush, - boolean_t should_return); +__private_extern__ +kern_return_t memory_manager_default_check(void); -extern ipc_port_t memory_manager_default_reference( - vm_size_t *cluster_size); +__private_extern__ +void memory_manager_default_init(void); -extern boolean_t memory_manager_default_port(ipc_port_t port); +__private_extern__ +void memory_object_control_bootstrap(void); +__private_extern__ +memory_object_control_t memory_object_control_allocate( + vm_object_t object); -extern kern_return_t memory_manager_default_check(void); +__private_extern__ +void memory_object_control_collapse( + memory_object_control_t control, + vm_object_t object); -extern void memory_manager_default_init(void); +__private_extern__ +vm_object_t memory_object_control_to_vm_object( + memory_object_control_t control); +extern +mach_port_t convert_mo_control_to_port( + memory_object_control_t control); + +extern +memory_object_control_t convert_port_to_mo_control( + mach_port_t port); + +extern +mach_port_t convert_memory_object_to_port( + memory_object_t object); + +extern +memory_object_t convert_port_to_memory_object( + mach_port_t port); extern kern_return_t memory_object_free_from_cache( host_t host, - int pager_id, + int *pager_id, int *count); -extern kern_return_t memory_object_remove_cached_object( - ipc_port_t port); - -extern void memory_object_deactivate_pages( - vm_object_t object, - vm_object_offset_t offset, - vm_object_size_t size, - boolean_t kill_page); - #endif /* _VM_MEMORY_OBJECT_H_ */ diff --git a/osfmk/vm/pmap.h b/osfmk/vm/pmap.h index 4dda94445..1013077cb 100644 --- a/osfmk/vm/pmap.h +++ b/osfmk/vm/pmap.h @@ -165,10 +165,15 @@ extern void pmap_enter( /* Enter a mapping */ vm_prot_t prot, boolean_t wired); +extern void pmap_remove_some_phys( + pmap_t pmap, + vm_offset_t pa); + /* * Routines that operate on physical addresses. */ + extern void pmap_page_protect( /* Restrict access to page. */ vm_offset_t phys, vm_prot_t prot); diff --git a/osfmk/vm/task_working_set.c b/osfmk/vm/task_working_set.c new file mode 100644 index 000000000..fa3f8f1d2 --- /dev/null +++ b/osfmk/vm/task_working_set.c @@ -0,0 +1,1103 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + */ +/* + * File: vm/task_working_set.c + * Author: Chris Youngworth + * Date: 2001 + * + * Working set detection and maintainence module + */ + + +#include <mach/rpc.h> +#include <vm/task_working_set.h> +#include <vm/vm_map.h> +#include <vm/vm_page.h> +#include <vm/vm_pageout.h> +#include <kern/sched.h> + +extern unsigned sched_tick; + +/* Note: all of the routines below depend on the associated map lock for */ +/* synchronization, the map lock will be on when the routines are called */ +/* and on when they return */ + +tws_hash_t +tws_hash_create( + unsigned int lines, + unsigned int rows, + unsigned int style) +{ + tws_hash_t tws; + int i,j; + + + if ((style != TWS_HASH_STYLE_BASIC) && + (style != TWS_HASH_STYLE_BASIC)) { + return((tws_hash_t)NULL); + } + + + tws = (tws_hash_t)(kalloc(sizeof(struct tws_hash))); + if(tws == (tws_hash_t)NULL) + return tws; + + if((tws->table[0] = (tws_hash_ele_t *) + kalloc(sizeof(tws_hash_ele_t) * 2 * lines * rows)) + == NULL) { + kfree((vm_offset_t)tws, sizeof(struct tws_hash)); + return (tws_hash_t)NULL; + } + if((tws->alt_table[0] = (tws_hash_ele_t *) + kalloc(sizeof(tws_hash_ele_t) * 2 * lines * rows)) + == NULL) { + kfree((vm_offset_t)tws, sizeof(struct tws_hash)); + kfree((vm_offset_t)tws->table[0], sizeof(tws_hash_ele_t) + * 2 * lines * rows); + return (tws_hash_t)NULL; + } + if((tws->cache[0] = (struct tws_hash_line *) + kalloc(sizeof(struct tws_hash_line) * lines)) + == NULL) { + kfree((vm_offset_t)tws, sizeof(struct tws_hash)); + kfree((vm_offset_t)tws->table[0], sizeof(tws_hash_ele_t) + * 2 * lines * rows); + kfree((vm_offset_t)tws->alt_table[0], sizeof(tws_hash_ele_t) + * 2 * lines * rows); + return (tws_hash_t)NULL; + } + + /* most defaults are such that a bzero will initialize */ + bzero((char *)tws->table[0],sizeof(tws_hash_ele_t) + * 2 * lines * rows); + bzero((char *)tws->alt_table[0],sizeof(tws_hash_ele_t) + * 2 * lines * rows); + bzero((char *)tws->cache[0], sizeof(struct tws_hash_line) + * lines); + + mutex_init(&tws->lock, ETAP_VM_MAP); + tws->style = style; + tws->current_line = 0; + tws->pageout_count = 0; + tws->line_count = 0; + tws->number_of_lines = lines; + tws->number_of_elements = rows; + tws->expansion_count = 1; + tws->lookup_count = 0; + tws->insert_count = 0; + tws->time_of_creation = sched_tick; + + return tws; +} + +int newtest = 0; +void +tws_hash_line_clear( + tws_hash_t tws, + tws_hash_line_t hash_line, + boolean_t live) +{ + struct tws_hash_ele *hash_ele; + int index; + unsigned int i, j, k; + int alt_index; + int dump_pmap; + int hash_loop; + + + if(tws->line_count < tws->number_of_lines) { + tws->line_count++; + dump_pmap = 1; + } else { + if(tws->pageout_count != vm_pageout_scan_event_counter) { + tws->pageout_count = + vm_pageout_scan_event_counter; + tws->line_count = 0; + dump_pmap = 1; + } else { + dump_pmap = 0; + } + } + hash_line->ele_count = 0; + for (i=0; i<tws->number_of_elements; i++) { + hash_loop = 0; + hash_ele = &(hash_line->list[i]); + if(hash_ele->object != 0) { + vm_offset_t vaddr_off = 0; + vm_object_offset_t local_off = 0; + + for (j = 0x1; j != 0; j = j<<1) { + if(j & hash_ele->page_cache) { + unsigned int alt_index; + alt_index = alt_tws_hash( + hash_ele->page_addr + vaddr_off, + tws->number_of_elements, + tws->number_of_lines); + for(k = 0; k < tws->expansion_count; k++) { + if(tws->alt_table[k][alt_index] == hash_ele) { + tws->alt_table[k][alt_index] = 0; + } + } + vaddr_off += PAGE_SIZE; + } + } + + if((hash_ele->map != NULL) && (live)) { + vm_page_t p; + + for (j = 0x1; j != 0; j = j<<1) { + if(j & hash_ele->page_cache) { + p = vm_page_lookup(hash_ele->object, + hash_ele->offset + local_off); + if((p != NULL) && (p->wire_count == 0) + && (dump_pmap == 1)) { + pmap_remove_some_phys((pmap_t) + vm_map_pmap(hash_ele->map), + p->phys_addr); + } + } + local_off += PAGE_SIZE_64; + } + } + if(tws->style == TWS_HASH_STYLE_SIGNAL) { + vm_object_deallocate(hash_ele->object); + vm_map_deallocate(hash_ele->map); + } + + index = do_tws_hash(hash_ele->object, hash_ele->offset, + tws->number_of_elements, tws->number_of_lines); + + while (hash_loop < TWS_MAX_REHASH) { + for(k = 0; k < tws->expansion_count; k++) { + if((tws->table[k][index] != 0) && + (tws->table[k][index] == hash_ele)) { + tws->table[k][index] = 0; + break; + } + if(k < tws->expansion_count) + break; + } + index += 17; + if(index >= (2 * + tws->number_of_lines + * tws->number_of_elements)) { + index = index - (2 * + tws->number_of_lines + * tws->number_of_elements); + } + hash_loop++; + } + hash_ele->object = 0; + hash_ele->page_cache = 0; + +if(newtest != 0) { + if (hash_loop == TWS_MAX_REHASH) { + panic("tws_hash_line_clear: Cache and Hash out of sync\n"); + } +} + } + } +} + +kern_return_t +tws_lookup( + tws_hash_t tws, + vm_object_offset_t offset, + vm_object_t object, + tws_hash_line_t *line) +{ + struct tws_hash_ele *hash_ele; + int index; + int k; + int loop; + + /* don't cache private objects */ + if(object->private) + return KERN_SUCCESS; + + if(!tws_lock_try(tws)) { + return KERN_FAILURE; + } + + index = do_tws_hash(object, offset, + tws->number_of_elements, tws->number_of_lines); + loop = 0; + + tws->lookup_count++; + if(tws->lookup_count == 0) + tws->insert_count = 0; + while (loop < TWS_MAX_REHASH) { + for(k=0; k<tws->expansion_count; k++) { + if((hash_ele = tws->table[k][index]) != 0) { + if((hash_ele->offset == (offset & TWS_HASH_OFF_MASK)) + && (hash_ele->object == object)) { + vm_offset_t pagenum; + + pagenum = (vm_offset_t) + (offset & TWS_INDEX_MASK); + pagenum = pagenum >> 12; + + if((1<<pagenum) & hash_ele->page_cache) { + int set; + int ele_line; + + set = hash_ele->line/tws->number_of_lines; + ele_line = hash_ele->line - set; + *line = &tws->cache[k][ele_line]; + tws_unlock(tws); + return KERN_SUCCESS; + } + } + } + } + index += 17; + if(index >= (2 * tws->number_of_lines * tws->number_of_elements)) { + index = index - + (2 * tws->number_of_lines * tws->number_of_elements); + } + loop++; + } + tws_unlock(tws); + return KERN_FAILURE; +} + +kern_return_t +tws_expand_working_set( + vm_offset_t tws, + int line_count) +{ + tws_hash_t new_tws; + tws_hash_t old_tws; + unsigned int i,j,k; + struct tws_hash temp; + + old_tws = (tws_hash_t)tws; + + /* Note we do an elaborate dance to preserve the header that */ + /* task is pointing to. In this way we can avoid taking a task */ + /* lock every time we want to access the tws */ + + if (old_tws->number_of_lines >= line_count) { + return KERN_FAILURE; + } + if((new_tws = tws_hash_create(line_count, + old_tws->number_of_elements, old_tws->style)) == 0) { + return(KERN_NO_SPACE); + } + tws_lock(old_tws); + + for(i = 0; i<old_tws->number_of_lines; i++) { + for(j = 0; j<old_tws->number_of_elements; j++) { + for(k = 0; k<old_tws->expansion_count; k++) { + tws_hash_ele_t entry; + vm_object_offset_t paddr; + unsigned int page_index; + entry = &old_tws->cache[k][i].list[j]; + if(entry->object != 0) { + paddr = 0; + for(page_index = 1; page_index != 0; + page_index = page_index << 1); { + if (entry->page_cache & page_index) { + tws_insert(new_tws, + entry->offset+paddr, + entry->object, + entry->page_addr+paddr, + entry->map); + } + paddr+=PAGE_SIZE; + } + + } + } + } + } + + temp.style = new_tws->style; + temp.current_line = new_tws->current_line; + temp.pageout_count = new_tws->pageout_count; + temp.line_count = new_tws->line_count; + temp.number_of_lines = new_tws->number_of_lines; + temp.number_of_elements = new_tws->number_of_elements; + temp.expansion_count = new_tws->expansion_count; + temp.lookup_count = new_tws->lookup_count; + temp.insert_count = new_tws->insert_count; + for(i = 0; i<new_tws->expansion_count; i++) { + temp.table[i] = new_tws->table[i]; + temp.alt_table[i] = new_tws->alt_table[i]; + temp.cache[i] = new_tws->cache[i]; + } + + new_tws->style = old_tws->style; + new_tws->current_line = old_tws->current_line; + new_tws->pageout_count = old_tws->pageout_count; + new_tws->line_count = old_tws->line_count; + new_tws->number_of_lines = old_tws->number_of_lines; + new_tws->number_of_elements = old_tws->number_of_elements; + new_tws->expansion_count = old_tws->expansion_count; + new_tws->lookup_count = old_tws->lookup_count; + new_tws->insert_count = old_tws->insert_count; + for(i = 0; i<old_tws->expansion_count; i++) { + new_tws->table[i] = old_tws->table[i]; + new_tws->alt_table[i] = old_tws->alt_table[i]; + new_tws->cache[i] = old_tws->cache[i]; + } + + old_tws->style = temp.style; + old_tws->current_line = temp.current_line; + old_tws->pageout_count = temp.pageout_count; + old_tws->line_count = temp.line_count; + old_tws->number_of_lines = temp.number_of_lines; + old_tws->number_of_elements = temp.number_of_elements; + old_tws->expansion_count = temp.expansion_count; + old_tws->lookup_count = temp.lookup_count; + old_tws->insert_count = temp.insert_count; + for(i = 0; i<temp.expansion_count; i++) { + old_tws->table[i] = temp.table[i]; + old_tws->alt_table[i] = temp.alt_table[i]; + old_tws->cache[i] = temp.cache[i]; + } + + tws_hash_destroy(new_tws); + tws_unlock(old_tws); + return KERN_SUCCESS; +} + +kern_return_t +tws_insert( + tws_hash_t tws, + vm_object_offset_t offset, + vm_object_t object, + vm_offset_t page_addr, + vm_map_t map) +{ + queue_t bucket; + struct tws_hash_ele *new_entry; + unsigned int index; + unsigned int alt_index; + unsigned int ele_index; + unsigned int page_index; + int i,k; + int alt_k; + int alt_hash_count; + int current_line; + int set; + int hash_loop; + + if(!tws_lock_try(tws)) { + return KERN_FAILURE; + } + tws->insert_count++; + current_line = 0xFFFFFFFF; + + /* This next bit of code, the and alternate hash */ + /* are all made necessary because of IPC COW */ + + alt_index = alt_tws_hash(page_addr, + tws->number_of_elements, tws->number_of_lines); + + for(alt_k=0; alt_k<tws->expansion_count; alt_k++) { + new_entry = tws->alt_table[alt_k][alt_index]; + if((new_entry == 0) || (new_entry->object == 0)) { + tws->alt_table[alt_k][alt_index] = 0; + continue; + } + if(!((new_entry->offset == (offset & TWS_HASH_OFF_MASK)) + && (new_entry->object == object))) { + + tws->alt_table[alt_k][alt_index] = 0; + + index = do_tws_hash( + new_entry->object, new_entry->offset, + tws->number_of_elements, tws->number_of_lines); + + hash_loop = 0; + while (hash_loop < TWS_MAX_REHASH) { + + for(k=0; k<tws->expansion_count; k++) { + if(tws->table[k][index] == new_entry) { + break; + } + } + + if(k == tws->expansion_count) { + index+=17; + if(index >= (2 * tws->number_of_lines + * tws->number_of_elements)) { + index = index - + (2 * tws->number_of_lines + * tws->number_of_elements); + } + } else { + break; + } + hash_loop++; + + } + if((k < tws->expansion_count) && + (tws->table[k][index] == new_entry)) { + page_index = (offset & TWS_INDEX_MASK) >> 12; + new_entry->page_cache &= + ~((unsigned int)(1 << page_index)); + + if(new_entry->page_cache == 0) { + + if(tws->style == + TWS_HASH_STYLE_SIGNAL) { + vm_object_deallocate( + new_entry->object); + vm_map_deallocate( + new_entry->map); + } + new_entry->object = 0; + tws->table[k][index] = 0; + current_line = new_entry->line; + set = current_line/tws->number_of_lines; + current_line = current_line - + (set * tws->number_of_lines); + tws->cache[set] + [current_line].ele_count--; + } + + } + break; + } + } + + index = do_tws_hash(object, offset, + tws->number_of_elements, tws->number_of_lines); + alt_hash_count = 0; + /* we will do MAX_REHASH hash attempts and then give up */ + while (alt_hash_count < TWS_MAX_REHASH) { + for(k=0; k<tws->expansion_count; k++) { + new_entry = tws->table[k][index]; + if(new_entry == NULL) + continue; + if((new_entry->object == object) && + (new_entry->offset == + (offset & TWS_HASH_OFF_MASK))) { + new_entry->page_cache |= + (1<<(((vm_offset_t) + (offset & TWS_INDEX_MASK))>>12)); + tws->alt_table[k][alt_index] = new_entry; + tws_unlock(tws); + return KERN_SUCCESS; + } + } + + alt_hash_count += 1; + index += 17; + if(index >= (2 * + tws->number_of_lines * tws->number_of_elements)) + index = index - + (2 * tws->number_of_lines * tws->number_of_elements); + } + alt_hash_count = 0; + index = do_tws_hash(object, offset, + tws->number_of_elements, tws->number_of_lines); + while (alt_hash_count < TWS_MAX_REHASH) { + for(k=0; k<tws->expansion_count; k++) { + new_entry = tws->table[k][index]; + if(new_entry == NULL) + break; + } + + if (k<tws->expansion_count) + break; + + alt_hash_count += 1; + index += 17; + if(index >= (2 * + tws->number_of_lines * tws->number_of_elements)) + index = index - + (2 * tws->number_of_lines * tws->number_of_elements); + } + + if(alt_hash_count == TWS_MAX_REHASH) { + tws_unlock(tws); + return KERN_FAILURE; + } + + if(tws->style == TWS_HASH_STYLE_SIGNAL) { + vm_object_reference(object); + vm_map_reference(map); + } + + if(current_line == 0xFFFFFFFF) { + + current_line = tws->current_line; + set = current_line/tws->number_of_lines; + current_line = current_line - (set * tws->number_of_lines); + + if(tws->cache[set][current_line].ele_count + >= tws->number_of_elements) { + current_line++; + tws->current_line++; + if(current_line == tws->number_of_lines) { + set++; + current_line = 0; + if (set == tws->expansion_count) { + if((tws->lookup_count < + (2 * tws->insert_count)) && + (set<TWS_HASH_EXPANSION_MAX)) { + tws->lookup_count = 0; + tws->insert_count = 0; + if(tws->number_of_lines + < TWS_HASH_LINE_COUNT) { + tws->current_line--; + tws_unlock(tws); + return KERN_NO_SPACE; + } + if((tws->table[set] = (tws_hash_ele_t *) + kalloc(sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements)) + == NULL) { + set = 0; + } else if((tws->alt_table[set] = + (tws_hash_ele_t *) + kalloc(sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements)) + == NULL) { + kfree((vm_offset_t)tws->table[set], + sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + tws->table[set] = NULL; + set = 0; + + } else if((tws->cache[set] = + (struct tws_hash_line *) + kalloc(sizeof + (struct tws_hash_line) + * tws->number_of_lines)) + == NULL) { + kfree((vm_offset_t)tws->table[set], + sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + kfree((vm_offset_t)tws->alt_table[set], + sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + tws->table[set] = NULL; + set = 0; + + } else { + bzero((char *)tws->table[set], + sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + bzero((char *)tws->alt_table[set], + sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + bzero((char *)tws->cache[set], + sizeof(struct tws_hash_line) + * tws->number_of_lines); + } + } else { + tws->lookup_count = 0; + tws->insert_count = 0; + set = 0; + } + } + tws->current_line = set * tws->number_of_lines; + } + if(set < tws->expansion_count) { + tws_hash_line_clear(tws, + &(tws->cache[set][current_line]), TRUE); + if(tws->cache[set][current_line].ele_count + >= tws->number_of_elements) { + if(tws->style == TWS_HASH_STYLE_SIGNAL) { + vm_object_deallocate(object); + vm_map_deallocate(map); + } + tws_unlock(tws); + return KERN_FAILURE; + } + } else { + tws->expansion_count++; + } + } + } + + ele_index = 0; + for(i = 0; i<tws->number_of_elements; i++) { + if(tws->cache[set][current_line]. + list[ele_index].object == 0) { + break; + } + ele_index++; + if(ele_index >= tws->number_of_elements) + ele_index = 0; + + } + + if(i == tws->number_of_elements) + panic("tws_insert: no free elements"); + + + tws->cache[set][current_line].list[ele_index].object = object; + tws->cache[set][current_line].list[ele_index].offset = + offset & TWS_HASH_OFF_MASK; + tws->cache[set][current_line]. + list[ele_index].page_addr = page_addr & TWS_HASH_OFF_MASK; + tws->cache[set][current_line].list[ele_index].map = map; + tws->cache[set][current_line].list[ele_index].line = + current_line + (set * tws->number_of_lines); + tws->cache[set][current_line].list[ele_index].page_cache = + 1<<(((vm_offset_t)(offset & TWS_INDEX_MASK))>>12); + + tws->table[k][index] = &tws->cache[set][current_line].list[ele_index]; + for(alt_k=0; alt_k<tws->expansion_count; alt_k++) { + if(tws->alt_table[alt_k][alt_index] == 0) { + tws->alt_table[alt_k][alt_index] = + &tws->cache[set][current_line].list[ele_index]; + break; + } + } + tws->cache[set][current_line].ele_count++; + + tws_unlock(tws); + return KERN_SUCCESS; +} + +/* + * tws_build_cluster + * lengthen the cluster of pages by the number of pages encountered in the + * working set up to the limit requested by the caller. The object needs + * to be locked on entry. The map does not because the tws_lookup function + * is used only to find if their is an entry in the cache. No transient + * data from the cache is de-referenced. + * + */ +#if MACH_PAGEMAP +/* + * MACH page map - an optional optimization where a bit map is maintained + * by the VM subsystem for internal objects to indicate which pages of + * the object currently reside on backing store. This existence map + * duplicates information maintained by the vnode pager. It is + * created at the time of the first pageout against the object, i.e. + * at the same time pager for the object is created. The optimization + * is designed to eliminate pager interaction overhead, if it is + * 'known' that the page does not exist on backing store. + * + * LOOK_FOR() evaluates to TRUE if the page specified by object/offset is + * either marked as paged out in the existence map for the object or no + * existence map exists for the object. LOOK_FOR() is one of the + * criteria in the decision to invoke the pager. It is also used as one + * of the criteria to terminate the scan for adjacent pages in a clustered + * pagein operation. Note that LOOK_FOR() always evaluates to TRUE for + * permanent objects. Note also that if the pager for an internal object + * has not been created, the pager is not invoked regardless of the value + * of LOOK_FOR() and that clustered pagein scans are only done on an object + * for which a pager has been created. + * + * PAGED_OUT() evaluates to TRUE if the page specified by the object/offset + * is marked as paged out in the existence map for the object. PAGED_OUT() + * PAGED_OUT() is used to determine if a page has already been pushed + * into a copy object in order to avoid a redundant page out operation. + */ +#define LOOK_FOR(o, f) (vm_external_state_get((o)->existence_map, (f)) \ + != VM_EXTERNAL_STATE_ABSENT) +#define PAGED_OUT(o, f) (vm_external_state_get((o)->existence_map, (f)) \ + == VM_EXTERNAL_STATE_EXISTS) +#else /* MACH_PAGEMAP */ +/* + * If the MACH page map optimization is not enabled, + * LOOK_FOR() always evaluates to TRUE. The pager will always be + * invoked to resolve missing pages in an object, assuming the pager + * has been created for the object. In a clustered page operation, the + * absence of a page on backing backing store cannot be used to terminate + * a scan for adjacent pages since that information is available only in + * the pager. Hence pages that may not be paged out are potentially + * included in a clustered request. The vnode pager is coded to deal + * with any combination of absent/present pages in a clustered + * pagein request. PAGED_OUT() always evaluates to FALSE, i.e. the pager + * will always be invoked to push a dirty page into a copy object assuming + * a pager has been created. If the page has already been pushed, the + * pager will ingore the new request. + */ +#define LOOK_FOR(o, f) TRUE +#define PAGED_OUT(o, f) FALSE +#endif /* MACH_PAGEMAP */ + +void +tws_build_cluster( + tws_hash_t tws, + vm_object_t object, + vm_object_offset_t *start, + vm_object_offset_t *end, + vm_size_t max_length) +{ + tws_hash_line_t line; + task_t task; + vm_object_offset_t before = *start; + vm_object_offset_t after = *end; + vm_size_t length = (vm_size_t)(*end - *start); + vm_page_t m; + kern_return_t kret; + vm_object_offset_t object_size; + int pre_heat_size; + int age_of_cache; + + if(object->private) + return; + + if (!object->internal) { + kret = vnode_pager_get_object_size( + object->pager, + &object_size); + } else { + object_size = 0xFFFFFFFFFFFFFFFF; + } + /* + * determine age of cache in seconds + */ + age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT); + + if (object->internal || age_of_cache > 15 || (age_of_cache > 5 && vm_page_free_count < (vm_page_free_target * 2 ))) { + pre_heat_size = 0; + } else { + if (object_size > (vm_object_offset_t)(1024 * 1024)) + pre_heat_size = 8 * PAGE_SIZE; + else if (object_size > (vm_object_offset_t)(128 * 1024)) + pre_heat_size = 4 * PAGE_SIZE; + else + pre_heat_size = 2 * PAGE_SIZE; + } + + while ((length < max_length) && + (object_size >= + (object->paging_offset + after + PAGE_SIZE_64))) { + + if(length >= pre_heat_size) + { + if(tws_lookup(tws, after, object, + &line) != KERN_SUCCESS) { + vm_object_offset_t extend; + + extend = after + PAGE_SIZE_64; + if(tws_lookup(tws, extend, object, + &line) != KERN_SUCCESS) { + break; + } + } + } + if (((object->existence_map != NULL) + && (!LOOK_FOR(object, after))) || + (vm_page_lookup(object, after) + != VM_PAGE_NULL)) { + break; + } + if (object->internal) { + /* + * need to acquire a real page in + * advance because this acts as + * a throttling mechanism for + * data_requests to the default + * pager. If this fails, give up + * trying to find any more pages + * in the cluster and send off the + * request for what we already have. + */ + if ((m = vm_page_grab()) == VM_PAGE_NULL) { + break; + } + } else if ((m = vm_page_grab_fictitious()) + == VM_PAGE_NULL) { + break; + } + m->absent = TRUE; + m->unusual = TRUE; + m->clustered = TRUE; + m->list_req_pending = TRUE; + + vm_page_insert(m, object, after); + object->absent_count++; + after += PAGE_SIZE_64; + length += PAGE_SIZE; + } + *end = after; + while (length < max_length) { + if (before == 0) + break; + before -= PAGE_SIZE_64; + + if(length >= pre_heat_size) + { + + if(tws_lookup(tws, before, object, + &line) != KERN_SUCCESS) { + vm_object_offset_t extend; + + extend = before; + if (extend == 0) + break; + extend -= PAGE_SIZE_64; + if(tws_lookup(tws, extend, object, + &line) != KERN_SUCCESS) { + break; + } + } + } + if (((object->existence_map != NULL) + && (!LOOK_FOR(object, before))) || + (vm_page_lookup(object, before) + != VM_PAGE_NULL)) { + break; + } + if (object->internal) { + /* + * need to acquire a real page in + * advance because this acts as + * a throttling mechanism for + * data_requests to the default + * pager. If this fails, give up + * trying to find any more pages + * in the cluster and send off the + * request for what we already have. + */ + if ((m = vm_page_grab()) == VM_PAGE_NULL) { + break; + } + } else if ((m = vm_page_grab_fictitious()) + == VM_PAGE_NULL) { + break; + } + m->absent = TRUE; + m->unusual = TRUE; + m->clustered = TRUE; + m->list_req_pending = TRUE; + + vm_page_insert(m, object, before); + object->absent_count++; + *start -= PAGE_SIZE_64; + length += PAGE_SIZE; + } +} + +tws_line_signal( + tws_hash_t tws, + vm_map_t map, + tws_hash_line_t hash_line, + vm_offset_t target_page) +{ + unsigned int i,j; + vm_object_t object; + vm_object_offset_t offset; + vm_object_offset_t before; + vm_object_offset_t after; + struct tws_hash_ele *element; + vm_page_t m,p; + kern_return_t rc; + + if(tws->style != TWS_HASH_STYLE_SIGNAL) + return; + + vm_map_lock(map); + for (i=0; i<tws->number_of_elements; i++) { + + vm_object_offset_t local_off = 0; + + if(hash_line->list[i].object == 0) + continue; + + element = &hash_line->list[i]; + + if (element->page_addr == target_page) + continue; + + j = 1; + while (j != 0) { + if(j & element->page_cache) + break; + j << 1; + local_off += PAGE_SIZE_64; + } + object = element->object; + offset = element->offset + local_off; + + /* first try a fast test to speed up no-op signal */ + if (((p = vm_page_lookup(object, offset)) != NULL) + || (object->pager == NULL) + || (object->shadow_severed)) { + continue; + } + + if((!object->alive) || + (!object->pager_created) || (!object->pager_ready)) + continue; + + if (object->internal) { + if (object->existence_map == NULL) { + if (object->shadow) + continue; + } else { + if(!LOOK_FOR(object, offset)) + continue; + } + } + + vm_object_reference(object); + vm_map_unlock(map); + + if(object->internal) { + m = vm_page_grab(); + } else { + m = vm_page_grab_fictitious(); + } + + if(m == NULL) { + vm_object_deallocate(object); + vm_map_lock(map); + continue; + } + + vm_object_lock(object); + if (((p = vm_page_lookup(object, offset)) != NULL) + || (object->pager == NULL) + || (object->shadow_severed)) { + VM_PAGE_FREE(m); + vm_object_unlock(object); + vm_object_deallocate(object); + vm_map_lock(map); + continue; + } + + vm_page_insert(m, object, offset); + + if (object->absent_count > vm_object_absent_max) { + VM_PAGE_FREE(m); + vm_object_unlock(object); + vm_object_deallocate(object); + vm_map_lock(map); + break; + } + m->list_req_pending = TRUE; + m->absent = TRUE; + m->unusual = TRUE; + object->absent_count++; + + before = offset; + after = offset + PAGE_SIZE_64; + tws_build_cluster(tws, object, &before, &after, 0x16000); + vm_object_unlock(object); + + rc = memory_object_data_request(object->pager, + before + object->paging_offset, + (vm_size_t)(after - before), VM_PROT_READ); + if (rc != KERN_SUCCESS) { + offset = before; + vm_object_lock(object); + while (offset < after) { + m = vm_page_lookup(object, offset); + if(m && m->absent && m->busy) + VM_PAGE_FREE(m); + offset += PAGE_SIZE; + } + vm_object_unlock(object); + vm_object_deallocate(object); + } else { + vm_object_deallocate(object); + } + vm_map_lock(map); + continue; + } + vm_map_unlock(map); +} + + + +void +tws_hash_destroy(tws_hash_t tws) +{ + int i,k; + vm_size_t cache_size; + + for (i=0; i<tws->number_of_lines; i++) { + for(k=0; k<tws->expansion_count; k++) { + /* clear the object refs */ + tws_hash_line_clear(tws, &(tws->cache[k][i]), FALSE); + } + } + i = 0; + while (i < tws->expansion_count) { + + kfree((vm_offset_t)tws->table[i], sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + kfree((vm_offset_t)tws->alt_table[i], sizeof(tws_hash_ele_t) + * 2 * tws->number_of_lines + * tws->number_of_elements); + kfree((vm_offset_t)tws->cache[i], sizeof(struct tws_hash_line) + * tws->number_of_lines); + i++; + } + kfree((vm_offset_t)tws, sizeof(struct tws_hash)); +} + +void +tws_hash_clear(tws_hash_t tws) +{ + int i, k; + + for (i=0; i<tws->number_of_lines; i++) { + for(k=0; k<tws->expansion_count; k++) { + /* clear the object refs */ + tws_hash_line_clear(tws, &(tws->cache[k][i]), FALSE); + } + } +} + +kern_return_t +task_working_set_create( + task_t task, + unsigned int lines, + unsigned int rows, + unsigned int style) +{ + + if (lines == 0) { + lines = TWS_HASH_LINE_COUNT; + } + if (rows == 0) { + rows = TWS_ARRAY_SIZE; + } + if (style == TWS_HASH_STYLE_DEFAULT) { + style = TWS_HASH_STYLE_BASIC; + } + task_lock(task); + if(task->dynamic_working_set != 0) { + task_unlock(task); + return(KERN_FAILURE); + } else if((task->dynamic_working_set + = (vm_offset_t) tws_hash_create(lines, rows, style)) == 0) { + task_unlock(task); + return(KERN_NO_SPACE); + } + task_unlock(task); + return KERN_SUCCESS; +} diff --git a/osfmk/vm/task_working_set.h b/osfmk/vm/task_working_set.h new file mode 100644 index 000000000..2eb74691b --- /dev/null +++ b/osfmk/vm/task_working_set.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + */ + +/* + * File: vm/task_working_set.h + * Author: Chris Youngworth + * Date: 2001 + * + * Working set detection and maintainence module + * + */ + +#ifndef _VM_TASK_WORKING_SET_H_ +#define _VM_TASK_WORKING_SET_H_ + +#include <kern/queue.h> +#include <vm/vm_object.h> + +/* task working set */ + +#define tws_lock(tws) mutex_lock(&(tws)->lock) +#define tws_lock_try(tws) mutex_try(&(tws)->lock) +#define tws_unlock(tws) mutex_unlock(&(tws)->lock) + + +#define TWS_ARRAY_SIZE 8 +#define TWS_HASH_LINE_COUNT 32 +/* start out size to allow monitoring of working set without excessive use */ +/* of wired memory resource. */ +#define TWS_SMALL_HASH_LINE_COUNT 4 + +/* +#define do_tws_hash(object,offset, rows, lines) \ + ((((natural_t)(object)) + \ + (((natural_t)(offset)) >> 11) + \ + (((natural_t)(offset)) >> 12)) & \ + ((2 * rows * lines) -1)) +*/ +/* + * do not think of changing this hash unless you understand the implications + * for the hash element page_cache field + */ +#define do_tws_hash(object,offset, rows, lines) \ + (((((natural_t)(object)) >> 2) + \ + ((natural_t)(object) >> 12) + \ + ((natural_t)(((vm_object_offset_t)(offset)) >> 12) \ + & 0xFFFFFFFFFFFFFFE0)) & \ + ((2 * rows * lines) -1)) +/* +#define do_tws_hash(object,offset, rows, lines) \ + (((((natural_t)(object)) >> 2) + \ + ((natural_t)(object) << 5) + \ + ((natural_t)(((vm_object_offset_t)(offset)) >> 17))) & \ + ((2 * rows * lines) -1)) +*/ + + +#define alt_tws_hash(addr, rows, lines) \ + ((((natural_t)(addr)) >> 12) & \ + ((2 * rows * lines) -1)) + +struct tws_hash_ele { + vm_object_t object; + vm_object_offset_t offset; + unsigned int page_cache; + vm_offset_t page_addr; + int line; + vm_map_t map; +}; +typedef struct tws_hash_ele *tws_hash_ele_t; + +#define TWS_HASH_OFF_MASK ((vm_object_offset_t)0xFFFFFFFFFFFE0000) +#define TWS_INDEX_MASK ((vm_object_offset_t)0x000000000001F000) + +struct tws_hash_line { + int ele_count; + struct tws_hash_ele list[TWS_ARRAY_SIZE]; +}; +typedef struct tws_hash_line *tws_hash_line_t; + +#define TWS_HASH_STYLE_DEFAULT 0x0 +#define TWS_HASH_STYLE_BASIC 0x1 +#define TWS_HASH_STYLE_SIGNAL 0x2 + + +#define TWS_HASH_EXPANSION_MAX 5 +#define TWS_MAX_REHASH 2 + + +struct tws_hash { + decl_mutex_data(,lock) /* tws_hash's lock */ + int style; + + int current_line; + unsigned int pageout_count; + int line_count; + + int number_of_lines; + int number_of_elements; + int expansion_count; + unsigned int time_of_creation; + + int lookup_count; + int insert_count; + + tws_hash_ele_t *table[TWS_HASH_EXPANSION_MAX]; + tws_hash_ele_t *alt_table[TWS_HASH_EXPANSION_MAX]; + struct tws_hash_line *cache[TWS_HASH_EXPANSION_MAX]; +}; + +typedef struct tws_hash *tws_hash_t; + + +extern tws_hash_t tws_hash_create(); + +extern void tws_hash_line_clear( + tws_hash_t tws, + tws_hash_line_t hash_line, + boolean_t live); + +extern kern_return_t tws_lookup( + tws_hash_t tws, + vm_object_offset_t offset, + vm_object_t object, + tws_hash_line_t *line); + +extern kern_return_t tws_insert( + tws_hash_t tws, + vm_object_offset_t offset, + vm_object_t object, + vm_offset_t page_addr, + vm_map_t map); + +extern void tws_build_cluster( + tws_hash_t tws, + vm_object_t object, + vm_object_offset_t *start, + vm_object_offset_t *end, + vm_size_t max_length); + +extern tws_line_signal( + tws_hash_t tws, + vm_map_t map, + tws_hash_line_t hash_line, + vm_offset_t target_page); + +extern void tws_hash_destroy( + tws_hash_t tws); + +extern void tws_hash_clear( + tws_hash_t tws); + +kern_return_t task_working_set_create( + task_t task, + unsigned int lines, + unsigned int rows, + unsigned int style); + +kern_return_t tws_expand_working_set( + vm_offset_t old_tws, + int line_count); + + +#endif /* _VM_TASK_WORKING_SET_H_ */ diff --git a/osfmk/vm/vm_fault.c b/osfmk/vm/vm_fault.c index e94ac06f4..72d3061c9 100644 --- a/osfmk/vm/vm_fault.c +++ b/osfmk/vm/vm_fault.c @@ -58,6 +58,7 @@ #ifdef MACH_BSD /* remove after component interface available */ extern int vnode_pager_workaround; +extern int device_pager_workaround; #endif #include <mach_cluster_stats.h> @@ -74,6 +75,9 @@ extern int vnode_pager_workaround; #include <kern/sched_prim.h> #include <kern/host.h> #include <kern/xpr.h> +#include <ppc/proc_reg.h> +#include <ppc/pmap_internals.h> +#include <vm/task_working_set.h> #include <vm/vm_map.h> #include <vm/vm_object.h> #include <vm/vm_page.h> @@ -274,9 +278,11 @@ vm_fault_page( /* More arguments: */ kern_return_t *error_code, /* code if page is in error */ boolean_t no_zero_fill, /* don't zero fill absent pages */ - boolean_t data_supply) /* treat as data_supply if + boolean_t data_supply, /* treat as data_supply if * it is a write fault and a full * page is provided */ + vm_map_t map, + vm_offset_t vaddr) { register vm_page_t m; @@ -299,11 +305,8 @@ vm_fault_page( kern_return_t wait_result; thread_t cur_thread; boolean_t interruptible_state; + boolean_t bumped_pagein = FALSE; -#ifdef MACH_BSD - kern_return_t vnode_pager_data_request(ipc_port_t, - ipc_port_t, vm_object_offset_t, vm_size_t, vm_prot_t); -#endif #if MACH_PAGEMAP /* @@ -650,17 +653,35 @@ vm_fault_page( * newly allocated -- in both cases * it can't be page locked by a pager. */ + m->no_isync = FALSE; + if (!no_zero_fill) { vm_object_unlock(object); vm_page_zero_fill(m); if (type_of_fault) *type_of_fault = DBG_ZERO_FILL_FAULT; VM_STAT(zero_fill_count++); + + if (bumped_pagein == TRUE) { + VM_STAT(pageins--); + current_task()->pageins--; + } vm_object_lock(object); } pmap_clear_modify(m->phys_addr); vm_page_lock_queues(); VM_PAGE_QUEUES_REMOVE(m); + m->page_ticket = vm_page_ticket; + vm_page_ticket_roll++; + if(vm_page_ticket_roll == + VM_PAGE_TICKETS_IN_ROLL) { + vm_page_ticket_roll = 0; + if(vm_page_ticket == + VM_PAGE_TICKET_ROLL_IDS) + vm_page_ticket= 0; + else + vm_page_ticket++; + } queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); m->inactive = TRUE; @@ -799,7 +820,6 @@ vm_fault_page( (integer_t)m, new_unlock_request, 0); if ((rc = memory_object_data_unlock( object->pager, - object->pager_request, offset + object->paging_offset, PAGE_SIZE, new_unlock_request)) @@ -884,7 +904,8 @@ vm_fault_page( dbgTrace(0xBEEF000C, (unsigned int) look_for_page, (unsigned int) object); /* (TEST/DEBUG) */ #endif if ((look_for_page || (object == first_object)) - && !must_be_resident) { + && !must_be_resident + && !(object->phys_contiguous)) { /* * Allocate a new page for this object/offset * pair. @@ -902,7 +923,7 @@ vm_fault_page( vm_page_insert(m, object, offset); } - if (look_for_page && !must_be_resident) { + if ((look_for_page && !must_be_resident)) { kern_return_t rc; /* @@ -913,7 +934,8 @@ vm_fault_page( #if TRACEFAULTPAGE dbgTrace(0xBEEF000E, (unsigned int) 0, (unsigned int) 0); /* (TEST/DEBUG) */ #endif - VM_PAGE_FREE(m); + if(m != VM_PAGE_NULL) + VM_PAGE_FREE(m); XPR(XPR_VM_FAULT, "vm_f_page: ready wait obj 0x%X, offset 0x%X\n", (integer_t)object, offset, 0, 0, 0); @@ -941,6 +963,13 @@ vm_fault_page( } } + if(object->phys_contiguous) { + if(m != VM_PAGE_NULL) { + VM_PAGE_FREE(m); + m = VM_PAGE_NULL; + } + goto no_clustering; + } if (object->internal) { /* * Requests to the default pager @@ -972,7 +1001,8 @@ vm_fault_page( #if TRACEFAULTPAGE dbgTrace(0xBEEF0010, (unsigned int) m, (unsigned int) 0); /* (TEST/DEBUG) */ #endif - VM_PAGE_FREE(m); + if(m != VM_PAGE_NULL) + VM_PAGE_FREE(m); /* take an extra ref so object won't die */ assert(object->ref_count > 0); object->ref_count++; @@ -1001,10 +1031,14 @@ vm_fault_page( * from the memory manager. */ - m->list_req_pending = TRUE; - m->absent = TRUE; - m->unusual = TRUE; - object->absent_count++; + if(m != VM_PAGE_NULL) { + + m->list_req_pending = TRUE; + m->absent = TRUE; + m->unusual = TRUE; + object->absent_count++; + + } cluster_start = offset; length = PAGE_SIZE; @@ -1019,6 +1053,7 @@ vm_fault_page( */ if (!vm_allow_clustered_pagein || behavior == VM_BEHAVIOR_RANDOM || + m == VM_PAGE_NULL || cluster_size == PAGE_SIZE) { cluster_start = trunc_page_64(cluster_start); goto no_clustering; @@ -1228,6 +1263,25 @@ give_up: #endif /* MACH_CLUSTER_STATS */ no_clustering: + /* + * lengthen the cluster by the pages in the working set + */ + if((map != NULL) && + (current_task()->dynamic_working_set != 0)) { + cluster_end = cluster_start + length; + /* tws values for start and end are just a + * suggestions. Therefore, as long as + * build_cluster does not use pointers or + * take action based on values that + * could be affected by re-entrance we + * do not need to take the map lock. + */ + tws_build_cluster((tws_hash_t) + current_task()->dynamic_working_set, + object, &cluster_start, + &cluster_end, 0x16000); + length = cluster_end - cluster_start; + } #if TRACEFAULTPAGE dbgTrace(0xBEEF0012, (unsigned int) object, (unsigned int) 0); /* (TEST/DEBUG) */ #endif @@ -1245,6 +1299,7 @@ no_clustering: *type_of_fault = DBG_PAGEIN_FAULT; VM_STAT(pageins++); current_task()->pageins++; + bumped_pagein = TRUE; /* * If this object uses a copy_call strategy, @@ -1270,29 +1325,11 @@ no_clustering: (integer_t)object, offset, (integer_t)m, access_required | wants_copy_flag, 0); -#ifdef MACH_BSD - if (((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == - ((rpc_subsystem_t) &vnode_pager_workaround)) { - rc = vnode_pager_data_request(object->pager, - object->pager_request, - cluster_start + object->paging_offset, - length, - access_required | wants_copy_flag); - } else { - rc = memory_object_data_request(object->pager, - object->pager_request, - cluster_start + object->paging_offset, - length, - access_required | wants_copy_flag); - } -#else rc = memory_object_data_request(object->pager, - object->pager_request, cluster_start + object->paging_offset, length, access_required | wants_copy_flag); -#endif #if TRACEFAULTPAGE dbgTrace(0xBEEF0013, (unsigned int) object, (unsigned int) rc); /* (TEST/DEBUG) */ @@ -1300,35 +1337,54 @@ no_clustering: if (rc != KERN_SUCCESS) { if (rc != MACH_SEND_INTERRUPTED && vm_fault_debug) - printf("%s(0x%x, 0x%x, 0x%x, 0x%x, 0x%x) failed, rc=%d, object=0x%x\n", + printf("%s(0x%x, 0x%x, 0x%x, 0x%x) failed, rc=%d\n", "memory_object_data_request", object->pager, - object->pager_request, cluster_start + object->paging_offset, - length, access_required, - rc, object); + length, access_required, rc); /* * Don't want to leave a busy page around, * but the data request may have blocked, * so check if it's still there and busy. */ - vm_object_lock(object); - for (; length; - length -= PAGE_SIZE, - cluster_start += PAGE_SIZE_64) { - vm_page_t p; - if ((p = vm_page_lookup(object, + if(!object->phys_contiguous) { + vm_object_lock(object); + for (; length; length -= PAGE_SIZE, + cluster_start += PAGE_SIZE_64) { + vm_page_t p; + if ((p = vm_page_lookup(object, cluster_start)) - && p->absent && p->busy - && p != first_m) { - VM_PAGE_FREE(m); - } + && p->absent && p->busy + && p != first_m) { + VM_PAGE_FREE(p); + } + } } vm_fault_cleanup(object, first_m); cur_thread->interruptible = interruptible_state; return((rc == MACH_SEND_INTERRUPTED) ? VM_FAULT_INTERRUPTED : VM_FAULT_MEMORY_ERROR); + } else { +#ifdef notdefcdy + tws_hash_line_t line; + task_t task; + + task = current_task(); + + if((map != NULL) && + (task->dynamic_working_set != 0)) { + if(tws_lookup + ((tws_hash_t) + task->dynamic_working_set, + offset, object, + &line) == KERN_SUCCESS) { + tws_line_signal((tws_hash_t) + task->dynamic_working_set, + map, line, vaddr); + } + } +#endif } /* @@ -1343,6 +1399,8 @@ no_clustering: cur_thread->interruptible = interruptible_state; return(VM_FAULT_INTERRUPTED); } + if(m == VM_PAGE_NULL) + break; continue; } @@ -1404,6 +1462,7 @@ no_clustering: cur_thread->interruptible = interruptible_state; return(VM_FAULT_MEMORY_SHORTAGE); } + m->no_isync = FALSE; if (!no_zero_fill) { vm_object_unlock(object); @@ -1411,10 +1470,25 @@ no_clustering: if (type_of_fault) *type_of_fault = DBG_ZERO_FILL_FAULT; VM_STAT(zero_fill_count++); + + if (bumped_pagein == TRUE) { + VM_STAT(pageins--); + current_task()->pageins--; + } vm_object_lock(object); } vm_page_lock_queues(); VM_PAGE_QUEUES_REMOVE(m); + m->page_ticket = vm_page_ticket; + vm_page_ticket_roll++; + if(vm_page_ticket_roll == VM_PAGE_TICKETS_IN_ROLL) { + vm_page_ticket_roll = 0; + if(vm_page_ticket == + VM_PAGE_TICKET_ROLL_IDS) + vm_page_ticket= 0; + else + vm_page_ticket++; + } queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); m->inactive = TRUE; @@ -1459,10 +1533,12 @@ no_clustering: dbgTrace(0xBEEF0015, (unsigned int) object, (unsigned int) m); /* (TEST/DEBUG) */ #endif #if EXTRA_ASSERTIONS - assert(m->busy && !m->absent); - assert((first_m == VM_PAGE_NULL) || - (first_m->busy && !first_m->absent && - !first_m->active && !first_m->inactive)); + if(m != VM_PAGE_NULL) { + assert(m->busy && !m->absent); + assert((first_m == VM_PAGE_NULL) || + (first_m->busy && !first_m->absent && + !first_m->active && !first_m->inactive)); + } #endif /* EXTRA_ASSERTIONS */ XPR(XPR_VM_FAULT, @@ -1476,7 +1552,7 @@ no_clustering: * by the top-level object. */ - if (object != first_object) { + if ((object != first_object) && (m != VM_PAGE_NULL)) { /* * We only really need to copy if we * want to write it. @@ -1598,7 +1674,8 @@ no_clustering: */ while (first_object->copy_strategy == MEMORY_OBJECT_COPY_DELAY && - (copy_object = first_object->copy) != VM_OBJECT_NULL) { + (copy_object = first_object->copy) != VM_OBJECT_NULL && + (m!= VM_PAGE_NULL)) { vm_object_offset_t copy_offset; vm_page_t copy_m; @@ -1846,8 +1923,10 @@ no_clustering: */ #if !VM_FAULT_STATIC_CONFIG - if (vm_fault_dirty_handling && (*protection & VM_PROT_WRITE)) + if (vm_fault_dirty_handling && (*protection & VM_PROT_WRITE) && + (m != VM_PAGE_NULL)) { m->dirty = TRUE; + } #endif #if TRACEFAULTPAGE dbgTrace(0xBEEF0018, (unsigned int) object, (unsigned int) vm_page_deactivate_behind); /* (TEST/DEBUG) */ @@ -1871,6 +1950,9 @@ no_clustering: dbgTrace(0xBEEF001A, (unsigned int) VM_FAULT_SUCCESS, 0); /* (TEST/DEBUG) */ #endif cur_thread->interruptible = interruptible_state; + if(*result_page == VM_PAGE_NULL) { + vm_object_unlock(object); + } return(VM_FAULT_SUCCESS); #if 0 @@ -2059,8 +2141,8 @@ vm_fault( if (m->busy) break; - if (m->unusual && (m->error || m->restart || - m->absent || (fault_type & m->page_lock))) { + if (m->unusual && (m->error || m->restart || m->private + || m->absent || (fault_type & m->page_lock))) { /* * Unusual case. Give up. @@ -2121,16 +2203,43 @@ FastPmapEnter: #endif /* MACH_KDB */ #endif /* STATIC_CONFIG */ PMAP_ENTER(pmap, vaddr, m, prot, wired); - pmap_attribute(pmap, - vaddr, - PAGE_SIZE, - MATTR_CACHE, - &mv_cache_sync); + + if (m->no_isync) { + pmap_attribute(pmap, + vaddr, + PAGE_SIZE, + MATTR_CACHE, + &mv_cache_sync); + + } + { + tws_hash_line_t line; + task_t task; + + task = current_task(); + if((map != NULL) && + (task->dynamic_working_set != 0)) { + if(tws_lookup + ((tws_hash_t) + task->dynamic_working_set, + cur_offset, object, + &line) != KERN_SUCCESS) { + if(tws_insert((tws_hash_t) + task->dynamic_working_set, + m->offset, m->object, + vaddr, pmap_map) + == KERN_NO_SPACE) { + tws_expand_working_set( + task->dynamic_working_set, + TWS_HASH_LINE_COUNT); + } + } + } + } if (m->clustered) { vm_pagein_cluster_used++; m->clustered = FALSE; - } /* * Grab the object lock to manipulate @@ -2146,7 +2255,14 @@ FastPmapEnter: */ vm_object_lock(object); vm_page_lock_queues(); - + /* + * we did the isync above... we're clearing + * the flag here to avoid holding a lock + * while calling pmap functions, however + * we need hold the object lock before + * we can modify the flag + */ + m->no_isync = FALSE; m->reference = TRUE; if (change_wiring) { @@ -2324,6 +2440,18 @@ FastPmapEnter: if (m == VM_PAGE_NULL) { break; } + /* + * This is a zero-fill or initial fill + * page fault. As such, we consider it + * undefined with respect to instruction + * execution. i.e. it is the responsibility + * of higher layers to call for an instruction + * sync after changing the contents and before + * sending a program into this area. We + * choose this approach for performance + */ + + m->no_isync = FALSE; if (cur_object != object) vm_object_unlock(cur_object); @@ -2348,6 +2476,19 @@ FastPmapEnter: } vm_page_lock_queues(); VM_PAGE_QUEUES_REMOVE(m); + + m->page_ticket = vm_page_ticket; + vm_page_ticket_roll++; + if(vm_page_ticket_roll == + VM_PAGE_TICKETS_IN_ROLL) { + vm_page_ticket_roll = 0; + if(vm_page_ticket == + VM_PAGE_TICKET_ROLL_IDS) + vm_page_ticket= 0; + else + vm_page_ticket++; + } + queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); m->inactive = TRUE; @@ -2403,7 +2544,7 @@ FastPmapEnter: lo_offset, hi_offset, behavior, &prot, &result_page, &top_page, &type_of_fault, - &error_code, map->no_zero_fill, FALSE); + &error_code, map->no_zero_fill, FALSE, map, vaddr); /* * If we didn't succeed, lose the object reference immediately. @@ -2443,9 +2584,11 @@ FastPmapEnter: m = result_page; - assert((change_wiring && !wired) ? - (top_page == VM_PAGE_NULL) : - ((top_page == VM_PAGE_NULL) == (m->object == object))); + if(m != VM_PAGE_NULL) { + assert((change_wiring && !wired) ? + (top_page == VM_PAGE_NULL) : + ((top_page == VM_PAGE_NULL) == (m->object == object))); + } /* * How to clean up the result of vm_fault_page. This @@ -2477,9 +2620,13 @@ FastPmapEnter: * since our last lookup. */ - old_copy_object = m->object->copy; + if(m != VM_PAGE_NULL) { + old_copy_object = m->object->copy; - vm_object_unlock(m->object); + vm_object_unlock(m->object); + } else { + old_copy_object = VM_OBJECT_NULL; + } if ((map != original_map) || !vm_map_verify(map, &version)) { vm_object_t retry_object; vm_object_offset_t retry_offset; @@ -2505,22 +2652,34 @@ FastPmapEnter: if (kr != KERN_SUCCESS) { vm_map_unlock_read(map); - vm_object_lock(m->object); - RELEASE_PAGE(m); - UNLOCK_AND_DEALLOCATE; + if(m != VM_PAGE_NULL) { + vm_object_lock(m->object); + RELEASE_PAGE(m); + UNLOCK_AND_DEALLOCATE; + } else { + vm_object_deallocate(object); + } goto done; } vm_object_unlock(retry_object); - vm_object_lock(m->object); + if(m != VM_PAGE_NULL) { + vm_object_lock(m->object); + } else { + vm_object_lock(object); + } if ((retry_object != object) || (retry_offset != offset)) { vm_map_unlock_read(map); if(pmap_map != map) vm_map_unlock(pmap_map); - RELEASE_PAGE(m); - UNLOCK_AND_DEALLOCATE; + if(m != VM_PAGE_NULL) { + RELEASE_PAGE(m); + UNLOCK_AND_DEALLOCATE; + } else { + vm_object_deallocate(object); + } goto RetryFault; } @@ -2529,17 +2688,27 @@ FastPmapEnter: * has been copied while we left the map unlocked. */ prot &= retry_prot; - vm_object_unlock(m->object); + if(m != VM_PAGE_NULL) { + vm_object_unlock(m->object); + } else { + vm_object_unlock(object); + } + } + if(m != VM_PAGE_NULL) { + vm_object_lock(m->object); + } else { + vm_object_lock(object); } - vm_object_lock(m->object); /* * If the copy object changed while the top-level object * was unlocked, then we must take away write permission. */ - if (m->object->copy != old_copy_object) - prot &= ~VM_PROT_WRITE; + if(m != VM_PAGE_NULL) { + if (m->object->copy != old_copy_object) + prot &= ~VM_PROT_WRITE; + } /* * If we want to wire down this page, but no longer have @@ -2550,17 +2719,15 @@ FastPmapEnter: vm_map_verify_done(map, &version); if(pmap_map != map) vm_map_unlock(pmap_map); - RELEASE_PAGE(m); - UNLOCK_AND_DEALLOCATE; + if(m != VM_PAGE_NULL) { + RELEASE_PAGE(m); + UNLOCK_AND_DEALLOCATE; + } else { + vm_object_deallocate(object); + } goto RetryFault; } - /* - * It's critically important that a wired-down page be faulted - * only once in each map for which it is wired. - */ - vm_object_unlock(m->object); - /* * Put this page into the physical map. * We had to do the unlock above because pmap_enter @@ -2568,44 +2735,121 @@ FastPmapEnter: * the pageout queues. If the pageout daemon comes * across the page, it will remove it from the queues. */ - PMAP_ENTER(pmap, vaddr, m, prot, wired); + if(m != VM_PAGE_NULL) { + if (m->no_isync) { + m->no_isync = FALSE; + + vm_object_unlock(m->object); + + PMAP_ENTER(pmap, vaddr, m, prot, wired); + + /* + * It's critically important that a wired-down page be faulted + * only once in each map for which it is wired. + */ + /* Sync I & D caches for new mapping */ + pmap_attribute(pmap, + vaddr, + PAGE_SIZE, + MATTR_CACHE, + &mv_cache_sync); + } else { + vm_object_unlock(m->object); + + PMAP_ENTER(pmap, vaddr, m, prot, wired); + } + { + tws_hash_line_t line; + task_t task; + + task = current_task(); + if((map != NULL) && + (task->dynamic_working_set != 0)) { + if(tws_lookup + ((tws_hash_t) + task->dynamic_working_set, + m->offset, m->object, + &line) != KERN_SUCCESS) { + tws_insert((tws_hash_t) + task->dynamic_working_set, + m->offset, m->object, + vaddr, pmap_map); + if(tws_insert((tws_hash_t) + task->dynamic_working_set, + m->offset, m->object, + vaddr, pmap_map) + == KERN_NO_SPACE) { + tws_expand_working_set( + task->dynamic_working_set, + TWS_HASH_LINE_COUNT); + } + } + } + } + } else { + +/* if __ppc__ not working until figure out phys copy on block maps */ +#ifdef notdefcdy + int memattr; + struct phys_entry *pp; + /* + * do a pmap block mapping from the physical address + * in the object + */ + if(pp = pmap_find_physentry( + (vm_offset_t)object->shadow_offset)) { + memattr = ((pp->pte1 & 0x00000078) >> 3); + } else { + memattr = PTE_WIMG_UNCACHED_COHERENT_GUARDED; + } - /* Sync I & D caches for new mapping*/ - pmap_attribute(pmap, - vaddr, - PAGE_SIZE, - MATTR_CACHE, - &mv_cache_sync); + pmap_map_block(pmap, vaddr, + (vm_offset_t)object->shadow_offset, + object->size, prot, + memattr, 0); /* Set up a block mapped area */ +//#else + vm_offset_t off; + for (off = 0; off < object->size; off += page_size) { + pmap_enter(pmap, vaddr + off, + object->shadow_offset + off, prot, TRUE); + /* Map it in */ + } +#endif + + } /* * If the page is not wired down and isn't already * on a pageout queue, then put it where the * pageout daemon can find it. */ - vm_object_lock(m->object); - vm_page_lock_queues(); - if (change_wiring) { - if (wired) - vm_page_wire(m); - else - vm_page_unwire(m); - } + if(m != VM_PAGE_NULL) { + vm_object_lock(m->object); + vm_page_lock_queues(); + + if (change_wiring) { + if (wired) + vm_page_wire(m); + else + vm_page_unwire(m); + } #if VM_FAULT_STATIC_CONFIG - else { - if (!m->active && !m->inactive) - vm_page_activate(m); - m->reference = TRUE; - } + else { + if (!m->active && !m->inactive) + vm_page_activate(m); + m->reference = TRUE; + } #else - else if (software_reference_bits) { - if (!m->active && !m->inactive) + else if (software_reference_bits) { + if (!m->active && !m->inactive) + vm_page_activate(m); + m->reference = TRUE; + } else { vm_page_activate(m); - m->reference = TRUE; - } else { - vm_page_activate(m); - } + } #endif - vm_page_unlock_queues(); + vm_page_unlock_queues(); + } /* * Unlock everything, and return @@ -2614,9 +2858,14 @@ FastPmapEnter: vm_map_verify_done(map, &version); if(pmap_map != map) vm_map_unlock(pmap_map); - PAGE_WAKEUP_DONE(m); + if(m != VM_PAGE_NULL) { + PAGE_WAKEUP_DONE(m); + UNLOCK_AND_DEALLOCATE; + } else { + vm_fault_cleanup(object, top_page); + vm_object_deallocate(object); + } kr = KERN_SUCCESS; - UNLOCK_AND_DEALLOCATE; #undef UNLOCK_AND_DEALLOCATE #undef RELEASE_PAGE @@ -2747,7 +2996,7 @@ vm_fault_unwire( &top_page, (int *)0, 0, map->no_zero_fill, - FALSE); + FALSE, NULL, 0); } while (result == VM_FAULT_RETRY); if (result != VM_FAULT_SUCCESS) @@ -2932,15 +3181,25 @@ vm_fault_wire_fast( * We have to unlock the object because pmap_enter * may cause other faults. */ - vm_object_unlock(object); + if (m->no_isync) { + m->no_isync = FALSE; + + vm_object_unlock(object); + + PMAP_ENTER(pmap, va, m, prot, TRUE); - PMAP_ENTER(pmap, va, m, prot, TRUE); - /* Sync I & D caches for new mapping */ - pmap_attribute(pmap, - va, - PAGE_SIZE, - MATTR_CACHE, - &mv_cache_sync); + /* Sync I & D caches for new mapping */ + pmap_attribute(pmap, + va, + PAGE_SIZE, + MATTR_CACHE, + &mv_cache_sync); + + } else { + vm_object_unlock(object); + + PMAP_ENTER(pmap, va, m, prot, TRUE); + } /* * Must relock object so that paging_in_progress can be cleared. @@ -3097,7 +3356,7 @@ vm_fault_copy( (int *)0, &error, dst_map->no_zero_fill, - FALSE)) { + FALSE, NULL, 0)) { case VM_FAULT_SUCCESS: break; case VM_FAULT_RETRY: @@ -3183,7 +3442,7 @@ vm_fault_copy( (int *)0, &error, FALSE, - FALSE)) { + FALSE, NULL, 0)) { case VM_FAULT_SUCCESS: break; @@ -3422,7 +3681,6 @@ vm_fault_page_overwrite( if ((rc = memory_object_data_unlock( dst_object->pager, - dst_object->pager_request, dst_offset + dst_object->paging_offset, PAGE_SIZE, u)) != KERN_SUCCESS) { diff --git a/osfmk/vm/vm_fault.h b/osfmk/vm/vm_fault.h index edab4633b..c8061ad0e 100644 --- a/osfmk/vm/vm_fault.h +++ b/osfmk/vm/vm_fault.h @@ -102,7 +102,9 @@ extern vm_fault_return_t vm_fault_page( /* More arguments: */ kern_return_t *error_code, /* code if page is in error */ boolean_t no_zero_fill, /* don't fill absent pages */ - boolean_t data_supply); /* treat as data_supply */ + boolean_t data_supply, /* treat as data_supply */ + vm_map_t map, + vm_offset_t vaddr); extern void vm_fault_cleanup( vm_object_t object, diff --git a/osfmk/vm/vm_init.c b/osfmk/vm/vm_init.c index fc085b3c8..a5a1c26ae 100644 --- a/osfmk/vm/vm_init.c +++ b/osfmk/vm/vm_init.c @@ -109,6 +109,8 @@ vm_mem_bootstrap(void) vm_fault_init(); vm_page_module_init(); memory_manager_default_init(); + memory_object_control_bootstrap(); + device_pager_bootstrap(); } void diff --git a/osfmk/vm/vm_kern.c b/osfmk/vm/vm_kern.c index 7d957c220..56143f42c 100644 --- a/osfmk/vm/vm_kern.c +++ b/osfmk/vm/vm_kern.c @@ -668,7 +668,6 @@ kmem_suballoc( vm_object_deallocate(vm_submap_object); return (kr); } - *new_map = map; return (KERN_SUCCESS); } @@ -713,143 +712,6 @@ kmem_init( + vm_page_inactive_count)); } -/* - * kmem_io_map_copyout: - * - * Establish temporary mapping in designated map for the memory - * passed in. Memory format must be a page_list vm_map_copy. - */ - -kern_return_t -kmem_io_map_copyout( - vm_map_t map, - vm_offset_t *addr, /* actual addr of data */ - vm_size_t *alloc_size, /* size allocated */ - vm_map_copy_t copy, - vm_size_t min_size, /* Do at least this much */ - vm_prot_t prot) /* Protection of mapping */ -{ - vm_offset_t myaddr, offset; - vm_size_t mysize, copy_size; - kern_return_t ret; - register - vm_page_t *page_list; - vm_map_copy_t new_copy; - register - int i; - - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - assert(min_size != 0); - - /* - * Figure out the size in vm pages. - */ - min_size += (vm_size_t)(copy->offset - trunc_page_64(copy->offset)); - min_size = round_page(min_size); - mysize = (vm_size_t)(round_page_64( - copy->offset + (vm_object_offset_t)copy->size) - - trunc_page_64(copy->offset)); - - /* - * If total size is larger than one page list and - * we don't have to do more than one page list, then - * only do one page list. - * - * XXX Could be much smarter about this ... like trimming length - * XXX if we need more than one page list but not all of them. - */ - - copy_size = ptoa(copy->cpy_npages); - if (mysize > copy_size && copy_size > min_size) - mysize = copy_size; - - /* - * Allocate some address space in the map (must be kernel - * space). - */ - myaddr = vm_map_min(map); - ret = vm_map_enter(map, &myaddr, mysize, - (vm_offset_t) 0, TRUE, - VM_OBJECT_NULL, (vm_object_offset_t) 0, FALSE, - prot, prot, VM_INHERIT_DEFAULT); - - if (ret != KERN_SUCCESS) - return(ret); - - /* - * Tell the pmap module that this will be wired, and - * enter the mappings. - */ - pmap_pageable(vm_map_pmap(map), myaddr, myaddr + mysize, TRUE); - - *addr = myaddr + (vm_offset_t) - (copy->offset - trunc_page_64(copy->offset)); - *alloc_size = mysize; - - offset = myaddr; - page_list = ©->cpy_page_list[0]; - while (TRUE) { - for ( i = 0; i < copy->cpy_npages; i++, offset+=PAGE_SIZE_64) { - PMAP_ENTER(vm_map_pmap(map), - (vm_offset_t)offset, *page_list, - prot, TRUE); - page_list++; - } - - if (offset == (myaddr + mysize)) - break; - - /* - * Onward to the next page_list. The extend_cont - * leaves the current page list's pages alone; - * they'll be cleaned up at discard. Reset this - * copy's continuation to discard the next one. - */ - vm_map_copy_invoke_extend_cont(copy, &new_copy, &ret); - - if (ret != KERN_SUCCESS) { - kmem_io_map_deallocate(map, myaddr, mysize); - return(ret); - } - copy->cpy_cont = vm_map_copy_discard_cont; - copy->cpy_cont_args = (vm_map_copyin_args_t) new_copy; - assert(new_copy != VM_MAP_COPY_NULL); - assert(new_copy->type == VM_MAP_COPY_PAGE_LIST); - copy = new_copy; - page_list = ©->cpy_page_list[0]; - } - - return(ret); -} - -/* - * kmem_io_map_deallocate: - * - * Get rid of the mapping established by kmem_io_map_copyout. - * Assumes that addr and size have been rounded to page boundaries. - */ - -void -kmem_io_map_deallocate( - vm_map_t map, - vm_offset_t addr, - vm_size_t size) -{ - - register vm_offset_t va, end; - - end = round_page(addr + size); - for (va = trunc_page(addr); va < end; va += PAGE_SIZE) - pmap_change_wiring(vm_map_pmap(map), va, FALSE); - - /* - * Remove the mappings. The pmap_remove is needed. - */ - - pmap_remove(vm_map_pmap(map), addr, addr + size); - vm_map_remove(map, addr, addr + size, VM_MAP_REMOVE_KUNWIRE); -} - /* * kmem_io_object_trunc: diff --git a/osfmk/vm/vm_kern.h b/osfmk/vm/vm_kern.h index ec3d2cf2d..95302993f 100644 --- a/osfmk/vm/vm_kern.h +++ b/osfmk/vm/vm_kern.h @@ -128,19 +128,6 @@ extern kern_return_t kmem_suballoc( boolean_t anywhere, vm_map_t *new_map); -extern kern_return_t kmem_io_map_copyout( - vm_map_t map, - vm_offset_t *addr, - vm_size_t *alloc_size, - vm_map_copy_t copy, - vm_size_t min_size, - vm_prot_t prot); - -extern void kmem_io_map_deallocate( - vm_map_t map, - vm_offset_t addr, - vm_size_t size); - extern void kmem_io_object_deallocate( vm_map_copy_t copy); diff --git a/osfmk/vm/vm_map.c b/osfmk/vm/vm_map.c index 0e1cf4a48..40e3da3fa 100644 --- a/osfmk/vm/vm_map.c +++ b/osfmk/vm/vm_map.c @@ -150,10 +150,6 @@ extern kern_return_t vm_map_copyout_kernel_buffer( vm_map_copy_t copy, boolean_t overwrite); -extern kern_return_t vm_map_copyin_page_list_cont( - vm_map_copyin_args_t cont_args, - vm_map_copy_t *copy_result); /* OUT */ - extern void vm_map_fork_share( vm_map_t old_map, vm_map_entry_t old_entry, @@ -295,6 +291,8 @@ vm_offset_t kentry_data; vm_size_t kentry_data_size; int kentry_count = 2048; /* to init kentry_data_size */ +#define NO_COALESCE_LIMIT (1024 * 128) + /* * Threshold for aggressive (eager) page map entering for vm copyout * operations. Any copyout larger will NOT be aggressively entered. @@ -1192,6 +1190,9 @@ vm_map_pmap_enter( vm_object_offset_t offset, vm_prot_t protection) { + + vm_machine_attribute_val_t mv_cache_sync = MATTR_VAL_CACHE_SYNC; + while (addr < end_addr) { register vm_page_t m; @@ -1222,7 +1223,17 @@ vm_map_pmap_enter( PMAP_ENTER(map->pmap, addr, m, protection, FALSE); + if (m->no_isync) { + pmap_attribute(map->pmap, + addr, + PAGE_SIZE, + MATTR_CACHE, + &mv_cache_sync); + } vm_object_lock(object); + + m->no_isync = FALSE; + PAGE_WAKEUP_DONE(m); vm_page_lock_queues(); if (!m->active && !m->inactive) @@ -1437,6 +1448,7 @@ vm_map_enter( (entry->max_protection == max_protection) && (entry->behavior == VM_BEHAVIOR_DEFAULT) && (entry->in_transition == 0) && + ((entry->vme_end - entry->vme_start) + size < NO_COALESCE_LIMIT) && (entry->wired_count == 0)) { /* implies user_wired_count == 0 */ if (vm_object_coalesce(entry->object.vm_object, VM_OBJECT_NULL, @@ -2087,6 +2099,8 @@ vm_map_wire_nested( kern_return_t rc; boolean_t need_wakeup; boolean_t main_map = FALSE; + boolean_t interruptible_state; + thread_t cur_thread; unsigned int last_timestamp; vm_size_t size; @@ -2098,6 +2112,11 @@ vm_map_wire_nested( VM_MAP_RANGE_CHECK(map, start, end); assert(page_aligned(start)); assert(page_aligned(end)); + if (start == end) { + /* We wired what the caller asked for, zero pages */ + vm_map_unlock(map); + return KERN_SUCCESS; + } if (vm_map_lookup_entry(map, start, &first_entry)) { entry = first_entry; @@ -2110,6 +2129,7 @@ vm_map_wire_nested( s=start; need_wakeup = FALSE; + cur_thread = current_thread(); while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) { /* * If another thread is wiring/unwiring this entry then @@ -2139,7 +2159,7 @@ vm_map_wire_nested( vm_map_entry_wait(map, (user_wire) ? THREAD_ABORTSAFE : THREAD_UNINT); - if (user_wire && current_thread()->wait_result == + if (user_wire && cur_thread->wait_result == THREAD_INTERRUPTED) { /* * undo the wirings we have done so far @@ -2454,10 +2474,20 @@ vm_map_wire_nested( * there when the map lock is acquired for the second time. */ vm_map_unlock(map); + + if (!user_wire && cur_thread != THREAD_NULL) { + interruptible_state = cur_thread->interruptible; + cur_thread->interruptible = FALSE; + } + if(map_pmap) rc = vm_fault_wire(map, &tmp_entry, map_pmap); else rc = vm_fault_wire(map, &tmp_entry, map->pmap); + + if (!user_wire && cur_thread != THREAD_NULL) + cur_thread->interruptible = interruptible_state; + vm_map_lock(map); if (last_timestamp+1 != map->timestamp) { @@ -3296,109 +3326,6 @@ vm_map_remove( } -/* - * vm_map_copy_steal_pages: - * - * Steal all the pages from a vm_map_copy page_list by copying ones - * that have not already been stolen. - */ -void -vm_map_copy_steal_pages( - vm_map_copy_t copy) -{ - register vm_page_t m, new_m; - register int i; - vm_object_t object; - - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - for (i = 0; i < copy->cpy_npages; i++) { - - /* - * If the page is not tabled, then it's already stolen. - */ - m = copy->cpy_page_list[i]; - if (!m->tabled) - continue; - - /* - * Page was not stolen, get a new - * one and do the copy now. - */ - while ((new_m = vm_page_grab()) == VM_PAGE_NULL) { - VM_PAGE_WAIT(); - } - - vm_page_gobble(new_m); /* mark as consumed internally */ - vm_page_copy(m, new_m); - - object = m->object; - vm_object_lock(object); - vm_page_lock_queues(); - if (!m->active && !m->inactive) - vm_page_activate(m); - vm_page_unlock_queues(); - PAGE_WAKEUP_DONE(m); - vm_object_paging_end(object); - vm_object_unlock(object); - - copy->cpy_page_list[i] = new_m; - } - copy->cpy_page_loose = TRUE; -} - -/* - * vm_map_copy_page_discard: - * - * Get rid of the pages in a page_list copy. If the pages are - * stolen, they are freed. If the pages are not stolen, they - * are unbusied, and associated state is cleaned up. - */ -void -vm_map_copy_page_discard( - vm_map_copy_t copy) -{ - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - while (copy->cpy_npages > 0) { - vm_page_t m; - - if ((m = copy->cpy_page_list[--(copy->cpy_npages)]) != - VM_PAGE_NULL) { - - /* - * If it's not in the table, then it's - * a stolen page that goes back - * to the free list. Else it belongs - * to some object, and we hold a - * paging reference on that object. - */ - if (!m->tabled) { - VM_PAGE_FREE(m); - } - else { - vm_object_t object; - - object = m->object; - - vm_object_lock(object); - vm_page_lock_queues(); - if (!m->active && !m->inactive) - vm_page_activate(m); - vm_page_unlock_queues(); - - if ((!m->busy)) { - kern_return_t kr; - kr = vm_page_unpin(m); - assert(kr == KERN_SUCCESS); - } else { - PAGE_WAKEUP_DONE(m); - } - vm_object_paging_end(object); - vm_object_unlock(object); - } - } - } -} - /* * Routine: vm_map_copy_discard * @@ -3431,41 +3358,6 @@ free_next_copy: case VM_MAP_COPY_OBJECT: vm_object_deallocate(copy->cpy_object); break; - case VM_MAP_COPY_PAGE_LIST: - - /* - * To clean this up, we have to unbusy all the pages - * and release the paging references in their objects. - */ - if (copy->cpy_npages > 0) - vm_map_copy_page_discard(copy); - - /* - * If there's a continuation, abort it. The - * abort routine releases any storage. - */ - if (vm_map_copy_has_cont(copy)) { - - assert(vm_map_copy_cont_is_valid(copy)); - /* - * Special case: recognize - * vm_map_copy_discard_cont and optimize - * here to avoid tail recursion. - */ - if (copy->cpy_cont == vm_map_copy_discard_cont) { - register vm_map_copy_t new_copy; - - new_copy = (vm_map_copy_t) copy->cpy_cont_args; - zfree(vm_map_copy_zone, (vm_offset_t) copy); - copy = new_copy; - goto free_next_copy; - } else { - vm_map_copy_abort_cont(copy); - } - } - - break; - case VM_MAP_COPY_KERNEL_BUFFER: /* @@ -3537,24 +3429,6 @@ vm_map_copy_copy( return new_copy; } -/* - * Routine: vm_map_copy_discard_cont - * - * Description: - * A version of vm_map_copy_discard that can be called - * as a continuation from a vm_map_copy page list. - */ -kern_return_t -vm_map_copy_discard_cont( - vm_map_copyin_args_t cont_args, - vm_map_copy_t *copy_result) /* OUT */ -{ - vm_map_copy_discard((vm_map_copy_t) cont_args); - if (copy_result != (vm_map_copy_t *)0) - *copy_result = VM_MAP_COPY_NULL; - return(KERN_SUCCESS); -} - kern_return_t vm_map_overwrite_submap_recurse( vm_map_t dst_map, @@ -3777,8 +3651,9 @@ vm_map_copy_overwrite_nested( */ if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) { - return(vm_map_copyout_kernel_buffer(dst_map, &dst_addr, - copy, TRUE)); + return(vm_map_copyout_kernel_buffer( + dst_map, &dst_addr, + copy, TRUE)); } /* @@ -4749,6 +4624,11 @@ vm_map_copy_overwrite_aligned( */ if (entry->needs_copy) prot &= ~VM_PROT_WRITE; + /* It is our policy to require */ + /* explicit sync from anyone */ + /* writing code and then */ + /* a pc to execute it. */ + /* No isync here */ PMAP_ENTER(pmap, va, m, prot, FALSE); @@ -4973,7 +4853,7 @@ vm_map_copyout_kernel_buffer( */ if (copyout((char *)copy->cpy_kdata, (char *)*addr, copy->size)) { - kr = KERN_INVALID_ADDRESS; + return(KERN_INVALID_ADDRESS); } } else { @@ -4989,7 +4869,7 @@ vm_map_copyout_kernel_buffer( if (copyout((char *)copy->cpy_kdata, (char *)*addr, copy->size)) { - kr = KERN_INVALID_ADDRESS; + return(KERN_INVALID_ADDRESS); } (void) vm_map_switch(oldmap); @@ -5099,9 +4979,6 @@ vm_map_copyout( copy, FALSE)); } - if (copy->type == VM_MAP_COPY_PAGE_LIST) - return(vm_map_copyout_page_list(dst_map, dst_addr, copy)); - /* * Find space for the data */ @@ -5357,515 +5234,145 @@ vm_map_copyout( boolean_t vm_map_aggressive_enter; /* not used yet */ + /* + * Routine: vm_map_copyin * - * vm_map_copyout_page_list: + * Description: + * Copy the specified region (src_addr, len) from the + * source address space (src_map), possibly removing + * the region from the source address space (src_destroy). * - * Version of vm_map_copyout() for page list vm map copies. + * Returns: + * A vm_map_copy_t object (copy_result), suitable for + * insertion into another address space (using vm_map_copyout), + * copying over another address space region (using + * vm_map_copy_overwrite). If the copy is unused, it + * should be destroyed (using vm_map_copy_discard). * + * In/out conditions: + * The source map should not be locked on entry. */ + +typedef struct submap_map { + vm_map_t parent_map; + vm_offset_t base_start; + vm_offset_t base_end; + struct submap_map *next; +} submap_map_t; + kern_return_t -vm_map_copyout_page_list( - register vm_map_t dst_map, - vm_offset_t *dst_addr, /* OUT */ - register vm_map_copy_t copy) +vm_map_copyin_common( + vm_map_t src_map, + vm_offset_t src_addr, + vm_size_t len, + boolean_t src_destroy, + boolean_t src_volatile, + vm_map_copy_t *copy_result, /* OUT */ + boolean_t use_maxprot) { - vm_size_t size; - vm_offset_t start; - vm_offset_t end; - vm_object_offset_t offset; - vm_map_entry_t last; + extern int msg_ool_size_small; + + vm_map_entry_t tmp_entry; /* Result of last map lookup -- + * in multi-level lookup, this + * entry contains the actual + * vm_object/offset. + */ register - vm_object_t object; - vm_page_t *page_list, m; - vm_map_entry_t entry; - vm_object_offset_t old_last_offset; - boolean_t cont_invoked, needs_wakeup; - kern_return_t result = KERN_SUCCESS; - vm_map_copy_t orig_copy; - vm_object_offset_t dst_offset; - boolean_t must_wire; - boolean_t aggressive_enter; + vm_map_entry_t new_entry = VM_MAP_ENTRY_NULL; /* Map entry for copy */ + + vm_offset_t src_start; /* Start of current entry -- + * where copy is taking place now + */ + vm_offset_t src_end; /* End of entire region to be + * copied */ + vm_offset_t base_start; /* submap fields to save offsets */ + /* in original map */ + vm_offset_t base_end; + vm_map_t base_map=src_map; + vm_map_entry_t base_entry; + boolean_t map_share=FALSE; + submap_map_t *parent_maps = NULL; + + register + vm_map_copy_t copy; /* Resulting copy */ + vm_offset_t copy_addr; /* - * Check for null copy object. + * Check for copies of zero bytes. */ - if (copy == VM_MAP_COPY_NULL) { - *dst_addr = 0; + if (len == 0) { + *copy_result = VM_MAP_COPY_NULL; return(KERN_SUCCESS); } - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - /* - * Make sure the pages are stolen, because we are - * going to put them in a new object. Assume that - * all pages are identical to first in this regard. + * If the copy is sufficiently small, use a kernel buffer instead + * of making a virtual copy. The theory being that the cost of + * setting up VM (and taking C-O-W faults) dominates the copy costs + * for small regions. */ - - page_list = ©->cpy_page_list[0]; - if (!copy->cpy_page_loose) - vm_map_copy_steal_pages(copy); + if ((len < msg_ool_size_small) && !use_maxprot) + return vm_map_copyin_kernel_buffer(src_map, src_addr, len, + src_destroy, copy_result); /* - * Find space for the data + * Compute start and end of region */ - size = round_page_64(copy->offset + (vm_object_offset_t)copy->size) - - trunc_page_64(copy->offset); -StartAgain: - vm_map_lock(dst_map); - must_wire = dst_map->wiring_required; - - assert(first_free_is_valid(dst_map)); - last = dst_map->first_free; - if (last == vm_map_to_entry(dst_map)) { - start = vm_map_min(dst_map); - } else { - start = last->vme_end; - } - - while (TRUE) { - vm_map_entry_t next = last->vme_next; - end = start + size; + src_start = trunc_page(src_addr); + src_end = round_page(src_addr + len); - if ((end > dst_map->max_offset) || (end < start)) { - if (dst_map->wait_for_space) { - if (size <= (dst_map->max_offset - - dst_map->min_offset)) { - assert_wait((event_t) dst_map, - THREAD_INTERRUPTIBLE); - vm_map_unlock(dst_map); - thread_block((void (*)(void))0); - goto StartAgain; - } - } - vm_map_unlock(dst_map); - return(KERN_NO_SPACE); - } + XPR(XPR_VM_MAP, "vm_map_copyin_common map 0x%x addr 0x%x len 0x%x dest %d\n", (natural_t)src_map, src_addr, len, src_destroy, 0); - if ((next == vm_map_to_entry(dst_map)) || - (next->vme_start >= end)) { - break; - } + /* + * Check that the end address doesn't overflow + */ - last = next; - start = last->vme_end; - } + if (src_end <= src_start) + if ((src_end < src_start) || (src_start != 0)) + return(KERN_INVALID_ADDRESS); /* - * See whether we can avoid creating a new entry (and object) by - * extending one of our neighbors. [So far, we only attempt to - * extend from below.] + * Allocate a header element for the list. * - * The code path below here is a bit twisted. If any of the - * extension checks fails, we branch to create_object. If - * it all works, we fall out the bottom and goto insert_pages. - */ - if (last == vm_map_to_entry(dst_map) || - last->vme_end != start || - last->is_shared != FALSE || - last->is_sub_map != FALSE || - last->inheritance != VM_INHERIT_DEFAULT || - last->protection != VM_PROT_DEFAULT || - last->max_protection != VM_PROT_ALL || - last->behavior != VM_BEHAVIOR_DEFAULT || - last->in_transition || - (must_wire ? (last->wired_count != 1 || - last->user_wired_count != 0) : - (last->wired_count != 0))) { - goto create_object; - } - - /* - * If this entry needs an object, make one. + * Use the start and end in the header to + * remember the endpoints prior to rounding. */ - if (last->object.vm_object == VM_OBJECT_NULL) { - object = vm_object_allocate( - (vm_size_t)(last->vme_end - last->vme_start + size)); - last->object.vm_object = object; - last->offset = 0; - } - else { - vm_object_offset_t prev_offset = last->offset; - vm_size_t prev_size = start - last->vme_start; - vm_size_t new_size; - /* - * This is basically vm_object_coalesce. - */ + copy = (vm_map_copy_t) zalloc(vm_map_copy_zone); + vm_map_copy_first_entry(copy) = + vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy); + copy->type = VM_MAP_COPY_ENTRY_LIST; + copy->cpy_hdr.nentries = 0; + copy->cpy_hdr.entries_pageable = TRUE; - object = last->object.vm_object; - vm_object_lock(object); + copy->offset = src_addr; + copy->size = len; + + new_entry = vm_map_copy_entry_create(copy); - /* - * Try to collapse the object first - */ - vm_object_collapse(object); +#define RETURN(x) \ + MACRO_BEGIN \ + vm_map_unlock(src_map); \ + if (new_entry != VM_MAP_ENTRY_NULL) \ + vm_map_copy_entry_dispose(copy,new_entry); \ + vm_map_copy_discard(copy); \ + { \ + submap_map_t *ptr; \ + \ + for(ptr = parent_maps; ptr != NULL; ptr = parent_maps) { \ + parent_maps=parent_maps->next; \ + kfree((vm_offset_t)ptr, sizeof(submap_map_t)); \ + } \ + } \ + MACRO_RETURN(x); \ + MACRO_END - - /* - * Can't coalesce if pages not mapped to - * last may be in use anyway: - * . more than one reference - * . paged out - * . shadows another object - * . has a copy elsewhere - * . paging references (pages might be in page-list) - */ - - if ((object->ref_count > 1) || - object->pager_created || - (object->shadow != VM_OBJECT_NULL) || - (object->copy != VM_OBJECT_NULL) || - (object->paging_in_progress != 0)) { - vm_object_unlock(object); - goto create_object; - } - - /* - * Extend the object if necessary. Don't have to call - * vm_object_page_remove because the pages aren't mapped, - * and vm_page_replace will free up any old ones it encounters. - */ - new_size = prev_offset + prev_size + size; - if (new_size > object->size) { -#if MACH_PAGEMAP - /* - * We cannot extend an object that has existence info, - * since the existence info might then fail to cover - * the entire object. - * - * This assertion must be true because the object - * has no pager, and we only create existence info - * for objects with pagers. - */ - assert(object->existence_map == VM_EXTERNAL_NULL); -#endif /* MACH_PAGEMAP */ - object->size = new_size; - } - vm_object_unlock(object); - } - - /* - * Coalesced the two objects - can extend - * the previous map entry to include the - * new range. - */ - dst_map->size += size; - last->vme_end = end; - UPDATE_FIRST_FREE(dst_map, dst_map->first_free); - - SAVE_HINT(dst_map, last); - - goto insert_pages; - -create_object: - - /* - * Create object - */ - object = vm_object_allocate(size); - - /* - * Create entry - */ - last = vm_map_entry_insert(dst_map, last, start, start + size, - object, 0, FALSE, FALSE, TRUE, - VM_PROT_DEFAULT, VM_PROT_ALL, - VM_BEHAVIOR_DEFAULT, - VM_INHERIT_DEFAULT, (must_wire ? 1 : 0)); - - /* - * Transfer pages into new object. - * Scan page list in vm_map_copy. - */ -insert_pages: - dst_offset = copy->offset & PAGE_MASK_64; - cont_invoked = FALSE; - orig_copy = copy; - last->in_transition = TRUE; - old_last_offset = last->offset - + (start - last->vme_start); - - aggressive_enter = (size <= vm_map_aggressive_enter_max); - - for (offset = 0; offset < size; offset += PAGE_SIZE_64) { - m = *page_list; - assert(m && !m->tabled); - - /* - * Must clear busy bit in page before inserting it. - * Ok to skip wakeup logic because nobody else - * can possibly know about this page. Also set - * dirty bit on the assumption that the page is - * not a page of zeros. - */ - - m->busy = FALSE; - m->dirty = TRUE; - vm_object_lock(object); - vm_page_lock_queues(); - vm_page_replace(m, object, old_last_offset + offset); - if (must_wire) { - vm_page_wire(m); - } else if (aggressive_enter) { - vm_page_activate(m); - } - vm_page_unlock_queues(); - vm_object_unlock(object); - - if (aggressive_enter || must_wire) { - PMAP_ENTER(dst_map->pmap, - last->vme_start + m->offset - last->offset, - m, last->protection, must_wire); - } - - *page_list++ = VM_PAGE_NULL; - assert(copy != VM_MAP_COPY_NULL); - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - if (--(copy->cpy_npages) == 0 && - vm_map_copy_has_cont(copy)) { - vm_map_copy_t new_copy; - - /* - * Ok to unlock map because entry is - * marked in_transition. - */ - cont_invoked = TRUE; - vm_map_unlock(dst_map); - vm_map_copy_invoke_cont(copy, &new_copy, &result); - - if (result == KERN_SUCCESS) { - - /* - * If we got back a copy with real pages, - * steal them now. Either all of the - * pages in the list are tabled or none - * of them are; mixtures are not possible. - * - * Save original copy for consume on - * success logic at end of routine. - */ - if (copy != orig_copy) - vm_map_copy_discard(copy); - - if ((copy = new_copy) != VM_MAP_COPY_NULL) { - page_list = ©->cpy_page_list[0]; - if (!copy->cpy_page_loose) - vm_map_copy_steal_pages(copy); - } - } - else { - /* - * Continuation failed. - */ - vm_map_lock(dst_map); - goto error; - } - - vm_map_lock(dst_map); - } - } - - *dst_addr = start + dst_offset; - - /* - * Clear the in transition bits. This is easy if we - * didn't have a continuation. - */ -error: - needs_wakeup = FALSE; - if (!cont_invoked) { - /* - * We didn't unlock the map, so nobody could - * be waiting. - */ - last->in_transition = FALSE; - assert(!last->needs_wakeup); - } - else { - if (!vm_map_lookup_entry(dst_map, start, &entry)) - panic("vm_map_copyout_page_list: missing entry"); - - /* - * Clear transition bit for all constituent entries that - * were in the original entry. Also check for waiters. - */ - while ((entry != vm_map_to_entry(dst_map)) && - (entry->vme_start < end)) { - assert(entry->in_transition); - entry->in_transition = FALSE; - if (entry->needs_wakeup) { - entry->needs_wakeup = FALSE; - needs_wakeup = TRUE; - } - entry = entry->vme_next; - } - } - - if (result != KERN_SUCCESS) - (void) vm_map_delete(dst_map, start, end, VM_MAP_NO_FLAGS); - - vm_map_unlock(dst_map); - - if (needs_wakeup) - vm_map_entry_wakeup(dst_map); - - /* - * Consume on success logic. - */ - if (copy != VM_MAP_COPY_NULL && copy != orig_copy) { - zfree(vm_map_copy_zone, (vm_offset_t) copy); - } - if (result == KERN_SUCCESS) { - assert(orig_copy != VM_MAP_COPY_NULL); - assert(orig_copy->type == VM_MAP_COPY_PAGE_LIST); - zfree(vm_map_copy_zone, (vm_offset_t) orig_copy); - } - - return(result); -} - -/* - * Routine: vm_map_copyin - * - * Description: - * Copy the specified region (src_addr, len) from the - * source address space (src_map), possibly removing - * the region from the source address space (src_destroy). - * - * Returns: - * A vm_map_copy_t object (copy_result), suitable for - * insertion into another address space (using vm_map_copyout), - * copying over another address space region (using - * vm_map_copy_overwrite). If the copy is unused, it - * should be destroyed (using vm_map_copy_discard). - * - * In/out conditions: - * The source map should not be locked on entry. - */ - -typedef struct submap_map { - vm_map_t parent_map; - vm_offset_t base_start; - vm_offset_t base_end; - struct submap_map *next; -} submap_map_t; - -kern_return_t -vm_map_copyin_common( - vm_map_t src_map, - vm_offset_t src_addr, - vm_size_t len, - boolean_t src_destroy, - boolean_t src_volatile, - vm_map_copy_t *copy_result, /* OUT */ - boolean_t use_maxprot) -{ - extern int msg_ool_size_small; - - vm_map_entry_t tmp_entry; /* Result of last map lookup -- - * in multi-level lookup, this - * entry contains the actual - * vm_object/offset. - */ - register - vm_map_entry_t new_entry = VM_MAP_ENTRY_NULL; /* Map entry for copy */ - - vm_offset_t src_start; /* Start of current entry -- - * where copy is taking place now - */ - vm_offset_t src_end; /* End of entire region to be - * copied */ - vm_offset_t base_start; /* submap fields to save offsets */ - /* in original map */ - vm_offset_t base_end; - vm_map_t base_map=src_map; - vm_map_entry_t base_entry; - boolean_t map_share=FALSE; - submap_map_t *parent_maps = NULL; - - register - vm_map_copy_t copy; /* Resulting copy */ - vm_offset_t copy_addr; - - /* - * Check for copies of zero bytes. - */ - - if (len == 0) { - *copy_result = VM_MAP_COPY_NULL; - return(KERN_SUCCESS); - } - - /* - * If the copy is sufficiently small, use a kernel buffer instead - * of making a virtual copy. The theory being that the cost of - * setting up VM (and taking C-O-W faults) dominates the copy costs - * for small regions. - */ - if ((len < msg_ool_size_small) && !use_maxprot) - return vm_map_copyin_kernel_buffer(src_map, src_addr, len, - src_destroy, copy_result); - - /* - * Compute start and end of region - */ - - src_start = trunc_page(src_addr); - src_end = round_page(src_addr + len); - - XPR(XPR_VM_MAP, "vm_map_copyin_common map 0x%x addr 0x%x len 0x%x dest %d\n", (natural_t)src_map, src_addr, len, src_destroy, 0); - - /* - * Check that the end address doesn't overflow - */ - - if (src_end <= src_start) - if ((src_end < src_start) || (src_start != 0)) - return(KERN_INVALID_ADDRESS); - - /* - * Allocate a header element for the list. - * - * Use the start and end in the header to - * remember the endpoints prior to rounding. - */ - - copy = (vm_map_copy_t) zalloc(vm_map_copy_zone); - vm_map_copy_first_entry(copy) = - vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy); - copy->type = VM_MAP_COPY_ENTRY_LIST; - copy->cpy_hdr.nentries = 0; - copy->cpy_hdr.entries_pageable = TRUE; - - copy->offset = src_addr; - copy->size = len; - - new_entry = vm_map_copy_entry_create(copy); - -#define RETURN(x) \ - MACRO_BEGIN \ - vm_map_unlock(src_map); \ - if (new_entry != VM_MAP_ENTRY_NULL) \ - vm_map_copy_entry_dispose(copy,new_entry); \ - vm_map_copy_discard(copy); \ - { \ - submap_map_t *ptr; \ - \ - for(ptr = parent_maps; ptr != NULL; ptr = parent_maps) { \ - parent_maps=parent_maps->next; \ - kfree((vm_offset_t)ptr, sizeof(submap_map_t)); \ - } \ - } \ - MACRO_RETURN(x); \ - MACRO_END - - /* - * Find the beginning of the region. - */ + /* + * Find the beginning of the region. + */ vm_map_lock(src_map); @@ -5936,6 +5443,15 @@ vm_map_copyin_common( vm_map_clip_start(src_map, tmp_entry, src_start); src_entry = tmp_entry; } + if ((tmp_entry->object.vm_object != VM_OBJECT_NULL) && + (tmp_entry->object.vm_object->phys_contiguous)) { + /* This is not, cannot be supported for now */ + /* we need a description of the caching mode */ + /* reflected in the object before we can */ + /* support copyin, and then the support will */ + /* be for direct copy */ + RETURN(KERN_PROTECTION_FAILURE); + } /* * Create a new address map entry to hold the result. * Fill in the fields from the appropriate source entries. @@ -6038,7 +5554,8 @@ RestartCopy: src_size); /* dec ref gained in copy_quickly */ vm_object_lock(src_object); - src_object->ref_count--; + src_object->ref_count--; + assert(src_object->ref_count > 0); vm_object_res_deallocate(src_object); vm_object_unlock(src_object); vm_map_lock(src_map); @@ -6319,801 +5836,6 @@ vm_map_copyin_object( return(KERN_SUCCESS); } -/* - * vm_map_copyin_page_list_cont: - * - * Continuation routine for vm_map_copyin_page_list. - * - * If vm_map_copyin_page_list can't fit the entire vm range - * into a single page list object, it creates a continuation. - * When the target of the operation has used the pages in the - * initial page list, it invokes the continuation, which calls - * this routine. If an error happens, the continuation is aborted - * (abort arg to this routine is TRUE). To avoid deadlocks, the - * pages are discarded from the initial page list before invoking - * the continuation. - * - * NOTE: This is not the same sort of continuation used by - * the scheduler. - */ - -kern_return_t -vm_map_copyin_page_list_cont( - vm_map_copyin_args_t cont_args, - vm_map_copy_t *copy_result) /* OUT */ -{ - kern_return_t result = KERN_SUCCESS; - register boolean_t abort, src_destroy, src_destroy_only; - - /* - * Check for cases that only require memory destruction. - */ - abort = (copy_result == (vm_map_copy_t *) 0); - src_destroy = (cont_args->destroy_len != (vm_size_t) 0); - src_destroy_only = (cont_args->src_len == (vm_size_t) 0); - - if (abort || src_destroy_only) { - if (src_destroy) - result = vm_map_remove(cont_args->map, - cont_args->destroy_addr, - cont_args->destroy_addr + cont_args->destroy_len, - VM_MAP_NO_FLAGS); - if (!abort) - *copy_result = VM_MAP_COPY_NULL; - } - else { - result = vm_map_copyin_page_list(cont_args->map, - cont_args->src_addr, cont_args->src_len, - cont_args->options, copy_result, TRUE); - - if (src_destroy && - (cont_args->options & VM_MAP_COPYIN_OPT_STEAL_PAGES) && - vm_map_copy_has_cont(*copy_result)) { - vm_map_copyin_args_t new_args; - /* - * Transfer old destroy info. - */ - new_args = (vm_map_copyin_args_t) - (*copy_result)->cpy_cont_args; - new_args->destroy_addr = cont_args->destroy_addr; - new_args->destroy_len = cont_args->destroy_len; - } - } - - vm_map_deallocate(cont_args->map); - kfree((vm_offset_t)cont_args, sizeof(vm_map_copyin_args_data_t)); - - return(result); -} - -/* - * vm_map_copyin_page_list: - * - * This is a variant of vm_map_copyin that copies in a list of pages. - * If steal_pages is TRUE, the pages are only in the returned list. - * If steal_pages is FALSE, the pages are busy and still in their - * objects. A continuation may be returned if not all the pages fit: - * the recipient of this copy_result must be prepared to deal with it. - */ - -kern_return_t -vm_map_copyin_page_list( - vm_map_t src_map, - vm_offset_t src_addr, - vm_size_t len, - int options, - vm_map_copy_t *copy_result, /* OUT */ - boolean_t is_cont) -{ - vm_map_entry_t src_entry; - vm_page_t m; - vm_offset_t src_start; - vm_offset_t src_end; - vm_size_t src_size; - register vm_object_t src_object; - register vm_object_offset_t src_offset; - vm_object_offset_t src_last_offset; - register vm_map_copy_t copy; /* Resulting copy */ - kern_return_t result = KERN_SUCCESS; - boolean_t need_map_lookup; - vm_map_copyin_args_t cont_args; - kern_return_t error_code; - vm_prot_t prot; - boolean_t wired; - boolean_t no_zero_fill; - - submap_map_t *parent_maps = NULL; - vm_map_t base_map = src_map; - - prot = (options & VM_MAP_COPYIN_OPT_VM_PROT); - no_zero_fill = (options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL); - - /* - * If steal_pages is FALSE, this leaves busy pages in - * the object. A continuation must be used if src_destroy - * is true in this case (!steal_pages && src_destroy). - * - * XXX Still have a more general problem of what happens - * XXX if the same page occurs twice in a list. Deadlock - * XXX can happen if vm_fault_page was called. A - * XXX possible solution is to use a continuation if vm_fault_page - * XXX is called and we cross a map entry boundary. - */ - - /* - * Check for copies of zero bytes. - */ - - if (len == 0) { - *copy_result = VM_MAP_COPY_NULL; - return(KERN_SUCCESS); - } - - /* - * Compute start and end of region - */ - - src_start = trunc_page(src_addr); - src_end = round_page(src_addr + len); - - /* - * If the region is not page aligned, override the no_zero_fill - * argument. - */ - - if (options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL) { - if (!page_aligned(src_addr) || !page_aligned(src_addr +len)) - options &= ~VM_MAP_COPYIN_OPT_NO_ZERO_FILL; - } - - /* - * Check that the end address doesn't overflow - */ - - if (src_end <= src_start && (src_end < src_start || src_start != 0)) { - return KERN_INVALID_ADDRESS; - } - - /* - * Allocate a header element for the page list. - * - * Record original offset and size, as caller may not - * be page-aligned. - */ - - copy = (vm_map_copy_t) zalloc(vm_map_copy_zone); - copy->type = VM_MAP_COPY_PAGE_LIST; - copy->cpy_npages = 0; - copy->cpy_page_loose = FALSE; - copy->offset = src_addr; - copy->size = len; - copy->cpy_cont = VM_MAP_COPY_CONT_NULL; - copy->cpy_cont_args = VM_MAP_COPYIN_ARGS_NULL; - - /* - * Find the beginning of the region. - */ - -do_map_lookup: - - vm_map_lock(src_map); - - if (!vm_map_lookup_entry(src_map, src_start, &src_entry)) { - result = KERN_INVALID_ADDRESS; - goto error; - } - need_map_lookup = FALSE; - - /* - * Go through entries until we get to the end. - */ - - while (TRUE) { - if ((src_entry->protection & prot) != prot) { - result = KERN_PROTECTION_FAILURE; - goto error; - } - - /* translate down through submaps to find the target entry */ - while(src_entry->is_sub_map) { - vm_size_t submap_len; - submap_map_t *ptr; - - ptr = (submap_map_t *)kalloc(sizeof(submap_map_t)); - ptr->next = parent_maps; - parent_maps = ptr; - ptr->parent_map = src_map; - ptr->base_start = src_start; - ptr->base_end = src_end; - submap_len = src_entry->vme_end - src_entry->vme_start; - if(submap_len > (src_end-src_start)) - submap_len = src_end-src_start; - ptr->base_start += submap_len; - - src_start -= src_entry->vme_start; - src_start += src_entry->offset; - src_end = src_start + submap_len; - src_map = src_entry->object.sub_map; - vm_map_lock(src_map); - vm_map_unlock(ptr->parent_map); - if (!vm_map_lookup_entry( - src_map, src_start, &src_entry)) { - result = KERN_INVALID_ADDRESS; - goto error; - } - vm_map_clip_start(src_map, src_entry, src_start); - } - - wired = (src_entry->wired_count != 0); - - if (src_end > src_entry->vme_end) - src_size = src_entry->vme_end - src_start; - else - src_size = src_end - src_start; - - src_object = src_entry->object.vm_object; - - /* - * If src_object is NULL, allocate it now; - * we're going to fault on it shortly. - */ - if (src_object == VM_OBJECT_NULL) { - src_object = vm_object_allocate((vm_size_t) - src_entry->vme_end - - src_entry->vme_start); - src_entry->object.vm_object = src_object; - } - else if (src_entry->needs_copy && (prot & VM_PROT_WRITE)) { - vm_object_shadow( - &src_entry->object.vm_object, - &src_entry->offset, - (vm_size_t) (src_entry->vme_end - - src_entry->vme_start)); - - src_entry->needs_copy = FALSE; - - /* reset src_object */ - src_object = src_entry->object.vm_object; - } - - /* - * calculate src_offset now, since vm_object_shadow - * may have changed src_entry->offset. - */ - src_offset = src_entry->offset + (src_start - src_entry->vme_start); - - /* - * Iterate over pages. Fault in ones that aren't present. - */ - src_last_offset = src_offset + src_size; - for (; (src_offset < src_last_offset); - src_offset += PAGE_SIZE_64, src_start += PAGE_SIZE) { - - if (copy->cpy_npages == VM_MAP_COPY_PAGE_LIST_MAX) { - vm_offset_t src_delta; -make_continuation: - /* - * At this point we have the max number of - * pages busy for this thread that we're - * willing to allow. Stop here and record - * arguments for the remainder. Note: - * this means that this routine isn't atomic, - * but that's the breaks. Note that only - * the first vm_map_copy_t that comes back - * from this routine has the right offset - * and size; those from continuations are - * page rounded, and short by the amount - * already done. - * - * Reset src_end so the src_destroy - * code at the bottom doesn't do - * something stupid. - */ - - src_delta = src_end - src_start; - while (src_map != base_map) { - submap_map_t *ptr; - - if(!need_map_lookup) { - vm_map_unlock(src_map); - } - ptr = parent_maps; - assert(ptr != NULL); - parent_maps = parent_maps->next; - src_map = ptr->parent_map; - src_start = ptr->base_start - src_delta; - src_delta = ptr->base_end - src_start; - kfree((vm_offset_t)ptr, sizeof(submap_map_t)); - - need_map_lookup = TRUE; - } - src_end = src_start; - - - cont_args = (vm_map_copyin_args_t) - kalloc(sizeof(vm_map_copyin_args_data_t)); - cont_args->map = src_map; - vm_map_reference(src_map); - cont_args->src_addr = src_start; - cont_args->src_len = len - (src_start - src_addr); - if (options & VM_MAP_COPYIN_OPT_SRC_DESTROY) { - cont_args->destroy_addr = cont_args->src_addr; - cont_args->destroy_len = cont_args->src_len; - } else { - cont_args->destroy_addr = (vm_offset_t) 0; - cont_args->destroy_len = (vm_offset_t) 0; - } - cont_args->options = options; - - copy->cpy_cont_args = cont_args; - copy->cpy_cont = vm_map_copyin_page_list_cont; - - break; - } - - /* - * Try to find the page of data. Have to - * fault it in if there's no page, or something - * going on with the page, or the object has - * a copy object. - */ - vm_object_lock(src_object); - vm_object_paging_begin(src_object); - if (((m = vm_page_lookup(src_object, src_offset)) != - VM_PAGE_NULL) && - !m->busy && !m->fictitious && !m->unusual && - ((prot & VM_PROT_WRITE) == 0 || - (m->object->copy == VM_OBJECT_NULL))) { - - if (!m->absent && - !(options & VM_MAP_COPYIN_OPT_STEAL_PAGES)) { - - /* - * The page is present and will not be - * replaced, prep it. Thus allowing - * mutiple access on this page - */ - kern_return_t kr; - - kr = vm_page_prep(m); - assert(kr == KERN_SUCCESS); - kr = vm_page_pin(m); - assert(kr == KERN_SUCCESS); - } else { - /* - * This is the page. Mark it busy - * and keep the paging reference on - * the object whilst we do our thing. - */ - - m->busy = TRUE; - } - } else { - vm_prot_t result_prot; - vm_page_t top_page; - kern_return_t kr; - boolean_t data_supply; - - /* - * Have to fault the page in; must - * unlock the map to do so. While - * the map is unlocked, anything - * can happen, we must lookup the - * map entry before continuing. - */ - vm_map_unlock(src_map); - need_map_lookup = TRUE; - data_supply = src_object->silent_overwrite && - (prot & VM_PROT_WRITE) && - src_start >= src_addr && - src_start + PAGE_SIZE <= - src_addr + len; - -retry: - result_prot = prot; - - XPR(XPR_VM_FAULT, - "vm_map_copyin_page_list -> vm_fault_page\n", - 0,0,0,0,0); - kr = vm_fault_page(src_object, src_offset, - prot, FALSE, THREAD_UNINT, - src_entry->offset, - src_entry->offset + - (src_entry->vme_end - - src_entry->vme_start), - VM_BEHAVIOR_SEQUENTIAL, - &result_prot, &m, &top_page, - (int *)0, - &error_code, - options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL, - data_supply); - /* - * Cope with what happened. - */ - switch (kr) { - case VM_FAULT_SUCCESS: - - /* - * If we lost write access, - * try again. - */ - if ((prot & VM_PROT_WRITE) && - !(result_prot & VM_PROT_WRITE)) { - vm_object_lock(src_object); - vm_object_paging_begin(src_object); - goto retry; - } - break; - case VM_FAULT_MEMORY_SHORTAGE: - VM_PAGE_WAIT(); - /* fall thru */ - case VM_FAULT_INTERRUPTED: /* ??? */ - case VM_FAULT_RETRY: - vm_object_lock(src_object); - vm_object_paging_begin(src_object); - goto retry; - case VM_FAULT_FICTITIOUS_SHORTAGE: - vm_page_more_fictitious(); - vm_object_lock(src_object); - vm_object_paging_begin(src_object); - goto retry; - case VM_FAULT_MEMORY_ERROR: - /* - * Something broke. If this - * is a continuation, return - * a partial result if possible, - * else fail the whole thing. - * In the continuation case, the - * next continuation call will - * get this error if it persists. - */ - vm_map_lock(src_map); - if (is_cont && - copy->cpy_npages != 0) - goto make_continuation; - - result = error_code ? error_code : KERN_MEMORY_ERROR; - goto error; - } - - if (top_page != VM_PAGE_NULL) { - vm_object_lock(src_object); - VM_PAGE_FREE(top_page); - vm_object_paging_end(src_object); - vm_object_unlock(src_object); - } - - } - - /* - * The page is busy, its object is locked, and - * we have a paging reference on it. Either - * the map is locked, or need_map_lookup is - * TRUE. - */ - - /* - * Put the page in the page list. - */ - copy->cpy_page_list[copy->cpy_npages++] = m; - vm_object_unlock(m->object); - - /* - * Pmap enter support. Only used for - * device I/O for colocated server. - * - * WARNING: This code assumes that this - * option is only used for well behaved - * memory. If the mapping has changed, - * the following code will make mistakes. - * - * XXXO probably ought to do pmap_extract first, - * XXXO to avoid needless pmap_enter, but this - * XXXO can't detect protection mismatch?? - */ - - if (options & VM_MAP_COPYIN_OPT_PMAP_ENTER) { - /* - * XXX Only used on kernel map. - * XXX Must not remove VM_PROT_WRITE on - * XXX an I/O only requiring VM_PROT_READ - * XXX as another I/O may be active on same page - * XXX assume that if mapping exists, it must - * XXX have the equivalent of at least VM_PROT_READ, - * XXX but don't assume it has VM_PROT_WRITE as the - * XXX pmap might not all the rights of the object - */ - assert(vm_map_pmap(src_map) == kernel_pmap); - - if ((prot & VM_PROT_WRITE) || - (pmap_extract(vm_map_pmap(src_map), - src_start) != m->phys_addr)) - - PMAP_ENTER(vm_map_pmap(src_map), src_start, - m, prot, wired); - } - if(need_map_lookup) { - need_map_lookup = FALSE; - vm_map_lock(src_map); - if (!vm_map_lookup_entry(src_map, src_start, &src_entry)) { - result = KERN_INVALID_ADDRESS; - goto error; - } - } - } - - /* - * Verify that there are no gaps in the region - */ - src_start = src_entry->vme_end; - if (src_start < src_end) { - src_entry = src_entry->vme_next; - if (need_map_lookup) { - need_map_lookup = FALSE; - vm_map_lock(src_map); - if(!vm_map_lookup_entry(src_map, - src_start, &src_entry)) { - result = KERN_INVALID_ADDRESS; - goto error; - } - } else if (src_entry->vme_start != src_start) { - result = KERN_INVALID_ADDRESS; - goto error; - } - } - - /* - * DETERMINE whether the entire region - * has been copied. - */ - - while ((src_start >= src_end) && (src_end != 0)) { - if (src_map != base_map) { - submap_map_t *ptr; - - ptr = parent_maps; - assert(ptr != NULL); - parent_maps = parent_maps->next; - src_start = ptr->base_start; - src_end = ptr->base_end; - if(need_map_lookup) { - need_map_lookup = FALSE; - } - else { - vm_map_unlock(src_map); - } - src_map = ptr->parent_map; - vm_map_lock(src_map); - if((src_start < src_end) && - (!vm_map_lookup_entry(ptr->parent_map, - src_start, &src_entry))) { - result = KERN_INVALID_ADDRESS; - kfree((vm_offset_t)ptr, sizeof(submap_map_t)); - goto error; - } - kfree((vm_offset_t)ptr, sizeof(submap_map_t)); - } else - break; - } - if ((src_start >= src_end) && (src_end != 0)) { - if (need_map_lookup) - vm_map_lock(src_map); - break; - } - - } - - /* - * If steal_pages is true, make sure all - * pages in the copy are not in any object - * We try to remove them from the original - * object, but we may have to copy them. - * - * At this point every page in the list is busy - * and holds a paging reference to its object. - * When we're done stealing, every page is busy, - * and in no object (m->tabled == FALSE). - */ - src_start = trunc_page(src_addr); - if (options & VM_MAP_COPYIN_OPT_STEAL_PAGES) { - register int i; - vm_offset_t page_vaddr; - vm_offset_t unwire_end; - vm_offset_t map_entry_end; - boolean_t share_map = FALSE; - - unwire_end = src_start; - map_entry_end = src_start; - for (i = 0; i < copy->cpy_npages; i++) { - - - /* - * Remove the page from its object if it - * can be stolen. It can be stolen if: - * - * (1) The source is being destroyed, - * the object is internal (hence - * temporary), and not shared. - * (2) The page is not precious. - * - * The not shared check consists of two - * parts: (a) there are no objects that - * shadow this object. (b) it is not the - * object in any shared map entries (i.e., - * use_shared_copy is not set). - * - * The first check (a) means that we can't - * steal pages from objects that are not - * at the top of their shadow chains. This - * should not be a frequent occurrence. - * - * Stealing wired pages requires telling the - * pmap module to let go of them. - * - * NOTE: stealing clean pages from objects - * whose mappings survive requires a call to - * the pmap module. Maybe later. - */ - m = copy->cpy_page_list[i]; - src_object = m->object; - vm_object_lock(src_object); - - page_vaddr = src_start + (i * PAGE_SIZE); - if(page_vaddr > map_entry_end) { - if (!vm_map_lookup_entry(src_map, page_vaddr, &src_entry)) - share_map = TRUE; - else if (src_entry->is_sub_map) { - map_entry_end = src_entry->vme_end; - share_map = TRUE; - } else { - map_entry_end = src_entry->vme_end; - share_map = FALSE; - } - } - - - if ((options & VM_MAP_COPYIN_OPT_SRC_DESTROY) && - src_object->internal && - !src_object->true_share && - (!src_object->shadowed) && - (src_object->copy_strategy == - MEMORY_OBJECT_COPY_SYMMETRIC) && - !m->precious && - !share_map) { - - if (m->wire_count > 0) { - - assert(m->wire_count == 1); - /* - * In order to steal a wired - * page, we have to unwire it - * first. We do this inline - * here because we have the page. - * - * Step 1: Unwire the map entry. - * Also tell the pmap module - * that this piece of the - * pmap is pageable. - */ - vm_object_unlock(src_object); - if (page_vaddr >= unwire_end) { - if (!vm_map_lookup_entry(src_map, - page_vaddr, &src_entry)) - panic("vm_map_copyin_page_list: missing wired map entry"); - - vm_map_clip_start(src_map, src_entry, - page_vaddr); - vm_map_clip_end(src_map, src_entry, - src_start + src_size); - -/* revisit why this assert fails CDY - assert(src_entry->wired_count > 0); -*/ - src_entry->wired_count = 0; - src_entry->user_wired_count = 0; - unwire_end = src_entry->vme_end; - pmap_pageable(vm_map_pmap(src_map), - page_vaddr, unwire_end, TRUE); - } - - /* - * Step 2: Unwire the page. - * pmap_remove handles this for us. - */ - vm_object_lock(src_object); - } - - /* - * Don't need to remove the mapping; - * vm_map_delete will handle it. - * - * Steal the page. Setting the wire count - * to zero is vm_page_unwire without - * activating the page. - */ - vm_page_lock_queues(); - vm_page_remove(m); - if (m->wire_count > 0) { - m->wire_count = 0; - vm_page_wire_count--; - } else { - VM_PAGE_QUEUES_REMOVE(m); - } - vm_page_unlock_queues(); - } else { - /* - * Have to copy this page. Have to - * unlock the map while copying, - * hence no further page stealing. - * Hence just copy all the pages. - * Unlock the map while copying; - * This means no further page stealing. - */ - vm_object_unlock(src_object); - vm_map_unlock(src_map); - vm_map_copy_steal_pages(copy); - vm_map_lock(src_map); - break; - } - - vm_object_paging_end(src_object); - vm_object_unlock(src_object); - } - - copy->cpy_page_loose = TRUE; - - /* - * If the source should be destroyed, do it now, since the - * copy was successful. - */ - - if (options & VM_MAP_COPYIN_OPT_SRC_DESTROY) { - (void) vm_map_delete(src_map, src_start, - src_end, VM_MAP_NO_FLAGS); - } - } else { - /* - * Not stealing pages leaves busy or prepped pages in the map. - * This will cause source destruction to hang. Use - * a continuation to prevent this. - */ - if ((options & VM_MAP_COPYIN_OPT_SRC_DESTROY) && - !vm_map_copy_has_cont(copy)) { - cont_args = (vm_map_copyin_args_t) - kalloc(sizeof(vm_map_copyin_args_data_t)); - vm_map_reference(src_map); - cont_args->map = src_map; - cont_args->src_addr = (vm_offset_t) 0; - cont_args->src_len = (vm_size_t) 0; - cont_args->destroy_addr = src_start; - cont_args->destroy_len = src_end - src_start; - cont_args->options = options; - - copy->cpy_cont_args = cont_args; - copy->cpy_cont = vm_map_copyin_page_list_cont; - } - } - - vm_map_unlock(src_map); - - *copy_result = copy; - return(result); - -error: - { - submap_map_t *ptr; - - vm_map_unlock(src_map); - vm_map_copy_discard(copy); - - for(ptr = parent_maps; ptr != NULL; ptr = parent_maps) { - parent_maps=parent_maps->next; - kfree((vm_offset_t)ptr, sizeof(submap_map_t)); - } - return(result); - } -} - void vm_map_fork_share( vm_map_t old_map, @@ -7719,6 +6441,7 @@ RetrySubMap: vm_object_t copy_object; vm_offset_t local_start; vm_offset_t local_end; + boolean_t copied_slowly = FALSE; if (vm_map_lock_read_to_write(map)) { vm_map_lock_read(map); @@ -7726,6 +6449,8 @@ RetrySubMap: old_end += end_delta; goto RetrySubMap; } + + if (submap_entry->object.vm_object == VM_OBJECT_NULL) { submap_entry->object.vm_object = vm_object_allocate( @@ -7745,12 +6470,28 @@ RetrySubMap: /* an entry in our space to the underlying */ /* object in the submap, bypassing the */ /* submap. */ + + + if(submap_entry->wired_count != 0) { + vm_object_lock( + submap_entry->object.vm_object); + vm_object_copy_slowly( + submap_entry->object.vm_object, + submap_entry->offset, + submap_entry->vme_end - + submap_entry->vme_start, + FALSE, + ©_object); + copied_slowly = TRUE; + } else { - /* set up shadow object */ - copy_object = submap_entry->object.vm_object; - submap_entry->object.vm_object->shadowed = TRUE; - submap_entry->needs_copy = TRUE; - vm_object_pmap_protect(submap_entry->object.vm_object, + /* set up shadow object */ + copy_object = submap_entry->object.vm_object; + vm_object_reference(copy_object); + submap_entry->object.vm_object->shadowed = TRUE; + submap_entry->needs_copy = TRUE; + vm_object_pmap_protect( + submap_entry->object.vm_object, submap_entry->offset, submap_entry->vme_end - submap_entry->vme_start, @@ -7759,6 +6500,7 @@ RetrySubMap: submap_entry->vme_start, submap_entry->protection & ~VM_PROT_WRITE); + } /* This works diffently than the */ @@ -7796,17 +6538,24 @@ RetrySubMap: /* shared map entry */ vm_map_deallocate(entry->object.sub_map); entry->is_sub_map = FALSE; - vm_object_reference(copy_object); entry->object.vm_object = copy_object; - entry->offset = submap_entry->offset; entry->protection |= VM_PROT_WRITE; entry->max_protection |= VM_PROT_WRITE; - entry->needs_copy = TRUE; + if(copied_slowly) { + entry->offset = 0; + entry->needs_copy = FALSE; + entry->is_shared = FALSE; + } else { + entry->offset = submap_entry->offset; + entry->needs_copy = TRUE; + if(entry->inheritance == VM_INHERIT_SHARE) + entry->inheritance = VM_INHERIT_COPY; + if (map != old_map) + entry->is_shared = TRUE; + } if(entry->inheritance == VM_INHERIT_SHARE) - entry->inheritance = VM_INHERIT_COPY; - if (map != old_map) - entry->is_shared = TRUE; + entry->inheritance = VM_INHERIT_COPY; vm_map_lock_write_to_read(map); } else { @@ -8071,7 +6820,7 @@ vm_region( extended->pages_resident = 0; extended->pages_swapped_out = 0; extended->pages_shared_now_private = 0; - extended->pages_referenced = 0; + extended->pages_dirtied = 0; extended->external_pager = 0; extended->shadow_depth = 0; @@ -8290,7 +7039,7 @@ LOOKUP_NEXT_BASE_ENTRY: extended.pages_resident = 0; extended.pages_swapped_out = 0; extended.pages_shared_now_private = 0; - extended.pages_referenced = 0; + extended.pages_dirtied = 0; extended.external_pager = 0; extended.shadow_depth = 0; @@ -8314,7 +7063,7 @@ LOOKUP_NEXT_BASE_ENTRY: submap_info->pages_swapped_out = extended.pages_swapped_out; submap_info->pages_shared_now_private = extended.pages_shared_now_private; - submap_info->pages_referenced = extended.pages_referenced; + submap_info->pages_dirtied = extended.pages_dirtied; submap_info->external_pager = extended.external_pager; submap_info->shadow_depth = extended.shadow_depth; @@ -8486,7 +7235,7 @@ LOOKUP_NEXT_BASE_ENTRY: extended.pages_resident = 0; extended.pages_swapped_out = 0; extended.pages_shared_now_private = 0; - extended.pages_referenced = 0; + extended.pages_dirtied = 0; extended.external_pager = 0; extended.shadow_depth = 0; @@ -8510,7 +7259,7 @@ LOOKUP_NEXT_BASE_ENTRY: submap_info->pages_swapped_out = extended.pages_swapped_out; submap_info->pages_shared_now_private = extended.pages_shared_now_private; - submap_info->pages_referenced = extended.pages_referenced; + submap_info->pages_dirtied = extended.pages_dirtied; submap_info->external_pager = extended.external_pager; submap_info->shadow_depth = extended.shadow_depth; @@ -8619,7 +7368,7 @@ vm_region_64( extended->pages_resident = 0; extended->pages_swapped_out = 0; extended->pages_shared_now_private = 0; - extended->pages_referenced = 0; + extended->pages_dirtied = 0; extended->external_pager = 0; extended->shadow_depth = 0; @@ -8683,6 +7432,7 @@ vm_region_top_walk( vm_region_top_info_t top) { register struct vm_object *obj, *tmp_obj; + register int ref_count; if (entry->object.vm_object == 0) { top->share_mode = SM_EMPTY; @@ -8697,12 +7447,15 @@ vm_region_top_walk( vm_object_lock(obj); + if ((ref_count = obj->ref_count) > 1 && obj->paging_in_progress) + ref_count--; + if (obj->shadow) { - if (obj->ref_count == 1) + if (ref_count == 1) top->private_pages_resident = obj->resident_page_count; else top->shared_pages_resident = obj->resident_page_count; - top->ref_count = obj->ref_count; + top->ref_count = ref_count; top->share_mode = SM_COW; while (tmp_obj = obj->shadow) { @@ -8710,16 +7463,19 @@ vm_region_top_walk( vm_object_unlock(obj); obj = tmp_obj; + if ((ref_count = obj->ref_count) > 1 && obj->paging_in_progress) + ref_count--; + top->shared_pages_resident += obj->resident_page_count; - top->ref_count += obj->ref_count - 1; + top->ref_count += ref_count - 1; } } else { if (entry->needs_copy) { top->share_mode = SM_COW; top->shared_pages_resident = obj->resident_page_count; } else { - if (obj->ref_count == 1 || - (obj->ref_count == 2 && !(obj->pager_trusted) && !(obj->internal))) { + if (ref_count == 1 || + (ref_count == 2 && !(obj->pager_trusted) && !(obj->internal))) { top->share_mode = SM_PRIVATE; top->private_pages_resident = obj->resident_page_count; } else { @@ -8727,7 +7483,7 @@ vm_region_top_walk( top->shared_pages_resident = obj->resident_page_count; } } - top->ref_count = obj->ref_count; + top->ref_count = ref_count; } top->obj_id = (int)obj; @@ -8747,9 +7503,11 @@ vm_region_walk( register struct vm_object *obj, *tmp_obj; register vm_offset_t last_offset; register int i; + register int ref_count; void vm_region_look_for_page(); - if (entry->object.vm_object == 0) { + if ((entry->object.vm_object == 0) || + (entry->object.vm_object->phys_contiguous)) { extended->share_mode = SM_EMPTY; extended->ref_count = 0; return; @@ -8762,13 +7520,16 @@ vm_region_walk( vm_object_lock(obj); + if ((ref_count = obj->ref_count) > 1 && obj->paging_in_progress) + ref_count--; + for (last_offset = offset + range; offset < last_offset; offset += PAGE_SIZE_64, va += PAGE_SIZE) - vm_region_look_for_page(obj, extended, offset, obj->ref_count, 0, map, va); + vm_region_look_for_page(obj, extended, offset, ref_count, 0, map, va); if (extended->shadow_depth || entry->needs_copy) extended->share_mode = SM_COW; else { - if (obj->ref_count == 1) + if (ref_count == 1) extended->share_mode = SM_PRIVATE; else { if (obj->true_share) @@ -8777,14 +7538,18 @@ vm_region_walk( extended->share_mode = SM_SHARED; } } - extended->ref_count = obj->ref_count - extended->shadow_depth; + extended->ref_count = ref_count - extended->shadow_depth; for (i = 0; i < extended->shadow_depth; i++) { if ((tmp_obj = obj->shadow) == 0) break; vm_object_lock(tmp_obj); vm_object_unlock(obj); - extended->ref_count += tmp_obj->ref_count; + + if ((ref_count = tmp_obj->ref_count) > 1 && tmp_obj->paging_in_progress) + ref_count--; + + extended->ref_count += ref_count; obj = tmp_obj; } vm_object_unlock(obj); @@ -8798,10 +7563,12 @@ vm_region_walk( last = vm_map_to_entry(map); my_refs = 0; + if ((ref_count = obj->ref_count) > 1 && obj->paging_in_progress) + ref_count--; for (cur = vm_map_first_entry(map); cur != last; cur = cur->vme_next) my_refs += vm_region_count_obj_refs(cur, obj); - if (my_refs == obj->ref_count) + if (my_refs == ref_count) extended->share_mode = SM_PRIVATE_ALIASED; else if (my_refs > 1) extended->share_mode = SM_SHARED_ALIASED; @@ -8810,6 +7577,8 @@ vm_region_walk( } +/* object is locked on entry and locked on return */ + void vm_region_look_for_page( @@ -8823,45 +7592,65 @@ vm_region_look_for_page( { register vm_page_t p; register vm_object_t shadow; + register int ref_count; + vm_object_t caller_object; shadow = object->shadow; + caller_object = object; - if ( !(object->pager_trusted) && !(object->internal)) - extended->external_pager = 1; + + while (TRUE) { - if ((p = vm_page_lookup(object, offset)) != VM_PAGE_NULL) { - if (shadow && (max_refcnt == 1)) - extended->pages_shared_now_private++; + if ( !(object->pager_trusted) && !(object->internal)) + extended->external_pager = 1; - if (pmap_extract(vm_map_pmap(map), va)) - extended->pages_referenced++; - extended->pages_resident++; + if ((p = vm_page_lookup(object, offset)) != VM_PAGE_NULL) { + if (shadow && (max_refcnt == 1)) + extended->pages_shared_now_private++; - return; - } - if (object->existence_map) { - if (vm_external_state_get(object->existence_map, offset) == VM_EXTERNAL_STATE_EXISTS) { - if (shadow && (max_refcnt == 1)) - extended->pages_shared_now_private++; - extended->pages_swapped_out++; + if (p->dirty || pmap_is_modified(p->phys_addr)) + extended->pages_dirtied++; + extended->pages_resident++; - return; - } - } - if (shadow) { - vm_object_lock(shadow); + if(object != caller_object) + vm_object_unlock(object); - if (++depth > extended->shadow_depth) - extended->shadow_depth = depth; + return; + } + if (object->existence_map) { + if (vm_external_state_get(object->existence_map, offset) == VM_EXTERNAL_STATE_EXISTS) { - if (shadow->ref_count > max_refcnt) - max_refcnt = shadow->ref_count; - - vm_region_look_for_page(shadow, extended, offset + object->shadow_offset, - max_refcnt, depth, map, va); - vm_object_unlock(shadow); + extended->pages_swapped_out++; - return; + if(object != caller_object) + vm_object_unlock(object); + + return; + } + } + if (shadow) { + vm_object_lock(shadow); + + if ((ref_count = shadow->ref_count) > 1 && shadow->paging_in_progress) + ref_count--; + + if (++depth > extended->shadow_depth) + extended->shadow_depth = depth; + + if (ref_count > max_refcnt) + max_refcnt = ref_count; + + if(object != caller_object) + vm_object_unlock(object); + + object = shadow; + shadow = object->shadow; + offset = offset + object->shadow_offset; + continue; + } + if(object != caller_object) + vm_object_unlock(object); + break; } } @@ -9098,23 +7887,6 @@ vm_map_behavior_set( } -int -vm_map_copy_cont_is_valid( - vm_map_copy_t copy) -{ - vm_map_copy_cont_t cont; - - assert(copy->type == VM_MAP_COPY_PAGE_LIST); - cont = copy->cpy_cont; - if ( - cont != vm_map_copy_discard_cont && - cont != vm_map_copyin_page_list_cont ) { - printf("vm_map_copy_cont_is_valid: bogus cont 0x%x\n", cont); - assert((integer_t) cont == 0xdeadbeef); - } - return 1; -} - #include <mach_kdb.h> #if MACH_KDB #include <ddb/db_output.h> @@ -9339,10 +8111,6 @@ vm_map_copy_print( printf("[object]"); break; - case VM_MAP_COPY_PAGE_LIST: - printf("[page_list]"); - break; - case VM_MAP_COPY_KERNEL_BUFFER: printf("[kernel_buffer]"); break; @@ -9373,26 +8141,6 @@ vm_map_copy_print( printf(", kalloc_size=0x%x\n", copy->cpy_kalloc_size); break; - case VM_MAP_COPY_PAGE_LIST: - iprintf("npages=%d", copy->cpy_npages); - printf(", cont=%x", copy->cpy_cont); - printf(", cont_args=%x\n", copy->cpy_cont_args); - if (copy->cpy_npages < 0) { - npages = 0; - } else if (copy->cpy_npages > VM_MAP_COPY_PAGE_LIST_MAX) { - npages = VM_MAP_COPY_PAGE_LIST_MAX; - } else { - npages = copy->cpy_npages; - } - iprintf("copy->cpy_page_list[0..%d] = {", npages); - for (i = 0; i < npages - 1; i++) { - printf("0x%x, ", copy->cpy_page_list[i]); - } - if (npages > 0) { - printf("0x%x", copy->cpy_page_list[npages - 1]); - } - printf("}\n"); - break; } db_indent -=2; @@ -9844,7 +8592,6 @@ vm_remap( inheritance, target_map->hdr. entries_pageable); - vm_map_deallocate(src_map); if (result != KERN_SUCCESS) { return result; diff --git a/osfmk/vm/vm_map.h b/osfmk/vm/vm_map.h index d9eb8c6c9..d98593232 100644 --- a/osfmk/vm/vm_map.h +++ b/osfmk/vm/vm_map.h @@ -154,7 +154,7 @@ struct vm_named_entry { vm_object_t object; /* object I point to */ vm_object_offset_t offset; /* offset into object */ union { - ipc_port_t pager; /* amo pager port */ + memory_object_t pager; /* amo pager port */ vm_map_t map; /* map backing submap */ } backing; unsigned int size; /* size of region */ @@ -165,9 +165,6 @@ struct vm_named_entry { /* boolean_t */ is_sub_map:1; /* is object is a submap? */ }; -typedef struct vm_named_entry *vm_named_entry_t; - - /* * Type: vm_map_entry_t [internal use only] * @@ -375,8 +372,7 @@ struct vm_map_copy { int type; #define VM_MAP_COPY_ENTRY_LIST 1 #define VM_MAP_COPY_OBJECT 2 -#define VM_MAP_COPY_PAGE_LIST 3 -#define VM_MAP_COPY_KERNEL_BUFFER 4 +#define VM_MAP_COPY_KERNEL_BUFFER 3 vm_object_offset_t offset; vm_size_t size; union { @@ -390,13 +386,6 @@ struct vm_map_copy { * vm_map_object_to_page_list */ } c_o; - struct { /* PAGE_LIST */ - int npages; - boolean_t page_loose; - vm_map_copy_cont_t cont; - vm_map_copyin_args_t cont_args; - vm_page_t page_list[VM_MAP_COPY_PAGE_LIST_MAX]; - } c_p; struct { /* KERNEL_BUFFER */ vm_offset_t kdata; vm_size_t kalloc_size; /* size of this copy_t */ @@ -410,12 +399,6 @@ struct vm_map_copy { #define cpy_object c_u.c_o.object #define cpy_index c_u.c_o.index -#define cpy_page_list c_u.c_p.page_list -#define cpy_npages c_u.c_p.npages -#define cpy_page_loose c_u.c_p.page_loose -#define cpy_cont c_u.c_p.cont -#define cpy_cont_args c_u.c_p.cont_args - #define cpy_kdata c_u.c_k.kdata #define cpy_kalloc_size c_u.c_k.kalloc_size @@ -431,47 +414,6 @@ struct vm_map_copy { #define vm_map_copy_last_entry(copy) \ ((copy)->cpy_hdr.links.prev) -/* - * Continuation macros for page list copy objects - */ - -#define vm_map_copy_invoke_cont(old_copy, new_copy, result) \ -MACRO_BEGIN \ - assert(vm_map_copy_cont_is_valid(old_copy)); \ - vm_map_copy_page_discard(old_copy); \ - *result = (*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args, \ - new_copy); \ - (old_copy)->cpy_cont = VM_MAP_COPY_CONT_NULL; \ -MACRO_END - -#define vm_map_copy_invoke_extend_cont(old_copy, new_copy, result) \ -MACRO_BEGIN \ - assert(vm_map_copy_cont_is_valid(old_copy)); \ - *result = (*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args, \ - new_copy); \ - (old_copy)->cpy_cont = VM_MAP_COPY_CONT_NULL; \ -MACRO_END - -#define vm_map_copy_abort_cont(old_copy) \ -MACRO_BEGIN \ - assert(vm_map_copy_cont_is_valid(old_copy)); \ - vm_map_copy_page_discard(old_copy); \ - (*((old_copy)->cpy_cont))((old_copy)->cpy_cont_args, \ - (vm_map_copy_t *) 0); \ - (old_copy)->cpy_cont = VM_MAP_COPY_CONT_NULL; \ - (old_copy)->cpy_cont_args = VM_MAP_COPYIN_ARGS_NULL; \ -MACRO_END - -#define vm_map_copy_has_cont(copy) \ - (((copy)->cpy_cont) != VM_MAP_COPY_CONT_NULL) - -/* - * Macro to determine number of pages in a page-list copy chain. - */ - -#define vm_map_copy_page_count(copy) \ - (round_page(((vm_offset_t)(copy)->offset - trunc_page((vm_offset_t)(copy)->offset)) + (copy)->size) / PAGE_SIZE) - /* * Macros: vm_map_lock, etc. [internal use only] * Description: @@ -523,12 +465,6 @@ extern boolean_t vm_map_lookup_entry( vm_offset_t address, vm_map_entry_t *entry); /* OUT */ -/* A version of vm_map_copy_discard that can be called - * as a continuation from a vm_map_copy page list. */ -extern kern_return_t vm_map_copy_discard_cont( - vm_map_copyin_args_t cont_args, - vm_map_copy_t *copy_result);/* OUT */ - /* Find the VM object, offset, and protection for a given virtual address * in the specified map, assuming a page fault of the type specified. */ extern kern_return_t vm_map_lookup_locked( @@ -787,16 +723,6 @@ extern kern_return_t vm_map_copy_overwrite( vm_map_copy_t copy, int interruptible); -/* Version of vm_map_copyout() for page list vm map copies. */ -extern kern_return_t vm_map_copyout_page_list( - vm_map_t dst_map, - vm_offset_t *dst_addr, /* OUT */ - vm_map_copy_t copy); - -/* Get rid of the pages in a page_list copy. */ -extern void vm_map_copy_page_discard( - vm_map_copy_t copy); - /* Create a copy object from an object. */ extern kern_return_t vm_map_copyin_object( vm_object_t object, @@ -804,17 +730,6 @@ extern kern_return_t vm_map_copyin_object( vm_object_size_t size, vm_map_copy_t *copy_result); /* OUT */ - -/* Make a copy of a region */ -/* Make a copy of a region using a page list copy */ -extern kern_return_t vm_map_copyin_page_list( - vm_map_t src_map, - vm_offset_t src_addr, - vm_size_t len, - int options, - vm_map_copy_t *copy_result, /* OUT */ - boolean_t is_cont); - extern vm_map_t vm_map_switch( vm_map_t map); @@ -945,6 +860,17 @@ extern kern_return_t vm_map_submap( vm_offset_t offset, boolean_t use_pmap); +extern kern_return_t vm_region_clone( + ipc_port_t src_region, + ipc_port_t dst_region); + +extern kern_return_t vm_map_region_replace( + vm_map_t target_map, + ipc_port_t old_region, + ipc_port_t new_region, + vm_offset_t start, + vm_offset_t end); + /* * Macros to invoke vm_map_copyin_common. vm_map_copyin is the * usual form; it handles a copyin based on the current protection @@ -1006,8 +932,58 @@ struct shared_region_object_chain { typedef struct shared_region_object_chain *shared_region_object_chain_t; +#else /* !MACH_KERNEL_PRIVATE */ + +typedef void *shared_region_mapping_t; + #endif /* MACH_KERNEL_PRIVATE */ +/* address space shared region descriptor */ + +extern kern_return_t shared_region_mapping_info( + shared_region_mapping_t shared_region, + ipc_port_t *text_region, + vm_size_t *text_size, + ipc_port_t *data_region, + vm_size_t *data_size, + vm_offset_t *region_mappings, + vm_offset_t *client_base, + vm_offset_t *alternate_base, + vm_offset_t *alternate_next, + int *flags, + shared_region_mapping_t *next); + +extern kern_return_t shared_region_mapping_create( + ipc_port_t text_region, + vm_size_t text_size, + ipc_port_t data_region, + vm_size_t data_size, + vm_offset_t region_mappings, + vm_offset_t client_base, + shared_region_mapping_t *shared_region, + vm_offset_t alt_base, + vm_offset_t alt_next); + +extern kern_return_t shared_region_mapping_ref( + shared_region_mapping_t shared_region); + +extern kern_return_t shared_region_mapping_dealloc( + shared_region_mapping_t shared_region); + +extern kern_return_t +shared_region_object_chain_attach( + shared_region_mapping_t target_region, + shared_region_mapping_t object_chain); + +/* +extern kern_return_t vm_get_shared_region( + task_t task, + shared_region_mapping_t *shared_region); + +extern kern_return_t vm_set_shared_region( + task_t task, + shared_region_mapping_t shared_region); +*/ #endif /* _VM_VM_MAP_H_ */ diff --git a/osfmk/vm/vm_object.c b/osfmk/vm/vm_object.c index 13443d22c..9cec5d486 100644 --- a/osfmk/vm/vm_object.c +++ b/osfmk/vm/vm_object.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -64,12 +64,12 @@ extern int vnode_pager_workaround; #include <mach_pagemap.h> #include <task_swapper.h> +#include <mach/mach_types.h> #include <mach/memory_object.h> #include <mach/memory_object_default.h> #include <mach/memory_object_control_server.h> #include <mach/vm_param.h> #include <ipc/ipc_port.h> -#include <ipc/ipc_space.h> #include <kern/assert.h> #include <kern/lock.h> #include <kern/queue.h> @@ -94,21 +94,16 @@ extern int vnode_pager_workaround; * page of memory exists within exactly one object. * * An object is only deallocated when all "references" - * are given up. Only one "reference" to a given - * region of an object should be writeable. + * are given up. * * Associated with each object is a list of all resident * memory pages belonging to that object; this list is * maintained by the "vm_page" module, but locked by the object's * lock. * - * Each object also records the memory object port + * Each object also records the memory object reference * that is used by the kernel to request and write - * back data (the memory object port, field "pager"), - * and the ports provided to the memory manager, the server that - * manages that data, to return data and control its - * use (the memory object control port, field "pager_request") - * and for naming (the memory object name port, field "pager_name"). + * back data (the memory object, field "pager"), etc... * * Virtual memory objects are allocated to provide * zero-filled memory (vm_allocate) or map a user-defined @@ -135,10 +130,10 @@ extern int vnode_pager_workaround; * * The kernel relies on a *default memory manager* to * provide backing storage for the zero-filled virtual - * memory objects. The memory object ports associated + * memory objects. The pager memory objects associated * with these temporary virtual memory objects are only - * generated and passed to the default memory manager - * when it becomes necessary. Virtual memory objects + * requested from the default memory manager when it + * becomes necessary. Virtual memory objects * that depend on the default memory manager are called * "internal". The "pager_created" field is provided to * indicate whether these ports have ever been allocated. @@ -167,51 +162,50 @@ extern int vnode_pager_workaround; */ /* Forward declarations for internal functions. */ -extern void _vm_object_allocate( +static void _vm_object_allocate( vm_object_size_t size, vm_object_t object); -extern kern_return_t vm_object_terminate( +static kern_return_t vm_object_terminate( vm_object_t object); extern void vm_object_remove( vm_object_t object); -extern vm_object_t vm_object_cache_trim( +static vm_object_t vm_object_cache_trim( boolean_t called_from_vm_object_deallocate); -extern void vm_object_deactivate_pages( +static void vm_object_deactivate_all_pages( vm_object_t object); -extern void vm_object_abort_activity( +static void vm_object_abort_activity( vm_object_t object); -extern kern_return_t vm_object_copy_call( +static kern_return_t vm_object_copy_call( vm_object_t src_object, vm_object_offset_t src_offset, vm_object_size_t size, vm_object_t *_result_object); -extern void vm_object_do_collapse( +static void vm_object_do_collapse( vm_object_t object, vm_object_t backing_object); -extern void vm_object_do_bypass( +static void vm_object_do_bypass( vm_object_t object, vm_object_t backing_object); -extern void memory_object_release( - ipc_port_t pager, - pager_request_t pager_request); +static void vm_object_release_pager( + memory_object_t pager); -zone_t vm_object_zone; /* vm backing store zone */ +static zone_t vm_object_zone; /* vm backing store zone */ /* * All wired-down kernel memory belongs to a single virtual * memory object (kernel_object) to avoid wasting data structures. */ -struct vm_object kernel_object_store; -vm_object_t kernel_object = &kernel_object_store; +static struct vm_object kernel_object_store; +__private_extern__ vm_object_t kernel_object = &kernel_object_store; /* * The submap object is used as a placeholder for vm_map_submap @@ -219,7 +213,7 @@ vm_object_t kernel_object = &kernel_object_store; * is exported by the vm_map module. The storage is declared * here because it must be initialized here. */ -struct vm_object vm_submap_object_store; +static struct vm_object vm_submap_object_store; /* * Virtual memory objects are initialized from @@ -227,9 +221,9 @@ struct vm_object vm_submap_object_store; * * When adding a new field to the virtual memory * object structure, be sure to add initialization - * (see vm_object_init). + * (see _vm_object_allocate()). */ -struct vm_object vm_object_template; +static struct vm_object vm_object_template; /* * Virtual memory objects that are not referenced by @@ -259,12 +253,12 @@ struct vm_object vm_object_template; * from the reference mechanism, so that the lock need * not be held to make simple references. */ -queue_head_t vm_object_cached_list; -int vm_object_cached_count; -int vm_object_cached_high; /* highest # of cached objects */ -int vm_object_cached_max = 500; /* may be patched*/ +static queue_head_t vm_object_cached_list; +static int vm_object_cached_count; +static int vm_object_cached_high; /* highest # cached objects */ +static int vm_object_cached_max = 512; /* may be patched*/ -decl_mutex_data(,vm_object_cached_lock_data) +static decl_mutex_data(,vm_object_cached_lock_data) #define vm_object_cache_lock() \ mutex_lock(&vm_object_cached_lock_data) @@ -274,12 +268,12 @@ decl_mutex_data(,vm_object_cached_lock_data) mutex_unlock(&vm_object_cached_lock_data) #define VM_OBJECT_HASH_COUNT 1024 -queue_head_t vm_object_hashtable[VM_OBJECT_HASH_COUNT]; -struct zone *vm_object_hash_zone; +static queue_head_t vm_object_hashtable[VM_OBJECT_HASH_COUNT]; +static struct zone *vm_object_hash_zone; struct vm_object_hash_entry { queue_chain_t hash_link; /* hash chain link */ - ipc_port_t pager; /* pager we represent */ + memory_object_t pager; /* pager we represent */ vm_object_t object; /* corresponding object */ boolean_t waiting; /* someone waiting for * termination */ @@ -297,9 +291,9 @@ typedef struct vm_object_hash_entry *vm_object_hash_entry_t; * and returns the corresponding entry, with optional removal. */ -vm_object_hash_entry_t +static vm_object_hash_entry_t vm_object_hash_lookup( - ipc_port_t pager, + memory_object_t pager, boolean_t remove_entry) { register queue_t bucket; @@ -328,7 +322,7 @@ vm_object_hash_lookup( * pager / cache object association in the hashtable. */ -void +static void vm_object_hash_insert( vm_object_hash_entry_t entry) { @@ -339,9 +333,9 @@ vm_object_hash_insert( queue_enter(bucket, entry, vm_object_hash_entry_t, hash_link); } -vm_object_hash_entry_t +static vm_object_hash_entry_t vm_object_hash_entry_alloc( - ipc_port_t pager) + memory_object_t pager) { vm_object_hash_entry_t entry; @@ -366,7 +360,7 @@ vm_object_hash_entry_free( * Returns a new object with the given size. */ -void +static void _vm_object_allocate( vm_object_size_t size, vm_object_t object) @@ -385,18 +379,18 @@ _vm_object_allocate( object->size = size; } -vm_object_t +__private_extern__ vm_object_t vm_object_allocate( vm_object_size_t size) { register vm_object_t object; - register ipc_port_t port; object = (vm_object_t) zalloc(vm_object_zone); -// dbgLog(object, size, 0, 2); /* (TEST/DEBUG) */ - - _vm_object_allocate(size, object); +// dbgLog(object, size, 0, 2); /* (TEST/DEBUG) */ + + if (object != VM_OBJECT_NULL) + _vm_object_allocate(size, object); return object; } @@ -406,7 +400,7 @@ vm_object_allocate( * * Initialize the VM objects module. */ -void +__private_extern__ void vm_object_bootstrap(void) { register i; @@ -443,9 +437,10 @@ vm_object_bootstrap(void) vm_object_template.copy = VM_OBJECT_NULL; vm_object_template.shadow = VM_OBJECT_NULL; vm_object_template.shadow_offset = (vm_object_offset_t) 0; + vm_object_template.cow_hint = 0; vm_object_template.true_share = FALSE; - vm_object_template.pager = IP_NULL; + vm_object_template.pager = MEMORY_OBJECT_NULL; vm_object_template.paging_offset = 0; vm_object_template.pager_request = PAGER_REQUEST_NULL; /* msr_q; init after allocation */ @@ -474,6 +469,7 @@ vm_object_bootstrap(void) vm_object_template.terminating = FALSE; vm_object_template.shadow_severed = FALSE; vm_object_template.phys_contiguous = FALSE; + vm_object_template.nophyscache = FALSE; /* End bitfields */ /* cached_list; init after allocation */ @@ -519,7 +515,7 @@ vm_object_bootstrap(void) #endif /* MACH_PAGEMAP */ } -void +__private_extern__ void vm_object_init(void) { /* @@ -527,120 +523,17 @@ vm_object_init(void) */ } -#if TASK_SWAPPER -/* - * vm_object_res_deallocate - * - * (recursively) decrement residence counts on vm objects and their shadows. - * Called from vm_object_deallocate and when swapping out an object. - * - * The object is locked, and remains locked throughout the function, - * even as we iterate down the shadow chain. Locks on intermediate objects - * will be dropped, but not the original object. - * - * NOTE: this function used to use recursion, rather than iteration. - */ - -void -vm_object_res_deallocate( - vm_object_t object) -{ - vm_object_t orig_object = object; - /* - * Object is locked so it can be called directly - * from vm_object_deallocate. Original object is never - * unlocked. - */ - assert(object->res_count > 0); - while (--object->res_count == 0) { - assert(object->ref_count >= object->res_count); - vm_object_deactivate_pages(object); - /* iterate on shadow, if present */ - if (object->shadow != VM_OBJECT_NULL) { - vm_object_t tmp_object = object->shadow; - vm_object_lock(tmp_object); - if (object != orig_object) - vm_object_unlock(object); - object = tmp_object; - assert(object->res_count > 0); - } else - break; - } - if (object != orig_object) - vm_object_unlock(object); -} - -/* - * vm_object_res_reference - * - * Internal function to increment residence count on a vm object - * and its shadows. It is called only from vm_object_reference, and - * when swapping in a vm object, via vm_map_swap. - * - * The object is locked, and remains locked throughout the function, - * even as we iterate down the shadow chain. Locks on intermediate objects - * will be dropped, but not the original object. - * - * NOTE: this function used to use recursion, rather than iteration. - */ - -void -vm_object_res_reference( - vm_object_t object) -{ - vm_object_t orig_object = object; - /* - * Object is locked, so this can be called directly - * from vm_object_reference. This lock is never released. - */ - while ((++object->res_count == 1) && - (object->shadow != VM_OBJECT_NULL)) { - vm_object_t tmp_object = object->shadow; - - assert(object->ref_count >= object->res_count); - vm_object_lock(tmp_object); - if (object != orig_object) - vm_object_unlock(object); - object = tmp_object; - } - if (object != orig_object) - vm_object_unlock(object); - assert(orig_object->ref_count >= orig_object->res_count); -} -#endif /* TASK_SWAPPER */ - -#if MACH_ASSERT -/* - * vm_object_reference: - * - * Gets another reference to the given object. - */ -void -vm_object_reference( - register vm_object_t object) -{ - if (object == VM_OBJECT_NULL) - return; - - vm_object_lock(object); - assert(object->ref_count > 0); - object->ref_count++; - vm_object_res_reference(object); - vm_object_unlock(object); -} -#endif /* MACH_ASSERT */ - /* remove the typedef below when emergency work-around is taken out */ typedef struct vnode_pager { - ipc_port_t pager; /* pager */ - ipc_port_t pager_handle; /* pager handle */ - ipc_port_t vm_obj_handle; /* memory object's control handle */ - void *vnode_handle; /* vnode handle */ + memory_object_t pager; + memory_object_t pager_handle; /* pager */ + memory_object_control_t control_handle; /* memory object's control handle */ + void *vnode_handle; /* vnode handle */ } *vnode_pager_t; #define MIGHT_NOT_CACHE_SHADOWS 1 #if MIGHT_NOT_CACHE_SHADOWS -int cache_shadows = TRUE; +static int cache_shadows = TRUE; #endif /* MIGHT_NOT_CACHE_SHADOWS */ /* @@ -654,7 +547,7 @@ int cache_shadows = TRUE; * * No object may be locked. */ -void +__private_extern__ void vm_object_deallocate( register vm_object_t object) { @@ -675,7 +568,31 @@ vm_object_deallocate( vm_object_cache_lock(); vm_object_lock(object); - assert(object->alive); + + assert(object->ref_count > 0); + + /* + * If the object has a named reference, and only + * that reference would remain, inform the pager + * about the last "mapping" reference going away. + */ + if ((object->ref_count == 2) && (object->named)) { + memory_object_t pager = object->pager; + + /* Notify the Pager that there are no */ + /* more mappers for this object */ + + if (pager != MEMORY_OBJECT_NULL) { + vm_object_unlock(object); + vm_object_cache_unlock(); + + memory_object_unmap(pager); + + vm_object_cache_lock(); + vm_object_lock(object); + assert(object->ref_count > 0); + } + } /* * Lose the reference. If other references @@ -685,37 +602,12 @@ vm_object_deallocate( * until any pending initialization is completed. */ - assert(object->ref_count > 0); - if ((object->ref_count > 1) || (object->terminating)) { - /* if the object is terminating, it cannot go into */ - /* the cache and we obviously should not call */ - /* terminate again. */ + /* if the object is terminating, it cannot go into */ + /* the cache and we obviously should not call */ + /* terminate again. */ + + if ((object->ref_count > 1) || object->terminating) { object->ref_count--; - { - /* The following is an emergency work-around for */ - /* no-mappings left notification to UBC. This fix */ - /* violates numerous layering boundaries, is not */ - /* provable with respect to races for new mappings */ - /* from the UBC layer and is just plain ugly. The */ - /* proper fix requires a guarantee of state */ - /* between the vnode and the memory object and a */ - /* sequenced delivery of empty status. This can */ - /* be provided by the object_named interface and */ - /* the effort to convert over should be undertaken */ - /* at the earliest possible moment. */ - if(object->ref_count == 1) { - vnode_pager_t vnode_pager; - if(object->pager) { - vnode_pager = (vnode_pager_t) - vnode_port_hash_lookup( - object->pager); - if(vnode_pager) { - extern void ubc_unmap(void *); - ubc_unmap(vnode_pager->vnode_handle); - } - } - } - } vm_object_res_deallocate(object); vm_object_unlock(object); vm_object_cache_unlock(); @@ -753,7 +645,7 @@ vm_object_deallocate( * way (can do it in-line, mostly). */ - if (object->can_persist) { + if ((object->can_persist) && (object->alive)) { /* * Now it is safe to decrement reference count, * and to return if reference count is > 0. @@ -800,7 +692,7 @@ vm_object_deallocate( queue_enter(&vm_object_cached_list, object, vm_object_t, cached_list); vm_object_cache_unlock(); - vm_object_deactivate_pages(object); + vm_object_deactivate_all_pages(object); vm_object_unlock(object); #if MIGHT_NOT_CACHE_SHADOWS @@ -948,7 +840,7 @@ boolean_t vm_object_terminate_remove_all = FALSE; * Purpose: * Free all resources associated with a vm_object. * In/out conditions: - * Upon entry, the object and the cache must be locked, + * Upon entry, the object must be locked, * and the object must have exactly one reference. * * The shadow object reference is left alone. @@ -960,32 +852,20 @@ boolean_t vm_object_terminate_remove_all = FALSE; * upon exit, the cache will be unlocked, and the * object will cease to exist. */ -kern_return_t +static kern_return_t vm_object_terminate( register vm_object_t object) { + memory_object_t pager; register vm_page_t p; vm_object_t shadow_object; XPR(XPR_VM_OBJECT, "vm_object_terminate, object 0x%X ref %d\n", (integer_t)object, object->ref_count, 0, 0, 0); - /* - * Make sure the object isn't already being terminated - */ - - assert(object->alive); - if(object->terminating) { - vm_object_cache_unlock(); - object->ref_count -= 1; - vm_object_unlock(object); - return KERN_FAILURE; - } - object->terminating = TRUE; - - vm_object_cache_unlock(); if (!object->pageout && (!object->temporary || object->can_persist) && (object->pager != NULL || object->shadow_severed)) { + vm_object_cache_unlock(); while (!queue_empty(&object->memq)) { /* * Clear pager_trusted bit so that the pages get yanked @@ -1030,7 +910,7 @@ vm_object_terminate( if (!p->dirty) p->dirty = pmap_is_modified(p->phys_addr); - if (p->dirty || p->precious) { + if ((p->dirty || p->precious) && !p->error && object->alive) { p->busy = TRUE; vm_object_paging_begin(object); /* protect the object from re-use/caching while it */ @@ -1047,35 +927,42 @@ vm_object_terminate( VM_PAGE_FREE(p); } } + vm_object_unlock(object); + vm_object_cache_lock(); + vm_object_lock(object); } + + /* + * Make sure the object isn't already being terminated + */ + if(object->terminating) { + object->ref_count -= 1; + assert(object->ref_count > 0); + vm_object_cache_unlock(); + vm_object_unlock(object); + return KERN_FAILURE; + } + + /* + * Did somebody get a reference to the object while we were + * cleaning it? + */ if(object->ref_count != 1) { object->ref_count -= 1; + assert(object->ref_count > 0); vm_object_res_deallocate(object); - object->terminating = FALSE; - /* kick off anyone waiting on terminating */ - vm_object_paging_begin(object); - vm_object_paging_end(object); + vm_object_cache_unlock(); vm_object_unlock(object); return KERN_FAILURE; } - object->alive = FALSE; - /* * Make sure no one can look us up now. */ - vm_object_cache_lock(); - - if(object->pager != IP_NULL) { - vm_object_hash_entry_t entry; - - entry = vm_object_hash_lookup(object->pager, FALSE); - if (entry != VM_OBJECT_HASH_ENTRY_NULL) - entry->object = VM_OBJECT_NULL; - } - - vm_object_cache_unlock(); + object->terminating = TRUE; + object->alive = FALSE; + vm_object_remove(object); /* * Detach the object from its shadow if we are the shadow's @@ -1094,15 +981,30 @@ vm_object_terminate( * The pageout daemon might be playing with our pages. * Now that the object is dead, it won't touch any more * pages, but some pages might already be on their way out. - * Hence, we wait until the active paging activities have ceased. + * Hence, we wait until the active paging activities have ceased + * before we break the association with the pager itself. */ - vm_object_paging_wait(object, THREAD_UNINT); + while (object->paging_in_progress != 0) { + vm_object_cache_unlock(); + vm_object_wait(object, + VM_OBJECT_EVENT_PAGING_IN_PROGRESS, + THREAD_UNINT); + vm_object_cache_lock(); + vm_object_lock(object); + } + + pager = object->pager; + object->pager = MEMORY_OBJECT_NULL; + + if (pager != MEMORY_OBJECT_NULL) + memory_object_control_disable(object->pager_request); + vm_object_cache_unlock(); + object->ref_count--; #if TASK_SWAPPER assert(object->res_count == 0); #endif /* TASK_SWAPPER */ -Restart: assert (object->ref_count == 0); /* @@ -1116,8 +1018,8 @@ Restart: vm_pageout_object_terminate(object); - } else if (object->temporary && ! object->can_persist || - object->pager == IP_NULL) { + } else if ((object->temporary && !object->can_persist) || + (pager == MEMORY_OBJECT_NULL)) { while (!queue_empty(&object->memq)) { p = (vm_page_t) queue_first(&object->memq); @@ -1131,25 +1033,19 @@ Restart: assert(object->paging_in_progress == 0); assert(object->ref_count == 0); - vm_object_remove(object); - /* - * Throw away port rights... note that they may - * already have been thrown away (by vm_object_destroy - * or memory_object_destroy). - * - * Instead of destroying the control port, - * we send all rights off to the memory manager, - * using memory_object_terminate. + * If the pager has not already been released by + * vm_object_destroy, we need to terminate it and + * release our reference to it here. */ - - vm_object_unlock(object); - if (object->pager != IP_NULL) { - /* consumes our rights for pager, pager_request */ - memory_object_release(object->pager, object->pager_request); + if (pager != MEMORY_OBJECT_NULL) { + vm_object_unlock(object); + vm_object_release_pager(pager); + vm_object_lock(object); } + /* kick off anyone waiting on terminating */ - vm_object_lock(object); + object->terminating = FALSE; vm_object_paging_begin(object); vm_object_paging_end(object); vm_object_unlock(object); @@ -1161,7 +1057,6 @@ Restart: /* * Free the space for the object. */ - zfree(vm_object_zone, (vm_offset_t) object); return KERN_SUCCESS; } @@ -1171,9 +1066,9 @@ Restart: * Purpose: Wake up anyone waiting for termination of a pager. */ -void +static void vm_object_pager_wakeup( - ipc_port_t pager) + memory_object_t pager) { vm_object_hash_entry_t entry; boolean_t waiting = FALSE; @@ -1195,161 +1090,35 @@ vm_object_pager_wakeup( } /* - * memory_object_release_name: - * Enforces name semantic on memory_object reference count decrement - * This routine should not be called unless the caller holds a name - * reference gained through the memory_object_named_create or the - * memory_object_rename call. - * If the TERMINATE_IDLE flag is set, the call will return if the - * reference count is not 1. i.e. idle with the only remaining reference - * being the name. - * If the decision is made to proceed the name field flag is set to - * false and the reference count is decremented. If the RESPECT_CACHE - * flag is set and the reference count has gone to zero, the - * memory_object is checked to see if it is cacheable otherwise when - * the reference count is zero, it is simply terminated. + * Routine: vm_object_release_pager + * Purpose: Terminate the pager and, upon completion, + * release our last reference to it. + * just like memory_object_terminate, except + * that we wake up anyone blocked in vm_object_enter + * waiting for termination message to be queued + * before calling memory_object_init. */ - -kern_return_t -memory_object_release_name( - vm_object_t object, - int flags) +static void +vm_object_release_pager( + memory_object_t pager) { - vm_object_t shadow; - boolean_t original_object = TRUE; - while (object != VM_OBJECT_NULL) { + /* + * Terminate the pager. + */ - /* - * The cache holds a reference (uncounted) to - * the object. We must locke it before removing - * the object. - * - */ - - vm_object_cache_lock(); - vm_object_lock(object); - assert(object->alive); - if(original_object) - assert(object->named); - assert(object->ref_count > 0); + (void) memory_object_terminate(pager); - /* - * We have to wait for initialization before - * destroying or caching the object. - */ + /* + * Wakeup anyone waiting for this terminate + */ + vm_object_pager_wakeup(pager); - if (object->pager_created && !object->pager_initialized) { - assert(!object->can_persist); - vm_object_assert_wait(object, - VM_OBJECT_EVENT_INITIALIZED, - THREAD_UNINT); - vm_object_unlock(object); - vm_object_cache_unlock(); - thread_block((void (*)(void)) 0); - continue; - } - - if (((object->ref_count > 1) - && (flags & MEMORY_OBJECT_TERMINATE_IDLE)) - || (object->terminating)) { - vm_object_unlock(object); - vm_object_cache_unlock(); - return KERN_FAILURE; - } else { - if (flags & MEMORY_OBJECT_RELEASE_NO_OP) { - vm_object_unlock(object); - vm_object_cache_unlock(); - return KERN_SUCCESS; - } - } - - if ((flags & MEMORY_OBJECT_RESPECT_CACHE) && - (object->ref_count == 1)) { - if(original_object) - object->named = FALSE; - vm_object_unlock(object); - vm_object_cache_unlock(); - /* let vm_object_deallocate push this thing into */ - /* the cache, if that it is where it is bound */ - vm_object_deallocate(object); - return KERN_SUCCESS; - } - VM_OBJ_RES_DECR(object); - shadow = object->pageout?VM_OBJECT_NULL:object->shadow; - if(object->ref_count == 1) { - if(vm_object_terminate(object) != KERN_SUCCESS) { - if(original_object) { - return KERN_FAILURE; - } else { - return KERN_SUCCESS; - } - } - if (shadow != VM_OBJECT_NULL) { - original_object = FALSE; - object = shadow; - continue; - } - return KERN_SUCCESS; - } else { - object->ref_count--; - if(original_object) - object->named = FALSE; - vm_object_unlock(object); - vm_object_cache_unlock(); - return KERN_SUCCESS; - } - } -} - -/* - * Routine: memory_object_release - * Purpose: Terminate the pager and release port rights, - * just like memory_object_terminate, except - * that we wake up anyone blocked in vm_object_enter - * waiting for termination message to be queued - * before calling memory_object_init. - */ -void -memory_object_release( - ipc_port_t pager, - pager_request_t pager_request) -{ -#ifdef MACH_BSD - kern_return_t vnode_pager_terminate(ipc_port_t, ipc_port_t); -#endif - - /* - * Keep a reference to pager port; - * the terminate might otherwise release all references. - */ - ipc_port_copy_send(pager); - - /* - * Terminate the pager. - */ - -#ifdef MACH_BSD - if(((rpc_subsystem_t)pager_mux_hash_lookup(pager)) == - ((rpc_subsystem_t) &vnode_pager_workaround)) { - (void) vnode_pager_terminate(pager, pager_request); - } else { - (void) memory_object_terminate(pager, pager_request); - } -#else - (void) memory_object_terminate(pager, pager_request); -#endif - - /* - * Wakeup anyone waiting for this terminate - */ - vm_object_pager_wakeup(pager); - - /* - * Release reference to pager port. - */ - ipc_port_release_send(pager); -} + /* + * Release reference to pager. + */ + memory_object_deallocate(pager); +} /* * Routine: vm_object_abort_activity [internal use only] @@ -1358,7 +1127,7 @@ memory_object_release( * In/out conditions: * The object is locked on entry and exit. */ -void +static void vm_object_abort_activity( vm_object_t object) { @@ -1409,29 +1178,24 @@ vm_object_abort_activity( } /* - * Routine: memory_object_destroy [user interface] + * Routine: vm_object_destroy * Purpose: - * Shut down a memory object, despite the + * Shut down a VM object, despite the * presence of address map (or other) references * to the vm_object. */ kern_return_t -memory_object_destroy( - register vm_object_t object, +vm_object_destroy( + vm_object_t object, kern_return_t reason) { - ipc_port_t old_object; - pager_request_t old_pager_request; - -#ifdef lint - reason++; -#endif /* lint */ + memory_object_t old_pager; if (object == VM_OBJECT_NULL) return(KERN_SUCCESS); /* - * Remove the port associations immediately. + * Remove the pager association immediately. * * This will prevent the memory manager from further * meddling. [If it wanted to flush data or make @@ -1441,48 +1205,45 @@ memory_object_destroy( vm_object_cache_lock(); vm_object_lock(object); - vm_object_remove(object); object->can_persist = FALSE; object->named = FALSE; - vm_object_cache_unlock(); + object->alive = FALSE; /* - * Rip out the ports from the vm_object now... this - * will prevent new memory_object calls from succeeding. + * Rip out the pager from the vm_object now... */ - old_object = object->pager; - old_pager_request = object->pager_request; - - object->pager = IP_NULL; - object->pager_request = PAGER_REQUEST_NULL; + vm_object_remove(object); + old_pager = object->pager; + object->pager = MEMORY_OBJECT_NULL; + if (old_pager != MEMORY_OBJECT_NULL) + memory_object_control_disable(object->pager_request); + vm_object_cache_unlock(); /* - * Wait for existing paging activity (that might - * have the old ports) to subside. + * Wait for the existing paging activity (that got + * through before we nulled out the pager) to subside. */ vm_object_paging_wait(object, THREAD_UNINT); vm_object_unlock(object); /* - * Shut down the ports now. - * - * [Paging operations may be proceeding concurrently -- - * they'll get the null values established above.] + * Terminate the object now. */ + if (old_pager != MEMORY_OBJECT_NULL) { + vm_object_release_pager(old_pager); + + /* + * JMM - Release the caller's reference. This assumes the + * caller had a reference to release, which is a big (but + * currently valid) assumption if this is driven from the + * vnode pager (it is holding a named reference when making + * this call).. + */ + vm_object_deallocate(object); - if (old_object != IP_NULL) { - /* consumes our rights for object, control */ - memory_object_release(old_object, old_pager_request); } - - /* - * Lose the reference that was donated for this routine - */ - - vm_object_deallocate(object); - return(KERN_SUCCESS); } @@ -1494,8 +1255,8 @@ memory_object_destroy( * * The object must be locked. */ -void -vm_object_deactivate_pages( +static void +vm_object_deactivate_all_pages( register vm_object_t object) { register vm_page_t p; @@ -1508,6 +1269,83 @@ vm_object_deactivate_pages( } } +__private_extern__ void +vm_object_deactivate_pages( + vm_object_t object, + vm_object_offset_t offset, + vm_object_size_t size, + boolean_t kill_page) +{ + vm_object_t orig_object; + int pages_moved = 0; + int pages_found = 0; + + /* + * entered with object lock held, acquire a paging reference to + * prevent the memory_object and control ports from + * being destroyed. + */ + orig_object = object; + + for (;;) { + register vm_page_t m; + vm_object_offset_t toffset; + vm_object_size_t tsize; + + vm_object_paging_begin(object); + vm_page_lock_queues(); + + for (tsize = size, toffset = offset; tsize; tsize -= PAGE_SIZE, toffset += PAGE_SIZE) { + + if ((m = vm_page_lookup(object, toffset)) != VM_PAGE_NULL) { + + pages_found++; + + if ((m->wire_count == 0) && (!m->private) && (!m->gobbled) && (!m->busy)) { + + m->reference = FALSE; + pmap_clear_reference(m->phys_addr); + + if ((kill_page) && (object->internal)) { + m->precious = FALSE; + m->dirty = FALSE; + pmap_clear_modify(m->phys_addr); + vm_external_state_clr(object->existence_map, offset); + } + VM_PAGE_QUEUES_REMOVE(m); + + queue_enter_first(&vm_page_queue_inactive, m, vm_page_t, pageq); + + m->inactive = TRUE; + if (!m->fictitious) + vm_page_inactive_count++; + + pages_moved++; + } + } + } + vm_page_unlock_queues(); + vm_object_paging_end(object); + + if (object->shadow) { + vm_object_t tmp_object; + + kill_page = 0; + + offset += object->shadow_offset; + + tmp_object = object->shadow; + vm_object_lock(tmp_object); + + if (object != orig_object) + vm_object_unlock(object); + object = tmp_object; + } else + break; + } + if (object != orig_object) + vm_object_unlock(object); +} /* * Routine: vm_object_pmap_protect @@ -1533,7 +1371,7 @@ vm_object_deactivate_pages( * pmap. */ -void +__private_extern__ void vm_object_pmap_protect( register vm_object_t object, register vm_object_offset_t offset, @@ -1649,7 +1487,7 @@ vm_object_pmap_protect( * an error, this parameter will contain the value * VM_OBJECT_NULL. */ -kern_return_t +__private_extern__ kern_return_t vm_object_copy_slowly( register vm_object_t src_object, vm_object_offset_t src_offset, @@ -1730,7 +1568,7 @@ vm_object_copy_slowly( VM_BEHAVIOR_SEQUENTIAL, &prot, &_result_page, &top_page, (int *)0, - &error_code, FALSE, FALSE); + &error_code, FALSE, FALSE, NULL, 0); switch(result) { case VM_FAULT_SUCCESS: @@ -1847,7 +1685,7 @@ vm_object_copy_slowly( */ /*ARGSUSED*/ -boolean_t +__private_extern__ boolean_t vm_object_copy_quickly( vm_object_t *_object, /* INOUT */ vm_object_offset_t offset, /* IN */ @@ -1907,9 +1745,9 @@ vm_object_copy_quickly( return(TRUE); } -int copy_call_count = 0; -int copy_call_sleep_count = 0; -int copy_call_restart_count = 0; +static int copy_call_count = 0; +static int copy_call_sleep_count = 0; +static int copy_call_restart_count = 0; /* * Routine: vm_object_copy_call [internal] @@ -1929,7 +1767,7 @@ int copy_call_restart_count = 0; * If the return value indicates an error, this parameter * is not valid. */ -kern_return_t +static kern_return_t vm_object_copy_call( vm_object_t src_object, vm_object_offset_t src_offset, @@ -2031,12 +1869,12 @@ Retry: return KERN_SUCCESS; } -int copy_delayed_lock_collisions = 0; -int copy_delayed_max_collisions = 0; -int copy_delayed_lock_contention = 0; -int copy_delayed_protect_iterate = 0; -int copy_delayed_protect_lookup = 0; -int copy_delayed_protect_lookup_wait = 0; +static int copy_delayed_lock_collisions = 0; +static int copy_delayed_max_collisions = 0; +static int copy_delayed_lock_contention = 0; +static int copy_delayed_protect_iterate = 0; +static int copy_delayed_protect_lookup = 0; +static int copy_delayed_protect_lookup_wait = 0; /* * Routine: vm_object_copy_delayed [internal] @@ -2051,7 +1889,7 @@ int copy_delayed_protect_lookup_wait = 0; * This routine will not block waiting for user-generated * events. It is not interruptible. */ -vm_object_t +__private_extern__ vm_object_t vm_object_copy_delayed( vm_object_t src_object, vm_object_offset_t src_offset, @@ -2277,7 +2115,7 @@ vm_object_copy_delayed( * declared strategy. This operation may block, * and may be interrupted. */ -kern_return_t +__private_extern__ kern_return_t vm_object_copy_strategically( register vm_object_t src_object, vm_object_offset_t src_offset, @@ -2373,7 +2211,7 @@ vm_object_copy_strategically( */ boolean_t vm_object_shadow_check = FALSE; -boolean_t +__private_extern__ boolean_t vm_object_shadow( vm_object_t *object, /* IN/OUT */ vm_object_offset_t *offset, /* IN/OUT */ @@ -2431,21 +2269,23 @@ vm_object_shadow( /* * The relationship between vm_object structures and - * the memory_object ports requires careful synchronization. + * the memory_object requires careful synchronization. * - * All associations are created by vm_object_enter. All three - * port fields are filled in, as follows: - * pager: the memory_object port itself, supplied by + * All associations are created by memory_object_create_named + * for external pagers and vm_object_pager_create for internal + * objects as follows: + * + * pager: the memory_object itself, supplied by * the user requesting a mapping (or the kernel, * when initializing internal objects); the * kernel simulates holding send rights by keeping * a port reference; + * * pager_request: * the memory object control port, * created by the kernel; the kernel holds * receive (and ownership) rights to this * port, but no other references. - * All of the ports are referenced by their global names. * * When initialization is complete, the "initialized" field * is asserted. Other mappings using a particular memory object, @@ -2473,108 +2313,59 @@ vm_object_shadow( * This is the normal case, and is done even * though one of the other cases has already been * done. - * vm_object_destroy: - * The memory_object port has been destroyed, - * meaning that the kernel cannot flush dirty - * pages or request new data or unlock existing - * data. * memory_object_destroy: * The memory manager has requested that the - * kernel relinquish rights to the memory object - * port. [The memory manager may not want to - * destroy the port, but may wish to refuse or - * tear down existing memory mappings.] + * kernel relinquish references to the memory + * object. [The memory manager may not want to + * destroy the memory object, but may wish to + * refuse or tear down existing memory mappings.] + * * Each routine that breaks an association must break all of * them at once. At some later time, that routine must clear - * the vm_object port fields and release the port rights. + * the pager field and release the memory object references. * [Furthermore, each routine must cope with the simultaneous * or previous operations of the others.] * * In addition to the lock on the object, the vm_object_cache_lock - * governs the port associations. References gained through the - * port association require use of the cache lock. + * governs the associations. References gained through the + * association require use of the cache lock. * - * Because the port fields may be cleared spontaneously, they + * Because the pager field may be cleared spontaneously, it * cannot be used to determine whether a memory object has * ever been associated with a particular vm_object. [This * knowledge is important to the shadow object mechanism.] * For this reason, an additional "created" attribute is * provided. * - * During various paging operations, the port values found in the - * vm_object must be valid. To prevent these port rights from being - * released, and to prevent the port associations from changing + * During various paging operations, the pager reference found in the + * vm_object must be valid. To prevent this from being released, * (other than being removed, i.e., made null), routines may use * the vm_object_paging_begin/end routines [actually, macros]. * The implementation uses the "paging_in_progress" and "wanted" fields. - * [Operations that alter the validity of the port values include the + * [Operations that alter the validity of the pager values include the * termination routines and vm_object_collapse.] */ -#define IKOT_PAGER_LOOKUP_TYPE IKOT_PAGING_REQUEST - -vm_object_t -vm_object_lookup( - ipc_port_t port) -{ - vm_object_t object; - -start_over: - object = VM_OBJECT_NULL; - - if (IP_VALID(port)) { - vm_object_cache_lock(); - ip_lock(port); - if (ip_active(port) && - (ip_kotype(port) == IKOT_PAGER_LOOKUP_TYPE)) { - object = (vm_object_t) port->ip_kobject; - if (!vm_object_lock_try(object)) { - /* - * failed to acquire object lock. Drop the - * other two locks and wait for it, then go - * back and start over in case the port - * associations changed in the interim. - */ - ip_unlock(port); - vm_object_cache_unlock(); - vm_object_lock(object); - vm_object_unlock(object); - goto start_over; - } - - assert(object->alive); - - if((object->ref_count == 0) && (!object->terminating)){ - queue_remove(&vm_object_cached_list, object, - vm_object_t, cached_list); - vm_object_cached_count--; - XPR(XPR_VM_OBJECT_CACHE, - "vm_object_lookup: removing %X, head (%X, %X)\n", - (integer_t)object, - (integer_t)vm_object_cached_list.next, - (integer_t)vm_object_cached_list.prev, 0,0); - } - - object->ref_count++; - vm_object_res_reference(object); - vm_object_unlock(object); - } - ip_unlock(port); - vm_object_cache_unlock(); - } - - return object; -} - - +#if 0 +/* + * Routine: vm_object_pager_dead + * + * Purpose: + * A port is being destroy, and the IPC kobject code + * can't tell if it represents a pager port or not. + * So this function is called each time it sees a port + * die. + * THIS IS HORRIBLY INEFFICIENT. We should only call + * this routine if we had requested a notification on + * the port. + */ -void -vm_object_destroy( +__private_extern__ void +vm_object_pager_dead( ipc_port_t pager) { vm_object_t object; vm_object_hash_entry_t entry; - pager_request_t old_pager_request; /* * Perform essentially the same operations as in vm_object_lookup, @@ -2612,18 +2403,13 @@ vm_object_destroy( assert(object->pager == pager); /* - * Remove the port associations. + * Remove the pager association. * * Note that the memory_object itself is dead, so * we don't bother with it. */ - object->pager = IP_NULL; - vm_object_remove(object); - - old_pager_request = object->pager_request; - - object->pager_request = PAGER_REQUEST_NULL; + object->pager = MEMORY_OBJECT_NULL; vm_object_unlock(object); vm_object_cache_unlock(); @@ -2631,23 +2417,22 @@ vm_object_destroy( vm_object_pager_wakeup(pager); /* - * Clean up the port references. Note that there's no + * Release the pager reference. Note that there's no * point in trying the memory_object_terminate call - * because the memory_object itself is dead. + * because the memory_object itself is dead. Also + * release the memory_object_control reference, since + * the pager didn't do that either. */ - ipc_port_release_send(pager); - - if ((ipc_port_t)old_pager_request != IP_NULL) - ipc_port_dealloc_kernel((ipc_port_t)old_pager_request); + memory_object_deallocate(pager); + memory_object_control_deallocate(object->pager_request); + /* * Restart pending page requests */ vm_object_lock(object); - vm_object_abort_activity(object); - vm_object_unlock(object); /* @@ -2656,6 +2441,7 @@ vm_object_destroy( vm_object_deallocate(object); } +#endif /* * Routine: vm_object_enter @@ -2666,22 +2452,18 @@ vm_object_destroy( */ vm_object_t vm_object_enter( - ipc_port_t pager, + memory_object_t pager, vm_object_size_t size, boolean_t internal, boolean_t init, - boolean_t check_named) + boolean_t named) { register vm_object_t object; vm_object_t new_object; boolean_t must_init; - ipc_port_t pager_request; vm_object_hash_entry_t entry, new_entry; -#ifdef MACH_BSD -kern_return_t vnode_pager_init( ipc_port_t, ipc_port_t, vm_object_size_t); -#endif - if (!IP_VALID(pager)) + if (pager == MEMORY_OBJECT_NULL) return(vm_object_allocate(size)); new_object = VM_OBJECT_NULL; @@ -2710,15 +2492,8 @@ restart: */ if (entry != VM_OBJECT_HASH_ENTRY_NULL) { - if (entry->object != VM_OBJECT_NULL) { - if(check_named) { - if(entry->object->named) { - vm_object_cache_unlock(); - return(entry->object); - } - } + if (entry->object != VM_OBJECT_NULL) break; - } entry->waiting = TRUE; assert_wait((event_t) pager, THREAD_UNINT); @@ -2763,8 +2538,10 @@ restart: vm_object_lock(object); assert(object->pager_created); assert(!internal || object->internal); - if (check_named) + if (named) { + assert(!object->named); object->named = TRUE; + } if (object->ref_count == 0) { XPR(XPR_VM_OBJECT_CACHE, "vm_object_enter: removing %x from cache, head (%x, %x)\n", @@ -2803,26 +2580,22 @@ restart: vm_object_hash_entry_free(new_entry); if (must_init) { + pager_request_t pager_request; /* * Allocate request port. */ - pager_request = ipc_port_alloc_kernel(); - assert (pager_request != IP_NULL); - ipc_kobject_set(pager_request, (ipc_kobject_t) object, - IKOT_PAGING_REQUEST); + pager_request = memory_object_control_allocate(object); + assert (pager_request != PAGER_REQUEST_NULL); vm_object_lock(object); /* - * Copy the naked send right we were given. + * Copy the reference we were given. */ - pager = ipc_port_copy_send(pager); - if (!IP_VALID(pager)) - panic("vm_object_enter: port died"); /* XXX */ - + memory_object_reference(pager); object->pager_created = TRUE; object->pager = pager; object->internal = internal; @@ -2834,32 +2607,19 @@ restart: object->pager_request = pager_request; object->pager_ready = FALSE; - if (check_named) - object->named = TRUE; vm_object_unlock(object); /* * Let the pager know we're using it. */ -#ifdef MACH_BSD - if(((rpc_subsystem_t)pager_mux_hash_lookup(pager)) == - ((rpc_subsystem_t) &vnode_pager_workaround)) { - (void) vnode_pager_init(pager, - object->pager_request, - PAGE_SIZE); - } else { - (void) memory_object_init(pager, - object->pager_request, - PAGE_SIZE); - } -#else - (void) memory_object_init(pager, - object->pager_request, - PAGE_SIZE); -#endif + (void) memory_object_init(pager, + object->pager_request, + PAGE_SIZE); vm_object_lock(object); + if (named) + object->named = TRUE; if (internal) { object->pager_ready = TRUE; vm_object_wakeup(object, VM_OBJECT_EVENT_PAGER_READY); @@ -2912,7 +2672,7 @@ void vm_object_pager_create( register vm_object_t object) { - ipc_port_t pager; + memory_object_t pager; vm_object_hash_entry_t entry; #if MACH_PAGEMAP vm_object_size_t size; @@ -2967,26 +2727,27 @@ vm_object_pager_create( #endif /* MACH_PAGEMAP */ /* - * Create the pager ports, and associate them with this object. + * Create the [internal] pager, and associate it with this object. * - * We make the port association here so that vm_object_enter() + * We make the association here so that vm_object_enter() * can look up the object to complete initializing it. No * user will ever map this object. */ { - ipc_port_t DMM; + memory_object_default_t dmm; vm_size_t cluster_size; - /* acquire a naked send right for the DMM */ - DMM = memory_manager_default_reference(&cluster_size); + /* acquire a reference for the default memory manager */ + dmm = memory_manager_default_reference(&cluster_size); assert(cluster_size >= PAGE_SIZE); object->cluster_size = cluster_size; /* XXX ??? */ assert(object->temporary); - /* consumes the naked send right for DMM */ - (void) memory_object_create(DMM, &pager, object->size); - assert(IP_VALID(pager)); + /* create our new memory object */ + (void) memory_object_create(dmm, object->size, &pager); + + memory_object_default_deallocate(dmm); } entry = vm_object_hash_entry_alloc(pager); @@ -2998,7 +2759,7 @@ vm_object_pager_create( vm_object_cache_unlock(); /* - * A naked send right was returned by + * A reference was returned by * memory_object_create(), and it is * copied by vm_object_enter(). */ @@ -3007,9 +2768,9 @@ vm_object_pager_create( panic("vm_object_pager_create: mismatch"); /* - * Drop the naked send right. + * Drop the reference we were passed. */ - ipc_port_release_send(pager); + memory_object_deallocate(pager); vm_object_lock(object); @@ -3027,26 +2788,21 @@ vm_object_pager_create( * Conditions: * The object cache must be locked. */ -void +__private_extern__ void vm_object_remove( vm_object_t object) { - ipc_port_t port; + memory_object_t pager; + pager_request_t pager_request; - if ((port = object->pager) != IP_NULL) { + if ((pager = object->pager) != MEMORY_OBJECT_NULL) { vm_object_hash_entry_t entry; - entry = vm_object_hash_lookup(port, FALSE); + entry = vm_object_hash_lookup(pager, FALSE); if (entry != VM_OBJECT_HASH_ENTRY_NULL) entry->object = VM_OBJECT_NULL; } - if ((port = object->pager_request) != IP_NULL) { - if (ip_kotype(port) == IKOT_PAGING_REQUEST) - ipc_kobject_set(port, IKO_NULL, IKOT_NONE); - else if (ip_kotype(port) != IKOT_NONE) - panic("vm_object_remove: bad request port"); - } } /* @@ -3055,26 +2811,27 @@ vm_object_remove( * Counts for normal collapses and bypasses. * Debugging variables, to watch or disable collapse. */ -long object_collapses = 0; -long object_bypasses = 0; +static long object_collapses = 0; +static long object_bypasses = 0; -boolean_t vm_object_collapse_allowed = TRUE; -boolean_t vm_object_bypass_allowed = TRUE; +static boolean_t vm_object_collapse_allowed = TRUE; +static boolean_t vm_object_bypass_allowed = TRUE; + +static int vm_external_discarded; +static int vm_external_collapsed; -int vm_external_discarded; -int vm_external_collapsed; /* - * vm_object_do_collapse: - * - * Collapse an object with the object backing it. - * Pages in the backing object are moved into the - * parent, and the backing object is deallocated. - * - * Both objects and the cache are locked; the page - * queues are unlocked. + * Routine: vm_object_do_collapse + * Purpose: + * Collapse an object with the object backing it. + * Pages in the backing object are moved into the + * parent, and the backing object is deallocated. + * Conditions: + * Both objects and the cache are locked; the page + * queues are unlocked. * */ -void +static void vm_object_do_collapse( vm_object_t object, vm_object_t backing_object) @@ -3086,7 +2843,6 @@ vm_object_do_collapse( backing_offset = object->shadow_offset; size = object->size; - /* * Move all in-memory pages from backing_object * to the parent. Pages that have been paged out @@ -3153,9 +2909,10 @@ vm_object_do_collapse( } } - assert(object->pager == IP_NULL || backing_object->pager == IP_NULL); + assert(object->pager == MEMORY_OBJECT_NULL || + backing_object->pager == MEMORY_OBJECT_NULL); - if (backing_object->pager != IP_NULL) { + if (backing_object->pager != MEMORY_OBJECT_NULL) { vm_object_hash_entry_t entry; /* @@ -3177,10 +2934,9 @@ vm_object_do_collapse( object->cluster_size = backing_object->cluster_size; object->paging_offset = backing_object->paging_offset + backing_offset; - if (object->pager_request != IP_NULL) { - ipc_kobject_set(object->pager_request, - (ipc_kobject_t) object, - IKOT_PAGING_REQUEST); + if (object->pager_request != PAGER_REQUEST_NULL) { + memory_object_control_collapse(object->pager_request, + object); } } @@ -3237,7 +2993,6 @@ vm_object_do_collapse( (backing_object->resident_page_count == 0) && (backing_object->paging_in_progress == 0)); - assert(backing_object->alive); backing_object->alive = FALSE; vm_object_unlock(backing_object); @@ -3249,7 +3004,7 @@ vm_object_do_collapse( object_collapses++; } -void +static void vm_object_do_bypass( vm_object_t object, vm_object_t backing_object) @@ -3350,6 +3105,7 @@ vm_object_do_bypass( object_bypasses++; } + /* * vm_object_collapse: @@ -3361,7 +3117,7 @@ vm_object_do_bypass( * Requires that the object be locked and the page queues be unlocked. * */ -void +__private_extern__ void vm_object_collapse( register vm_object_t object) { @@ -3371,6 +3127,8 @@ vm_object_collapse( register vm_object_offset_t new_offset; register vm_page_t p; + vm_offset_t current_offset; + if (! vm_object_collapse_allowed && ! vm_object_bypass_allowed) { return; } @@ -3436,36 +3194,16 @@ vm_object_collapse( * object (if the parent is the only reference to * it) or (perhaps) remove the parent's reference * to it. - */ - - /* - * If there is exactly one reference to the backing - * object, we may be able to collapse it into the parent. * - * XXXO (norma vm): + * If there is exactly one reference to the backing + * object, we may be able to collapse it into the + * parent. * * The backing object must not have a pager * created for it, since collapsing an object * into a backing_object dumps new pages into * the backing_object that its pager doesn't - * know about, and we've already declared pages. - * This page dumping is deadly if other kernels - * are shadowing this object; this is the - * distributed equivalent of the ref_count == 1 - * condition. - * - * With some work, we could downgrade this - * restriction to the backing object must not - * be cachable, since when a temporary object - * is uncachable we are allowed to do anything - * to it. We would have to do something like - * call declare_pages again, and we would have - * to be prepared for the memory manager - * disabling temporary termination, which right - * now is a difficult race to deal with, since - * the memory manager currently assumes that - * termination is the only possible failure - * for disabling temporary termination. + * know about. */ if (backing_object->ref_count == 1 && @@ -3509,6 +3247,7 @@ vm_object_collapse( return; } + /* * If the backing object has a pager but no pagemap, * then we cannot bypass it, because we don't know @@ -3523,6 +3262,20 @@ vm_object_collapse( return; } + /* + * If the object has a pager but no pagemap, + * then we cannot bypass it, because we don't know + * what pages it has. + */ + if (object->pager_created +#if MACH_PAGEMAP + && (object->existence_map == VM_EXTERNAL_NULL) +#endif /* MACH_PAGEMAP */ + ) { + vm_object_unlock(backing_object); + return; + } + backing_offset = object->shadow_offset; size = object->size; @@ -3537,104 +3290,55 @@ vm_object_collapse( * we must check examine its existence info * as well. * - * XXX - * Should have a check for a 'small' number - * of pages here. */ - /* - * First, check pages resident in the backing object. - */ + if(object->cow_hint >= size) + object->cow_hint = 0; + current_offset = object->cow_hint; + while(TRUE) { + if (vm_page_lookup(object, + (vm_object_offset_t)current_offset) + != VM_PAGE_NULL) { + current_offset+=PAGE_SIZE; + } else if ((object->pager_created) && + (object->existence_map != NULL) && + (vm_external_state_get(object->existence_map, + current_offset) + != VM_EXTERNAL_STATE_ABSENT)) { + current_offset+=PAGE_SIZE; + } else if (vm_page_lookup(backing_object, + (vm_object_offset_t)current_offset + + backing_offset)!= VM_PAGE_NULL) { + /* found a dependency */ + object->cow_hint = current_offset; + vm_object_unlock(backing_object); + return; + } else if ((backing_object->pager_created) && + (backing_object->existence_map != NULL) && + (vm_external_state_get( + backing_object->existence_map, + current_offset + backing_offset) + != VM_EXTERNAL_STATE_ABSENT)) { + /* found a dependency */ + object->cow_hint = current_offset; + vm_object_unlock(backing_object); + return; + } else { + current_offset+=PAGE_SIZE; + } + if(current_offset >= size) { + /* wrap at end of object */ + current_offset = 0; + } + if(current_offset == object->cow_hint) { + /* we are free of shadow influence */ + break; + } + } + /* reset the cow_hint for any objects deeper in the chain */ + object->cow_hint = 0; - queue_iterate(&backing_object->memq, p, vm_page_t, listq) { - - /* - * If the parent has a page here, or if - * this page falls outside the parent, - * keep going. - * - * Otherwise, the backing_object must be - * left in the chain. - */ - - new_offset = (p->offset - backing_offset); - if (p->offset < backing_offset || new_offset >= size) { - /* - * Page falls outside of parent. - * Keep going. - */ - - continue; - } - - if ((vm_page_lookup(object, new_offset) == VM_PAGE_NULL) -#if MACH_PAGEMAP - && - (vm_external_state_get(object->existence_map, - new_offset) - != VM_EXTERNAL_STATE_EXISTS) -#endif /* MACH_PAGEMAP */ - ) { - - /* - * Page still needed. - * Can't go any further. - */ - - vm_object_unlock(backing_object); - return; - } - } - -#if MACH_PAGEMAP - /* - * Next, if backing object has been paged out, - * we must check its existence info for pages - * that the parent doesn't have. - */ - - if (backing_object->pager_created) { - assert(backing_object->existence_map - != VM_EXTERNAL_NULL); - for (new_offset = 0; new_offset < object->size; - new_offset += PAGE_SIZE_64) { - vm_object_offset_t - offset = new_offset + backing_offset; - - /* - * If this page doesn't exist in - * the backing object's existence - * info, then continue. - */ - - if (vm_external_state_get( - backing_object->existence_map, - offset) == VM_EXTERNAL_STATE_ABSENT) { - continue; - } - - /* - * If this page is neither resident - * in the parent nor paged out to - * the parent's pager, then we cannot - * bypass the backing object. - */ - - if ((vm_page_lookup(object, new_offset) == - VM_PAGE_NULL) && - ((object->existence_map == VM_EXTERNAL_NULL) - || (vm_external_state_get( - object->existence_map, new_offset) - == VM_EXTERNAL_STATE_ABSENT))) { - vm_object_unlock(backing_object); - return; - } - } - } -#else /* MACH_PAGEMAP */ - assert(! backing_object->pager_created); -#endif /* MACH_PAGEMAP */ /* * All interesting pages in the backing object @@ -3666,7 +3370,7 @@ vm_object_collapse( unsigned int vm_object_page_remove_lookup = 0; unsigned int vm_object_page_remove_iterate = 0; -void +__private_extern__ void vm_object_page_remove( register vm_object_t object, register vm_object_offset_t start, @@ -3711,6 +3415,7 @@ vm_object_page_remove( } } + /* * Routine: vm_object_coalesce * Function: Coalesces two objects backing up adjoining @@ -3734,9 +3439,9 @@ vm_object_page_remove( * The object(s) must *not* be locked. The map must be locked * to preserve the reference to the object(s). */ -int vm_object_coalesce_count = 0; +static int vm_object_coalesce_count = 0; -boolean_t +__private_extern__ boolean_t vm_object_coalesce( register vm_object_t prev_object, vm_object_t next_object, @@ -3865,6 +3570,8 @@ vm_object_page_map( } vm_page_init(m, addr); + /* private normally requires lock_queues but since we */ + /* are initializing the page, its not necessary here */ m->private = TRUE; /* don`t free page */ m->wire_count = 1; vm_page_insert(m, object, offset); @@ -3955,23 +3662,27 @@ vm_follow_object( { extern db_indent; - int count = 1; + int count = 0; + int orig_db_indent = db_indent; - if (object == VM_OBJECT_NULL) - return 0; + while (TRUE) { + if (object == VM_OBJECT_NULL) { + db_indent = orig_db_indent; + return count; + } - iprintf("object 0x%x", object); - printf(", shadow=0x%x", object->shadow); - printf(", copy=0x%x", object->copy); - printf(", pager=0x%x", object->pager); - printf(", ref=%d\n", object->ref_count); + count += 1; - db_indent += 2; - if (object->shadow) - count += vm_follow_object(object->shadow); + iprintf("object 0x%x", object); + printf(", shadow=0x%x", object->shadow); + printf(", copy=0x%x", object->copy); + printf(", pager=0x%x", object->pager); + printf(", ref=%d\n", object->ref_count); + + db_indent += 2; + object = object->shadow; + } - db_indent -= 2; - return count; } /* @@ -4203,6 +3914,91 @@ vm_object_find( #endif /* MACH_KDB */ +kern_return_t +vm_object_populate_with_private( + vm_object_t object, + vm_object_offset_t offset, + vm_offset_t phys_addr, + vm_size_t size) +{ + vm_offset_t base_addr; + vm_object_offset_t base_offset; + + + if(!object->private) + return KERN_FAILURE; + + if((base_addr = trunc_page(phys_addr)) != phys_addr) { + return KERN_FAILURE; + } + + + vm_object_lock(object); + if(!object->phys_contiguous) { + vm_page_t m; + if((base_offset = trunc_page(offset)) != offset) { + vm_object_unlock(object); + return KERN_FAILURE; + } + base_offset += object->paging_offset; + while(size) { + m = vm_page_lookup(object, base_offset); + if(m != VM_PAGE_NULL) { + if(m->fictitious) { + vm_page_lock_queues(); + m->fictitious = FALSE; + m->private = TRUE; + m->phys_addr = base_addr; + if(!m->busy) { + m->busy = TRUE; + } + if(!m->absent) { + m->absent = TRUE; + object->absent_count++; + } + m->list_req_pending = TRUE; + vm_page_unlock_queues(); + } else if (m->phys_addr != base_addr) { + /* pmap call to clear old mapping */ + pmap_page_protect(m->phys_addr, + VM_PROT_NONE); + m->phys_addr = base_addr; + } + } else { + while ((m = vm_page_grab_fictitious()) + == VM_PAGE_NULL) + vm_page_more_fictitious(); + vm_page_lock_queues(); + m->fictitious = FALSE; + m->private = TRUE; + m->phys_addr = base_addr; + m->list_req_pending = TRUE; + m->absent = TRUE; + m->unusual = TRUE; + object->absent_count++; + vm_page_unlock_queues(); + vm_page_insert(m, object, base_offset); + } + base_addr += PAGE_SIZE; + base_offset += PAGE_SIZE; + size -= PAGE_SIZE; + } + } else { + /* NOTE: we should check the original settings here */ + /* if we have a size > zero a pmap call should be made */ + /* to disable the range */ + + /* pmap_? */ + + /* shadows on contiguous memory are not allowed */ + /* we therefore can use the offset field */ + object->shadow_offset = (vm_object_offset_t)phys_addr; + object->size = size; + } + vm_object_unlock(object); + return KERN_SUCCESS; +} + /* * memory_object_free_from_cache: * @@ -4210,15 +4006,15 @@ vm_object_find( * which are backed by the pager identified by the caller, (pager_id). * Remove up to "count" objects, if there are that may available * in the cache. + * * Walk the list at most once, return the number of vm_objects * actually freed. - * */ -kern_return_t +__private_extern__ kern_return_t memory_object_free_from_cache( host_t host, - int pager_id, + int *pager_id, int *count) { @@ -4238,8 +4034,7 @@ memory_object_free_from_cache( queue_iterate(&vm_object_cached_list, object, vm_object_t, cached_list) { - if (pager_id == (int) pager_mux_hash_lookup( - (ipc_port_t)object->pager)) { + if (object->pager && (pager_id == object->pager->pager)) { vm_object_lock(object); queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); @@ -4247,9 +4042,9 @@ memory_object_free_from_cache( /* * Since this object is in the cache, we know - * that it is initialized and has no references. - * Take a reference to avoid recursive - * deallocations. + * that it is initialized and has only a pager's + * (implicit) reference. Take a reference to avoid + * recursive deallocations. */ assert(object->pager_initialized); @@ -4281,216 +4076,389 @@ memory_object_free_from_cache( return KERN_SUCCESS; } -/* - * memory_object_remove_cached_object: - * - * Check for the existance of a memory object represented by the - * supplied port. If one exists and it is not in use, remove the - * memory object from the vm_object cache. - * If the memory object is in use, turn off the the "can_persist" - * property so that it will not go in the cache when the last user - * gives it up. - * - */ + kern_return_t -memory_object_remove_cached_object( - ipc_port_t port) +memory_object_create_named( + memory_object_t pager, + memory_object_offset_t size, + memory_object_control_t *control) { - vm_object_t object; - vm_object_t shadow; + vm_object_t object; + vm_object_hash_entry_t entry; -repeat_lock_acquire: - object = VM_OBJECT_NULL; + *control = MEMORY_OBJECT_CONTROL_NULL; + if (pager == MEMORY_OBJECT_NULL) + return KERN_INVALID_ARGUMENT; - if (IP_VALID(port)) { - vm_object_cache_lock(); - ip_lock(port); - if (ip_active(port) && - (ip_kotype(port) == IKOT_PAGER_LOOKUP_TYPE)) { - object = (vm_object_t) port->ip_kobject; - if (!vm_object_lock_try(object)) { - /* - * failed to acquire object lock. Drop the - * other two locks and wait for it, then go - * back and start over in case the port - * associations changed in the interim. - */ - ip_unlock(port); - vm_object_cache_unlock(); - vm_object_lock(object); - vm_object_unlock(object); - goto repeat_lock_acquire; - } + vm_object_cache_lock(); + entry = vm_object_hash_lookup(pager, FALSE); + if ((entry != VM_OBJECT_HASH_ENTRY_NULL) && + (entry->object != VM_OBJECT_NULL)) { + if (entry->object->named == TRUE) + panic("memory_object_create_named: caller already holds the right"); } - if(object->terminating) { - ip_unlock(port); - vm_object_unlock(object); - vm_object_cache_unlock(); - return KERN_RIGHT_EXISTS; - } + vm_object_cache_unlock(); + if ((object = vm_object_enter(pager, size, FALSE, FALSE, TRUE)) + == VM_OBJECT_NULL) { + return(KERN_INVALID_OBJECT); + } + + /* wait for object (if any) to be ready */ + if (object != VM_OBJECT_NULL) { + vm_object_lock(object); + object->named = TRUE; + while (!object->pager_ready) { + vm_object_wait(object, + VM_OBJECT_EVENT_PAGER_READY, + FALSE); + vm_object_lock(object); + } + *control = object->pager_request; + vm_object_unlock(object); + } + return (KERN_SUCCESS); +} - assert(object->alive); - ip_unlock(port); - if (object->ref_count == 0) { - queue_remove(&vm_object_cached_list, object, - vm_object_t, cached_list); - vm_object_cached_count--; - object->ref_count++; - /* - * Terminate the object. - * If the object had a shadow, we let - * vm_object_deallocate deallocate it. - * "pageout" objects have a shadow, but - * maintain a "paging reference" rather - * than a normal reference. - * (We are careful here to limit - * recursion.) - */ - shadow = object->pageout? - VM_OBJECT_NULL:object->shadow; - /* will do the vm_object_cache_unlock */ - if((vm_object_terminate(object) - == KERN_SUCCESS) - && (shadow != VM_OBJECT_NULL)) { - /* will lock and unlock cache_lock */ - vm_object_deallocate(shadow); - } - } - else { - /* - * We cannot free object but we can - * make sure it doesn't go into the - * cache when it is no longer in - * use. - */ - object->can_persist = FALSE; +/* + * Routine: memory_object_recover_named [user interface] + * Purpose: + * Attempt to recover a named reference for a VM object. + * VM will verify that the object has not already started + * down the termination path, and if it has, will optionally + * wait for that to finish. + * Returns: + * KERN_SUCCESS - we recovered a named reference on the object + * KERN_FAILURE - we could not recover a reference (object dead) + * KERN_INVALID_ARGUMENT - bad memory object control + */ +kern_return_t +memory_object_recover_named( + memory_object_control_t control, + boolean_t wait_on_terminating) +{ + vm_object_t object; - vm_object_unlock(object); - vm_object_cache_unlock(); - return KERN_RIGHT_EXISTS; - } + vm_object_cache_lock(); + object = memory_object_control_to_vm_object(control); + if (object == VM_OBJECT_NULL) { + vm_object_cache_unlock(); + return (KERN_INVALID_ARGUMENT); + } +restart: + vm_object_lock(object); - } - else { - ip_unlock(port); - vm_object_cache_unlock(); - } - } else { - return KERN_INVALID_ARGUMENT; + if (object->terminating && wait_on_terminating) { + vm_object_cache_unlock(); + vm_object_wait(object, + VM_OBJECT_EVENT_PAGING_IN_PROGRESS, + THREAD_UNINT); + vm_object_cache_lock(); + goto restart; + } + + if (!object->alive) { + vm_object_cache_unlock(); + vm_object_unlock(object); + return KERN_FAILURE; } + if (object->named == TRUE) { + vm_object_cache_unlock(); + vm_object_unlock(object); + return KERN_SUCCESS; + } - return KERN_SUCCESS; + if((object->ref_count == 0) && (!object->terminating)){ + queue_remove(&vm_object_cached_list, object, + vm_object_t, cached_list); + vm_object_cached_count--; + XPR(XPR_VM_OBJECT_CACHE, + "memory_object_recover_named: removing %X, head (%X, %X)\n", + (integer_t)object, + (integer_t)vm_object_cached_list.next, + (integer_t)vm_object_cached_list.prev, 0,0); + } + + vm_object_cache_unlock(); + + object->named = TRUE; + object->ref_count++; + vm_object_res_reference(object); + while (!object->pager_ready) { + vm_object_wait(object, + VM_OBJECT_EVENT_PAGER_READY, + FALSE); + vm_object_lock(object); + } + vm_object_unlock(object); + return (KERN_SUCCESS); } -kern_return_t -memory_object_create_named( - ipc_port_t port, - vm_object_size_t size, - vm_object_t *object_ptr) + +/* + * vm_object_release_name: + * + * Enforces name semantic on memory_object reference count decrement + * This routine should not be called unless the caller holds a name + * reference gained through the memory_object_create_named. + * + * If the TERMINATE_IDLE flag is set, the call will return if the + * reference count is not 1. i.e. idle with the only remaining reference + * being the name. + * If the decision is made to proceed the name field flag is set to + * false and the reference count is decremented. If the RESPECT_CACHE + * flag is set and the reference count has gone to zero, the + * memory_object is checked to see if it is cacheable otherwise when + * the reference count is zero, it is simply terminated. + */ + +__private_extern__ kern_return_t +vm_object_release_name( + vm_object_t object, + int flags) { - vm_object_t object; - vm_object_hash_entry_t entry; + vm_object_t shadow; + boolean_t original_object = TRUE; - *object_ptr = (vm_object_t)NULL; - if (IP_VALID(port)) { + while (object != VM_OBJECT_NULL) { + /* + * The cache holds a reference (uncounted) to + * the object. We must locke it before removing + * the object. + * + */ + vm_object_cache_lock(); - entry = vm_object_hash_lookup(port, FALSE); - if ((entry != VM_OBJECT_HASH_ENTRY_NULL) && - (entry->object != VM_OBJECT_NULL)) { - if (entry->object->named == TRUE) - panic("memory_object_create_named: caller already holds the right"); + vm_object_lock(object); + assert(object->alive); + if(original_object) + assert(object->named); + assert(object->ref_count > 0); + + /* + * We have to wait for initialization before + * destroying or caching the object. + */ + + if (object->pager_created && !object->pager_initialized) { + assert(!object->can_persist); + vm_object_assert_wait(object, + VM_OBJECT_EVENT_INITIALIZED, + THREAD_UNINT); + vm_object_unlock(object); + vm_object_cache_unlock(); + thread_block((void (*)(void)) 0); + continue; } - vm_object_cache_unlock(); - if ((object = vm_object_enter(port, size, FALSE, FALSE, TRUE)) - == VM_OBJECT_NULL) - return(KERN_INVALID_OBJECT); - - /* wait for object (if any) to be ready */ - if (object != VM_OBJECT_NULL) { - vm_object_lock(object); - object->named = TRUE; - while (!object->pager_ready) { - vm_object_wait(object, - VM_OBJECT_EVENT_PAGER_READY, - FALSE); - vm_object_lock(object); + if (((object->ref_count > 1) + && (flags & MEMORY_OBJECT_TERMINATE_IDLE)) + || (object->terminating)) { + vm_object_unlock(object); + vm_object_cache_unlock(); + return KERN_FAILURE; + } else { + if (flags & MEMORY_OBJECT_RELEASE_NO_OP) { + vm_object_unlock(object); + vm_object_cache_unlock(); + return KERN_SUCCESS; } + } + + if ((flags & MEMORY_OBJECT_RESPECT_CACHE) && + (object->ref_count == 1)) { + if(original_object) + object->named = FALSE; vm_object_unlock(object); + vm_object_cache_unlock(); + /* let vm_object_deallocate push this thing into */ + /* the cache, if that it is where it is bound */ + vm_object_deallocate(object); + return KERN_SUCCESS; + } + VM_OBJ_RES_DECR(object); + shadow = object->pageout?VM_OBJECT_NULL:object->shadow; + if(object->ref_count == 1) { + if(vm_object_terminate(object) != KERN_SUCCESS) { + if(original_object) { + return KERN_FAILURE; + } else { + return KERN_SUCCESS; + } + } + if (shadow != VM_OBJECT_NULL) { + original_object = FALSE; + object = shadow; + continue; + } + return KERN_SUCCESS; + } else { + object->ref_count--; + assert(object->ref_count > 0); + if(original_object) + object->named = FALSE; + vm_object_unlock(object); + vm_object_cache_unlock(); + return KERN_SUCCESS; } - *object_ptr = object; - return (KERN_SUCCESS); - } else { - return (KERN_INVALID_ARGUMENT); } } -kern_return_t -memory_object_recover_named( - ipc_port_t pager, - boolean_t wait_on_terminating, - vm_object_t *object_ptr) + +__private_extern__ kern_return_t +vm_object_lock_request( + vm_object_t object, + vm_object_offset_t offset, + vm_object_size_t size, + memory_object_return_t should_return, + int flags, + vm_prot_t prot) { - vm_object_t object; - vm_object_hash_entry_t entry; + vm_object_offset_t original_offset = offset; + boolean_t should_flush=flags & MEMORY_OBJECT_DATA_FLUSH; - *object_ptr = (vm_object_t)NULL; -lookup_entry: - if (IP_VALID(pager)) { + XPR(XPR_MEMORY_OBJECT, + "vm_o_lock_request, obj 0x%X off 0x%X size 0x%X flags %X prot %X\n", + (integer_t)object, offset, size, + (((should_return&1)<<1)|should_flush), prot); - vm_object_cache_lock(); - entry = vm_object_hash_lookup(pager, FALSE); - if ((entry != VM_OBJECT_HASH_ENTRY_NULL) && - (entry->object != VM_OBJECT_NULL)) { - if (entry->object->named == TRUE) - panic("memory_object_recover_named: caller already holds the right"); - object = entry->object; - vm_object_lock(object); - vm_object_cache_unlock(); - if (object->terminating && wait_on_terminating) { - vm_object_wait(object, - VM_OBJECT_EVENT_PAGING_IN_PROGRESS, - THREAD_UNINT); - vm_object_unlock(object); - goto lookup_entry; - } - } else { - vm_object_cache_unlock(); - return KERN_FAILURE; - } + /* + * Check for bogus arguments. + */ + if (object == VM_OBJECT_NULL) + return (KERN_INVALID_ARGUMENT); - if((object->ref_count == 0) && (!object->terminating)){ - queue_remove(&vm_object_cached_list, object, - vm_object_t, cached_list); - vm_object_cached_count--; - XPR(XPR_VM_OBJECT_CACHE, - "memory_object_recover_named: removing %X, head (%X, %X)\n", - (integer_t)object, - (integer_t)vm_object_cached_list.next, - (integer_t)vm_object_cached_list.prev, 0,0); - } + if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE) + return (KERN_INVALID_ARGUMENT); - object->named = TRUE; - object->ref_count++; - vm_object_res_reference(object); - while (!object->pager_ready) { - vm_object_wait(object, - VM_OBJECT_EVENT_PAGER_READY, - FALSE); - vm_object_lock(object); - } + size = round_page(size); + + /* + * Lock the object, and acquire a paging reference to + * prevent the memory_object reference from being released. + */ + vm_object_lock(object); + vm_object_paging_begin(object); + offset -= object->paging_offset; + + (void)vm_object_update(object, + offset, size, should_return, flags, prot); + + vm_object_paging_end(object); + vm_object_unlock(object); + + return (KERN_SUCCESS); +} + + + +#if TASK_SWAPPER +/* + * vm_object_res_deallocate + * + * (recursively) decrement residence counts on vm objects and their shadows. + * Called from vm_object_deallocate and when swapping out an object. + * + * The object is locked, and remains locked throughout the function, + * even as we iterate down the shadow chain. Locks on intermediate objects + * will be dropped, but not the original object. + * + * NOTE: this function used to use recursion, rather than iteration. + */ + +__private_extern__ void +vm_object_res_deallocate( + vm_object_t object) +{ + vm_object_t orig_object = object; + /* + * Object is locked so it can be called directly + * from vm_object_deallocate. Original object is never + * unlocked. + */ + assert(object->res_count > 0); + while (--object->res_count == 0) { + assert(object->ref_count >= object->res_count); + vm_object_deactivate_all_pages(object); + /* iterate on shadow, if present */ + if (object->shadow != VM_OBJECT_NULL) { + vm_object_t tmp_object = object->shadow; + vm_object_lock(tmp_object); + if (object != orig_object) + vm_object_unlock(object); + object = tmp_object; + assert(object->res_count > 0); + } else + break; + } + if (object != orig_object) vm_object_unlock(object); - *object_ptr = object; - return (KERN_SUCCESS); - } else { - return (KERN_INVALID_ARGUMENT); +} + +/* + * vm_object_res_reference + * + * Internal function to increment residence count on a vm object + * and its shadows. It is called only from vm_object_reference, and + * when swapping in a vm object, via vm_map_swap. + * + * The object is locked, and remains locked throughout the function, + * even as we iterate down the shadow chain. Locks on intermediate objects + * will be dropped, but not the original object. + * + * NOTE: this function used to use recursion, rather than iteration. + */ + +__private_extern__ void +vm_object_res_reference( + vm_object_t object) +{ + vm_object_t orig_object = object; + /* + * Object is locked, so this can be called directly + * from vm_object_reference. This lock is never released. + */ + while ((++object->res_count == 1) && + (object->shadow != VM_OBJECT_NULL)) { + vm_object_t tmp_object = object->shadow; + + assert(object->ref_count >= object->res_count); + vm_object_lock(tmp_object); + if (object != orig_object) + vm_object_unlock(object); + object = tmp_object; } + if (object != orig_object) + vm_object_unlock(object); + assert(orig_object->ref_count >= orig_object->res_count); } +#endif /* TASK_SWAPPER */ + +/* + * vm_object_reference: + * + * Gets another reference to the given object. + */ +#ifdef vm_object_reference +#undef vm_object_reference +#endif +__private_extern__ void +vm_object_reference( + register vm_object_t object) +{ + if (object == VM_OBJECT_NULL) + return; + + vm_object_lock(object); + assert(object->ref_count > 0); + vm_object_reference_locked(object); + vm_object_unlock(object); +} + #ifdef MACH_BSD /* * Scale the vm_object_cache diff --git a/osfmk/vm/vm_object.h b/osfmk/vm/vm_object.h index 81a303fb4..92044ab01 100644 --- a/osfmk/vm/vm_object.h +++ b/osfmk/vm/vm_object.h @@ -72,25 +72,23 @@ #include <kern/queue.h> #include <kern/lock.h> #include <kern/assert.h> +#include <kern/ipc_mig.h> +#include <kern/misc_protos.h> #include <kern/macro_help.h> #include <ipc/ipc_types.h> #include <vm/pmap.h> -#include <kern/misc_protos.h> #if MACH_PAGEMAP #include <vm/vm_external.h> #endif /* MACH_PAGEMAP */ -typedef struct ipc_port * pager_request_t; +typedef memory_object_control_t pager_request_t; #define PAGER_REQUEST_NULL ((pager_request_t) 0) /* * Types defined: * * vm_object_t Virtual memory object. - * - * We use "struct ipc_port *" instead of "ipc_port_t" - * to avoid include file circularities. */ typedef unsigned long long vm_object_size_t; @@ -124,7 +122,7 @@ struct vm_object { struct vm_object *shadow; /* My shadow */ vm_object_offset_t shadow_offset; /* Offset into shadow */ - struct ipc_port *pager; /* Where to get data */ + memory_object_t pager; /* Where to get data */ vm_object_offset_t paging_offset; /* Offset into memory object */ pager_request_t pager_request; /* Where data comes back */ @@ -236,7 +234,7 @@ struct vm_object { * an error rather than a * zero filled page. */ - /* boolean_t */ phys_contiguous:1; + /* boolean_t */ phys_contiguous:1, /* Memory is wired and * guaranteed physically * contiguous. However @@ -245,6 +243,12 @@ struct vm_object { * memory rules w.r.t pmap * access bits. */ + /* boolean_t */ nophyscache:1; + /* When mapped at the + * pmap level, don't allow + * primary caching. (for + * I/O) + */ @@ -263,6 +267,8 @@ struct vm_object { vm_external_map_t existence_map; /* bitmap of pages written to * backing storage */ #endif /* MACH_PAGEMAP */ + int cow_hint; /* last page present in */ + /* shadow but not in object */ #if MACH_ASSERT struct vm_object *paging_object; /* object which pages to be * swapped out are temporary @@ -274,9 +280,10 @@ struct vm_object { #endif /* UBC_DEBUG */ }; -extern +__private_extern__ vm_object_t kernel_object; /* the single kernel object */ +__private_extern__ int vm_object_absent_max; /* maximum number of absent pages at a time for each object */ @@ -317,33 +324,67 @@ typedef struct msync_req *msync_req_t; * Declare procedures that operate on VM objects. */ -extern void vm_object_bootstrap(void); +__private_extern__ void vm_object_bootstrap(void); -extern void vm_object_init(void); +__private_extern__ void vm_object_init(void); -extern vm_object_t vm_object_allocate( +__private_extern__ vm_object_t vm_object_allocate( vm_object_size_t size); +#if TASK_SWAPPER + +__private_extern__ void vm_object_res_reference( + vm_object_t object); +__private_extern__ void vm_object_res_deallocate( + vm_object_t object); +#define VM_OBJ_RES_INCR(object) (object)->res_count++ +#define VM_OBJ_RES_DECR(object) (object)->res_count-- + +#else /* TASK_SWAPPER */ + +#define VM_OBJ_RES_INCR(object) +#define VM_OBJ_RES_DECR(object) +#define vm_object_res_reference(object) +#define vm_object_res_deallocate(object) + +#endif /* TASK_SWAPPER */ + +#define vm_object_reference_locked(object) \ +MACRO_BEGIN \ + vm_object_t RLObject = (object); \ + assert((RLObject)->ref_count > 0); \ + (RLObject)->ref_count++; \ + vm_object_res_reference(RLObject); \ +MACRO_END + + #if MACH_ASSERT -extern void vm_object_reference( + +__private_extern__ void vm_object_reference( vm_object_t object); + #else /* MACH_ASSERT */ + #define vm_object_reference(object) \ MACRO_BEGIN \ - vm_object_t Object = (object); \ - if (Object) { \ - vm_object_lock(Object); \ - Object->ref_count++; \ - vm_object_res_reference(Object); \ - vm_object_unlock(Object); \ + vm_object_t RObject = (object); \ + if (RObject) { \ + vm_object_lock(RObject); \ + vm_object_reference_locked(RObject); \ + vm_object_unlock(RObject); \ } \ MACRO_END + #endif /* MACH_ASSERT */ -extern void vm_object_deallocate( +__private_extern__ void vm_object_deallocate( vm_object_t object); -extern void vm_object_pmap_protect( +__private_extern__ kern_return_t vm_object_release_name( + vm_object_t object, + int flags); + +__private_extern__ void vm_object_pmap_protect( vm_object_t object, vm_object_offset_t offset, vm_size_t size, @@ -351,12 +392,18 @@ extern void vm_object_pmap_protect( vm_offset_t pmap_start, vm_prot_t prot); -extern void vm_object_page_remove( +__private_extern__ void vm_object_page_remove( vm_object_t object, vm_object_offset_t start, vm_object_offset_t end); -extern boolean_t vm_object_coalesce( +__private_extern__ void vm_object_deactivate_pages( + vm_object_t object, + vm_object_offset_t offset, + vm_object_size_t size, + boolean_t kill_page); + +__private_extern__ boolean_t vm_object_coalesce( vm_object_t prev_object, vm_object_t next_object, vm_object_offset_t prev_offset, @@ -364,28 +411,22 @@ extern boolean_t vm_object_coalesce( vm_object_size_t prev_size, vm_object_size_t next_size); -extern boolean_t vm_object_shadow( +__private_extern__ boolean_t vm_object_shadow( vm_object_t *object, vm_object_offset_t *offset, vm_object_size_t length); -extern void vm_object_collapse( +__private_extern__ void vm_object_collapse( vm_object_t object); -extern vm_object_t vm_object_lookup( - ipc_port_t port); - -extern ipc_port_t vm_object_name( - vm_object_t object); - -extern boolean_t vm_object_copy_quickly( +__private_extern__ boolean_t vm_object_copy_quickly( vm_object_t *_object, vm_object_offset_t src_offset, vm_object_size_t size, boolean_t *_src_needs_copy, boolean_t *_dst_needs_copy); -extern kern_return_t vm_object_copy_strategically( +__private_extern__ kern_return_t vm_object_copy_strategically( vm_object_t src_object, vm_object_offset_t src_offset, vm_object_size_t size, @@ -393,23 +434,28 @@ extern kern_return_t vm_object_copy_strategically( vm_object_offset_t *dst_offset, boolean_t *dst_needs_copy); -extern kern_return_t vm_object_copy_slowly( +__private_extern__ kern_return_t vm_object_copy_slowly( vm_object_t src_object, vm_object_offset_t src_offset, vm_object_size_t size, int interruptible, vm_object_t *_result_object); -extern void vm_object_pager_create( - vm_object_t object); +__private_extern__ vm_object_t vm_object_copy_delayed( + vm_object_t src_object, + vm_object_offset_t src_offset, + vm_object_size_t size); + -extern void vm_object_destroy( - ipc_port_t pager); -extern void vm_object_pager_wakeup( - ipc_port_t pager); +__private_extern__ kern_return_t vm_object_destroy( + vm_object_t object, + kern_return_t reason); -extern void vm_object_page_map( +__private_extern__ void vm_object_pager_create( + vm_object_t object); + +__private_extern__ void vm_object_page_map( vm_object_t object, vm_object_offset_t offset, vm_object_size_t size, @@ -417,38 +463,48 @@ extern void vm_object_page_map( (void *, vm_object_offset_t), void *map_fn_data); -#if TASK_SWAPPER +__private_extern__ kern_return_t vm_object_upl_request( + vm_object_t object, + vm_object_offset_t offset, + vm_size_t size, + upl_t *upl, + upl_page_info_t *page_info, + unsigned int *count, + int flags); + +__private_extern__ boolean_t vm_object_sync( + vm_object_t object, + vm_object_offset_t offset, + vm_size_t size, + boolean_t should_flush, + boolean_t should_return); -extern void vm_object_res_reference( - vm_object_t object); -extern void vm_object_res_deallocate( - vm_object_t object); -#define VM_OBJ_RES_INCR(object) (object)->res_count++ -#define VM_OBJ_RES_DECR(object) (object)->res_count-- +__private_extern__ kern_return_t vm_object_update( + vm_object_t object, + vm_object_offset_t offset, + vm_size_t size, /* should be 64 */ + memory_object_return_t should_return, + int flags, + vm_prot_t prot); -#else /* TASK_SWAPPER */ +__private_extern__ kern_return_t vm_object_lock_request( + vm_object_t object, + vm_object_offset_t offset, + vm_object_size_t size, + memory_object_return_t should_return, + int flags, + vm_prot_t prot); -#define VM_OBJ_RES_INCR(object) -#define VM_OBJ_RES_DECR(object) -#define vm_object_res_reference(object) -#define vm_object_res_deallocate(object) -#endif /* TASK_SWAPPER */ -extern vm_object_t vm_object_enter( - ipc_port_t pager, +__private_extern__ vm_object_t vm_object_enter( + memory_object_t pager, vm_object_size_t size, boolean_t internal, boolean_t init, boolean_t check_named); -extern vm_object_t vm_object_copy_delayed( - vm_object_t src_object, - vm_object_offset_t src_offset, - vm_object_size_t size); - - /* * Event waiting handling */ diff --git a/osfmk/vm/vm_page.h b/osfmk/vm/vm_page.h index fd2594146..2cb7f1a00 100644 --- a/osfmk/vm/vm_page.h +++ b/osfmk/vm/vm_page.h @@ -69,6 +69,24 @@ #include <kern/macro_help.h> +/* + * Each page entered on the inactive queue obtains a ticket from a + * particular ticket roll. Pages granted tickets from a particular + * roll generally flow through the queue as a group. In this way when a + * page with a ticket from a particular roll is pulled from the top of the + * queue it is extremely likely that the pages near the top will have tickets + * from the same or adjacent rolls. In this way the proximity to the top + * of the queue can be loosely ascertained by determining the identity of + * the roll the pages ticket came from. + */ + + +extern int vm_page_ticket_roll; +extern int vm_page_ticket; + +#define VM_PAGE_TICKETS_IN_ROLL 512 +#define VM_PAGE_TICKET_ROLL_IDS 16 + /* * Management of resident (logical) pages. * @@ -105,24 +123,26 @@ struct vm_page { vm_object_offset_t offset; /* offset into that object (O,P) */ unsigned int wire_count:16, /* how many wired down maps use me? (O&P) */ - page_error:8, /* error from I/O operations */ + page_ticket:4, /* age of the page on the */ + /* inactive queue. */ /* boolean_t */ inactive:1, /* page is in inactive list (P) */ active:1, /* page is in active list (P) */ laundry:1, /* page is being cleaned now (P)*/ free:1, /* page is on free list (P) */ reference:1, /* page has been used (P) */ - limbo:1, /* page prepped then stolen (P) */ pageout:1, /* page wired & busy for pageout (P) */ - gobbled:1; /* page used internally (P) */ - /* we've used up all 32 bits */ + gobbled:1, /* page used internally (P) */ + private:1, /* Page should not be returned to + * the free list (O) */ + :0; unsigned int + page_error:8, /* error from I/O operations */ /* boolean_t */ busy:1, /* page is in transit (O) */ wanted:1, /* someone is waiting for page (O) */ tabled:1, /* page is in VP table (O) */ fictitious:1, /* Physical page doesn't exist (O) */ - private:1, /* Page should not be returned to - * the free list (O) */ + no_isync:1, /* page has not been instruction synced */ absent:1, /* Data has been requested, but is * not yet available (O) */ error:1, /* Data manager was unable to provide @@ -149,25 +169,18 @@ struct vm_page { /* allows creation of list */ /* requests on pages that are */ /* actively being paged. */ - :0; + dump_cleaning:1; /* set by the pageout daemon when */ + /* a page being cleaned is */ + /* encountered and targeted as */ + /* a pageout candidate */ + /* we've used up all 32 bits */ vm_offset_t phys_addr; /* Physical address of page, passed * to pmap_enter (read-only) */ - union { - struct { - unsigned int prep:16, /* page prep count */ - pin:16; /* page pin pount */ - } pp_counts; - unsigned int pp_both; /* used to test for both zero */ - } prep_pin_u; }; typedef struct vm_page *vm_page_t; -#define prep_count prep_pin_u.pp_counts.prep -#define pin_count prep_pin_u.pp_counts.pin -#define prep_pin_count prep_pin_u.pp_both - #define VM_PAGE_NULL ((vm_page_t) 0) #define NEXT_PAGE(m) ((vm_page_t) (m)->pageq.next) @@ -355,20 +368,6 @@ extern void vm_set_page_size(void); extern void vm_page_gobble( vm_page_t page); -extern kern_return_t vm_page_prep( - vm_page_t m); - -extern kern_return_t vm_page_pin( - vm_page_t m); - -extern kern_return_t vm_page_unprep( - vm_page_t m); - -extern kern_return_t vm_page_unpin( - vm_page_t m); - -extern void cleanup_limbo_queue(void); - /* * Functions implemented as macros. m->wanted and m->busy are * protected by the object lock. diff --git a/osfmk/vm/vm_pageout.c b/osfmk/vm/vm_pageout.c index cc5e40edb..b5c35da62 100644 --- a/osfmk/vm/vm_pageout.c +++ b/osfmk/vm/vm_pageout.c @@ -56,10 +56,6 @@ * * The proverbial page-out daemon. */ -#ifdef MACH_BSD -/* remove after component merge */ -extern int vnode_pager_workaround; -#endif #include <mach_pagemap.h> #include <mach_cluster_stats.h> @@ -69,13 +65,13 @@ extern int vnode_pager_workaround; #include <mach/mach_types.h> #include <mach/memory_object.h> #include <mach/memory_object_default.h> +#include <mach/memory_object_control_server.h> #include <mach/mach_host_server.h> #include <mach/vm_param.h> #include <mach/vm_statistics.h> #include <kern/host_statistics.h> #include <kern/counters.h> #include <kern/thread.h> -#include <kern/thread_swap.h> #include <kern/xpr.h> #include <vm/pmap.h> #include <vm/vm_map.h> @@ -88,7 +84,7 @@ extern int vnode_pager_workaround; extern ipc_port_t memory_manager_default; #ifndef VM_PAGE_LAUNDRY_MAX -#define VM_PAGE_LAUNDRY_MAX 10 /* outstanding DMM page cleans */ +#define VM_PAGE_LAUNDRY_MAX 6 /* outstanding DMM page cleans */ #endif /* VM_PAGEOUT_LAUNDRY_MAX */ #ifndef VM_PAGEOUT_BURST_MAX @@ -151,9 +147,17 @@ extern ipc_port_t memory_manager_default; #ifndef VM_PAGE_FREE_RESERVED #define VM_PAGE_FREE_RESERVED \ - ((8 * VM_PAGE_LAUNDRY_MAX) + NCPUS) + ((16 * VM_PAGE_LAUNDRY_MAX) + NCPUS) #endif /* VM_PAGE_FREE_RESERVED */ +/* + * Exported variable used to broadcast the activation of the pageout scan + * Working Set uses this to throttle its use of pmap removes. In this + * way, code which runs within memory in an uncontested context does + * not keep encountering soft faults. + */ + +unsigned int vm_pageout_scan_event_counter = 0; /* * Forward declarations for internal routines. @@ -197,10 +201,6 @@ unsigned int vm_pageout_inactive_used = 0; /* debugging */ unsigned int vm_pageout_inactive_clean = 0; /* debugging */ unsigned int vm_pageout_inactive_dirty = 0; /* debugging */ unsigned int vm_pageout_dirty_no_pager = 0; /* debugging */ -unsigned int vm_pageout_inactive_pinned = 0; /* debugging */ -unsigned int vm_pageout_inactive_limbo = 0; /* debugging */ -unsigned int vm_pageout_setup_limbo = 0; /* debugging */ -unsigned int vm_pageout_setup_unprepped = 0; /* debugging */ unsigned int vm_stat_discard = 0; /* debugging */ unsigned int vm_stat_discard_sent = 0; /* debugging */ unsigned int vm_stat_discard_failure = 0; /* debugging */ @@ -277,8 +277,6 @@ unsigned long vm_pageout_cluster_conversions = 0; unsigned long vm_pageout_target_collisions = 0; unsigned long vm_pageout_target_page_dirtied = 0; unsigned long vm_pageout_target_page_freed = 0; -unsigned long vm_pageout_target_page_pinned = 0; -unsigned long vm_pageout_target_page_limbo = 0; #define CLUSTER_STAT(clause) clause #else /* MACH_CLUSTER_STATS */ #define CLUSTER_STAT(clause) @@ -331,6 +329,12 @@ vm_pageout_object_terminate( if(m == VM_PAGE_NULL) continue; assert(m->cleaning); + /* used as a trigger on upl_commit etc to recognize the */ + /* pageout daemon's subseqent desire to pageout a cleaning */ + /* page. When the bit is on the upl commit code will */ + /* respect the pageout bit in the target page over the */ + /* caller's page list indication */ + m->dump_cleaning = FALSE; /* * Account for the paging reference taken when @@ -389,30 +393,6 @@ vm_pageout_object_terminate( vm_page_unwire(m);/* reactivates */ VM_STAT(reactivations++); PAGE_WAKEUP_DONE(m); - } else if (m->prep_pin_count != 0) { - vm_page_pin_lock(); - if (m->pin_count != 0) { - /* page is pinned; reactivate */ - CLUSTER_STAT( - vm_pageout_target_page_pinned++;) - vm_page_unwire(m);/* reactivates */ - VM_STAT(reactivations++); - PAGE_WAKEUP_DONE(m); - } else { - /* - * page is prepped but not pinned; send - * it into limbo. Note that - * vm_page_free (which will be called - * after releasing the pin lock) knows - * how to handle a page with limbo set. - */ - m->limbo = TRUE; - CLUSTER_STAT( - vm_pageout_target_page_limbo++;) - } - vm_page_pin_unlock(); - if (m->limbo) - vm_page_free(m); } else { CLUSTER_STAT(vm_pageout_target_page_freed++;) vm_page_free(m);/* clears busy, etc. */ @@ -426,8 +406,8 @@ vm_pageout_object_terminate( * If prep_pin_count is nonzero, then someone is using the * page, so make it active. */ - if (!m->active && !m->inactive) { - if (m->reference || m->prep_pin_count != 0) + if (!m->active && !m->inactive && !m->private) { + if (m->reference) vm_page_activate(m); else vm_page_deactivate(m); @@ -556,15 +536,9 @@ vm_pageout_setup( /* * Create a place-holder page where the old one was, to prevent * attempted pageins of this page while we're unlocked. - * If the pageout daemon put this page in limbo and we're not - * going to clean in place, get another fictitious page to - * exchange for it now. */ VM_PAGE_GRAB_FICTITIOUS(holding_page); - if (m->limbo) - VM_PAGE_GRAB_FICTITIOUS(new_page); - vm_object_lock(old_object); offset = m->offset; @@ -579,41 +553,11 @@ vm_pageout_setup( new_m = holding_page; holding_page = VM_PAGE_NULL; - /* - * If the pageout daemon put this page in limbo, exchange the - * identities of the limbo page and the new fictitious page, - * and continue with the new page, unless the prep count has - * gone to zero in the meantime (which means no one is - * interested in the page any more). In that case, just clear - * the limbo bit and free the extra fictitious page. - */ - if (m->limbo) { - if (m->prep_pin_count == 0) { - /* page doesn't have to be in limbo any more */ - m->limbo = FALSE; - vm_page_lock_queues(); - vm_page_free(new_page); - vm_page_unlock_queues(); - vm_pageout_setup_unprepped++; - } else { - vm_page_lock_queues(); - VM_PAGE_QUEUES_REMOVE(m); - vm_page_remove(m); - vm_page_limbo_exchange(m, new_page); - vm_pageout_setup_limbo++; - vm_page_release_limbo(m); - m = new_page; - vm_page_insert(m, old_object, offset); - vm_page_unlock_queues(); - } - } - /* * Set up new page to be private shadow of real page. */ new_m->phys_addr = m->phys_addr; new_m->fictitious = FALSE; - new_m->private = TRUE; new_m->pageout = TRUE; /* @@ -624,6 +568,7 @@ vm_pageout_setup( */ pmap_clear_modify(m->phys_addr); vm_page_lock_queues(); + new_m->private = TRUE; vm_page_wire(new_m); m->cleaning = TRUE; m->pageout = TRUE; @@ -647,28 +592,6 @@ vm_pageout_setup( VM_PAGE_QUEUES_REMOVE(m); vm_page_remove(m); - /* - * If the pageout daemon put this page in limbo, exchange the - * identities of the limbo page and the new fictitious page, - * and continue with the new page, unless the prep count has - * gone to zero in the meantime (which means no one is - * interested in the page any more). In that case, just clear - * the limbo bit and free the extra fictitious page. - */ - if (m->limbo) { - if (m->prep_pin_count == 0) { - /* page doesn't have to be in limbo any more */ - m->limbo = FALSE; - vm_page_free(new_page); - vm_pageout_setup_unprepped++; - } else { - vm_page_limbo_exchange(m, new_page); - vm_pageout_setup_limbo++; - vm_page_release_limbo(m); - m = new_page; - } - } - vm_page_insert(holding_page, old_object, offset); vm_page_unlock_queues(); @@ -890,10 +813,6 @@ vm_pageout_initialize_page( vm_page_unlock_queues(); vm_object_unlock(m->object); vm_pageout_throttle(m); - copy = NULL; - - VM_STAT(pageouts++); - /* VM_STAT(pages_pagedout++); */ /* * Write the data to its pager. @@ -904,9 +823,7 @@ vm_pageout_initialize_page( * to the eventual recipient.] */ memory_object_data_initialize(object->pager, - object->pager_request, paging_offset, - POINTER_T(copy), PAGE_SIZE); vm_object_lock(object); @@ -950,7 +867,6 @@ vm_pageout_cluster( vm_object_offset_t offset_within_cluster; vm_size_t length_of_data; vm_page_t friend, holding_page; - vm_map_copy_t copy; kern_return_t rc; boolean_t precious_clean = TRUE; int pages_in_cluster; @@ -1117,10 +1033,6 @@ vm_pageout_cluster( assert(rc == KERN_SUCCESS); pages_in_cluster = length_of_data/PAGE_SIZE; - if(m->dirty || m->object->internal) { - VM_STAT(pageouts++); - } - /* VM_STAT(pages_pagedout += pages_in_cluster); */ #if MACH_CLUSTER_STATS (cluster_stats[pages_at_lower_offsets].pages_at_lower_offsets)++; @@ -1132,34 +1044,13 @@ vm_pageout_cluster( * Send the data to the pager. */ paging_offset = cluster_start + object->paging_offset; -#ifdef MACH_BSD - if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == - ((rpc_subsystem_t) &vnode_pager_workaround)) { - rc = vnode_pager_data_return(object->pager, - object->pager_request, - paging_offset, - POINTER_T(copy), - length_of_data, - !precious_clean, - FALSE); - } else { - rc = memory_object_data_return(object->pager, - object->pager_request, - paging_offset, - POINTER_T(copy), - length_of_data, - !precious_clean, - FALSE); - } -#else + rc = memory_object_data_return(object->pager, - object->pager_request, paging_offset, - POINTER_T(copy), length_of_data, !precious_clean, FALSE); -#endif + vm_object_lock(object); vm_object_paging_end(object); @@ -1172,126 +1063,6 @@ vm_pageout_cluster( vm_object_unlock(object); } -/* - * vm_pageout_return_write_pages - * Recover pages from an aborted write attempt - * - */ - -vm_pageout_return_write_pages( - ipc_port_t control_port, - vm_object_offset_t object_offset, - vm_map_copy_t copy) -{ - vm_object_t object; - int offset; - int size; - int shadow_offset; - int copy_offset; - int j; - vm_page_t m; - - - object = copy->cpy_object; - copy_offset = copy->offset; - size = copy->size; - - if((copy->type != VM_MAP_COPY_OBJECT) || (object->shadow == 0)) { - object = (vm_object_t)control_port->ip_kobject; - shadow_offset = (object_offset - object->paging_offset) - - copy->offset; - } else { - /* get the offset from the copy object */ - shadow_offset = object->shadow_offset; - /* find the backing object */ - object = object->shadow; - } - vm_object_lock(object); - - for(offset = 0, j=0; offset < size; offset+=page_size, j++) { - m = vm_page_lookup(object, - offset + shadow_offset + copy_offset); - if((m == VM_PAGE_NULL) || m->fictitious) { - - vm_page_t p; - int i; - vm_object_t copy_object; - - /* m might be fictitious if the original page */ - /* was found to be in limbo at the time of */ - /* vm_pageout_setup */ - - if((m != VM_PAGE_NULL) && m->fictitious) { - m->cleaning = FALSE; - vm_page_remove(m); - /* if object is not pager trusted then */ - /* this fictitious page will be removed */ - /* as the holding page in vm_pageout_cluster */ - if (object->pager_trusted) - vm_page_free(m); - if(vm_page_laundry_count) - vm_page_laundry_count--; - if (vm_page_laundry_count - < vm_page_laundry_min) { - vm_page_laundry_min = 0; - thread_wakeup((event_t) - &vm_page_laundry_count); - } - } - else if ((object->pager_trusted) && - (copy->type == VM_MAP_COPY_OBJECT)) { - vm_object_paging_end(object); - } - - copy_object = copy->cpy_object; - - if(copy->type == VM_MAP_COPY_OBJECT) { - p = (vm_page_t) queue_first(©_object->memq); - - for(i = 0; - i < copy_object->resident_page_count; - i++) { - if(p->offset == (offset + copy_offset)) - break; - p = (vm_page_t) queue_next(&p->listq); - } - - vm_page_remove(p); - } else { - p = copy->cpy_page_list[j]; - copy->cpy_page_list[j] = 0; - p->gobbled = FALSE; - } - - vm_page_insert(p, object, - offset + shadow_offset + copy_offset); - p->busy = TRUE; - p->dirty = TRUE; - p->laundry = FALSE; - if (p->pageout) { - p->pageout = FALSE; /*dont throw away target*/ - vm_page_unwire(p);/* reactivates */ - } - } else if(m->pageout) { - m->pageout = FALSE; /* dont throw away target pages */ - vm_page_unwire(m);/* reactivates */ - } - } - - vm_object_unlock(object); - vm_map_copy_discard(copy); - vm_object_lock(object); - - for(offset = 0; offset < size; offset+=page_size) { - m = vm_page_lookup(object, - offset + shadow_offset + copy_offset); - m->dirty = TRUE; /* we'll send the pages home later */ - m->busy = FALSE; /* allow system access again */ - } - - vm_object_unlock(object); -} - /* * Trusted pager throttle. * Object must be unlocked, page queues must be unlocked. @@ -1309,6 +1080,7 @@ vm_pageout_throttle( * should wake us up. */ vm_page_laundry_min = vm_page_laundry_max/2; + assert_wait((event_t) &vm_page_laundry_count, THREAD_UNINT); vm_page_unlock_queues(); @@ -1357,7 +1129,6 @@ vm_pageout_cluster_page( return(VM_PAGE_NULL); if (m->busy || m->absent || m->cleaning || - m->prep_pin_count != 0 || (m->wire_count != 0) || m->error) return(VM_PAGE_NULL); @@ -1433,19 +1204,20 @@ vm_pageout_scan(void) * might return memory to zones. */ + Restart: +#if THREAD_SWAPPER mutex_lock(&vm_page_queue_free_lock); now = (vm_page_free_count < vm_page_free_min); mutex_unlock(&vm_page_queue_free_lock); -#if THREAD_SWAPPER + swapout_threads(now); #endif /* THREAD_SWAPPER */ stack_collect(); consider_task_collect(); consider_thread_collect(); - cleanup_limbo_queue(); consider_zone_gc(); consider_machine_collect(); @@ -1463,7 +1235,6 @@ vm_pageout_scan(void) for (burst_count = 0;;) { register vm_page_t m; register vm_object_t object; - unsigned int free_count; /* * Recalculate vm_page_inactivate_target. @@ -1540,6 +1311,7 @@ vm_pageout_scan(void) queue_enter(&vm_page_queue_active, m, vm_page_t, pageq); vm_page_unlock_queues(); + mutex_pause(); vm_page_lock_queues(); continue; @@ -1578,16 +1350,15 @@ vm_pageout_scan(void) * We are done if we have met our target *and* * nobody is still waiting for a page. */ - - mutex_lock(&vm_page_queue_free_lock); - free_count = vm_page_free_count; - if ((free_count >= vm_page_free_target) && - (vm_page_free_wanted == 0)) { - vm_page_unlock_queues(); - break; + if (vm_page_free_count >= vm_page_free_target) { + mutex_lock(&vm_page_queue_free_lock); + if ((vm_page_free_count >= vm_page_free_target) && + (vm_page_free_wanted == 0)) { + vm_page_unlock_queues(); + break; + } + mutex_unlock(&vm_page_queue_free_lock); } - mutex_unlock(&vm_page_queue_free_lock); - /* * Sometimes we have to pause: * 1) No inactive pages - nothing to do. @@ -1620,6 +1391,7 @@ vm_pageout_scan(void) (msecs < vm_pageout_empty_wait)) msecs = vm_pageout_empty_wait; vm_page_unlock_queues(); + assert_wait_timeout(msecs, THREAD_INTERRUPTIBLE); counter(c_vm_pageout_scan_block++); @@ -1631,6 +1403,7 @@ vm_pageout_scan(void) if (wait_result != THREAD_TIMED_OUT) thread_cancel_timer(); vm_pageout_scan_continue(); + goto Restart; /*NOTREACHED*/ } @@ -1694,12 +1467,14 @@ vm_pageout_scan(void) if (!vm_object_lock_try(object)) { /* * Move page to end and continue. + * Don't re-issue ticket */ queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq); queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); vm_page_unlock_queues(); + mutex_pause(); vm_pageout_inactive_nolock++; continue; @@ -1724,6 +1499,10 @@ vm_pageout_scan(void) * there will be enough other inactive pages to * page out so that the thread which currently * initializes the pager will succeed. + * Don't re-grant the ticket, the page should + * pulled from the queue and paged out whenever + * one of its logically adjacent fellows is + * targeted. */ queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq); @@ -1783,11 +1562,10 @@ vm_pageout_scan(void) #if MACH_CLUSTER_STATS vm_pageout_cluster_conversions++; #endif - if (m->prep_pin_count == 0) { - m->busy = TRUE; - m->pageout = TRUE; - vm_page_wire(m); - } + m->busy = TRUE; + m->pageout = TRUE; + m->dump_cleaning = TRUE; + vm_page_wire(m); vm_object_unlock(object); vm_page_unlock_queues(); continue; @@ -1813,28 +1591,10 @@ vm_pageout_scan(void) continue; } - if (m->prep_pin_count != 0) { - boolean_t pinned = FALSE; - - vm_page_pin_lock(); - if (m->pin_count != 0) { - /* skip and reactivate pinned page */ - pinned = TRUE; - vm_pageout_inactive_pinned++; - } else { - /* page is prepped; send it into limbo */ - m->limbo = TRUE; - vm_pageout_inactive_limbo++; - } - vm_page_pin_unlock(); - if (pinned) - goto reactivate_page; - } - #if ADVISORY_PAGEOUT if (object->advisory_pageout) { boolean_t do_throttle; - ipc_port_t port; + memory_object_t pager; vm_object_offset_t discard_offset; if (m->discard_request) { @@ -1844,11 +1604,17 @@ vm_pageout_scan(void) assert(object->pager_initialized); m->discard_request = TRUE; - port = object->pager; + pager = object->pager; /* system-wide throttle */ do_throttle = (vm_page_free_count <= vm_page_free_reserved); + +#if 0 + /* + * JMM - Do we need a replacement throttle + * mechanism for pagers? + */ if (!do_throttle) { /* throttle on this pager */ /* XXX lock ordering ? */ @@ -1856,6 +1622,8 @@ vm_pageout_scan(void) do_throttle= imq_full(&port->ip_messages); ip_unlock(port); } +#endif + if (do_throttle) { vm_stat_discard_throttle++; #if 0 @@ -1877,9 +1645,9 @@ vm_pageout_scan(void) vm_stat_discard_sent++; vm_page_unlock_queues(); vm_object_unlock(object); + /* memory_object_discard_request(object->pager, - object->pager_request, discard_offset, PAGE_SIZE); */ @@ -1898,9 +1666,9 @@ vm_pageout_scan(void) m->busy = TRUE; pmap_page_protect(m->phys_addr, VM_PROT_NONE); + if (!m->dirty) m->dirty = pmap_is_modified(m->phys_addr); - /* * If it's clean and not precious, we can free the page. */ @@ -1952,7 +1720,8 @@ vm_pageout_scan(void) continue; } - if (object->pager_initialized && object->pager == IP_NULL) { + if ((object->pager_initialized) && + (object->pager == MEMORY_OBJECT_NULL)) { /* * This pager has been destroyed by either * memory_object_destroy or vm_object_destroy, and @@ -2036,13 +1805,22 @@ void vm_pageout(void) { thread_t self = current_thread(); + spl_t s; /* * Set thread privileges. */ self->vm_privilege = TRUE; stack_privilege(self); - thread_swappable(current_act(), FALSE); + + s = splsched(); + thread_lock(self); + + self->priority = BASEPRI_PREEMPT - 1; + self->sched_pri = self->priority; + + thread_unlock(self); + splx(s); /* * Initialize some paging parameters. @@ -2083,6 +1861,7 @@ vm_pageout(void) * vm_page_inactive_target. */ for (;;) { + vm_pageout_scan_event_counter++; vm_pageout_scan(); /* we hold vm_page_queue_free_lock now */ assert(vm_page_free_wanted == 0); @@ -2095,8 +1874,67 @@ vm_pageout(void) } -void -upl_dealloc( +static upl_t +upl_create( + boolean_t internal) +{ + upl_t upl; + + if(internal) { + upl = (upl_t)kalloc(sizeof(struct upl) + + (sizeof(struct upl_page_info)*MAX_UPL_TRANSFER)); + } else { + upl = (upl_t)kalloc(sizeof(struct upl)); + } + upl->flags = 0; + upl->src_object = NULL; + upl->kaddr = (vm_offset_t)0; + upl->size = 0; + upl->map_object = NULL; + upl->ref_count = 1; + upl_lock_init(upl); +#ifdef UBC_DEBUG + upl->ubc_alias1 = 0; + upl->ubc_alias2 = 0; +#endif /* UBC_DEBUG */ + return(upl); +} + +static void +upl_destroy( + upl_t upl) +{ + +#ifdef UBC_DEBUG + { + upl_t upl_ele; + vm_object_lock(upl->map_object->shadow); + queue_iterate(&upl->map_object->shadow->uplq, + upl_ele, upl_t, uplq) { + if(upl_ele == upl) { + queue_remove(&upl->map_object->shadow->uplq, + upl_ele, upl_t, uplq); + break; + } + } + vm_object_unlock(upl->map_object->shadow); + } +#endif /* UBC_DEBUG */ +#ifdef notdefcdy + if(!(upl->flags & UPL_DEVICE_MEMORY)) +#endif + vm_object_deallocate(upl->map_object); + if(upl->flags & UPL_INTERNAL) { + kfree((vm_offset_t)upl, + sizeof(struct upl) + + (sizeof(struct upl_page_info) * MAX_UPL_TRANSFER)); + } else { + kfree((vm_offset_t)upl, sizeof(struct upl)); + } +} + +__private_extern__ void +uc_upl_dealloc( upl_t upl) { upl->ref_count -= 1; @@ -2105,9 +1943,19 @@ upl_dealloc( } } +void +upl_deallocate( + upl_t upl) +{ + + upl->ref_count -= 1; + if(upl->ref_count == 0) { + upl_destroy(upl); + } +} /* - * Routine: vm_fault_list_request + * Routine: vm_object_upl_request * Purpose: * Cause the population of a portion of a vm_object. * Depending on the nature of the request, the pages @@ -2149,19 +1997,18 @@ upl_dealloc( * the vm_objects (cache objects), they support. * */ -kern_return_t -vm_fault_list_request( +__private_extern__ kern_return_t +vm_object_upl_request( vm_object_t object, - vm_object_offset_t offset, - vm_size_t size, + vm_object_offset_t offset, + vm_size_t size, upl_t *upl_ptr, - upl_page_info_t **user_page_list_ptr, - int page_list_count, - int cntrl_flags) + upl_page_info_array_t user_page_list, + unsigned int *page_list_count, + int cntrl_flags) { vm_page_t dst_page; vm_object_offset_t dst_offset = offset; - upl_page_info_t *user_page_list; vm_size_t xfer_size = size; boolean_t do_m_lock = FALSE; boolean_t dirty; @@ -2170,47 +2017,62 @@ vm_fault_list_request( boolean_t encountered_lrp = FALSE; vm_page_t alias_page = NULL; + int page_ticket; + + + page_ticket = (cntrl_flags & UPL_PAGE_TICKET_MASK) + >> UPL_PAGE_TICKET_SHIFT; + + if(((size/page_size) > MAX_UPL_TRANSFER) && !object->phys_contiguous) { + size = MAX_UPL_TRANSFER * page_size; + } if(cntrl_flags & UPL_SET_INTERNAL) - page_list_count = MAX_UPL_TRANSFER; - if(((user_page_list_ptr || (cntrl_flags & UPL_SET_INTERNAL)) && - !(object->private)) && (page_list_count < (size/page_size))) + if(page_list_count != NULL) + *page_list_count = MAX_UPL_TRANSFER; + if(((cntrl_flags & UPL_SET_INTERNAL) && !(object->phys_contiguous)) && + ((page_list_count != NULL) && (*page_list_count != 0) + && *page_list_count < (size/page_size))) return KERN_INVALID_ARGUMENT; if((!object->internal) && (object->paging_offset != 0)) - panic("vm_fault_list_request: vnode object with non-zero paging offset\n"); + panic("vm_object_upl_request: vnode object with non-zero paging offset\n"); if((cntrl_flags & UPL_COPYOUT_FROM) && (upl_ptr == NULL)) { return KERN_SUCCESS; } if(upl_ptr) { - if((cntrl_flags & UPL_SET_INTERNAL) && !(object->private)) { + if(cntrl_flags & UPL_SET_INTERNAL) { upl = upl_create(TRUE); user_page_list = (upl_page_info_t *) (((vm_offset_t)upl) + sizeof(struct upl)); - if(user_page_list_ptr) - *user_page_list_ptr = user_page_list; upl->flags |= UPL_INTERNAL; } else { upl = upl_create(FALSE); - if(user_page_list_ptr) - user_page_list = *user_page_list_ptr; - else - user_page_list = NULL; - if(object->private) { - upl->size = size; - upl->offset = offset; - *upl_ptr = upl; - if(user_page_list) { - user_page_list[0].phys_addr = offset; - user_page_list[0].device = TRUE; - } - upl->flags = UPL_DEVICE_MEMORY; - return KERN_SUCCESS; + } + if(object->phys_contiguous) { + upl->size = size; + upl->offset = offset + object->paging_offset; + *upl_ptr = upl; + if(user_page_list) { + user_page_list[0].phys_addr = + offset + object->shadow_offset; + user_page_list[0].device = TRUE; } + upl->map_object = vm_object_allocate(size); + vm_object_lock(upl->map_object); + upl->map_object->shadow = object; + upl->flags = UPL_DEVICE_MEMORY | UPL_INTERNAL; + upl->map_object->pageout = TRUE; + upl->map_object->can_persist = FALSE; + upl->map_object->copy_strategy + = MEMORY_OBJECT_COPY_NONE; + upl->map_object->shadow_offset = offset; + vm_object_unlock(upl->map_object); + return KERN_SUCCESS; + } - } upl->map_object = vm_object_allocate(size); vm_object_lock(upl->map_object); upl->map_object->shadow = object; @@ -2248,7 +2110,14 @@ vm_fault_list_request( !dst_page->pageout) || ((!(dst_page->dirty || dst_page->precious || pmap_is_modified(dst_page->phys_addr))) - && (cntrl_flags & UPL_RET_ONLY_DIRTY))) { + && (cntrl_flags & UPL_RET_ONLY_DIRTY)) || + ((!(dst_page->inactive)) + && (dst_page->page_ticket != page_ticket) + && ((dst_page->page_ticket+1) != page_ticket) + && (cntrl_flags & UPL_PAGEOUT)) || + ((!dst_page->list_req_pending) && + (cntrl_flags & UPL_RET_ONLY_DIRTY) && + pmap_is_referenced(dst_page->phys_addr))) { if(user_page_list) user_page_list[entry].phys_addr = 0; } else { @@ -2276,7 +2145,6 @@ vm_fault_list_request( } /* Someone else already cleaning the page? */ if((dst_page->cleaning || dst_page->absent || - dst_page->prep_pin_count != 0 || dst_page->wire_count != 0) && !dst_page->list_req_pending) { if(user_page_list) @@ -2338,7 +2206,8 @@ vm_fault_list_request( alias_page->absent = FALSE; alias_page = NULL; - if(!(cntrl_flags & UPL_CLEAN_IN_PLACE)) { + if((!(cntrl_flags & UPL_CLEAN_IN_PLACE)) + || (cntrl_flags & UPL_PAGEOUT)) { /* deny access to the target page */ /* while it is being worked on */ if((!dst_page->pageout) && @@ -2376,41 +2245,59 @@ vm_fault_list_request( } dst_page = vm_page_lookup(object, dst_offset); if(dst_page != VM_PAGE_NULL) { - if((dst_page->cleaning) && - !(dst_page->list_req_pending)) { - /*someone else is writing to the */ - /* page. We will have to wait. */ - PAGE_ASSERT_WAIT(dst_page, THREAD_UNINT); - vm_object_unlock(object); - thread_block((void(*)(void))0); - vm_object_lock(object); - continue; - } - if ((dst_page->fictitious && - dst_page->list_req_pending)) { - /* dump the fictitious page */ - dst_page->list_req_pending = FALSE; - dst_page->clustered = FALSE; - vm_page_lock_queues(); - vm_page_free(dst_page); - vm_page_unlock_queues(); - } else if ((dst_page->absent && - dst_page->list_req_pending)) { - /* the default_pager case */ - dst_page->list_req_pending = FALSE; - dst_page->busy = FALSE; - dst_page->clustered = FALSE; - } + if((dst_page->cleaning) && + !(dst_page->list_req_pending)) { + /*someone else is writing to the */ + /* page. We will have to wait. */ + PAGE_ASSERT_WAIT(dst_page,THREAD_UNINT); + vm_object_unlock(object); + thread_block((void(*)(void))0); + vm_object_lock(object); + continue; + } + if ((dst_page->fictitious && + dst_page->list_req_pending)) { + /* dump the fictitious page */ + dst_page->list_req_pending = FALSE; + dst_page->clustered = FALSE; + vm_page_lock_queues(); + vm_page_free(dst_page); + vm_page_unlock_queues(); + } else if ((dst_page->absent && + dst_page->list_req_pending)) { + /* the default_pager case */ + dst_page->list_req_pending = FALSE; + dst_page->busy = FALSE; + dst_page->clustered = FALSE; + } } - if((dst_page = vm_page_lookup( - object, dst_offset)) == VM_PAGE_NULL) { + if((dst_page = vm_page_lookup(object, dst_offset)) == + VM_PAGE_NULL) { + if(object->private) { + /* + * This is a nasty wrinkle for users + * of upl who encounter device or + * private memory however, it is + * unavoidable, only a fault can + * reslove the actual backing + * physical page by asking the + * backing device. + */ + if(user_page_list) + user_page_list[entry] + .phys_addr = 0; + entry++; + dst_offset += PAGE_SIZE_64; + xfer_size -= PAGE_SIZE; + continue; + } /* need to allocate a page */ dst_page = vm_page_alloc(object, dst_offset); if (dst_page == VM_PAGE_NULL) { - vm_object_unlock(object); - VM_PAGE_WAIT(); - vm_object_lock(object); - continue; + vm_object_unlock(object); + VM_PAGE_WAIT(); + vm_object_lock(object); + continue; } dst_page->busy = FALSE; #if 0 @@ -2494,7 +2381,7 @@ vm_fault_list_request( user_page_list[entry].phys_addr = dst_page->phys_addr; user_page_list[entry].dirty = - dst_page->dirty; + dst_page->dirty; user_page_list[entry].pageout = dst_page->pageout; user_page_list[entry].absent = @@ -2509,11 +2396,21 @@ vm_fault_list_request( xfer_size -= PAGE_SIZE; } } + + if (upl->flags & UPL_INTERNAL) { + if(page_list_count != NULL) + *page_list_count = 0; + } else if (*page_list_count > entry) { + if(page_list_count != NULL) + *page_list_count = entry; + } + if(alias_page != NULL) { vm_page_lock_queues(); vm_page_free(alias_page); vm_page_unlock_queues(); } + if(do_m_lock) { vm_prot_t access_required; /* call back all associated pages from other users of the pager */ @@ -2544,7 +2441,6 @@ vm_fault_list_request( if (rc = memory_object_data_unlock( object->pager, - object->pager_request, dst_offset + object->paging_offset, size, access_required)) { @@ -2569,21 +2465,88 @@ vm_fault_list_request( return KERN_SUCCESS; } - +/* JMM - Backward compatability for now */ kern_return_t -upl_system_list_request( - vm_object_t object, +vm_fault_list_request( + memory_object_control_t control, vm_object_offset_t offset, vm_size_t size, - vm_size_t super_cluster, - upl_t *upl, + upl_t *upl_ptr, upl_page_info_t **user_page_list_ptr, int page_list_count, int cntrl_flags) { + int local_list_count; + upl_page_info_t *user_page_list; + kern_return_t kr; + + if (user_page_list_ptr != NULL) { + local_list_count = page_list_count; + user_page_list = *user_page_list_ptr; + } else { + local_list_count = 0; + user_page_list = NULL; + } + kr = memory_object_upl_request(control, + offset, + size, + upl_ptr, + user_page_list, + &local_list_count, + cntrl_flags); + + if(kr != KERN_SUCCESS) + return kr; + + if ((user_page_list_ptr != NULL) && (cntrl_flags & UPL_INTERNAL)) { + *user_page_list_ptr = UPL_GET_INTERNAL_PAGE_LIST(*upl_ptr); + } + + return KERN_SUCCESS; +} + + + +/* + * Routine: vm_object_super_upl_request + * Purpose: + * Cause the population of a portion of a vm_object + * in much the same way as memory_object_upl_request. + * Depending on the nature of the request, the pages + * returned may be contain valid data or be uninitialized. + * However, the region may be expanded up to the super + * cluster size provided. + */ + +__private_extern__ kern_return_t +vm_object_super_upl_request( + vm_object_t object, + vm_object_offset_t offset, + vm_size_t size, + vm_size_t super_cluster, + upl_t *upl, + upl_page_info_t *user_page_list, + unsigned int *page_list_count, + int cntrl_flags) +{ + vm_page_t target_page; + int ticket; + if(object->paging_offset > offset) return KERN_FAILURE; + offset = offset - object->paging_offset; + if(cntrl_flags & UPL_PAGEOUT) { + if((target_page = vm_page_lookup(object, offset)) + != VM_PAGE_NULL) { + ticket = target_page->page_ticket; + cntrl_flags = cntrl_flags & ~(int)UPL_PAGE_TICKET_MASK; + cntrl_flags = cntrl_flags | + ((ticket << UPL_PAGE_TICKET_SHIFT) + & UPL_PAGE_TICKET_MASK); + } + } + /* turns off super cluster exercised by the default_pager */ /* @@ -2602,7 +2565,7 @@ super_cluster = size; super_size = ((base_offset + super_size) > object->size) ? (object->size - base_offset) : super_size; if(offset > (base_offset + super_size)) - panic("upl_system_list_request: Missed target pageout 0x%x,0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", offset, base_offset, super_size, super_cluster, size, object->paging_offset); + panic("vm_object_super_upl_request: Missed target pageout 0x%x,0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", offset, base_offset, super_size, super_cluster, size, object->paging_offset); /* apparently there is a case where the vm requests a */ /* page to be written out who's offset is beyond the */ /* object size */ @@ -2612,13 +2575,14 @@ super_cluster = size; offset = base_offset; size = super_size; } - vm_fault_list_request(object, offset, size, upl, user_page_list_ptr, - page_list_count, cntrl_flags); + vm_object_upl_request(object, offset, size, + upl, user_page_list, page_list_count, + cntrl_flags); } kern_return_t -uc_upl_map( +vm_upl_map( vm_map_t map, upl_t upl, vm_offset_t *dst_addr) @@ -2629,9 +2593,16 @@ uc_upl_map( vm_page_t m; kern_return_t kr; + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + upl_lock(upl); + /* check to see if already mapped */ - if(UPL_PAGE_LIST_MAPPED & upl->flags) + if(UPL_PAGE_LIST_MAPPED & upl->flags) { + upl_unlock(upl); return KERN_FAILURE; + } offset = 0; /* Always map the entire object */ size = upl->size; @@ -2649,8 +2620,10 @@ uc_upl_map( upl->map_object, offset, FALSE, VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT); - if (kr != KERN_SUCCESS) + if (kr != KERN_SUCCESS) { + upl_unlock(upl); return(kr); + } for(addr=*dst_addr; size > 0; size-=PAGE_SIZE,addr+=PAGE_SIZE) { m = vm_page_lookup(upl->map_object, offset); @@ -2659,38 +2632,51 @@ uc_upl_map( } offset+=PAGE_SIZE_64; } - + upl->ref_count++; /* hold a reference for the mapping */ upl->flags |= UPL_PAGE_LIST_MAPPED; upl->kaddr = *dst_addr; + upl_unlock(upl); return KERN_SUCCESS; } kern_return_t -uc_upl_un_map( +vm_upl_unmap( vm_map_t map, upl_t upl) { + vm_address_t addr; vm_size_t size; + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + upl_lock(upl); if(upl->flags & UPL_PAGE_LIST_MAPPED) { + addr = upl->kaddr; size = upl->size; - vm_deallocate(map, upl->kaddr, size); + assert(upl->ref_count > 1); + upl->ref_count--; /* removing mapping ref */ upl->flags &= ~UPL_PAGE_LIST_MAPPED; upl->kaddr = (vm_offset_t) 0; + upl_unlock(upl); + + vm_deallocate(map, addr, size); return KERN_SUCCESS; - } else { - return KERN_FAILURE; } + upl_unlock(upl); + return KERN_FAILURE; } kern_return_t -uc_upl_commit_range( +upl_commit_range( upl_t upl, vm_offset_t offset, vm_size_t size, int flags, - upl_page_info_t *page_list) + upl_page_info_t *page_list, + mach_msg_type_number_t count, + boolean_t *empty) { vm_size_t xfer_size = size; vm_object_t shadow_object = upl->map_object->shadow; @@ -2699,9 +2685,19 @@ uc_upl_commit_range( vm_object_offset_t page_offset; int entry; + *empty = FALSE; + + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + if (count == 0) + page_list = NULL; + + upl_lock(upl); if(upl->flags & UPL_DEVICE_MEMORY) { xfer_size = 0; } else if ((offset + size) > upl->size) { + upl_unlock(upl); return KERN_FAILURE; } @@ -2736,7 +2732,8 @@ uc_upl_commit_range( m->pageout = TRUE; vm_page_wire(m); } else if (page_list[entry].phys_addr && - !p->pageout && m->pageout) { + !p->pageout && m->pageout && + !m->dump_cleaning) { m->pageout = FALSE; m->absent = FALSE; m->overwriting = FALSE; @@ -2745,6 +2742,7 @@ uc_upl_commit_range( } page_list[entry].phys_addr = 0; } + m->dump_cleaning = FALSE; if(m->laundry) { vm_page_laundry_count--; m->laundry = FALSE; @@ -2768,48 +2766,24 @@ uc_upl_commit_range( vm_page_unwire(m);/* reactivates */ VM_STAT(reactivations++); PAGE_WAKEUP_DONE(m); - } else if (m->prep_pin_count != 0) { - vm_page_pin_lock(); - if (m->pin_count != 0) { - /* page is pinned; reactivate */ - CLUSTER_STAT( - vm_pageout_target_page_pinned++;) - vm_page_unwire(m);/* reactivates */ - VM_STAT(reactivations++); - PAGE_WAKEUP_DONE(m); - } else { - /* - * page is prepped but not pinned; - * send it into limbo. Note that - * vm_page_free (which will be - * called after releasing the pin - * lock) knows how to handle a page - * with limbo set. - */ - m->limbo = TRUE; - CLUSTER_STAT( - vm_pageout_target_page_limbo++;) - } - vm_page_pin_unlock(); - if (m->limbo) - vm_page_free(m); - } else { + } else { CLUSTER_STAT( vm_pageout_target_page_freed++;) vm_page_free(m);/* clears busy, etc. */ + VM_STAT(pageouts++); } vm_page_unlock_queues(); target_offset += PAGE_SIZE_64; xfer_size -= PAGE_SIZE; entry++; continue; - } + } if (flags & UPL_COMMIT_INACTIVATE) { vm_page_deactivate(m); m->reference = FALSE; pmap_clear_reference(m->phys_addr); } else if (!m->active && !m->inactive) { - if (m->reference || m->prep_pin_count != 0) + if (m->reference) vm_page_activate(m); else vm_page_deactivate(m); @@ -2872,20 +2846,23 @@ uc_upl_commit_range( } vm_object_unlock(shadow_object); - if(flags & UPL_COMMIT_FREE_ON_EMPTY) { + if(flags & UPL_COMMIT_NOTIFY_EMPTY) { if((upl->flags & UPL_DEVICE_MEMORY) - || (queue_empty(&upl->map_object->memq))) { - upl_dealloc(upl); - } + || (queue_empty(&upl->map_object->memq))) + *empty = TRUE; } + upl_unlock(upl); + return KERN_SUCCESS; } -uc_upl_abort_range( +kern_return_t +upl_abort_range( upl_t upl, vm_offset_t offset, vm_size_t size, - int error) + int error, + boolean_t *empty) { vm_size_t xfer_size = size; vm_object_t shadow_object = upl->map_object->shadow; @@ -2894,13 +2871,19 @@ uc_upl_abort_range( vm_object_offset_t page_offset; int entry; + *empty = FALSE; + + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + upl_lock(upl); if(upl->flags & UPL_DEVICE_MEMORY) { xfer_size = 0; } else if ((offset + size) > upl->size) { + upl_unlock(upl); return KERN_FAILURE; } - vm_object_lock(shadow_object); entry = offset/PAGE_SIZE; @@ -2981,6 +2964,7 @@ uc_upl_abort_range( m->pageout = FALSE; vm_page_unwire(m); } + m->dump_cleaning = FALSE; m->cleaning = FALSE; m->busy = FALSE; m->overwriting = FALSE; @@ -3002,17 +2986,17 @@ uc_upl_abort_range( entry++; } vm_object_unlock(shadow_object); - if(error & UPL_ABORT_FREE_ON_EMPTY) { + if(error & UPL_ABORT_NOTIFY_EMPTY) { if((upl->flags & UPL_DEVICE_MEMORY) - || (queue_empty(&upl->map_object->memq))) { - upl_dealloc(upl); - } + || (queue_empty(&upl->map_object->memq))) + *empty = TRUE; } + upl_unlock(upl); return KERN_SUCCESS; } kern_return_t -uc_upl_abort( +upl_abort( upl_t upl, int error) { @@ -3024,14 +3008,20 @@ uc_upl_abort( int i; vm_page_t t,m; + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + upl_lock(upl); if(upl->flags & UPL_DEVICE_MEMORY) { - upl_dealloc(upl); + upl_unlock(upl); return KERN_SUCCESS; } + object = upl->map_object; - if(object == NULL) { + if (object == NULL) { panic("upl_abort: upl object is not backed by an object"); + upl_unlock(upl); return KERN_INVALID_ARGUMENT; } @@ -3101,6 +3091,7 @@ uc_upl_abort( m->pageout = FALSE; vm_page_unwire(m); } + m->dump_cleaning = FALSE; m->cleaning = FALSE; m->busy = FALSE; m->overwriting = FALSE; @@ -3133,16 +3124,24 @@ uc_upl_abort( VM_PAGE_FREE(p); } - upl_dealloc(upl); + upl_unlock(upl); return KERN_SUCCESS; } /* an option on commit should be wire */ kern_return_t -uc_upl_commit( - upl_t upl, - upl_page_info_t *page_list) +upl_commit( + upl_t upl, + upl_page_info_t *page_list, + mach_msg_type_number_t count) { + if (upl == UPL_NULL) + return KERN_INVALID_ARGUMENT; + + if (count == 0) + page_list = NULL; + + upl_lock(upl); if (upl->flags & UPL_DEVICE_MEMORY) page_list = NULL; if ((upl->flags & UPL_CLEAR_DIRTY) || @@ -3221,7 +3220,8 @@ uc_upl_commit( vm_page_wire(m); vm_page_unlock_queues(); } else if (page_list[entry].phys_addr && - !p->pageout && m->pageout) { + !p->pageout && m->pageout && + !m->dump_cleaning) { vm_page_lock_queues(); m->pageout = FALSE; m->absent = FALSE; @@ -3238,67 +3238,10 @@ uc_upl_commit( vm_object_unlock(shadow_object); } - upl_dealloc(upl); + upl_unlock(upl); return KERN_SUCCESS; } -upl_t -upl_create( - boolean_t internal) -{ - upl_t upl; - - if(internal) { - upl = (upl_t)kalloc(sizeof(struct upl) - + (sizeof(struct upl_page_info)*MAX_UPL_TRANSFER)); - } else { - upl = (upl_t)kalloc(sizeof(struct upl)); - } - upl->flags = 0; - upl->src_object = NULL; - upl->kaddr = (vm_offset_t)0; - upl->size = 0; - upl->map_object = NULL; - upl->ref_count = 1; - upl_lock_init(upl); -#ifdef UBC_DEBUG - upl->ubc_alias1 = 0; - upl->ubc_alias2 = 0; -#endif /* UBC_DEBUG */ - return(upl); -} - -void -upl_destroy( - upl_t upl) -{ - -#ifdef UBC_DEBUG - { - upl_t upl_ele; - vm_object_lock(upl->map_object->shadow); - queue_iterate(&upl->map_object->shadow->uplq, - upl_ele, upl_t, uplq) { - if(upl_ele == upl) { - queue_remove(&upl->map_object->shadow->uplq, - upl_ele, upl_t, uplq); - break; - } - } - vm_object_unlock(upl->map_object->shadow); - } -#endif /* UBC_DEBUG */ - if(!(upl->flags & UPL_DEVICE_MEMORY)) - vm_object_deallocate(upl->map_object); - if(upl->flags & UPL_INTERNAL) { - kfree((vm_offset_t)upl, - sizeof(struct upl) + - (sizeof(struct upl_page_info) * MAX_UPL_TRANSFER)); - } else { - kfree((vm_offset_t)upl, sizeof(struct upl)); - } -} - vm_size_t upl_get_internal_pagelist_offset() { @@ -3321,10 +3264,6 @@ upl_clear_dirty( #ifdef MACH_BSD -boolean_t upl_page_present(upl_page_info_t *upl, int index); -boolean_t upl_dirty_page(upl_page_info_t *upl, int index); -boolean_t upl_valid_page(upl_page_info_t *upl, int index); -vm_offset_t upl_phys_page(upl_page_info_t *upl, int index); boolean_t upl_page_present(upl_page_info_t *upl, int index) { @@ -3343,7 +3282,8 @@ vm_offset_t upl_phys_page(upl_page_info_t *upl, int index) return((vm_offset_t)UPL_PHYS_PAGE(upl, index)); } -void vm_countdirtypages(void) +void +vm_countdirtypages(void) { vm_page_t m; int dpages; @@ -3428,8 +3368,6 @@ void db_vm(void) { extern int vm_page_gobble_count; - extern int vm_page_limbo_count, vm_page_limbo_real_count; - extern int vm_page_pin_count; iprintf("VM Statistics:\n"); db_indent += 2; @@ -3440,9 +3378,8 @@ db_vm(void) vm_page_free_count); printf(" wire %5d gobbl %5d\n", vm_page_wire_count, vm_page_gobble_count); - iprintf("laund %5d limbo %5d lim_r %5d pin %5d\n", - vm_page_laundry_count, vm_page_limbo_count, - vm_page_limbo_real_count, vm_page_pin_count); + iprintf("laund %5d\n", + vm_page_laundry_count); db_indent -= 2; iprintf("target:\n"); db_indent += 2; @@ -3473,8 +3410,6 @@ db_vm(void) void db_pageout(void) { - extern int c_limbo_page_free; - extern int c_limbo_convert; #if MACH_COUNTERS extern int c_laundry_pages_freed; #endif /* MACH_COUNTERS */ @@ -3489,11 +3424,6 @@ db_pageout(void) iprintf("used %5d clean %5d dirty %5d\n", vm_pageout_inactive_used, vm_pageout_inactive_clean, vm_pageout_inactive_dirty); - iprintf("pinned %5d limbo %5d setup_limbo %5d setup_unprep %5d\n", - vm_pageout_inactive_pinned, vm_pageout_inactive_limbo, - vm_pageout_setup_limbo, vm_pageout_setup_unprepped); - iprintf("limbo_page_free %5d limbo_convert %5d\n", - c_limbo_page_free, c_limbo_convert); #if MACH_COUNTERS iprintf("laundry_pages_freed %d\n", c_laundry_pages_freed); #endif /* MACH_COUNTERS */ @@ -3511,8 +3441,6 @@ db_pageout(void) iprintf("collisions %5d page_dirtied %5d page_freed %5d\n", vm_pageout_target_collisions, vm_pageout_target_page_dirtied, vm_pageout_target_page_freed); - iprintf("page_pinned %5d page_limbo %5d\n", - vm_pageout_target_page_pinned, vm_pageout_target_page_limbo); db_indent -= 2; #endif /* MACH_CLUSTER_STATS */ db_indent -= 2; @@ -3527,8 +3455,6 @@ unsigned long vm_pageout_cluster_conversions = 0; unsigned long vm_pageout_target_collisions = 0; unsigned long vm_pageout_target_page_dirtied = 0; unsigned long vm_pageout_target_page_freed = 0; -unsigned long vm_pageout_target_page_pinned = 0; -unsigned long vm_pageout_target_page_limbo = 0; #define CLUSTER_STAT(clause) clause #else /* MACH_CLUSTER_STATS */ #define CLUSTER_STAT(clause) diff --git a/osfmk/vm/vm_pageout.h b/osfmk/vm/vm_pageout.h index 8e67e9553..e9515c4d7 100644 --- a/osfmk/vm/vm_pageout.h +++ b/osfmk/vm/vm_pageout.h @@ -65,6 +65,11 @@ #include <vm/vm_object.h> #include <vm/vm_page.h> + + + +extern unsigned int vm_pageout_scan_event_counter; + /* * The following ifdef only exists because XMM must (currently) * be given a page at a time. This should be removed @@ -148,6 +153,10 @@ struct upl { #define UPL_INTERNAL 0x10 #define UPL_PAGE_SYNC_DONE 0x20 #define UPL_DEVICE_MEMORY 0x40 +#define UPL_PAGEOUT 0x80 + +#define UPL_PAGE_TICKET_MASK 0xF00 +#define UPL_PAGE_TICKET_SHIFT 8 diff --git a/osfmk/vm/vm_resident.c b/osfmk/vm/vm_resident.c index be2bb3971..7fd4fc0e6 100644 --- a/osfmk/vm/vm_resident.c +++ b/osfmk/vm/vm_resident.c @@ -74,6 +74,12 @@ #include <zone_debug.h> #include <vm/cpm.h> +/* Variables used to indicate the relative age of pages in the + * inactive list + */ + +int vm_page_ticket_roll = 0; +int vm_page_ticket = 0; /* * Associated with page of user-allocatable memory is a * page structure. @@ -314,6 +320,7 @@ vm_page_bootstrap( m->free = FALSE; m->reference = FALSE; m->pageout = FALSE; + m->dump_cleaning = FALSE; m->list_req_pending = FALSE; m->busy = TRUE; @@ -330,7 +337,6 @@ vm_page_bootstrap( m->lock_supplied = FALSE; m->unusual = FALSE; m->restart = FALSE; - m->limbo = FALSE; m->phys_addr = 0; /* reset later */ @@ -1027,9 +1033,6 @@ void vm_page_more_fictitious(void) c_vm_page_more_fictitious++; - /* this may free up some fictitious pages */ - cleanup_limbo_queue(); - /* * Allocate a single page from the zone_map. Do not wait if no physical * pages are immediately available, and do not zero the space. We need @@ -1111,6 +1114,8 @@ vm_page_convert( m->fictitious = FALSE; vm_page_lock_queues(); + m->no_isync = TRUE; + real_m->no_isync = FALSE; if (m->active) vm_page_active_count++; else if (m->inactive) @@ -1196,6 +1201,7 @@ vm_page_grab(void) mem = vm_page_queue_free; vm_page_queue_free = (vm_page_t) mem->pageq.next; mem->free = FALSE; + mem->no_isync = TRUE; mutex_unlock(&vm_page_queue_free_lock); /* @@ -1271,56 +1277,6 @@ vm_page_release( mutex_unlock(&vm_page_queue_free_lock); } -/* - * Release a page to the limbo list. - * Put real pages at the head of the queue, fictitious at the tail. - * Page queues must be locked. - */ -void -vm_page_release_limbo( - register vm_page_t m) -{ - assert(m->limbo); - vm_page_limbo_count++; - if (m->fictitious) { - queue_enter(&vm_page_queue_limbo, m, vm_page_t, pageq); - } else { - vm_page_limbo_real_count++; - queue_enter_first(&vm_page_queue_limbo, m, vm_page_t, pageq); - } -} - -/* - * Exchange a real page in limbo (limbo_m) with a fictitious page (new_m). - * The end result is that limbo_m is fictitious and still in limbo, and new_m - * is the real page. The prep and pin counts remain with the page in limbo - * although they will be briefly cleared by vm_page_init. This is OK since - * there will be no interrupt-level interactions (the page is in limbo) and - * vm_page_unprep must lock the page queues before changing the prep count. - * - * Page queues must be locked, and limbo_m must have been removed from its - * object. - */ -void -vm_page_limbo_exchange( - register vm_page_t limbo_m, - register vm_page_t new_m) -{ - assert(limbo_m->limbo && !limbo_m->fictitious); - assert(!limbo_m->tabled); - assert(new_m->fictitious); - - *new_m = *limbo_m; - vm_page_init(limbo_m, vm_page_fictitious_addr); - - limbo_m->fictitious = TRUE; - limbo_m->limbo = TRUE; - new_m->limbo = FALSE; - - limbo_m->prep_pin_count = new_m->prep_pin_count; - new_m->prep_pin_count = 0; -} - /* * vm_page_wait: * @@ -1344,15 +1300,20 @@ vm_page_wait( * a call to vm_page_wait must really block. */ kern_return_t wait_result; + int need_wakeup = 0; mutex_lock(&vm_page_queue_free_lock); if (vm_page_free_count < vm_page_free_target) { if (vm_page_free_wanted++ == 0) - thread_wakeup((event_t)&vm_page_free_wanted); + need_wakeup = 1; assert_wait((event_t)&vm_page_free_count, interruptible); mutex_unlock(&vm_page_queue_free_lock); counter(c_vm_page_wait_block++); + + if (need_wakeup) + thread_wakeup((event_t)&vm_page_free_wanted); wait_result = thread_block((void (*)(void))0); + return(wait_result == THREAD_AWAKENED); } else { mutex_unlock(&vm_page_queue_free_lock); @@ -1385,8 +1346,6 @@ vm_page_alloc( return(mem); } -int c_limbo_page_free = 0; /* debugging */ -int c_limbo_convert = 0; /* debugging */ counter(unsigned int c_laundry_pages_freed = 0;) int vm_pagein_cluster_unused = 0; @@ -1449,23 +1408,7 @@ vm_page_free( if (mem->absent) vm_object_absent_release(object); - if (mem->limbo) { - /* - * The pageout daemon put this page into limbo and then freed - * it. The page has already been removed from the object and - * queues, so any attempt to look it up will fail. Put it - * on the limbo queue; the pageout daemon will convert it to a - * fictitious page and/or free the real one later. - */ - /* assert that it came from pageout daemon (how?) */ - assert(!mem->fictitious && !mem->absent); - c_limbo_page_free++; - vm_page_release_limbo(mem); - return; - } - assert(mem->prep_pin_count == 0); - - /* Some of these may be unnecessary */ + /* Some of these may be unnecessary */ mem->page_lock = 0; mem->unlock_request = 0; mem->busy = TRUE; @@ -1614,6 +1557,17 @@ vm_page_deactivate( VM_PAGE_QUEUES_REMOVE(m); } if (m->wire_count == 0 && !m->inactive) { + m->page_ticket = vm_page_ticket; + vm_page_ticket_roll++; + + if(vm_page_ticket_roll == VM_PAGE_TICKETS_IN_ROLL) { + vm_page_ticket_roll = 0; + if(vm_page_ticket == VM_PAGE_TICKET_ROLL_IDS) + vm_page_ticket= 0; + else + vm_page_ticket++; + } + queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq); m->inactive = TRUE; if (!m->fictitious) @@ -1766,200 +1720,6 @@ vm_page_copy( pmap_copy_page(src_m->phys_addr, dest_m->phys_addr); } -/* - * Limbo pages are placed on the limbo queue to await their prep count - * going to zero. A page is put into limbo by the pageout daemon. If the - * page is real, then the pageout daemon did not need to page out the page, - * it just freed it. When the prep_pin_count is zero the page can be freed. - * Real pages with a non-zero prep count are converted to fictitious pages - * so that the memory can be reclaimed; the fictitious page will remain on - * the limbo queue until its prep count reaches zero. - * - * cleanup_limbo_queue is called by vm_page_more_fictitious and the pageout - * daemon since it can free both real and fictitious pages. - * It returns the number of fictitious pages freed. - */ -void -cleanup_limbo_queue(void) -{ - register vm_page_t free_m, m; - vm_offset_t phys_addr; - - vm_page_lock_queues(); - assert(vm_page_limbo_count >= vm_page_limbo_real_count); - - /* - * first free up all pages with prep/pin counts of zero. This - * may free both real and fictitious pages, which may be needed - * later to convert real ones. - */ - m = (vm_page_t)queue_first(&vm_page_queue_limbo); - while (!queue_end(&vm_page_queue_limbo, (queue_entry_t)m)) { - if (m->prep_pin_count == 0) { - free_m = m; - m = (vm_page_t)queue_next(&m->pageq); - queue_remove(&vm_page_queue_limbo, free_m, vm_page_t, - pageq); - vm_page_limbo_count--; - if (!free_m->fictitious) - vm_page_limbo_real_count--; - free_m->limbo = FALSE; - vm_page_free(free_m); - assert(vm_page_limbo_count >= 0); - assert(vm_page_limbo_real_count >= 0); - } else { - m = (vm_page_t)queue_next(&m->pageq); - } - } - - /* - * now convert any remaining real pages to fictitious and free the - * real ones. - */ - while (vm_page_limbo_real_count > 0) { - queue_remove_first(&vm_page_queue_limbo, m, vm_page_t, pageq); - assert(!m->fictitious); - assert(m->limbo); - - /* - * Try to get a fictitious page. If impossible, - * requeue the real one and give up. - */ - free_m = vm_page_grab_fictitious(); - if (free_m == VM_PAGE_NULL) { - queue_enter_first(&vm_page_queue_limbo, m, vm_page_t, - pageq); - break; - } - c_limbo_convert++; - vm_page_limbo_exchange(m, free_m); - assert(m->limbo && m->fictitious); - assert(!free_m->limbo && !free_m->fictitious); - queue_enter(&vm_page_queue_limbo, m, vm_page_t, pageq); - vm_page_free(free_m); - vm_page_limbo_real_count--; - } - - vm_page_unlock_queues(); -} - -/* - * Increment prep_count on a page. - * Must be called in thread context. Page must not disappear: object - * must be locked. - */ -kern_return_t -vm_page_prep( - register vm_page_t m) -{ - kern_return_t retval = KERN_SUCCESS; - - assert(m != VM_PAGE_NULL); - vm_page_lock_queues(); - if (!m->busy && !m->error && !m->fictitious && !m->absent) { - if (m->prep_pin_count != 0) { - vm_page_pin_lock(); - m->prep_count++; - vm_page_pin_unlock(); - } else { - m->prep_count++; - } - assert(m->prep_count != 0); /* check for wraparound */ - } else { - retval = KERN_FAILURE; - } - vm_page_unlock_queues(); - return retval; -} - - -/* - * Pin a page (increment pin count). - * Must have been previously prepped. - * - * MUST BE CALLED AT SPLVM. - * - * May be called from thread or interrupt context. - * If page is in "limbo" it cannot be pinned. - */ -kern_return_t -vm_page_pin( - register vm_page_t m) -{ - kern_return_t retval = KERN_SUCCESS; - - assert(m != VM_PAGE_NULL); - vm_page_pin_lock(); - if (m->limbo || m->prep_count == 0) { - retval = KERN_FAILURE; - } else { - assert(!m->fictitious); - if (m->pin_count == 0) - vm_page_pin_count++; - m->pin_count++; - } - vm_page_pin_unlock(); - return retval; -} - - -/* - * Unprep a page (decrement prep count). - * Must have been previously prepped. - * Called to decrement prep count after an attempt to pin failed. - * Must be called from thread context. - */ -kern_return_t -vm_page_unprep( - register vm_page_t m) -{ - kern_return_t retval = KERN_SUCCESS; - - assert(m != VM_PAGE_NULL); - vm_page_lock_queues(); - vm_page_pin_lock(); - assert(m->prep_count != 0); - if (m->prep_count == 0) - retval = KERN_FAILURE; /* shouldn't happen */ - else - m->prep_count--; - vm_page_pin_unlock(); - vm_page_unlock_queues(); - return retval; -} - - -/* - * Unpin a page: decrement pin AND prep counts. - * Must have been previously prepped AND pinned. - * - * MUST BE CALLED AT SPLVM. - * - * May be called from thread or interrupt context. - */ -kern_return_t -vm_page_unpin( - register vm_page_t m) -{ - kern_return_t retval = KERN_SUCCESS; - - assert(m != VM_PAGE_NULL); - vm_page_pin_lock(); - assert(m->prep_count != 0 && m->pin_count != 0); - assert(m->prep_count >= m->pin_count); - assert(!m->limbo && !m->fictitious); - if (m->prep_count != 0 && m->pin_count != 0) { - m->prep_count--; - m->pin_count--; - if (m->pin_count == 0) - vm_page_pin_count--; - } else { - retval = KERN_FAILURE; /* shouldn't happen */ - } - vm_page_pin_unlock(); - return retval; -} - /* * Currently, this is a primitive allocator that grabs * free pages from the system, sorts them by physical @@ -2330,8 +2090,6 @@ vm_page_print( iprintf("object=0x%x", p->object); printf(", offset=0x%x", p->offset); printf(", wire_count=%d", p->wire_count); - printf(", prep_count=%d", p->prep_count); - printf(", pin_count=%d\n", p->pin_count); iprintf("%sinactive, %sactive, %sgobbled, %slaundry, %sfree, %sref, %sdiscard\n", (p->inactive ? "" : "!"), @@ -2355,12 +2113,11 @@ vm_page_print( (p->cleaning ? "" : "!"), (p->pageout ? "" : "!"), (p->clustered ? "" : "!")); - iprintf("%slock_supplied, %soverwriting, %srestart, %sunusual, %slimbo\n", + iprintf("%slock_supplied, %soverwriting, %srestart, %sunusual\n", (p->lock_supplied ? "" : "!"), (p->overwriting ? "" : "!"), (p->restart ? "" : "!"), - (p->unusual ? "" : "!"), - (p->limbo ? "" : "!")); + (p->unusual ? "" : "!")); iprintf("phys_addr=0x%x", p->phys_addr); printf(", page_error=0x%x", p->page_error); diff --git a/osfmk/vm/vm_shared_memory_server.c b/osfmk/vm/vm_shared_memory_server.c index 626fb5fb9..b1fc23972 100644 --- a/osfmk/vm/vm_shared_memory_server.c +++ b/osfmk/vm/vm_shared_memory_server.c @@ -233,10 +233,11 @@ copyin_shared_file( vm_offset_t *base_address, int map_cnt, sf_mapping_t *mappings, - vm_object_t file_object, + memory_object_control_t file_control, shared_region_task_mappings_t sm_info, int *flags) { + vm_object_t file_object; vm_map_entry_t entry; shared_file_info_t *shared_file_header; load_struct_t *file_entry; @@ -301,7 +302,7 @@ copyin_shared_file( /* Find the entry in the map associated with the current mapping */ /* of the file object */ - + file_object = memory_object_control_to_vm_object(file_control); if(vm_map_lookup_entry(current_map(), mapped_file, &entry)) { vm_object_t mapped_object; if(entry->is_sub_map) { diff --git a/osfmk/vm/vm_user.c b/osfmk/vm/vm_user.c index ec4dcfbf2..06794d0b1 100644 --- a/osfmk/vm/vm_user.c +++ b/osfmk/vm/vm_user.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -55,10 +55,6 @@ * * User-exported virtual memory functions. */ -#ifdef MACH_BSD -/* remove after component interface available */ -extern int vnode_pager_workaround; -#endif #include <vm_cpm.h> #include <mach/boolean.h> @@ -512,6 +508,7 @@ vm_map_64( named_entry_unlock(named_entry); return(KERN_INVALID_OBJECT); } + object->true_share = TRUE; named_entry->object = object; named_entry_unlock(named_entry); /* create an extra reference for the named entry */ @@ -528,8 +525,18 @@ vm_map_64( vm_object_unlock(object); } } - } else { - if ((object = vm_object_enter(port, size, FALSE, FALSE, FALSE)) + } else if (ip_kotype(port) == IKOT_MEMORY_OBJECT) { + /* + * JMM - This is temporary until we unify named entries + * and raw memory objects. + * + * Detected fake ip_kotype for a memory object. In + * this case, the port isn't really a port at all, but + * instead is just a raw memory object. + */ + + if ((object = vm_object_enter((memory_object_t)port, + size, FALSE, FALSE, FALSE)) == VM_OBJECT_NULL) return(KERN_INVALID_OBJECT); @@ -544,6 +551,8 @@ vm_map_64( } vm_object_unlock(object); } + } else { + return (KERN_INVALID_OBJECT); } *address = trunc_page(*address); @@ -837,7 +846,7 @@ vm_msync( kill_pages = -1; } if (kill_pages != -1) - memory_object_deactivate_pages(object, offset, + vm_object_deactivate_pages(object, offset, (vm_object_size_t)flush_size, kill_pages); vm_object_unlock(object); vm_map_unlock(map); @@ -848,8 +857,8 @@ vm_msync( * Don't bother to sync internal objects, since there can't * be any "permanent" storage for these objects anyway. */ - if ((object->pager == IP_NULL) || (object->internal) || - (object->private)) { + if ((object->pager == MEMORY_OBJECT_NULL) || + (object->internal) || (object->private)) { vm_object_unlock(object); vm_map_unlock(map); continue; @@ -864,7 +873,7 @@ vm_msync( vm_map_unlock(map); - do_sync_req = memory_object_sync(object, + do_sync_req = vm_object_sync(object, offset, flush_size, sync_flags & VM_SYNC_INVALIDATE, @@ -917,31 +926,11 @@ re_iterate: queue_enter(&req_q, new_msr, msync_req_t, req_q); -#ifdef MACH_BSD - if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) == - ((rpc_subsystem_t) &vnode_pager_workaround)) { - (void) vnode_pager_synchronize( - object->pager, - object->pager_request, - offset, - flush_size, - sync_flags); - } else { - (void) memory_object_synchronize( - object->pager, - object->pager_request, - offset, - flush_size, - sync_flags); - } -#else (void) memory_object_synchronize( object->pager, - object->pager_request, offset, flush_size, sync_flags); -#endif }/* while */ /* @@ -1249,7 +1238,7 @@ mach_memory_object_memory_entry_64( boolean_t internal, vm_object_offset_t size, vm_prot_t permission, - ipc_port_t pager, + memory_object_t pager, ipc_port_t *entry_handle) { vm_named_entry_t user_object; @@ -1305,7 +1294,7 @@ mach_memory_object_memory_entry( boolean_t internal, vm_size_t size, vm_prot_t permission, - ipc_port_t pager, + memory_object_t pager, ipc_port_t *entry_handle) { return mach_memory_object_memory_entry_64( host, internal, @@ -1450,10 +1439,11 @@ redo_lookup: /* set up an object which will not be pulled from */ /* under us. */ - if (map_entry->needs_copy || object->shadowed || + if ((map_entry->needs_copy || object->shadowed || (object->size > ((vm_object_size_t)map_entry->vme_end - - map_entry->vme_start))) { + map_entry->vme_start))) + && !object->true_share) { if (vm_map_lock_read_to_write(target_map)) { vm_map_lock_read(target_map); goto redo_lookup; @@ -1875,6 +1865,10 @@ set_dp_control_port( { if (host_priv == HOST_PRIV_NULL) return (KERN_INVALID_HOST); + + if (IP_VALID(dynamic_pager_control_port)) + ipc_port_release_send(dynamic_pager_control_port); + dynamic_pager_control_port = control_port; return KERN_SUCCESS; } @@ -1886,41 +1880,25 @@ get_dp_control_port( { if (host_priv == HOST_PRIV_NULL) return (KERN_INVALID_HOST); - *control_port = dynamic_pager_control_port; + + *control_port = ipc_port_copy_send(dynamic_pager_control_port); return KERN_SUCCESS; } -void -mach_destroy_upl( - ipc_port_t port) -{ - upl_t upl; -#if MACH_ASSERT - assert(ip_kotype(port) == IKOT_NAMED_ENTRY); -#endif /* MACH_ASSERT */ - upl = (upl_t)port->ip_kobject; - mutex_lock(&(upl)->Lock); - upl->ref_count-=1; - if(upl->ref_count == 0) { - mutex_unlock(&(upl)->Lock); - uc_upl_abort(upl, UPL_ABORT_ERROR); - } else - mutex_unlock(&(upl)->Lock); -} /* Retrieve a upl for an object underlying an address range in a map */ kern_return_t vm_map_get_upl( - vm_map_t map, - vm_offset_t offset, - vm_size_t *upl_size, - upl_t *upl, - upl_page_info_t **page_list, - int *count, - int *flags, - int force_data_sync) + vm_map_t map, + vm_address_t offset, + vm_size_t *upl_size, + upl_t *upl, + upl_page_info_array_t page_list, + unsigned int *count, + int *flags, + int force_data_sync) { vm_map_entry_t entry; int caller_flags; @@ -1936,12 +1914,34 @@ vm_map_get_upl( } if(upl == NULL) return KERN_INVALID_ARGUMENT; + + REDISCOVER_ENTRY: vm_map_lock(map); if (vm_map_lookup_entry(map, offset, &entry)) { + if (entry->object.vm_object == VM_OBJECT_NULL || + !entry->object.vm_object->phys_contiguous) { + if((*upl_size/page_size) > MAX_UPL_TRANSFER) { + *upl_size = MAX_UPL_TRANSFER * page_size; + } + } if((entry->vme_end - offset) < *upl_size) { *upl_size = entry->vme_end - offset; } + if (caller_flags & UPL_QUERY_OBJECT_TYPE) { + if (entry->object.vm_object == VM_OBJECT_NULL) { + *flags = 0; + } else if (entry->object.vm_object->private) { + *flags = UPL_DEV_MEMORY; + if (entry->object.vm_object->phys_contiguous) { + *flags |= UPL_PHYS_CONTIG; + } + } else { + *flags = 0; + } + vm_map_unlock(map); + return KERN_SUCCESS; + } /* * Create an object if necessary. */ @@ -1951,8 +1951,7 @@ REDISCOVER_ENTRY: entry->offset = 0; } if (!(caller_flags & UPL_COPYOUT_FROM)) { - if (entry->needs_copy - || entry->object.vm_object->copy) { + if (entry->needs_copy) { vm_map_t local_map; vm_object_t object; vm_object_offset_t offset_hi; @@ -2003,7 +2002,8 @@ REDISCOVER_ENTRY: } if (sync_cow_data) { - if (entry->object.vm_object->shadow) { + if (entry->object.vm_object->shadow + || entry->object.vm_object->copy) { int flags; local_object = entry->object.vm_object; @@ -2036,14 +2036,21 @@ REDISCOVER_ENTRY: vm_object_unlock(local_object); } - memory_object_lock_request( - local_object, ((offset - local_start) - + local_offset) + - local_object->paging_offset, - (vm_object_size_t)*upl_size, FALSE, - flags, - VM_PROT_NO_CHANGE, NULL, 0); + if (entry->object.vm_object->shadow && + entry->object.vm_object->copy) { + vm_object_lock_request( + local_object->shadow, + (vm_object_offset_t) + ((offset - local_start) + + local_offset) + + local_object->shadow_offset + + local_object->paging_offset, + *upl_size, FALSE, + MEMORY_OBJECT_DATA_SYNC, + VM_PROT_NO_CHANGE); + } sync_cow_data = FALSE; + vm_object_deallocate(local_object); goto REDISCOVER_ENTRY; } } @@ -2074,15 +2081,16 @@ REDISCOVER_ENTRY: vm_object_unlock(local_object); } - memory_object_lock_request( - local_object, ((offset - local_start) - + local_offset) + - local_object->paging_offset, + vm_object_lock_request( + local_object, + (vm_object_offset_t) + ((offset - local_start) + local_offset) + + local_object->paging_offset, (vm_object_size_t)*upl_size, FALSE, MEMORY_OBJECT_DATA_SYNC, - VM_PROT_NO_CHANGE, - NULL, 0); + VM_PROT_NO_CHANGE); force_data_sync = FALSE; + vm_object_deallocate(local_object); goto REDISCOVER_ENTRY; } @@ -2102,12 +2110,13 @@ REDISCOVER_ENTRY: local_start = entry->vme_start; vm_object_reference(local_object); vm_map_unlock(map); - ret = (vm_fault_list_request(local_object, - ((offset - local_start) + local_offset), + ret = (vm_object_upl_request(local_object, + (vm_object_offset_t) + ((offset - local_start) + local_offset), *upl_size, upl, page_list, - *count, + count, caller_flags)); vm_object_deallocate(local_object); return(ret); @@ -2118,227 +2127,6 @@ REDISCOVER_ENTRY: } - -kern_return_t -vm_object_upl_request( - vm_object_t object, - vm_object_offset_t offset, - vm_size_t size, - ipc_port_t *upl, - upl_page_info_t *page_list, - mach_msg_type_number_t *count, - int cntrl_flags) -{ - upl_t upl_object; - ipc_port_t upl_port; - ipc_port_t previous; - upl_page_info_t *pl; - kern_return_t kr; - - pl = page_list; - kr = vm_fault_list_request(object, offset, size, &upl_object, - &pl, *count, cntrl_flags); - - - if(kr != KERN_SUCCESS) { - *upl = MACH_PORT_NULL; - return KERN_FAILURE; - } - - upl_port = ipc_port_alloc_kernel(); - - - ip_lock(upl_port); - - /* make a sonce right */ - upl_port->ip_sorights++; - ip_reference(upl_port); - - upl_port->ip_destination = IP_NULL; - upl_port->ip_receiver_name = MACH_PORT_NULL; - upl_port->ip_receiver = ipc_space_kernel; - - /* make a send right */ - upl_port->ip_mscount++; - upl_port->ip_srights++; - ip_reference(upl_port); - - ipc_port_nsrequest(upl_port, 1, upl_port, &previous); - /* nsrequest unlocks user_handle */ - - /* Create a named object based on a submap of specified size */ - - - ipc_kobject_set(upl_port, (ipc_kobject_t) upl_object, IKOT_UPL); - *upl = upl_port; - return KERN_SUCCESS; -} - -kern_return_t -vm_pager_upl_request( - vm_object_t object, - vm_object_offset_t offset, - vm_size_t size, - vm_size_t super_size, - ipc_port_t *upl, - upl_page_info_t *page_list, - mach_msg_type_number_t *count, - int cntrl_flags) -{ - upl_t upl_object; - ipc_port_t upl_port; - ipc_port_t previous; - upl_page_info_t *pl; - kern_return_t kr; - - pl = page_list; - kr = upl_system_list_request(object, offset, size, super_size, - &upl_object, &pl, *count, cntrl_flags); - - if(kr != KERN_SUCCESS) { - *upl = MACH_PORT_NULL; - return KERN_FAILURE; - } - - - upl_port = ipc_port_alloc_kernel(); - - - ip_lock(upl_port); - - /* make a sonce right */ - upl_port->ip_sorights++; - ip_reference(upl_port); - - upl_port->ip_destination = IP_NULL; - upl_port->ip_receiver_name = MACH_PORT_NULL; - upl_port->ip_receiver = ipc_space_kernel; - - /* make a send right */ - upl_port->ip_mscount++; - upl_port->ip_srights++; - ip_reference(upl_port); - - ipc_port_nsrequest(upl_port, 1, upl_port, &previous); - /* nsrequest unlocks user_handle */ - - /* Create a named object based on a submap of specified size */ - - - ipc_kobject_set(upl_port, (ipc_kobject_t) upl_object, IKOT_UPL); - *upl = upl_port; - return KERN_SUCCESS; -} - -kern_return_t -vm_upl_map( - vm_map_t map, - ipc_port_t upl_port, - vm_offset_t *dst_addr) -{ - upl_t upl; - kern_return_t kr; - - if (!IP_VALID(upl_port)) { - return KERN_INVALID_ARGUMENT; - } else if (ip_kotype(upl_port) == IKOT_UPL) { - upl_lock(upl); - upl = (upl_t)upl_port->ip_kobject; - kr = uc_upl_map(map, upl, dst_addr); - upl_unlock(upl); - return kr; - } else { - return KERN_FAILURE; - } -} - - -kern_return_t -vm_upl_unmap( - vm_map_t map, - ipc_port_t upl_port) -{ - upl_t upl; - kern_return_t kr; - - if (!IP_VALID(upl_port)) { - return KERN_INVALID_ARGUMENT; - } else if (ip_kotype(upl_port) == IKOT_UPL) { - upl_lock(upl); - upl = (upl_t)upl_port->ip_kobject; - kr = uc_upl_un_map(map, upl); - upl_unlock(upl); - return kr; - } else { - return KERN_FAILURE; - } -} - -kern_return_t -vm_upl_commit( - upl_t upl, - upl_page_list_ptr_t page_list, - mach_msg_type_number_t count) -{ - kern_return_t kr; - upl_lock(upl); - if(count) { - kr = uc_upl_commit(upl, (upl_page_info_t *)page_list); - } else { - kr = uc_upl_commit(upl, (upl_page_info_t *) NULL); - } - upl_unlock(upl); - return kr; -} - -kern_return_t -vm_upl_commit_range( - upl_t upl, - vm_offset_t offset, - vm_size_t size, - upl_page_list_ptr_t page_list, - int flags, - mach_msg_type_number_t count) -{ - kern_return_t kr; - upl_lock(upl); - if(count) { - kr = uc_upl_commit_range(upl, offset, size, flags, - (upl_page_info_t *)page_list); - } else { - kr = uc_upl_commit_range(upl, offset, size, flags, - (upl_page_info_t *) NULL); - } - upl_unlock(upl); - return kr; -} - -kern_return_t -vm_upl_abort_range( - upl_t upl, - vm_offset_t offset, - vm_size_t size, - int abort_flags) -{ - kern_return_t kr; - upl_lock(upl); - kr = uc_upl_abort_range(upl, offset, size, abort_flags); - upl_unlock(upl); - return kr; -} - -kern_return_t -vm_upl_abort( - upl_t upl, - int abort_type) -{ - kern_return_t kr; - upl_lock(upl); - kr = uc_upl_abort(upl, abort_type); - upl_unlock(upl); - return kr; -} - /* ******* Temporary Internal calls to UPL for BSD ***** */ kern_return_t kernel_upl_map( @@ -2346,209 +2134,88 @@ kernel_upl_map( upl_t upl, vm_offset_t *dst_addr) { - kern_return_t kr; - - upl_lock(upl); - kr = uc_upl_map(map, upl, dst_addr); - if(kr == KERN_SUCCESS) { - upl->ref_count += 1; - } - upl_unlock(upl); - return kr; + return (vm_upl_map(map, upl, dst_addr)); } kern_return_t kernel_upl_unmap( vm_map_t map, - upl_t upl) + upl_t upl) { - kern_return_t kr; - - upl_lock(upl); - kr = uc_upl_un_map(map, upl); - if(kr == KERN_SUCCESS) { - if(upl->ref_count == 1) { - upl_dealloc(upl); - } else { - upl->ref_count -= 1; - upl_unlock(upl); - } - } else { - upl_unlock(upl); - } - return kr; + return(vm_upl_unmap(map, upl)); } kern_return_t kernel_upl_commit( upl_t upl, - upl_page_list_ptr_t page_list, - mach_msg_type_number_t count) + upl_page_info_t *pl, + mach_msg_type_number_t count) { - kern_return_t kr; - upl_lock(upl); - upl->ref_count += 1; - if(count) { - kr = uc_upl_commit(upl, (upl_page_info_t *)page_list); - } else { - kr = uc_upl_commit(upl, (upl_page_info_t *) NULL); - } - if(upl->ref_count == 1) { - upl_dealloc(upl); - } else { - upl->ref_count -= 1; - upl_unlock(upl); - } + kern_return_t kr; + + kr = upl_commit(upl, pl, count); + upl_deallocate(upl); return kr; } + kern_return_t kernel_upl_commit_range( upl_t upl, vm_offset_t offset, vm_size_t size, int flags, - upl_page_list_ptr_t page_list, - mach_msg_type_number_t count) + upl_page_info_array_t pl, + mach_msg_type_number_t count) { - kern_return_t kr; - upl_lock(upl); - upl->ref_count += 1; - if(count) { - kr = uc_upl_commit_range(upl, offset, size, flags, - (upl_page_info_t *)page_list); - } else { - kr = uc_upl_commit_range(upl, offset, size, flags, - (upl_page_info_t *) NULL); - } - if(upl->ref_count == 1) { - upl_dealloc(upl); - } else { - upl->ref_count -= 1; - upl_unlock(upl); - } + boolean_t finished = FALSE; + kern_return_t kr; + + if (flags & UPL_COMMIT_FREE_ON_EMPTY) + flags |= UPL_COMMIT_NOTIFY_EMPTY; + + kr = upl_commit_range(upl, offset, size, flags, pl, count, &finished); + + if ((flags & UPL_COMMIT_NOTIFY_EMPTY) && finished) + upl_deallocate(upl); + return kr; } kern_return_t kernel_upl_abort_range( - upl_t upl, - vm_offset_t offset, - vm_size_t size, - int abort_flags) + upl_t upl, + vm_offset_t offset, + vm_size_t size, + int abort_flags) { - kern_return_t kr; - upl_lock(upl); - upl->ref_count += 1; - kr = uc_upl_abort_range(upl, offset, size, abort_flags); - if(upl->ref_count == 1) { - upl_dealloc(upl); - } else { - upl->ref_count -= 1; - upl_unlock(upl); - } - return kr; -} + kern_return_t kr; + boolean_t finished = FALSE; -kern_return_t -kernel_upl_abort( - upl_t upl, - int abort_type) -{ - kern_return_t kr; - upl_lock(upl); - upl->ref_count += 1; - kr = uc_upl_abort(upl, abort_type); - if(upl->ref_count == 1) { - upl_dealloc(upl); - } else { - upl->ref_count -= 1; - upl_unlock(upl); - } - return kr; -} + if (abort_flags & UPL_COMMIT_FREE_ON_EMPTY) + abort_flags |= UPL_COMMIT_NOTIFY_EMPTY; + kr = upl_abort_range(upl, offset, size, abort_flags, &finished); + if ((abort_flags & UPL_COMMIT_FREE_ON_EMPTY) && finished) + upl_deallocate(upl); -/* code snippet from vm_map */ -kern_return_t -vm_object_create_nomap(ipc_port_t port, vm_object_size_t size) -{ - vm_object_t object_ptr; - return memory_object_create_named(port, size, &object_ptr); + return kr; } - -/* - * Temporary interface to overcome old style ipc artifacts, and allow - * ubc to call this routine directly. Will disappear with new RPC - * component architecture. - * NOTE: call to memory_object_destroy removes the vm_object's association - * with its abstract memory object and hence the named flag is set to false. - */ kern_return_t -memory_object_destroy_named( - vm_object_t object, - kern_return_t reason) +kernel_upl_abort( + upl_t upl, + int abort_type) { - vm_object_lock(object); - if(object->named == FALSE) { - panic("memory_object_destroy_named called by party which doesn't hold right"); - } - object->ref_count++; - vm_object_res_reference(object); - vm_object_unlock(object); - return (memory_object_destroy(object, reason)); -} + kern_return_t kr; -/* - * Temporary interface to overcome old style ipc artifacts, and allow - * ubc to call this routine directly. Will disappear with new RPC - * component architecture. - * Note: No change is made in the named flag. - */ -kern_return_t -memory_object_lock_request_named( - vm_object_t object, - vm_object_offset_t offset, - vm_object_size_t size, - memory_object_return_t should_return, - boolean_t should_flush, - vm_prot_t prot, - ipc_port_t reply_to) -{ - vm_object_lock(object); - if(object->named == FALSE) { - panic("memory_object_lock_request_named called by party which doesn't hold right"); - } - object->ref_count++; - vm_object_res_reference(object); - vm_object_unlock(object); - return (memory_object_lock_request(object, - offset, size, should_return, should_flush, prot, - reply_to, 0)); + kr = upl_abort(upl, abort_type); + upl_deallocate(upl); + return kr; } -kern_return_t -memory_object_change_attributes_named( - vm_object_t object, - memory_object_flavor_t flavor, - memory_object_info_t attributes, - mach_msg_type_number_t count, - ipc_port_t reply_to, - mach_msg_type_name_t reply_to_type) -{ - vm_object_lock(object); - if(object->named == FALSE) { - panic("memory_object_lock_request_named called by party which doesn't hold right"); - } - object->ref_count++; - vm_object_res_reference(object); - vm_object_unlock(object); - return (memory_object_change_attributes(object, - flavor, attributes, count, reply_to, reply_to_type)); -} kern_return_t vm_get_shared_region( diff --git a/pexpert/conf/Makefile b/pexpert/conf/Makefile index aa0f1eb82..4baa6f1cf 100644 --- a/pexpert/conf/Makefile +++ b/pexpert/conf/Makefile @@ -24,11 +24,11 @@ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf: make build_setup $(COMPOBJROOT)/$(PEXPERT_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ - $(SOURCE)/MASTER.$(arch_config) \ + $(SOURCE)/MASTER.$(ARCH_CONFIG_LC) \ $(SOURCE)/Makefile.template \ - $(SOURCE)/Makefile.$(arch_config) \ + $(SOURCE)/Makefile.$(ARCH_CONFIG_LC) \ $(SOURCE)/files \ - $(SOURCE)/files.$(arch_config) \ + $(SOURCE)/files.$(ARCH_CONFIG_LC) \ $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf @echo "Running doconf for $(PEXPERT_KERNEL_CONFIG)"; (doconf_target=$(addsuffix /conf, $(TARGET)); \ @@ -37,7 +37,7 @@ $(COMPOBJROOT)/$(PEXPERT_KERNEL_CONFIG)/Makefile : $(SOURCE)/MASTER \ cd $${doconf_target}; \ rm -f $(notdir $?); \ cp $? $${doconf_target}; \ - $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(arch_config) -d $(TARGET)/$(PEXPERT_KERNEL_CONFIG) $(PEXPERT_KERNEL_CONFIG); \ + $(OBJROOT)/$(KERNEL_CONFIG)_$(ARCH_CONFIG)/$(COMPONENT)/doconf -c -cpu $(ARCH_CONFIG_LC) -d $(TARGET)/$(PEXPERT_KERNEL_CONFIG) $(PEXPERT_KERNEL_CONFIG); \ ); .ORDER: $(COMPOBJROOT)/$(PEXPERT_KERNEL_CONFIG)/Makefile @@ -52,6 +52,7 @@ do_all: do_setup_conf ${MAKE} MAKEFILES=$(TARGET)/$(PEXPERT_KERNEL_CONFIG)/Makefile \ SOURCE=$${next_source} \ TARGET=$(TARGET) \ + INCL_MAKEDEP=FALSE \ build_all \ ); \ echo "[ $(SOURCE) ] Returning do_all $(COMPONENT) $(PEXPERT_KERNEL_CONFIG) $(ARCH_CONFIG) $(TARGET)"; diff --git a/pexpert/conf/Makefile.template b/pexpert/conf/Makefile.template index 54eb92200..624ab530c 100644 --- a/pexpert/conf/Makefile.template +++ b/pexpert/conf/Makefile.template @@ -104,8 +104,6 @@ do_build_all: do_depend %RULES --include Makedep - include $(MakeInc_rule) include $(MakeInc_dir) diff --git a/pexpert/conf/version.minor b/pexpert/conf/version.minor index 573541ac9..d00491fd7 100644 --- a/pexpert/conf/version.minor +++ b/pexpert/conf/version.minor @@ -1 +1 @@ -0 +1 diff --git a/pexpert/conf/version.variant b/pexpert/conf/version.variant index 7f8f011eb..e69de29bb 100644 --- a/pexpert/conf/version.variant +++ b/pexpert/conf/version.variant @@ -1 +0,0 @@ -7 diff --git a/pexpert/gen/pe_gen.c b/pexpert/gen/pe_gen.c index 0e28b1f09..2d96feadf 100644 --- a/pexpert/gen/pe_gen.c +++ b/pexpert/gen/pe_gen.c @@ -55,3 +55,86 @@ void PE_init_printf(boolean_t vm_initialized) vcattach(); } } + +unsigned char appleClut8[ 256 * 3 ] = { +// 00 + 0xFF,0xFF,0xFF, 0xFF,0xFF,0xCC, 0xFF,0xFF,0x99, 0xFF,0xFF,0x66, + 0xFF,0xFF,0x33, 0xFF,0xFF,0x00, 0xFF,0xCC,0xFF, 0xFF,0xCC,0xCC, + 0xFF,0xCC,0x99, 0xFF,0xCC,0x66, 0xFF,0xCC,0x33, 0xFF,0xCC,0x00, + 0xFF,0x99,0xFF, 0xFF,0x99,0xCC, 0xFF,0x99,0x99, 0xFF,0x99,0x66, +// 10 + 0xFF,0x99,0x33, 0xFF,0x99,0x00, 0xFF,0x66,0xFF, 0xFF,0x66,0xCC, + 0xFF,0x66,0x99, 0xFF,0x66,0x66, 0xFF,0x66,0x33, 0xFF,0x66,0x00, + 0xFF,0x33,0xFF, 0xFF,0x33,0xCC, 0xFF,0x33,0x99, 0xFF,0x33,0x66, + 0xFF,0x33,0x33, 0xFF,0x33,0x00, 0xFF,0x00,0xFF, 0xFF,0x00,0xCC, +// 20 + 0xFF,0x00,0x99, 0xFF,0x00,0x66, 0xFF,0x00,0x33, 0xFF,0x00,0x00, + 0xCC,0xFF,0xFF, 0xCC,0xFF,0xCC, 0xCC,0xFF,0x99, 0xCC,0xFF,0x66, + 0xCC,0xFF,0x33, 0xCC,0xFF,0x00, 0xCC,0xCC,0xFF, 0xCC,0xCC,0xCC, + 0xCC,0xCC,0x99, 0xCC,0xCC,0x66, 0xCC,0xCC,0x33, 0xCC,0xCC,0x00, +// 30 + 0xCC,0x99,0xFF, 0xCC,0x99,0xCC, 0xCC,0x99,0x99, 0xCC,0x99,0x66, + 0xCC,0x99,0x33, 0xCC,0x99,0x00, 0xCC,0x66,0xFF, 0xCC,0x66,0xCC, + 0xCC,0x66,0x99, 0xCC,0x66,0x66, 0xCC,0x66,0x33, 0xCC,0x66,0x00, + 0xCC,0x33,0xFF, 0xCC,0x33,0xCC, 0xCC,0x33,0x99, 0xCC,0x33,0x66, +// 40 + 0xCC,0x33,0x33, 0xCC,0x33,0x00, 0xCC,0x00,0xFF, 0xCC,0x00,0xCC, + 0xCC,0x00,0x99, 0xCC,0x00,0x66, 0xCC,0x00,0x33, 0xCC,0x00,0x00, + 0x99,0xFF,0xFF, 0x99,0xFF,0xCC, 0x99,0xFF,0x99, 0x99,0xFF,0x66, + 0x99,0xFF,0x33, 0x99,0xFF,0x00, 0x99,0xCC,0xFF, 0x99,0xCC,0xCC, +// 50 + 0x99,0xCC,0x99, 0x99,0xCC,0x66, 0x99,0xCC,0x33, 0x99,0xCC,0x00, + 0x99,0x99,0xFF, 0x99,0x99,0xCC, 0x99,0x99,0x99, 0x99,0x99,0x66, + 0x99,0x99,0x33, 0x99,0x99,0x00, 0x99,0x66,0xFF, 0x99,0x66,0xCC, + 0x99,0x66,0x99, 0x99,0x66,0x66, 0x99,0x66,0x33, 0x99,0x66,0x00, +// 60 + 0x99,0x33,0xFF, 0x99,0x33,0xCC, 0x99,0x33,0x99, 0x99,0x33,0x66, + 0x99,0x33,0x33, 0x99,0x33,0x00, 0x99,0x00,0xFF, 0x99,0x00,0xCC, + 0x99,0x00,0x99, 0x99,0x00,0x66, 0x99,0x00,0x33, 0x99,0x00,0x00, + 0x66,0xFF,0xFF, 0x66,0xFF,0xCC, 0x66,0xFF,0x99, 0x66,0xFF,0x66, +// 70 + 0x66,0xFF,0x33, 0x66,0xFF,0x00, 0x66,0xCC,0xFF, 0x66,0xCC,0xCC, + 0x66,0xCC,0x99, 0x66,0xCC,0x66, 0x66,0xCC,0x33, 0x66,0xCC,0x00, + 0x66,0x99,0xFF, 0x66,0x99,0xCC, 0x66,0x99,0x99, 0x66,0x99,0x66, + 0x66,0x99,0x33, 0x66,0x99,0x00, 0x66,0x66,0xFF, 0x66,0x66,0xCC, +// 80 + 0x66,0x66,0x99, 0x66,0x66,0x66, 0x66,0x66,0x33, 0x66,0x66,0x00, + 0x66,0x33,0xFF, 0x66,0x33,0xCC, 0x66,0x33,0x99, 0x66,0x33,0x66, + 0x66,0x33,0x33, 0x66,0x33,0x00, 0x66,0x00,0xFF, 0x66,0x00,0xCC, + 0x66,0x00,0x99, 0x66,0x00,0x66, 0x66,0x00,0x33, 0x66,0x00,0x00, +// 90 + 0x33,0xFF,0xFF, 0x33,0xFF,0xCC, 0x33,0xFF,0x99, 0x33,0xFF,0x66, + 0x33,0xFF,0x33, 0x33,0xFF,0x00, 0x33,0xCC,0xFF, 0x33,0xCC,0xCC, + 0x33,0xCC,0x99, 0x33,0xCC,0x66, 0x33,0xCC,0x33, 0x33,0xCC,0x00, + 0x33,0x99,0xFF, 0x33,0x99,0xCC, 0x33,0x99,0x99, 0x33,0x99,0x66, +// a0 + 0x33,0x99,0x33, 0x33,0x99,0x00, 0x33,0x66,0xFF, 0x33,0x66,0xCC, + 0x33,0x66,0x99, 0x33,0x66,0x66, 0x33,0x66,0x33, 0x33,0x66,0x00, + 0x33,0x33,0xFF, 0x33,0x33,0xCC, 0x33,0x33,0x99, 0x33,0x33,0x66, + 0x33,0x33,0x33, 0x33,0x33,0x00, 0x33,0x00,0xFF, 0x33,0x00,0xCC, +// b0 + 0x33,0x00,0x99, 0x33,0x00,0x66, 0x33,0x00,0x33, 0x33,0x00,0x00, + 0x00,0xFF,0xFF, 0x00,0xFF,0xCC, 0x00,0xFF,0x99, 0x00,0xFF,0x66, + 0x00,0xFF,0x33, 0x00,0xFF,0x00, 0x00,0xCC,0xFF, 0x00,0xCC,0xCC, + 0x00,0xCC,0x99, 0x00,0xCC,0x66, 0x00,0xCC,0x33, 0x00,0xCC,0x00, +// c0 + 0x00,0x99,0xFF, 0x00,0x99,0xCC, 0x00,0x99,0x99, 0x00,0x99,0x66, + 0x00,0x99,0x33, 0x00,0x99,0x00, 0x00,0x66,0xFF, 0x00,0x66,0xCC, + 0x00,0x66,0x99, 0x00,0x66,0x66, 0x00,0x66,0x33, 0x00,0x66,0x00, + 0x00,0x33,0xFF, 0x00,0x33,0xCC, 0x00,0x33,0x99, 0x00,0x33,0x66, +// d0 + 0x00,0x33,0x33, 0x00,0x33,0x00, 0x00,0x00,0xFF, 0x00,0x00,0xCC, + 0x00,0x00,0x99, 0x00,0x00,0x66, 0x00,0x00,0x33, 0xEE,0x00,0x00, + 0xDD,0x00,0x00, 0xBB,0x00,0x00, 0xAA,0x00,0x00, 0x88,0x00,0x00, + 0x77,0x00,0x00, 0x55,0x00,0x00, 0x44,0x00,0x00, 0x22,0x00,0x00, +// e0 + 0x11,0x00,0x00, 0x00,0xEE,0x00, 0x00,0xDD,0x00, 0x00,0xBB,0x00, + 0x00,0xAA,0x00, 0x00,0x88,0x00, 0x00,0x77,0x00, 0x00,0x55,0x00, + 0x00,0x44,0x00, 0x00,0x22,0x00, 0x00,0x11,0x00, 0x00,0x00,0xEE, + 0x00,0x00,0xDD, 0x00,0x00,0xBB, 0x00,0x00,0xAA, 0x00,0x00,0x88, +// f0 + 0x00,0x00,0x77, 0x00,0x00,0x55, 0x00,0x00,0x44, 0x00,0x00,0x22, + 0x00,0x00,0x11, 0xEE,0xEE,0xEE, 0xDD,0xDD,0xDD, 0xBB,0xBB,0xBB, + 0xAA,0xAA,0xAA, 0x88,0x88,0x88, 0x77,0x77,0x77, 0x55,0x55,0x55, + 0x44,0x44,0x44, 0x22,0x22,0x22, 0x11,0x11,0x11, 0x00,0x00,0x00 +}; diff --git a/pexpert/i386/fakePPCDeviceTree.c b/pexpert/i386/fakePPCDeviceTree.c index fd767a69b..93c83ee7b 100644 --- a/pexpert/i386/fakePPCDeviceTree.c +++ b/pexpert/i386/fakePPCDeviceTree.c @@ -25,72 +25,86 @@ #include "fakePPCStructs.h" boot_args fakePPCBootArgs = { - 0, // Revision - kBootArgsVersion, // Version - "", // CommandLine - 0, // PhysicalDRAM - 0, // machine_type - 0, // deviceTreeP - 0, // deviceTreeLength - 0, // topOfKernelData + 0, // Revision + kBootArgsVersion, // Version + "", // CommandLine + 0, // PhysicalDRAM + 0, // machine_type + 0, // deviceTreeP + 0, // deviceTreeLength + 0, // topOfKernelData }; -void * createdt(dt_init *template, long *retSize) +void * createdt(dt_init * template, long * retSize) { - dt_init * next; - int size, allocSize; + dt_init * next; + int size, allocSize; vm_address_t out, saveout; - void * source; + void * source; // calc size of expanded data - for( next = template, allocSize = 0; - next; - next++) { - - if( next->nodeInit.zero == 0) { - if( next->nodeInit.nProps == 0) - break; - allocSize += 2 * sizeof( long); - } else - allocSize += (32 + 4 + 3 + next->propInit.length) & (-4); + for ( next = template, allocSize = 0; + next; + next++ ) + { + if ( next->nodeInit.zero == 0 ) + { + if( next->nodeInit.nProps == 0) break; + allocSize += 2 * sizeof( long); + } + else if ( next->dataInit.one == 1 ) + { + allocSize += *(next->dataInit.length); + } + else + { + allocSize += (32 + 4 + 3 + next->propInit.length) & (-4); + } } - saveout = out = kalloc( allocSize); + saveout = out = kalloc(allocSize); + if ( out == 0 ) return 0; // copy out - for( next = template; - next; - next++) { - - if( next->nodeInit.zero == 0) { - - if( next->nodeInit.nProps == 0) - break; - source = &next->nodeInit.nProps; - size = 2 * sizeof( long); - - } else { - - bcopy( next->propInit.name, out, 32); - out += 32; - size = next->propInit.length; - *(long *)out = size; - out += sizeof( long); - if( size == 4) - source = &next->propInit.value; - else { - source = next->propInit.value; - size = (size + 3) & (-4); - } - } - bcopy( source, out, size); - out += size; + for ( next = template; next; next++) + { + if ( next->nodeInit.zero == 0 ) + { + if ( next->nodeInit.nProps == 0 ) break; + source = &next->nodeInit.nProps; + size = 2 * sizeof( long); + } + else if ( next->dataInit.one == 1 ) + { + *(next->dataInit.address) = out; + source = 0; + size = *(next->dataInit.length); + } + else + { + bcopy( next->propInit.name, (void *)out, 32); + out += 32; + size = next->propInit.length; + *(long *)out = size; + out += sizeof(long); + if ( size == 4 ) + source = &next->propInit.value; + else { + source = next->propInit.value; + size = (size + 3) & (-4); + } + } + if ( source ) + bcopy(source, (void *)out, size); + else + bzero((void *)out, size); + out += size; } if( allocSize != (out - saveout)) printf("WARNING: DT corrupt (%x)\n", (out - saveout) - allocSize); *retSize = allocSize; - return( (void *)saveout); + return( (void *)saveout ); } unsigned char *nptr; diff --git a/pexpert/i386/fakePPCDeviceTree.h b/pexpert/i386/fakePPCDeviceTree.h index c3f921131..40300fbb3 100644 --- a/pexpert/i386/fakePPCDeviceTree.h +++ b/pexpert/i386/fakePPCDeviceTree.h @@ -20,41 +20,18 @@ * @APPLE_LICENSE_HEADER_END@ */ -unsigned long busRange[] = { 0, 0 }; -unsigned long picAddress[] = { 0x00008000, 0x00000000, 0x00000000, - 0xC8000000, 0x00080000}; +extern dt_data gMemoryMapNode; +extern dt_data gDriversProp; -dt_init fakePPCDeviceTree[] = { - NODE( 7, 2 ), +dt_init fakePPCDeviceTree[] = +{ + NODE( 2, 1 ), PROP( "name", "device-tree"), - PROP( "model", "Power Macintosh"), - PROP( "compatible", "AAPL,9900\0MacRISC"), - INTPROP( "AAPL,cpu-id", 0x39006086), - INTPROP( "clock-frequency", 0x02FAF080), - INTPROP( "#address-cells", 1), - INTPROP( "#size-cells", 1), - - NODE( 1,0 ), - PROP( "name", "ps2controller"), - - NODE( 3,0 ), - PROP( "name", "display"), - PROP( "model", "silly"), - INTPROP( "AAPL,boot-display", 1), -#if 0 - NODE( 6,1 ), - PROP( "name", "i386generic"), - PROP( "device_type", "pci"), - INTPROP( "#address-cells", 3), - INTPROP( "#size-cells", 2), - PROP( "bus-range", busRange), - NULLPROP( "ranges" ), - - NODE( 4, 0), - PROP( "name", "i386pic"), - PROP( "device_type", "pic"), - PROP( "reg", picAddress), - PROP( "assigned-addresses", picAddress), -#endif + PROP( "compatible", "X86PC"), + NODE( 1, 1 ), + PROP( "name", "chosen" ), + DATANODE( gMemoryMapNode ), + PROP( "name", "memory-map" ), + DATAPROP( gDriversProp ), NODE( 0, 0), }; diff --git a/pexpert/i386/fakePPCStructs.h b/pexpert/i386/fakePPCStructs.h index 622b8441e..2f0fef665 100644 --- a/pexpert/i386/fakePPCStructs.h +++ b/pexpert/i386/fakePPCStructs.h @@ -23,37 +23,54 @@ #include <pexpert/boot.h> typedef struct { - char * name; - unsigned long length; - void * value; + char * name; + unsigned long length; + void * value; } prop_init; typedef struct { - long zero; - long nProps; - long nChildren; + long zero; + long nProps; + long nChildren; } node_init; +typedef struct { + long one; + long * length; + long * address; +} data_init; + typedef union { - prop_init propInit; - node_init nodeInit; + prop_init propInit; + node_init nodeInit; + data_init dataInit; } dt_init; +typedef struct { + long length; + long * address; +} dt_data; + extern boot_args fakePPCBootArgs; extern unsigned char *nptr; -void printdt(void); -void * createdt(dt_init *template, long *retSize); +void printdt(void); +void * createdt(dt_init * template, long * retSize); +#define NODE(props,children) \ + {{(char *)0, props, (void *)children }} -#define NODE(props,children) \ - {{(char *)0, props, (void *)children }} +#define INTPROP(name,value) \ + {{name, 4, (void *)value }} -#define INTPROP(name,value) \ - {{name, 4, (void *)value }} +#define PROP(name,value) \ + {{name, sizeof( value), value }} -#define PROP(name,value) \ - {{name, sizeof( value), value }} +#define NULLPROP(name) \ + {{name, 0, (void *)0 }} -#define NULLPROP(name) \ - {{name, 0, (void *)0 }} +#define DATAPROP(data) \ + {{(char *)1, (long)&((data).length), (void *)&((data).address) }} + +#define DATANODE(data) \ + {{(char *)1, (long)&((data).length), (void *)&((data).address) }} diff --git a/pexpert/i386/kd.c b/pexpert/i386/kd.c index e0f0fd17a..0e8dd758f 100644 --- a/pexpert/i386/kd.c +++ b/pexpert/i386/kd.c @@ -77,950 +77,102 @@ /* $ Header: $ */ -#include <string.h> -#include "kd.h" - -#include <mach/i386/vm_param.h> - -#define at386_io_lock_state() -#define at386_io_lock(op) (TRUE) -#define at386_io_unlock() - - -typedef unsigned short i386_ioport_t; - -/* read a byte */ -extern unsigned char inb( - i386_ioport_t port); -/* write a longword */ -extern void outb( - i386_ioport_t port, - unsigned char datum); - -extern __inline__ unsigned char inb( - i386_ioport_t port) -{ - unsigned char datum; - __asm__ volatile("inb %1, %0" : "=a" (datum) : "d" (port)); - return(datum); -} - -extern __inline__ void outb( - i386_ioport_t port, - unsigned char datum) -{ - __asm__ volatile("outb %0, %1" : : "a" (datum), "d" (port)); -} - -/* Forward */ - -extern void kd_sendcmd(unsigned char ch); -extern void kdreboot(void); -extern int kd_dogetc(int wait); -extern void kd_handle_ack(void); -extern void kd_resend(void); -extern int do_modifier( - int state, - Scancode c, - int up); -extern int kdcheckmagic( - Scancode sc, - int * regs); -extern int kdstate2idx( - int state, - int extended); -extern void kdinit(void); -extern void kd_belloff(void); -extern void kd_bellon(void); -extern void kd_senddata(unsigned char c); -extern unsigned char kd_getdata(void); -extern unsigned char kd_cmdreg_read(void); -extern void set_kd_state( - int newstate); -extern unsigned char state2leds( - int state); -extern void kd_setleds1( - unsigned char val); -extern void kd_setleds2(void); -extern void cnsetleds( - unsigned char val); -extern int kd_kbd_magic( - int scancode); - -extern int cngetc(void); -extern int cnmaygetc(void); -extern void kdreboot(void); -extern int kd_dogetc(int wait); - -/* reboot on CTL-ALT-DEL ? */ -extern int rebootflag; -/* enter kernel debugger on CTR-ALT-d ? */ -int kbdkdbflag = 1; -/* allow keyboard mouse ? */ -int kbdmouseflag = 0; - -/* - * kd_state shows the state of the modifier keys (ctrl, caps lock, - * etc.) It should normally be changed by calling set_kd_state(), so - * that the keyboard status LEDs are updated correctly. - */ -int kd_state = KS_NORMAL; -int kb_mode = KB_ASCII; /* event/ascii */ - -int kd_kbd_mouse = 0; -int kd_kbd_magic_scale = 6; -int kd_kbd_magic_button = 0; - -/* - * Some keyboard commands work by sending a command, waiting for an - * ack (handled by kdintr), then sending data, which generates a - * second ack. If we are in the middle of such a sequence, kd_ack - * shows what the ack is for. - * - * When a byte is sent to the keyboard, it is kept around in last_sent - * in case it needs to be resent. - * - * The rest of the variables here hold the data required to complete - * the sequence. - * - * XXX - the System V driver keeps a command queue, I guess in case we - * want to start a command while another is in progress. Is this - * something we should worry about? - */ -enum why_ack {NOT_WAITING, SET_LEDS, DATA_ACK}; -enum why_ack kd_ack = NOT_WAITING; - -unsigned char last_sent = 0; - -unsigned char kd_nextled = 0; - -/* - * We don't provide any mutex protection for this flag because we know - * that this module will have been initialized by the time multiple - * threads are running. - */ -int kd_initialized = FALSE; /* driver initialized? */ -int kd_extended = FALSE; +#include <pexpert/pexpert.h> /* - * This array maps scancodes to Ascii characters (or character - * sequences). - * Each row corresponds to one key. There are NUMOUTPUT bytes per key - * state. The states are ordered: Normal, SHIFT, CTRL, ALT, - * SHIFT/ALT. + * Common I/O ports. */ -unsigned char key_map[NUMKEYS][WIDTH_KMAP] = { -{NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC}, -{K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC, K_ESC,NC,NC}, -{K_ONE,NC,NC, K_BANG,NC,NC, K_ONE,NC,NC, 0x1b,0x4e,0x31, 0x1b,0x4e,0x21}, -{K_TWO,NC,NC, K_ATSN,NC,NC, K_NUL,NC,NC, 0x1b,0x4e,0x32, 0x1b,0x4e,0x40}, -{K_THREE,NC,NC, K_POUND,NC,NC, K_THREE,NC,NC, 0x1b,0x4e,0x33, 0x1b,0x4e,0x23}, -{K_FOUR,NC,NC, K_DOLLAR,NC,NC, K_FOUR,NC,NC, 0x1b,0x4e,0x34, 0x1b,0x4e,0x24}, -{K_FIVE,NC,NC, K_PERC,NC,NC, K_FIVE,NC,NC, 0x1b,0x4e,0x35, 0x1b,0x4e,0x25}, -{K_SIX,NC,NC, K_CARET,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x36, 0x1b,0x4e,0x5e}, -{K_SEVEN,NC,NC, K_AMPER,NC,NC, K_SEVEN,NC,NC, 0x1b,0x4e,0x37, 0x1b,0x4e,0x26}, -{K_EIGHT,NC,NC, K_ASTER,NC,NC, K_EIGHT,NC,NC, 0x1b,0x4e,0x38, 0x1b,0x4e,0x2a}, -{K_NINE,NC,NC, K_LPAREN,NC,NC, K_NINE,NC,NC, 0x1b,0x4e,0x39,0x1b,0x4e,0x28}, -{K_ZERO,NC,NC, K_RPAREN,NC,NC, K_ZERO,NC,NC, 0x1b,0x4e,0x30,0x1b,0x4e,0x29}, -{K_MINUS,NC,NC, K_UNDSC,NC,NC, K_US,NC,NC, 0x1b,0x4e,0x2d, 0x1b,0x4e,0x5f}, -{K_EQL,NC,NC, K_PLUS,NC,NC, K_EQL,NC,NC, 0x1b,0x4e,0x3d, 0x1b,0x4e,0x2b}, -{K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC, K_BS,NC,NC}, -{K_HT,NC,NC, K_GS,NC,NC, K_HT,NC,NC, K_HT,NC,NC, K_GS,NC,NC}, -{K_q,NC,NC, K_Q,NC,NC, K_DC1,NC,NC, 0x1b,0x4e,0x71, 0x1b,0x4e,0x51}, -{K_w,NC,NC, K_W,NC,NC, K_ETB,NC,NC, 0x1b,0x4e,0x77, 0x1b,0x4e,0x57}, -{K_e,NC,NC, K_E,NC,NC, K_ENQ,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45}, -{K_r,NC,NC, K_R,NC,NC, K_DC2,NC,NC, 0x1b,0x4e,0x72, 0x1b,0x4e,0x52}, -{K_t,NC,NC, K_T,NC,NC, K_DC4,NC,NC, 0x1b,0x4e,0x74, 0x1b,0x4e,0x54}, -{K_y,NC,NC, K_Y,NC,NC, K_EM,NC,NC, 0x1b,0x4e,0x79, 0x1b,0x4e,0x59}, -{K_u,NC,NC, K_U,NC,NC, K_NAK,NC,NC, 0x1b,0x4e,0x75, 0x1b,0x4e,0x55}, -{K_i,NC,NC, K_I,NC,NC, K_HT,NC,NC, 0x1b,0x4e,0x69, 0x1b,0x4e,0x49}, -{K_o,NC,NC, K_O,NC,NC, K_SI,NC,NC, 0x1b,0x4e,0x6f, 0x1b,0x4e,0x4f}, -{K_p,NC,NC, K_P,NC,NC, K_DLE,NC,NC, 0x1b,0x4e,0x70, 0x1b,0x4e,0x50}, -{K_LBRKT,NC,NC, K_LBRACE,NC,NC, K_ESC,NC,NC, 0x1b,0x4e,0x5b, 0x1b,0x4e,0x7b}, -{K_RBRKT,NC,NC, K_RBRACE,NC,NC, K_GS,NC,NC, 0x1b,0x4e,0x5d, 0x1b,0x4e,0x7d}, -{K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC, K_CR,NC,NC}, -{K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, K_SCAN,K_CTLSC,NC, - K_SCAN,K_CTLSC,NC}, -{K_a,NC,NC, K_A,NC,NC, K_SOH,NC,NC, 0x1b,0x4e,0x61, 0x1b,0x4e,0x41}, -{K_s,NC,NC, K_S,NC,NC, K_DC3,NC,NC, 0x1b,0x4e,0x73, 0x1b,0x4e,0x53}, -{K_d,NC,NC, K_D,NC,NC, K_EOT,NC,NC, 0x1b,0x4e,0x65, 0x1b,0x4e,0x45}, -{K_f,NC,NC, K_F,NC,NC, K_ACK,NC,NC, 0x1b,0x4e,0x66, 0x1b,0x4e,0x46}, -{K_g,NC,NC, K_G,NC,NC, K_BEL,NC,NC, 0x1b,0x4e,0x67, 0x1b,0x4e,0x47}, -{K_h,NC,NC, K_H,NC,NC, K_BS,NC,NC, 0x1b,0x4e,0x68, 0x1b,0x4e,0x48}, -{K_j,NC,NC, K_J,NC,NC, K_LF,NC,NC, 0x1b,0x4e,0x6a, 0x1b,0x4e,0x4a}, -{K_k,NC,NC, K_K,NC,NC, K_VT,NC,NC, 0x1b,0x4e,0x6b, 0x1b,0x4e,0x4b}, -{K_l,NC,NC, K_L,NC,NC, K_FF,NC,NC, 0x1b,0x4e,0x6c, 0x1b,0x4e,0x4c}, -{K_SEMI,NC,NC, K_COLON,NC,NC, K_SEMI,NC,NC, 0x1b,0x4e,0x3b, 0x1b,0x4e,0x3a}, -{K_SQUOTE,NC,NC,K_DQUOTE,NC,NC,K_SQUOTE,NC,NC,0x1b,0x4e,0x27,0x1b,0x4e,0x22}, -{K_GRAV,NC,NC, K_TILDE,NC,NC, K_RS,NC,NC, 0x1b,0x4e,0x60, 0x1b,0x4e,0x7e}, -{K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, K_SCAN,K_LSHSC,NC, - K_SCAN,K_LSHSC,NC}, -{K_BSLSH,NC,NC, K_PIPE,NC,NC, K_FS,NC,NC, 0x1b,0x4e,0x5c, 0x1b,0x4e,0x7c}, -{K_z,NC,NC, K_Z,NC,NC, K_SUB,NC,NC, 0x1b,0x4e,0x7a, 0x1b,0x4e,0x5a}, -{K_x,NC,NC, K_X,NC,NC, K_CAN,NC,NC, 0x1b,0x4e,0x78, 0x1b,0x4e,0x58}, -{K_c,NC,NC, K_C,NC,NC, K_ETX,NC,NC, 0x1b,0x4e,0x63, 0x1b,0x4e,0x43}, -{K_v,NC,NC, K_V,NC,NC, K_SYN,NC,NC, 0x1b,0x4e,0x76, 0x1b,0x4e,0x56}, -{K_b,NC,NC, K_B,NC,NC, K_STX,NC,NC, 0x1b,0x4e,0x62, 0x1b,0x4e,0x42}, -{K_n,NC,NC, K_N,NC,NC, K_SO,NC,NC, 0x1b,0x4e,0x6e, 0x1b,0x4e,0x4e}, -{K_m,NC,NC, K_M,NC,NC, K_CR,NC,NC, 0x1b,0x4e,0x6d, 0x1b,0x4e,0x4d}, -{K_COMMA,NC,NC, K_LTHN,NC,NC, K_COMMA,NC,NC, 0x1b,0x4e,0x2c, 0x1b,0x4e,0x3c}, -{K_PERIOD,NC,NC, K_GTHN,NC,NC, K_PERIOD,NC,NC,0x1b,0x4e,0x2e,0x1b,0x4e,0x3e}, -{K_SLASH,NC,NC, K_QUES,NC,NC, K_SLASH,NC,NC, 0x1b,0x4e,0x2f, 0x1b,0x4e,0x3f}, -{K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, K_SCAN,K_RSHSC,NC, - K_SCAN,K_RSHSC,NC}, -{K_ASTER,NC,NC, K_ASTER,NC,NC, K_ASTER,NC,NC, 0x1b,0x4e,0x2a,0x1b,0x4e,0x2a}, -{K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, K_SCAN,K_ALTSC,NC, - K_SCAN,K_ALTSC,NC}, -{K_SPACE,NC,NC, K_SPACE,NC,NC, K_NUL,NC,NC, K_SPACE,NC,NC, K_SPACE,NC,NC}, -{K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC, - K_SCAN,K_CLCKSC,NC, K_SCAN,K_CLCKSC,NC}, -{K_F1, K_F1S, K_F1, K_F1, K_F1S}, -{K_F2, K_F2S, K_F2, K_F2, K_F2S}, -{K_F3, K_F3S, K_F3, K_F3, K_F3S}, -{K_F4, K_F4S, K_F4, K_F4, K_F4S}, -{K_F5, K_F5S, K_F5, K_F5, K_F5S}, -{K_F6, K_F6S, K_F6, K_F6, K_F6S}, -{K_F7, K_F7S, K_F7, K_F7, K_F7S}, -{K_F8, K_F8S, K_F8, K_F8, K_F8S}, -{K_F9, K_F9S, K_F9, K_F9, K_F9S}, -{K_F10, K_F10S, K_F10, K_F10, K_F10S}, -{K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC, - K_SCAN,K_NLCKSC,NC, K_SCAN,K_NLCKSC,NC}, -{K_SCRL, K_NUL,NC,NC, K_SCRL, K_SCRL, K_NUL,NC,NC}, -{K_HOME, K_SEVEN,NC,NC, K_HOME, K_HOME, 0x1b,0x4e,0x37}, -{K_UA, K_EIGHT,NC,NC, K_UA, K_UA, 0x1b,0x4e,0x38}, -{K_PUP, K_NINE,NC,NC, K_PUP, K_PUP, 0x1b,0x4e,0x39}, -{0x1b,0x5b,0x53, K_MINUS,NC,NC, 0x1b,0x5b,0x53,0x1b,0x5b,0x53,0x1b,0x4e,0x2d}, -{K_LA, K_FOUR,NC,NC, K_LA, K_LA, 0x1b,0x4e,0x34}, -{0x1b,0x5b,0x47,K_FIVE,NC,NC,0x1b,0x5b,0x47, 0x1b,0x5b,0x47, 0x1b,0x4e,0x35}, -{K_RA, K_SIX,NC,NC, K_RA, K_RA, 0x1b,0x4e,0x36}, -{0x1b,0x5b,0x54,K_PLUS,NC,NC, 0x1b,0x5b,0x54, 0x1b,0x5b,0x54, 0x1b,0x4e,0x2b}, -{K_END, K_ONE,NC,NC, K_END, K_END, 0x1b,0x4e,0x31}, -{K_DA, K_TWO,NC,NC, K_DA, K_DA, 0x1b,0x4e,0x32}, -{K_PDN, K_THREE,NC,NC, K_PDN, K_PDN, 0x1b,0x4e,0x33}, -{K_INS, K_ZERO,NC,NC, K_INS, K_INS, 0x1b,0x4e,0x30}, -{K_DEL,NC,NC, K_PERIOD,NC,NC, K_DEL,NC,NC, K_DEL,NC,NC, 0x1b,0x4e,0x2e}, -{NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC}, -{NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC}, -{NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC,NC}, -{K_F11, K_F11S, K_F11, K_F11, K_F11S}, -{K_F12, K_F12S, K_F12, K_F12, K_F12S} -}; - -extern void cnputc(unsigned char ch); +#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ +#define K_STATUS 0x64 /* keybd status (read-only) */ +#define K_CMD 0x64 /* keybd ctlr command (write-only) */ /* - * Switch for poll vs. interrupt. + * Bit definitions for K_STATUS port. */ -int kd_pollc = 0; +#define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */ +#define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */ +#define K_SYSFLAG 0x04 /* "System Flag" */ +#define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */ +#define K_KBD_INHBT 0x10 /* 0 if keyboard inhibited */ +#define K_XMT_TIMEOUT 0x20 /* Transmit time out */ +#define K_RCV_TIMEOUT 0x40 /* Receive time out */ -int (*cgetc)( - int wait) = kd_dogetc; - /* get a char. from console */ -void (*cputc)( - char ch) = cnputc; - /* put a char. to console */ +/* + * Keyboard controller commands (sent to K_CMD port). + */ +#define K_CMD_READ 0x20 /* read controller command byte */ +#define K_CMD_WRITE 0x60 /* write controller command byte */ +#define K_CMD_TEST 0xab /* test interface */ +#define K_CMD_DUMP 0xac /* diagnostic dump */ +#define K_CMD_DISBLE 0xad /* disable keyboard */ +#define K_CMD_ENBLE 0xae /* enable keyboard */ +#define K_CMD_RDKBD 0xc4 /* read keyboard ID */ +#define K_CMD_ECHO 0xee /* used for diagnostic testing */ +#define K_CMD_RESET 0xfe /* issue a system reset */ /* - * cngetc: + * cngetc / cnmaygetc * - * Get one character using polling, rather than interrupts. Used - * by the kernel debugger. Note that Caps Lock is ignored. - * Normally this routine is called with interrupts already - * disabled, but there is code in place so that it will be more - * likely to work even if interrupts are turned on. + * Get one character using polling, rather than interrupts. + * Used by the kernel debugger. */ int cngetc(void) { - int ret; + char c; - ret = (*cgetc)(TRUE); - - return ret; + if ( 0 == (*PE_poll_input)(0, &c) ) + return ( c ); + else + return ( 0 ); } int cnmaygetc(void) { - int ret; - - ret = (*cgetc)(FALSE); - - return ret; -} - -int -kd_dogetc( - int wait) -{ - unsigned char c; - unsigned char scancode; - unsigned int char_idx; - int up; - - kdinit(); - kd_extended = FALSE; - - for ( ; ; ) { - while (!(inb(K_STATUS) & K_OBUF_FUL)) - if (!wait) - return (-1); - up = FALSE; - /* - * We'd come here for mouse events in debugger, if - * the mouse were on. - */ - if ((inb(K_STATUS) & 0x20) == 0x20) { - printf("M%xP", inb(K_RDWR)); - continue; - } - scancode = inb(K_RDWR); - /* - * Handle extend modifier and - * ack/resend, otherwise we may never receive - * a key. - */ - if (scancode == K_EXTEND) { - kd_extended = TRUE; - continue; - } else if (scancode == K_RESEND) { -/* printf("kd_getc: resend"); */ - kd_resend(); - continue; - } else if (scancode == K_ACKSC) { -/* printf("kd_getc: handle_ack"); */ - kd_handle_ack(); - continue; - } - if (scancode & K_UP) { - up = TRUE; - scancode &= ~K_UP; - } - if (kd_kbd_mouse) - kd_kbd_magic(scancode); - if (scancode < NUMKEYS) { - /* Lookup in map, then process. */ - char_idx = kdstate2idx(kd_state, kd_extended); - c = key_map[scancode][char_idx]; - if (c == K_SCAN) { - c = key_map[scancode][++char_idx]; - kd_state = do_modifier(kd_state, c, up); -#ifdef notdef - cnsetleds(state2leds(kd_state)); -#endif - } else if (!up) { - /* regular key-down */ - if (c == K_CR) - c = K_LF; -#ifdef notdef - splx(o_pri); -#endif - return(c & 0177); - } - } - } -} - - -int old_kb_mode; - -#if MACH_KDB -#define poll_spl() db_splhigh() /* prevent race w/ kdintr() */ -#define poll_splx(s) db_splx(s) -#else /* MACH_KDB */ -#define poll_spl() SPLKD() -#define poll_splx(s) splx(s) -#endif /* MACH_KDB */ - - -void -cnpollc( - int on) -{ - int old_spl; /* spl we're called at... */ - - if (cpu_number()) { - return; - } - if (on) { - old_spl = poll_spl(); - - old_kb_mode = kb_mode; - kb_mode = KB_ASCII; - poll_splx(old_spl); - - kd_pollc++; - } else { - --kd_pollc; - - old_spl = poll_spl(); - kb_mode = old_kb_mode; - poll_splx(old_spl); + char c; - - } + if ( 0 == (*PE_poll_input)(0, &c) ) + return ( c ); + else + return ( 0 ); } -/* - * kd_handle_ack: - * - * For pending commands, complete the command. For data bytes, - * drop the ack on the floor. - */ - -void -kd_handle_ack(void) -{ - switch (kd_ack) { - case SET_LEDS: - kd_setleds2(); - kd_ack = DATA_ACK; - break; - case DATA_ACK: - kd_ack = NOT_WAITING; - break; - case NOT_WAITING: - printf("unexpected ACK from keyboard\n"); - break; - default: - panic("bogus kd_ack\n"); - break; - } -} - -/* - * kd_resend: - * - * Resend a missed keyboard command or data byte. - */ - -void -kd_resend(void) -{ - if (kd_ack == NOT_WAITING) - printf("unexpected RESEND from keyboard\n"); - else - kd_senddata(last_sent); -} - - /* - * do_modifier: + * kd_sendcmd * - * Change keyboard state according to which modifier key and - * whether it went down or up. + * This function sends a command byte to the keyboard command + * port, but first waits until the input/output data buffer is + * clear before sending the data. * - * input: the current state, the key, and the key's direction. - * The key can be any key, not just a modifier key. - * - * output: the new state */ -int -do_modifier( - int state, - Scancode c, - int up) +static void +kd_sendcmd(unsigned char ch) { - switch (c) { - case (K_ALTSC): - if (up) - state &= ~KS_ALTED; - else - state |= KS_ALTED; - kd_extended = FALSE; - break; -#ifndef ORC - case (K_CLCKSC): -#endif /* ORC */ - case (K_CTLSC): - if (up) - state &= ~KS_CTLED; - else - state |= KS_CTLED; - kd_extended = FALSE; - break; -#ifdef ORC - case (K_CLCKSC): - if (!up) - state ^= KS_CLKED; - break; -#endif /* ORC */ - case (K_NLCKSC): - if (!up) - state ^= KS_NLKED; - break; - case (K_LSHSC): - case (K_RSHSC): - if (up) - state &= ~KS_SHIFTED; - else - state |= KS_SHIFTED; - kd_extended = FALSE; - break; - } - - return(state); + while (inb(K_STATUS) & K_IBUF_FUL); + outb(K_CMD, ch); } - -/* - * kdcheckmagic: - * - * Check for magic keystrokes for invoking the debugger or - * rebooting or ... - * - * input: an unprocessed scancode - * - * output: TRUE if a magic key combination was recognized and - * processed. FALSE otherwise. - * - * side effects: - * various actions possible, depending on which keys are - * pressed. If the debugger is called, steps are taken - * to ensure that the system doesn't think the magic keys - * are still held down. - */ - -int -kdcheckmagic( - Scancode scancode, - int *regs) -{ - static int magic_state = KS_NORMAL; /* like kd_state */ - int up = FALSE; - extern int rebootflag; - - if (scancode == 0x46 && kbdmouseflag) /* scroll lock */ - { - kd_kbd_mouse = !kd_kbd_mouse; - kd_kbd_magic_button = 0; - return(TRUE); - } - if (scancode & K_UP) { - up = TRUE; - scancode &= ~K_UP; - } - magic_state = do_modifier(magic_state, scancode, up); - - if ((magic_state&(KS_CTLED|KS_ALTED)) == (KS_CTLED|KS_ALTED)) { - switch (scancode) { -#if MACH_KDB - case K_dSC: /* ctl-alt-d */ - if (!kbdkdbflag) - return(FALSE); - - kdb_kintr(); /* invoke debugger */ - - /* Returned from debugger, so reset kbd state. */ - (void)SPLKD(); - magic_state = KS_NORMAL; - if (kb_mode == KB_ASCII) - kd_state = KS_NORMAL; - /* setting leds kills kbd */ - - return(TRUE); - break; -#endif /* MACH_KDB */ - case K_DELSC: /* ctl-alt-del */ - /* if rebootflag is on, reboot the system */ - if (rebootflag) - kdreboot(); - break; - } - } - return(FALSE); -} - - /* - * kdstate2idx: - * - * Return the value for the 2nd index into key_map that - * corresponds to the given state. - */ - -int -kdstate2idx( - int state, /* bit vector, not a state index */ - int extended) -{ - int state_idx = NORM_STATE; - - if ((!extended) && state != KS_NORMAL) { - if ((state&(KS_SHIFTED|KS_ALTED)) == (KS_SHIFTED|KS_ALTED)) - state_idx = SHIFT_ALT; - else if (state&KS_SHIFTED) - state_idx = SHIFT_STATE; - else if (state&KS_ALTED) - state_idx = ALT_STATE; - else if (state&KS_CTLED) - state_idx = CTRL_STATE; - } - - return (CHARIDX(state_idx)); -} - -/* - * kdinit: - * - * This code initializes the structures and sets up the port registers - * for the console driver. - * - * Each bitmap-based graphics card is likely to require a unique - * way to determine the card's presence. The driver runs through - * each "special" card that it knows about and uses the first one - * that it finds. If it doesn't find any, it assumes that an - * EGA-like card is installed. - * - * input : None. Interrupts are assumed to be disabled - * output : Driver is initialized + * kdreboot * + * Send a command to the motherboard keyboard controller to + * issue a hardware reset. */ -void -kdinit(void) -{ - unsigned char k_comm; /* keyboard command byte */ - unsigned char kd_stat; - - if (kd_initialized) - return; - kd_initialized = TRUE; - - /* get rid of any garbage in output buffer */ - if (inb(K_STATUS) & K_OBUF_FUL) - (void)inb(K_RDWR); - - cnsetleds(kd_state = KS_NORMAL); - - kd_sendcmd(KC_CMD_READ); /* ask for the ctlr command byte */ - k_comm = kd_getdata(); - k_comm &= ~K_CB_DISBLE; /* clear keyboard disable bit */ - k_comm |= K_CB_ENBLIRQ; /* enable interrupt */ - kd_sendcmd(KC_CMD_WRITE); /* write new ctlr command byte */ - kd_senddata(k_comm); - -/* set_kd_state(KS_NORMAL); does only HALF of set-leds sequence - - leaves kbd dead */ - - /* get rid of any garbage in output buffer */ - (void)inb(K_RDWR); -} - -/* - * kd_belloff: - * - * This routine shuts the bell off, by sending the appropriate code - * to the speaker port. - * - * input : None - * output : bell is turned off - * - */ - -void -kd_belloff(void) -{ - unsigned char status; - - status = (inb(K_PORTB) & ~(K_SPKRDATA | K_ENABLETMR2)); - outb(K_PORTB, status); -} - - -/* - * kd_bellon: - * - * This routine turns the bell on. - * - * input : None - * output : bell is turned on - * - */ - -void -kd_bellon(void) -{ - unsigned char status; - - /* program timer 2 */ - outb(K_TMRCTL, K_SELTMR2 | K_RDLDTWORD | K_TSQRWAVE | K_TBINARY); - outb(K_TMR2, 1500 & 0xff); /* LSB */ - outb(K_TMR2, (int)1500 >> 8); /* MSB */ - - /* start speaker - why must we turn on K_SPKRDATA? */ - status = (inb(K_PORTB)| K_ENABLETMR2 | K_SPKRDATA); - outb(K_PORTB, status); - return; -} - -/* - * kd_senddata: - * - * This function sends a byte to the keyboard RDWR port, but - * first waits until the input/output data buffer is clear before - * sending the data. Note that this byte can be either data or a - * keyboard command. - * - */ - -void -kd_senddata( - unsigned char ch) -{ - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_RDWR, ch); - last_sent = ch; -} - -/* - * kd_sendcmd: - * - * This function sends a command byte to the keyboard command - * port, but first waits until the input/output data buffer is - * clear before sending the data. - * - */ - -void -kd_sendcmd( - unsigned char ch) -{ - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_CMD, ch); -} - - -/* - * kd_getdata: - * - * This function returns a data byte from the keyboard RDWR port, - * after waiting until the port is flagged as having something to - * read. - */ - -unsigned char -kd_getdata(void) -{ - while ((inb(K_STATUS) & K_OBUF_FUL) == 0); - return(inb(K_RDWR)); -} - -unsigned char -kd_cmdreg_read(void) -{ - int ch=KC_CMD_READ; - - while (inb(K_STATUS) & (K_IBUF_FUL | K_OBUF_FUL)); - outb(K_CMD, ch); - - while ((inb(K_STATUS) & K_OBUF_FUL) == 0); - return(inb(K_RDWR)); -} - -void -kd_cmdreg_write( - unsigned char val) -{ - int ch=KC_CMD_WRITE; - - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_CMD, ch); - - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_RDWR, val); -} - -int kd_mouse_write_no_ack = 0; - -int -kd_mouse_write( - unsigned char val) -{ - int ch=0xd4; /* output byte to aux device (i.e. mouse) */ - int ret = 0; - - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_CMD, ch); - - while (inb(K_STATUS) & K_IBUF_FUL); - outb(K_RDWR, val); - - if (kd_mouse_write_no_ack) goto done; - - while ((inb(K_STATUS) & K_OBUF_FUL) == 0); - if ((inb(K_STATUS) & 0x20) == 0x20) { - switch (ret = inb(K_RDWR)) { - case 0xfa: - break; - case 0xfe: - case 0xfc: - default: - printf("kd_mouse_write: saw %x for %x\n", - ret, val); - } - } else { /* abort */ - printf("kd_mouse_write: sync error ??? on %x\n", val); - } - -done: - return ret; -} - -void -kd_mouse_read( - int no, - char *buf) -{ - - while (no-- > 0) { - while ((inb(K_STATUS) & K_OBUF_FUL) == 0); - /* - * We may have seen a mouse event. - */ - if ((inb(K_STATUS) & 0x20) == 0x20) { - *buf++ = (unsigned char)inb(K_RDWR); - } else { /* abort */ - int junk = inb(K_RDWR); - printf("kd_mouse_read: sync error, received: 0x%x\n", - junk); - break; - } - } -} - -void -kd_mouse_drain(void) -{ - int i; - while(inb(K_STATUS) & K_IBUF_FUL); - while((i = inb(K_STATUS)) & K_OBUF_FUL) - printf("kbd: S = %x D = %x\n", i, inb(K_RDWR)); -} - -/* - * set_kd_state: - * - * Set kd_state and update the keyboard status LEDs. - */ - -void -set_kd_state( - int newstate) -{ - kd_state = newstate; - kd_setleds1(state2leds(newstate)); -} - -/* - * state2leds: - * - * Return a byte containing LED settings for the keyboard, given - * a state vector. - */ - -unsigned char -state2leds( - int state) -{ - unsigned char result = 0; - - if (state & KS_NLKED) - result |= K_LED_NUMLK; - if (state & KS_CLKED) - result |= K_LED_CAPSLK; - return(result); -} - -/* - * kd_setleds[12]: - * - * Set the keyboard LEDs according to the given byte. - */ - -void -kd_setleds1( - unsigned char val) -{ - if (kd_ack != NOT_WAITING) { - printf("kd_setleds1: unexpected state (%d)\n", kd_ack); - return; - } - - kd_ack = SET_LEDS; - kd_nextled = val; - kd_senddata(K_CMD_LEDS); -} - -void -kd_setleds2(void) -{ - kd_senddata(kd_nextled); -} - - -/* - * cnsetleds: - * - * like kd_setleds[12], but not interrupt-based. - * Currently disabled because cngetc ignores caps lock and num - * lock anyway. - */ - -void -cnsetleds( - unsigned char val) -{ - kd_senddata(K_CMD_LEDS); - (void)kd_getdata(); /* XXX - assume is ACK */ - kd_senddata(val); - (void)kd_getdata(); /* XXX - assume is ACK */ -} - void kdreboot(void) { - kd_sendcmd(0xFE); /* XXX - magic # */ - /* - * DRAT. We're still here. Let's try a "CPU shutdown", which consists - * of clearing the IDTR and causing an exception. It's in locore.s - */ - cpu_shutdown(); - /*NOTREACHED*/ -} - -int -kd_kbd_magic( - int scancode) -{ -int new_button = 0; + extern void cpu_shutdown(void); - if (kd_kbd_mouse == 2) - printf("sc = %x\n", scancode); + kd_sendcmd( K_CMD_RESET ); - switch (scancode) { -/* f1 f2 f3 */ - case 0x3d: - new_button++; - case 0x3c: - new_button++; - case 0x3b: - new_button++; - if (kd_kbd_magic_button && (new_button != kd_kbd_magic_button)) { - /* down w/o up */ - } - /* normal */ - if (kd_kbd_magic_button == new_button) { - kd_kbd_magic_button = 0; - } else { - kd_kbd_magic_button = new_button; - } - break; - default: - return 0; - } - return 1; + /* + * DRAT. We're still here. Let's try a "CPU shutdown", which consists + * of clearing the IDTR and causing an exception. It's in locore.s + */ + cpu_shutdown(); + /*NOTREACHED*/ } diff --git a/pexpert/i386/kd.h b/pexpert/i386/kd.h deleted file mode 100644 index af525d912..000000000 --- a/pexpert/i386/kd.h +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * HISTORY - * - * Revision 1.1.1.1.12.1 1998/10/06 20:27:13 ehewitt - * Updated for framebuffer support. Added pexpert calls. - * - * Revision 1.1.1.1 1998/09/22 21:05:39 wsanchez - * Import of Mac OS X kernel (~semeria) - * - * Revision 1.1.1.1 1998/03/07 02:25:38 wsanchez - * Import of OSF Mach kernel (~mburg) - * - * Revision 1.1.22.1 1996/11/29 16:56:42 stephen - * nmklinux_1.0b3_shared into pmk1.1 - * Include mach/mach_ioctl.h instead of sys/ioctl.h and use the - * "MACH"-prefixed ioctl definitions. - * Include mach/time_value.h instead of sys/time.h and use the - * new time types. - * Replaced u_char, u_short and u_int types with real ones. - * [96/09/18 barbou] - * - * Revision 1.1.18.1 1996/09/17 16:33:38 bruel - * use standalone includes only - * [1996/09/17 15:27:38 bruel] - * - * Revision 1.1.6.5 1996/07/31 20:49:24 paire - * Merged with changes from 1.1.6.4 - * [1996/07/31 20:38:47 paire] - * - * Merged with changes from 1.1.6.4 - * [1996/07/31 14:58:21 paire] - * - * Revision 1.1.6.4 1996/07/31 13:23:35 paire - * Merged with nmk20b7_shared (1.1.11.1) - * [96/06/07 paire] - * - * Revision 1.1.11.1 1996/03/04 16:11:12 bernadat - * Changed mouse_rawbuf struct to keep same kd_event struct size. - * [96/02/22 bernadat] - * - * Revision 1.1.6.2 1996/02/19 13:35:33 bernadat - * Adapted to be exported to users (added some #ifdef MACH_KERNEL). - * Modified kd_event structure to allow raw (unprocessed) mouse events. - * [96/01/29 barbou] - * - * Revision 1.1.6.1 1994/09/23 01:42:33 ezf - * change marker to not FREE - * [1994/09/22 21:18:52 ezf] - * - * Revision 1.1.2.4 1993/08/09 19:38:22 dswartz - * Add ANSI prototypes - CR#9523 - * [1993/08/06 17:50:44 dswartz] - * - * Revision 1.1.2.3 1993/08/03 18:29:12 gm - * CR9596: Change KERNEL to MACH_KERNEL. - * [1993/08/02 16:04:31 gm] - * - * Revision 1.1.2.2 1993/06/02 23:20:30 jeffc - * Added to OSF/1 R1.3 from NMK15.0. - * [1993/06/02 21:02:41 jeffc] - * - * Revision 1.1 1992/09/30 02:27:08 robert - * Initial revision - * - * $EndLog$ - */ -/* CMU_HIST */ -/* - * Revision 2.7.9.1 92/02/18 18:55:07 jeffreyh - * Added two defines to detect if a PC Keyboard is present - * [91/06/25 bernadat] - * - * Revision 2.7 91/05/14 16:26:55 mrt - * Correcting copyright - * - * Revision 2.6 91/03/16 14:46:53 rpd - * Fixed ioctl definitions for ANSI C. - * [91/02/20 rpd] - * - * Revision 2.5 91/02/05 17:19:03 mrt - * Changed to new Mach copyright - * [91/02/01 17:45:28 mrt] - * - * Revision 2.4 90/11/26 14:50:27 rvb - * jsb bet me to XMK34, sigh ... - * [90/11/26 rvb] - * Synched 2.5 & 3.0 at I386q (r1.5.1.5) & XMK35 (r2.4) - * [90/11/15 rvb] - * - * Revision 1.5.1.4 90/06/07 08:05:44 rvb - * Move CURRENT_COLUMN here. - * [90/06/06 rvb] - * - * Revision 2.3 90/08/09 16:32:09 rpd - * Added kdb/X support from rvb. - * [90/08/09 rpd] - * - * Revision 1.5.1.3 90/05/14 13:21:26 rvb - * Support for entering kdb from X; - * [90/04/30 rvb] - * - * Revision 2.2 90/05/03 15:44:47 dbg - * First checkin. - * - * Revision 1.5.1.2 90/02/28 15:50:17 rvb - * Fix numerous typo's in Olivetti disclaimer. - * [90/02/28 rvb] - * - * Revision 1.5.1.1 90/01/08 13:30:59 rvb - * Add Olivetti copyright. - * [90/01/08 rvb] - * - * Revision 1.5 89/07/17 10:41:10 rvb - * Olivetti Changes to X79 upto 5/9/89: - * [89/07/11 rvb] - * - * Revision 1.6 89/07/07 16:24:24 kupfer - * X79 merge, 2nd attempt - * - * Revision 1.4.1.1 89/04/27 12:20:58 kupfer - * Merge X79 with our latest and greatest. - * - * Revision 1.1.1.1 89/04/27 11:53:41 kupfer - * X79 from CMU. - * - * Revision 1.4 89/03/09 20:06:33 rpd - * More cleanup. - * - * Revision 1.3 89/02/26 12:37:13 gm0w - * Changes for cleanup. - * - */ -/* CMU_ENDHIST */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: kd.h - * Description: definitions for AT keyboard/display driver - * Authors: Eugene Kuerner, Adrienne Jardetzky, Mike Kupfer - * - * $ Header: $ - * - * Copyright Ing. C. Olivetti & C. S.p.A. 1988, 1989. - * All rights reserved. - * - * Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc., - * Cupertino, California. - * - * All Rights Reserved - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby - * granted, provided that the above copyright notice appears in all - * copies and that both the copyright notice and this permission notice - * appear in supporting documentation, and that the name of Olivetti - * not be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * - * OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, - * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION - * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * This file contains defines and structures that implement hardware - * keyboard mapping into ansi defined output codes. Note that this - * is structured so that "re-mapping" of actual keys is allowed at - * anytime during execution of the console driver. And each scan code - * is potentially expanded into NUMKEYS characters. Which is programmable - * at runtime or whenever. - * - * 02 Nov 1988 orc!eugene - * - */ - -#ifndef _MACHINE_KD_H_ -#define _MACHINE_KD_H_ - -#include <mach/boolean.h> -#include <mach/time_value.h> - - -/* - * Where memory for various graphics adapters starts. - */ -#define EGA_START 0x0b8000 -#define CGA_START 0x0b8000 -#define MONO_START 0x0b0000 - -/* - * Common I/O ports. - */ -#define K_TMR0 0x40 /* timer 0, 1, or 2 value (r/w) */ -#define K_TMR1 0x41 -#define K_TMR2 0x42 -#define K_TMRCTL 0x43 /* timer control (write-only) */ -#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */ -#define K_PORTB 0x61 /* r/w. speaker & status lines */ -#define K_STATUS 0x64 /* keybd status (read-only) */ -#define K_CMD 0x64 /* keybd ctlr command (write-only) */ - -/* - * I/O ports for various graphics adapters. - */ -#define EGA_IDX_REG 0x3d4 -#define EGA_IO_REG 0x3d5 -#define CGA_IDX_REG 0x3d4 -#define CGA_IO_REG 0x3d5 -#define MONO_IDX_REG 0x3b4 -#define MONO_IO_REG 0x3b5 - -/* - * Commands sent to graphics adapter. - */ -#define C_LOW 0x0f /* return low byte of cursor addr */ -#define C_HIGH 0x0e /* high byte */ - -/* - * Bit definitions for K_STATUS port. - */ -#define K_OBUF_FUL 0x01 /* output (from keybd) buffer full */ -#define K_IBUF_FUL 0x02 /* input (to keybd) buffer full */ -#define K_SYSFLAG 0x04 /* "System Flag" */ -#define K_CMD_DATA 0x08 /* 1 = input buf has cmd, 0 = data */ -#define K_KBD_INHBT 0x10 /* 0 if keyboard inhibited */ -#define K_XMT_TIMEOUT 0x20 /* Transmit time out */ -#define K_RCV_TIMEOUT 0x40 /* Receive time out */ - -/* - * Keyboard controller commands (sent to K_CMD port). - */ -#define KC_CMD_READ 0x20 /* read controller command byte */ -#define KC_CMD_WRITE 0x60 /* write controller command byte */ -#define KC_CMD_TEST 0xab /* test interface */ -#define KC_CMD_DUMP 0xac /* diagnostic dump */ -#define KC_CMD_DISBLE 0xad /* disable keyboard */ -#define KC_CMD_ENBLE 0xae /* enable keyboard */ -#define KC_CMD_RDKBD 0xc4 /* read keyboard ID */ -#define KC_CMD_ECHO 0xee /* used for diagnostic testing */ - -/* - * Keyboard commands (send to K_RDWR). - */ -#define K_CMD_LEDS 0xed /* set status LEDs (caps lock, etc.) */ - -/* - * Bit definitions for controller command byte (sent following - * K_CMD_WRITE command). - */ -#define K_CB_ENBLIRQ 0x01 /* enable data-ready intrpt */ -#define K_CB_SETSYSF 0x04 /* Set System Flag */ -#define K_CB_INHBOVR 0x08 /* Inhibit Override */ -#define K_CB_DISBLE 0x10 /* disable keyboard */ - -/* - * Bit definitions for "Indicator Status Byte" (sent after a - * K_CMD_LEDS command). If the bit is on, the LED is on. Undefined - * bit positions must be 0. - */ -#define K_LED_SCRLLK 0x1 /* scroll lock */ -#define K_LED_NUMLK 0x2 /* num lock */ -#define K_LED_CAPSLK 0x4 /* caps lock */ - -/* - * Bit definitions for "Miscellaneous port B" (K_PORTB). - */ -/* read/write */ -#define K_ENABLETMR2 0x01 /* enable output from timer 2 */ -#define K_SPKRDATA 0x02 /* direct input to speaker */ -#define K_ENABLEPRTB 0x04 /* "enable" port B */ -#define K_EIOPRTB 0x08 /* enable NMI on parity error */ -/* read-only */ -#define K_REFRESHB 0x10 /* refresh flag from INLTCONT PAL */ -#define K_OUT2B 0x20 /* timer 2 output */ -#define K_ICKB 0x40 /* I/O channel check (parity error) */ - -/* - * Bit definitions for timer control port (K_TMRCTL). - */ -/* select timer 0, 1, or 2. Don't mess with 0 or 1. */ -#define K_SELTMRMASK 0xc0 -#define K_SELTMR0 0x00 -#define K_SELTMR1 0x40 -#define K_SELTMR2 0x80 - -/* read/load control */ -#define K_RDLDTMRMASK 0x30 -#define K_HOLDTMR 0x00 /* freeze timer until read */ -#define K_RDLDTLSB 0x10 /* read/load LSB */ -#define K_RDLDTMSB 0x20 /* read/load MSB */ -#define K_RDLDTWORD 0x30 /* read/load LSB then MSB */ - -/* mode control */ -#define K_TMDCTLMASK 0x0e -#define K_TCOUNTINTR 0x00 /* "Term Count Intr" */ -#define K_TONESHOT 0x02 /* "Progr One-Shot" */ -#define K_TRATEGEN 0x04 /* "Rate Gen (/n)" */ -#define K_TSQRWAVE 0x06 /* "Sqr Wave Gen" */ -#define K_TSOFTSTRB 0x08 /* "Softw Trig Strob" */ -#define K_THARDSTRB 0x0a /* "Hardw Trig Strob" */ - -/* count mode */ -#define K_TCNTMDMASK 0x01 -#define K_TBINARY 0x00 /* 16-bit binary counter */ -#define K_TBCD 0x01 /* 4-decade BCD counter */ - - - -/* - * Fun definitions for displayed characters and characters read from - * the keyboard. - */ - -/* - * Attributes for character sent to display. - */ -#define KA_NORMAL 0x07 -#define KA_REVERSE 0x70 - -/* - * For an EGA-like display, each character takes two bytes, one for the - * actual character, followed by one for its attributes. - * Be very careful if you change ONE_SPACE, as these constants are also used - * to define the device-independent display implemented by kd.c. - * (See kdsoft.h for more details on the device-independent display.) - */ -#define ONE_SPACE 2 /* bytes in 1 char, EGA-like display */ -#define ONE_LINE (kd_cols * ONE_SPACE) /* 160 number of bytes in line */ -#define ONE_PAGE (kd_lines * ONE_LINE) /* 4000 number of bytes in page */ -#define BOTTOM_LINE ((kd_lines - 1) * ONE_LINE) /* 3840 1st byte in last line of display */ - -#define BEG_OF_LINE(pos) ((pos) - (pos)%ONE_LINE) -#define CURRENT_COLUMN(pos) (((pos) % ONE_LINE) / ONE_SPACE) - -#define NUMKEYS 89 -#define NUMSTATES 5 /* NORMAL_STATE, ... */ -#define NUMOUTPUT 3 /* max size of byte seq from key */ -#define WIDTH_KMAP (NUMSTATES * NUMOUTPUT) - -/* - * Keyboard states. Used for KDGKBENT, KDSKBENT ioctl's. If you - * change these values, you should also rearrange the entries in - * key_map. - */ -/* "state indices" (for computing key_map index) */ -#define NORM_STATE 0 -#define SHIFT_STATE 1 -#define CTRL_STATE 2 -#define ALT_STATE 3 -#define SHIFT_ALT 4 -/* macro to convert from state index to actual key_map index */ -#define CHARIDX(sidx) ((sidx) * NUMOUTPUT) - /* where sidx is in [NORM_STATE ... SHIFT_ALT] */ - -/* "state bits" for kd_state vector */ -#define KS_NORMAL 0x00 -#define KS_SLKED 0x01 -#define KS_NLKED 0x02 -#define KS_CLKED 0x04 -#define KS_ALTED 0x08 -#define KS_SHIFTED 0x10 -#define KS_CTLED 0x20 - - -/* - * Scancode values, not to be confused with Ascii values. - */ -typedef unsigned char Scancode; - -/* special codes */ -#define K_UP 0x80 /* OR'd in if key below is released */ -#define K_EXTEND 0xe0 /* marker for "extended" sequence */ -#define K_ACKSC 0xfa /* ack for keyboard command */ -#define K_RESEND 0xfe /* request to resend keybd cmd */ - -/* modifier keys */ -#define K_CTLSC 0x1d /* control down */ -#define K_LSHSC 0x2a /* left shift down */ -#define K_RSHSC 0x36 /* right shift down */ -#define K_ALTSC 0x38 /* alt key down */ -#define K_CLCKSC 0x3a /* caps lock */ -#define K_NLCKSC 0x45 /* num lock down */ - -/* "special keys" */ -#define K_BSSC 0x0e /* backspace */ -#define K_TABSC 0x0f /* tab */ -#define K_RETSC 0x1c /* return */ -#define K_SPSC 0x39 /* space */ -#define K_ESCSC 0x01 /* ESC */ - -/* alphabetic keys */ -#define K_qSC 0x10 -#define K_wSC 0x11 -#define K_eSC 0x12 -#define K_rSC 0x13 -#define K_tSC 0x14 -#define K_ySC 0x15 -#define K_uSC 0x16 -#define K_iSC 0x17 -#define K_oSC 0x18 -#define K_pSC 0x19 - -#define K_aSC 0x1e -#define K_sSC 0x1f -#define K_dSC 0x20 -#define K_fSC 0x21 -#define K_gSC 0x22 -#define K_hSC 0x23 -#define K_jSC 0x24 -#define K_kSC 0x25 -#define K_lSC 0x26 - -#define K_zSC 0x2c -#define K_xSC 0x2d -#define K_cSC 0x2e -#define K_vSC 0x2f -#define K_bSC 0x30 -#define K_nSC 0x31 -#define K_mSC 0x32 - -/* numbers and punctuation */ -#define K_ONESC 0x02 /* 1 */ -#define K_TWOSC 0x03 /* 2 */ -#define K_THREESC 0x04 /* 3 */ -#define K_FOURSC 0x05 /* 4 */ -#define K_FIVESC 0x06 /* 5 */ -#define K_SIXSC 0x07 /* 6 */ -#define K_SEVENSC 0x08 /* 7 */ -#define K_EIGHTSC 0x09 /* 8 */ -#define K_NINESC 0x0a /* 9 */ -#define K_ZEROSC 0x0b /* 0 */ - -#define K_MINUSSC 0x0c /* - */ -#define K_EQLSC 0x0d /* = */ -#define K_LBRKTSC 0x1a /* [ */ -#define K_RBRKTSC 0x1b /* ] */ -#define K_SEMISC 0x27 /* ; */ -#define K_SQUOTESC 0x28 /* ' */ -#define K_GRAVSC 0x29 /* ` */ -#define K_BSLSHSC 0x2b /* \ */ -#define K_COMMASC 0x33 /* , */ -#define K_PERIODSC 0x34 /* . */ -#define K_SLASHSC 0x35 /* / */ - -/* keypad keys */ -#define K_HOMESC 0x47 /* scancode for home */ -#define K_DELSC 0x53 /* scancode for del */ - -/* - * Ascii values and flag characters for key map. - * A function key is represented by the 3-byte char sequence that it - * corresponds to. - * Other mappable non-Ascii keys (e.g., "ctrl") are represented by a - * two-byte sequence: K_SCAN, followed by the key's scan code. - */ -#define K_DONE 0xff /* must be same as NC */ -#define NC 0xff /* No character defined */ - -#define K_SCAN 0xfe /* followed by scan code */ - -/* ascii char set */ -#define K_NUL 0x00 /* Null character */ -#define K_SOH 0x01 -#define K_STX 0x02 -#define K_ETX 0x03 -#define K_EOT 0x04 -#define K_ENQ 0x05 -#define K_ACK 0x06 -#define K_BEL 0x07 /* bell character */ -#define K_BS 0x08 /* back space */ -#define K_HT 0x09 -#define K_LF 0x0a /* line feed */ -#define K_VT 0x0b -#define K_FF 0x0c -#define K_CR 0x0d /* carriage return */ -#define K_SO 0x0e -#define K_SI 0x0f -#define K_DLE 0x10 -#define K_DC1 0x11 -#define K_DC2 0x12 -#define K_DC3 0x13 -#define K_DC4 0x14 -#define K_NAK 0x15 -#define K_SYN 0x16 -#define K_ETB 0x17 -#define K_CAN 0x18 -#define K_EM 0x19 -#define K_SUB 0x1a -#define K_ESC 0x1b /* escape character */ -#define K_FS 0x1c -#define K_GS 0x1d -#define K_RS 0x1e -#define K_US 0x1f -#define K_SPACE 0x20 /* space character */ -#define K_BANG 0x21 /* ! */ -#define K_DQUOTE 0x22 /* " */ -#define K_POUND 0x23 /* # */ -#define K_DOLLAR 0x24 /* $ */ -#define K_PERC 0x25 /* % */ -#define K_AMPER 0x26 /* & */ -#define K_SQUOTE 0x27 /* ' */ -#define K_LPAREN 0x28 /* ( */ -#define K_RPAREN 0x29 /* ) */ -#define K_ASTER 0x2a /* * */ -#define K_PLUS 0x2b /* + */ -#define K_COMMA 0x2c /* , */ -#define K_MINUS 0x2d /* - */ -#define K_PERIOD 0x2e /* . */ -#define K_SLASH 0x2f /* / */ -#define K_ZERO 0x30 /* 0 */ -#define K_ONE 0x31 /* 1 */ -#define K_TWO 0x32 /* 2 */ -#define K_THREE 0x33 /* 3 */ -#define K_FOUR 0x34 /* 4 */ -#define K_FIVE 0x35 /* 5 */ -#define K_SIX 0x36 /* 6 */ -#define K_SEVEN 0x37 /* 7 */ -#define K_EIGHT 0x38 /* 8 */ -#define K_NINE 0x39 /* 9 */ -#define K_COLON 0x3a /* : */ -#define K_SEMI 0x3b /* ; */ -#define K_LTHN 0x3c /* < */ -#define K_EQL 0x3d /* = */ -#define K_GTHN 0x3e /* > */ -#define K_QUES 0x3f /* ? */ -#define K_ATSN 0x40 /* @ */ -#define K_A 0x41 /* A */ -#define K_B 0x42 /* B */ -#define K_C 0x43 /* C */ -#define K_D 0x44 /* D */ -#define K_E 0x45 /* E */ -#define K_F 0x46 /* F */ -#define K_G 0x47 /* G */ -#define K_H 0x48 /* H */ -#define K_I 0x49 /* I */ -#define K_J 0x4a /* J */ -#define K_K 0x4b /* K */ -#define K_L 0x4c /* L */ -#define K_M 0x4d /* M */ -#define K_N 0x4e /* N */ -#define K_O 0x4f /* O */ -#define K_P 0x50 /* P */ -#define K_Q 0x51 /* Q */ -#define K_R 0x52 /* R */ -#define K_S 0x53 /* S */ -#define K_T 0x54 /* T */ -#define K_U 0x55 /* U */ -#define K_V 0x56 /* V */ -#define K_W 0x57 /* W */ -#define K_X 0x58 /* X */ -#define K_Y 0x59 /* Y */ -#define K_Z 0x5a /* Z */ -#define K_LBRKT 0x5b /* [ */ -#define K_BSLSH 0x5c /* \ */ -#define K_RBRKT 0x5d /* ] */ -#define K_CARET 0x5e /* ^ */ -#define K_UNDSC 0x5f /* _ */ -#define K_GRAV 0x60 /* ` */ -#define K_a 0x61 /* a */ -#define K_b 0x62 /* b */ -#define K_c 0x63 /* c */ -#define K_d 0x64 /* d */ -#define K_e 0x65 /* e */ -#define K_f 0x66 /* f */ -#define K_g 0x67 /* g */ -#define K_h 0x68 /* h */ -#define K_i 0x69 /* i */ -#define K_j 0x6a /* j */ -#define K_k 0x6b /* k */ -#define K_l 0x6c /* l */ -#define K_m 0x6d /* m */ -#define K_n 0x6e /* n */ -#define K_o 0x6f /* o */ -#define K_p 0x70 /* p */ -#define K_q 0x71 /* q */ -#define K_r 0x72 /* r */ -#define K_s 0x73 /* s */ -#define K_t 0x74 /* t */ -#define K_u 0x75 /* u */ -#define K_v 0x76 /* v */ -#define K_w 0x77 /* w */ -#define K_x 0x78 /* x */ -#define K_y 0x79 /* y */ -#define K_z 0x7a /* z */ -#define K_LBRACE 0x7b /* { */ -#define K_PIPE 0x7c /* | */ -#define K_RBRACE 0x7d /* } */ -#define K_TILDE 0x7e /* ~ */ -#define K_DEL 0x7f /* delete */ - -/* Ascii sequences to be generated by the named key */ -#define K_F1 0x1b,0x4f,0x50 -#define K_F1S 0x1b,0x4f,0x70 -#define K_F2 0x1b,0x4f,0x51 -#define K_F2S 0x1b,0x4f,0x71 -#define K_F3 0x1b,0x4f,0x52 -#define K_F3S 0x1b,0x4f,0x72 -#define K_F4 0x1b,0x4f,0x53 -#define K_F4S 0x1b,0x4f,0x73 -#define K_F5 0x1b,0x4f,0x54 -#define K_F5S 0x1b,0x4f,0x74 -#define K_F6 0x1b,0x4f,0x55 -#define K_F6S 0x1b,0x4f,0x75 -#define K_F7 0x1b,0x4f,0x56 -#define K_F7S 0x1b,0x4f,0x76 -#define K_F8 0x1b,0x4f,0x57 -#define K_F8S 0x1b,0x4f,0x77 -#define K_F9 0x1b,0x4f,0x58 -#define K_F9S 0x1b,0x4f,0x78 -#define K_F10 0x1b,0x4f,0x59 -#define K_F10S 0x1b,0x4f,0x79 -#define K_F11 0x1b,0x4f,0x5a -#define K_F11S 0x1b,0x4f,0x7a -#define K_F12 0x1b,0x4f,0x41 -#define K_F12S 0x1b,0x4f,0x61 - -#define K_SCRL 0x1b,0x5b,0x4d -#define K_HOME 0x1b,0x5b,0x48 -#define K_UA 0x1b,0x5b,0x41 -#define K_PUP 0x1b,0x5b,0x56 -#define K_LA 0x1b,0x5b,0x44 -#define K_RA 0x1b,0x5b,0x43 -#define K_END 0x1b,0x5b,0x59 -#define K_DA 0x1b,0x5b,0x42 -#define K_PDN 0x1b,0x5b,0x55 -#define K_INS 0x1b,0x5b,0x40 - - -/* - * This array maps scancodes to Ascii characters (or character - * sequences). - * The first index is the scancode. The first NUMOUTPUT characters - * (accessed using the second index) correspond to the key's char - * sequence for the Normal state. The next NUMOUTPUT characters - * are for the Shift state, then Ctrl, then Alt, then Shift/Alt. - */ -extern unsigned char key_map[NUMKEYS][WIDTH_KMAP]; - - - -/* - * These routines are declared here so that all the modules making - * up the kd driver agree on how to do locking. - */ - -#define SPLKD spltty - - -/* - * Ioctl's on /dev/console. - */ - -/* - * KDGKBENT, KDSKBENT - Get and set keyboard table entry. Useful for - * remapping keys. - * - * KDGSTATE - Get the keyboard state variable, which flags the - * modifier keys (shift, ctrl, etc.) that are down. See - * KS_NORMAL et al above. Used for debugging. - * - * KDSETBELL - Turns the bell on or off. - */ - -#define KDGKBENT _MACH_IOWR('k', 1, struct kbentry) /* get keybd entry */ - -#define KDSKBENT _MACH_IOW('k', 2, struct kbentry) /* set keybd entry */ - -#define KDGSTATE _MACH_IOR('k', 3, int) /* get keybd state */ - -#define KDSETBELL _MACH_IOW('k', 4, int) /* turn bell on or off */ -# define KD_BELLON 1 -# define KD_BELLOFF 0 - -/* - * This struct is used for getting and setting key definitions. The - * values for kb_index are obtainable from the man page for - * keyboard(7) (though they should really be defined here!). - */ -struct kbentry { - unsigned char kb_state; /* which state to use */ - unsigned char kb_index; /* which keycode */ - unsigned char kb_value[NUMOUTPUT]; /* value to get/set */ -}; - - -/* - * Ioctl's on /dev/kbd. - */ - -/* - * KDSKBDMODE - When the console is in "ascii" mode, keyboard events are - * converted to Ascii characters that are readable from /dev/console. - * When the console is in "event" mode, keyboard events are - * timestamped and queued up on /dev/kbd as kd_events. When the last - * close is done on /dev/kbd, the console automatically reverts to ascii - * mode. - * When /dev/mouse is opened, mouse events are timestamped and queued - * on /dev/mouse, again as kd_events. - * - * KDGKBDTYPE - Returns the type of keyboard installed. Currently - * there is only one type, KB_VANILLAKB, which is your standard PC-AT - * keyboard. - */ - -extern int kb_mode; - -#define KDSKBDMODE _MACH_IOW('K', 1, int) /* set keyboard mode */ -#define KB_EVENT 1 -#define KB_ASCII 2 - -#define KDGKBDTYPE _MACH_IOR('K', 2, int) /* get keyboard type */ -#define KB_VANILLAKB 0 - -struct X_kdb { - unsigned int *ptr; - unsigned int size; -}; - -#define K_X_KDB_ENTER _MACH_IOW('K', 16, struct X_kdb) -#define K_X_KDB_EXIT _MACH_IOW('K', 17, struct X_kdb) - -#define K_X_IN 0x01000000 -#define K_X_OUT 0x02000000 -#define K_X_BYTE 0x00010000 -#define K_X_WORD 0x00020000 -#define K_X_LONG 0x00040000 -#define K_X_TYPE 0x03070000 -#define K_X_PORT 0x0000ffff - - -typedef unsigned short kev_type; /* kd event type */ - -/* (used for event records) */ -struct mouse_motion { - short mm_deltaX; /* units? */ - short mm_deltaY; -}; - -#define MOUSEBUFSIZE 5 /* num bytes def'd by protocol */ - -struct mouse_rawbuf { - unsigned char mr_bufsize; - unsigned char mr_buf[1]; -}; - -typedef struct { - kev_type type; /* see below */ - struct time_value time; /* timestamp */ - union { /* value associated with event */ - boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */ - Scancode sc; /* KEYBD_EVENT */ - struct mouse_motion mmotion; /* MOUSE_MOTION */ - struct mouse_rawbuf mrawbuf; /* MOUSE_RAW */ - } value; -} kd_event; - -#define m_deltaX mmotion.mm_deltaX -#define m_deltaY mmotion.mm_deltaY -#define r_buf mrawbuf.mr_buf -#define r_bufsize mrawbuf.mr_bufsize - -/* - * kd_event ID's. - */ -#define MOUSE_LEFT 1 /* mouse left button up/down */ -#define MOUSE_MIDDLE 2 -#define MOUSE_RIGHT 3 -#define MOUSE_MOTION 4 /* mouse motion */ -#define KEYBD_EVENT 5 /* key up/down */ - -/* CMOS Info */ - -#define CMOS_ADDR 0x70 /* port for CMOS ram address */ -#define CMOS_DATA 0x71 /* port for CMOS ram data */ - - -/* Addresses, related masks, and potential results */ - -#define CMOS_EB 0x14 /* read Equipment Byte */ -#define CM_SCRMSK 0x30 /* mask for EB query to get screen */ -#define CM_EGA_VGA 0x00 /* "not CGA or MONO" */ -#define CM_CGA_40 0x10 -#define CM_CGA_80 0x20 -#define CM_MONO_80 0x30 - - -#endif /* _MACHINE_KD_H_ */ diff --git a/pexpert/i386/pe_init.c b/pexpert/i386/pe_init.c index a483e72f6..aa1c089ec 100644 --- a/pexpert/i386/pe_init.c +++ b/pexpert/i386/pe_init.c @@ -43,9 +43,12 @@ extern void initialize_screen(void *, unsigned int); static vm_offset_t mapframebuffer(caddr_t,int); static vm_offset_t PE_fb_vaddr = 0; static int PE_fb_mode = TEXT_MODE; +static KERNBOOTSTRUCT * PE_kbp = 0; /* private globals */ -PE_state_t PE_state; +PE_state_t PE_state; +dt_data gMemoryMapNode; +dt_data gDriversProp; /* Clock Frequency Info */ clock_frequency_info_t gPEClockFrequencyInfo; @@ -107,9 +110,53 @@ void PE_init_iokit(void) unsigned char * data; unsigned char * clut; - dt = (long *) createdt( - fakePPCDeviceTree, - &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength); + typedef struct { + char name[32]; + unsigned long length; + unsigned long value[2]; + } DriversPackageProp; + + /* + * Update the fake device tree with the driver information provided by + * the booter. + */ + + gDriversProp.length = PE_kbp->numBootDrivers * sizeof(DriversPackageProp); + gMemoryMapNode.length = 2 * sizeof(long); + + dt = (long *) createdt( fakePPCDeviceTree, + &((boot_args*)PE_state.fakePPCBootArgs)->deviceTreeLength ); + + if ( dt ) + { + DriversPackageProp * prop = (DriversPackageProp *) gDriversProp.address; + int i; + + /* Copy driver info in kernBootStruct to fake device tree */ + + for ( i = 0; i < PE_kbp->numBootDrivers; i++, prop++ ) + { + switch ( PE_kbp->driverConfig[i].type ) + { + case kBootDriverTypeKEXT: + sprintf(prop->name, "Driver-%lx", PE_kbp->driverConfig[i].address); + break; + + case kBootDriverTypeMKEXT: + sprintf(prop->name, "DriversPackage-%lx", PE_kbp->driverConfig[i].address); + break; + + default: + sprintf(prop->name, "DriverBogus-%lx", PE_kbp->driverConfig[i].address); + break; + } + prop->length = sizeof(prop->value); + prop->value[0] = PE_kbp->driverConfig[i].address; + prop->value[1] = PE_kbp->driverConfig[i].size; + } + + *gMemoryMapNode.address = PE_kbp->numBootDrivers + 1; + } /* Setup powermac_info and powermac_machine_info structures */ @@ -142,17 +189,19 @@ void PE_init_platform(boolean_t vm_initialized, void * args) if (PE_state.initialized == FALSE) { extern unsigned int halt_in_debugger, disableDebugOuput; - unsigned int debug_arg; + unsigned int debug_arg; + + PE_kbp = (KERNBOOTSTRUCT *) args; PE_state.initialized = TRUE; PE_state.bootArgs = args; - PE_state.video.v_baseAddr = ((KERNBOOTSTRUCT *)args)->video.v_baseAddr; - PE_state.video.v_rowBytes = ((KERNBOOTSTRUCT *)args)->video.v_rowBytes; - PE_state.video.v_height = ((KERNBOOTSTRUCT *)args)->video.v_height; - PE_state.video.v_width = ((KERNBOOTSTRUCT *)args)->video.v_width; - PE_state.video.v_depth = ((KERNBOOTSTRUCT *)args)->video.v_depth; - PE_state.video.v_display = ((KERNBOOTSTRUCT *)args)->video.v_display; - PE_fb_mode = ((KERNBOOTSTRUCT *)args)->graphicsMode; + PE_state.video.v_baseAddr = PE_kbp->video.v_baseAddr; + PE_state.video.v_rowBytes = PE_kbp->video.v_rowBytes; + PE_state.video.v_height = PE_kbp->video.v_height; + PE_state.video.v_width = PE_kbp->video.v_width; + PE_state.video.v_depth = PE_kbp->video.v_depth; + PE_state.video.v_display = PE_kbp->video.v_display; + PE_fb_mode = PE_kbp->graphicsMode; PE_state.fakePPCBootArgs = (boot_args *)&fakePPCBootArgs; ((boot_args *)PE_state.fakePPCBootArgs)->machineType = 386; @@ -175,8 +224,8 @@ void PE_init_platform(boolean_t vm_initialized, void * args) if (PE_parse_boot_arg("debug", &debug_arg)) { if (debug_arg & DB_HALT) halt_in_debugger = 1; if (debug_arg & DB_PRT) disableDebugOuput = FALSE; - } - } + } + } if (!vm_initialized) { @@ -184,13 +233,13 @@ void PE_init_platform(boolean_t vm_initialized, void * args) outb(0x21, 0xff); /* Maskout all interrupts Pic1 */ outb(0xa1, 0xff); /* Maskout all interrupts Pic2 */ - pe_identify_machine(args); + pe_identify_machine(args); } else { - pe_init_debug(); - - PE_create_console(); + pe_init_debug(); + + PE_create_console(); } } @@ -222,6 +271,13 @@ int PE_current_console( PE_Video * info ) * when we are in Text mode. */ info->v_baseAddr = 0; + + /* + * Scale the size of the text screen from characters + * to pixels. + */ + info->v_width *= 8; // CHARWIDTH + info->v_height *= 16; // CHARHEIGHT } return (0); @@ -290,3 +346,21 @@ mapframebuffer( caddr_t physaddr, /* start of framebuffer */ return vmaddr; } + +/* + * The default (non-functional) PE_poll_input handler. + */ +static int +PE_stub_poll_input(unsigned int options, char * c) +{ + *c = 0xff; + return 1; /* 0 for success, 1 for unsupported */ +} + +/* + * Called by the kernel debugger to poll for keyboard input. + * Keyboard drivers may replace the default stub function + * with their polled-mode input function. + */ +int (*PE_poll_input)(unsigned int options, char * c) + = PE_stub_poll_input; diff --git a/pexpert/pexpert/i386/boot.h b/pexpert/pexpert/i386/boot.h index 80d6adde1..f41b3ec8c 100644 --- a/pexpert/pexpert/i386/boot.h +++ b/pexpert/pexpert/i386/boot.h @@ -26,91 +26,63 @@ * What the booter leaves behind for the kernel. */ -/* The config table has room for 13 drivers if their config files - * are the maximum size allowed. +/* + * Maximum number of boot drivers that can be loaded. */ -#define CONFIG_SIZE (13 * 4096) +#define NDRIVERS 500 -/* Maximum number of boot drivers supported, assuming their - * config files fit in the bootstruct. +/* + * Types of boot driver that may be loaded by the booter. */ -#define NDRIVERS 64 +enum { + kBootDriverTypeInvalid = 0, + kBootDriverTypeKEXT = 1, + kBootDriverTypeMKEXT = 2 +}; typedef struct { - char *address; // address where driver was loaded - int size; // entry point for driver + unsigned long address; // address where driver was loaded + unsigned long size; // number of bytes + unsigned long type; // driver type } driver_config_t; +/* + * APM BIOS information. + */ typedef struct { - unsigned short major_vers; // == 0 if not present - unsigned short minor_vers; - unsigned long cs32_base; - unsigned long cs16_base; - unsigned long ds_base; - unsigned long cs_length; - unsigned long ds_length; - unsigned long entry_offset; + unsigned short major_vers; // == 0 if not present + unsigned short minor_vers; + unsigned long cs32_base; + unsigned long cs16_base; + unsigned long ds_base; + unsigned long cs_length; + unsigned long ds_length; + unsigned long entry_offset; union { - struct { - unsigned long mode_16 :1; - unsigned long mode_32 :1; - unsigned long idle_slows_cpu :1; - unsigned long reserved :29; - } f; - unsigned long data; + struct { + unsigned long mode_16 :1; + unsigned long mode_32 :1; + unsigned long idle_slows_cpu :1; + unsigned long reserved :29; + } f; + unsigned long data; } flags; - unsigned long connected; + unsigned long connected; } APM_config_t; -typedef struct _EISA_slot_info_t { - union { - struct { - unsigned char duplicateID :4; - unsigned char slotType :1; - unsigned char prodIDPresent :1; - unsigned char dupIDPresent :1; - } s; - unsigned char d; - } u_ID; - unsigned char configMajor; - unsigned char configMinor; - unsigned short checksum; - unsigned char numFunctions; - union { - struct { - unsigned char fnTypesPresent :1; - unsigned char memoryPresent :1; - unsigned char irqPresent :1; - unsigned char dmaPresent :1; - unsigned char portRangePresent:1; - unsigned char portInitPresent :1; - unsigned char freeFormPresent :1; - unsigned char reserved:1; - } s; - unsigned char d; - } u_resources; - unsigned char id[8]; -} EISA_slot_info_t; - -typedef struct _EISA_func_info_t { - unsigned char slot; - unsigned char function; - unsigned char reserved[2]; - unsigned char data[320]; -} EISA_func_info_t; - -#define NUM_EISA_SLOTS 64 - +/* + * PCI bus information. + */ typedef struct _PCI_bus_info_t { union { - struct { - unsigned char configMethod1 :1; - unsigned char configMethod2 :1; - unsigned char :2; - unsigned char specialCycle1 :1; - unsigned char specialCycle2 :1; - } s; - unsigned char d; + struct { + unsigned char configMethod1 :1; + unsigned char configMethod2 :1; + unsigned char :2; + unsigned char specialCycle1 :1; + unsigned char specialCycle2 :1; + } s; + unsigned char d; } u_bus; unsigned char maxBusNum; unsigned char majorVersion; @@ -119,69 +91,55 @@ typedef struct _PCI_bus_info_t { } PCI_bus_info_t; /* - * Video information.. + * Video information. */ - struct boot_video { - unsigned long v_baseAddr; /* Base address of video memory */ - unsigned long v_display; /* Display Code (if Applicable */ - unsigned long v_rowBytes; /* Number of bytes per pixel row */ - unsigned long v_width; /* Width */ - unsigned long v_height; /* Height */ - unsigned long v_depth; /* Pixel Depth */ + unsigned long v_baseAddr; // Base address of video memory + unsigned long v_display; // Display Code (if Applicable + unsigned long v_rowBytes; // Number of bytes per pixel row + unsigned long v_width; // Width + unsigned long v_height; // Height + unsigned long v_depth; // Pixel Depth }; -typedef struct boot_video boot_video; +typedef struct boot_video boot_video; + +#define GRAPHICS_MODE 1 +#define TEXT_MODE 0 -#define BOOT_STRING_LEN 160 +#define BOOT_STRING_LEN 160 +#define CONFIG_SIZE (12 * 4096) typedef struct { - short version; - char bootString[BOOT_STRING_LEN];// string we booted with - int magicCookie; // KERNBOOTMAGIC if struct valid - int numIDEs; // how many IDE drives - int rootdev; // booters guess as to rootdev - int convmem; // conventional memory - int extmem; // extended memory - char boot_file[128]; // name of the kernel we booted - int first_addr0; // first address for kern convmem - int diskInfo[4]; // bios info for bios dev 80-83 - int graphicsMode; // did we boot in graphics mode? - int kernDev; // device kernel was fetched from - int numBootDrivers; // number of drivers loaded by booter - char *configEnd; // pointer to end of config files - int kaddr; // kernel load address - int ksize; // size of kernel - void *rld_entry; // entry point for standalone rld - - driver_config_t driverConfig[NDRIVERS]; - APM_config_t apm_config; - - char _reserved[7500]; - - boot_video video; - - PCI_bus_info_t pciInfo; - - int eisaConfigFunctions; - EISA_slot_info_t eisaSlotInfo[NUM_EISA_SLOTS];// EISA slot information - - char config[CONFIG_SIZE]; // the config file contents + short version; + char bootString[BOOT_STRING_LEN]; // boot arguments + int magicCookie; // KERNBOOTMAGIC + int numIDEs; // number of IDE drives + int rootdev; // root device + int convmem; // conventional memory + int extmem; // extended memory + char bootFile[128]; // kernel file name + int firstAddr0; // first address for kern convmem + int diskInfo[4]; // info for bios dev 80-83 + int graphicsMode; // booted in graphics mode? + int kernDev; // device kernel was fetched from + int numBootDrivers; // number of drivers loaded + char * configEnd; // pointer to end of config files + int kaddr; // kernel load address + int ksize; // size of kernel + driver_config_t driverConfig[NDRIVERS]; + char _reserved[2052]; + boot_video video; + PCI_bus_info_t pciInfo; + APM_config_t apmConfig; + char config[CONFIG_SIZE]; } KERNBOOTSTRUCT; -#define GRAPHICS_MODE 1 -#define TEXT_MODE 0 - -#define KERNSTRUCT_ADDR ((KERNBOOTSTRUCT *)0x11000) -#define KERNBOOTMAGIC 0xa7a7a7a7 - -#ifndef EISA_CONFIG_ADDR -#define EISA_CONFIG_ADDR 0x20000 -#define EISA_CONFIG_LEN 0x10000 -#endif +#define KERNSTRUCT_ADDR ((KERNBOOTSTRUCT *) 0x11000) +#define KERNBOOTMAGIC 0xa7a7a7a7 #ifndef KERNEL -extern KERNBOOTSTRUCT *kernBootStruct; +extern KERNBOOTSTRUCT * kernBootStruct; #endif #define BOOT_LINE_LENGTH 256 diff --git a/pexpert/pexpert/i386/protos.h b/pexpert/pexpert/i386/protos.h index cdb4d4583..355e023bf 100644 --- a/pexpert/pexpert/i386/protos.h +++ b/pexpert/pexpert/i386/protos.h @@ -63,13 +63,12 @@ __OUT(b, char) __OUT(w, short) __OUT(l, long) -//------------------------------------------------------------------------ -// from bsd/dev/ppc/busses.h which clashes with mach/device/device_types.h -typedef int io_req_t; - - -// typedef struct ipc_port *ipc_port_t; +extern void cninit(void); +extern void bcopy(void * from, void * to, int size); +extern int sprintf(char * str, const char * format, ...); -extern void cninit(void); +extern boolean_t vc_progress_initialize( void * desc, + unsigned char * data, + unsigned char * clut ); #endif /* _PEXPERT_I386_PROTOS_H */ -- 2.45.2